人に聞けない痔の悩み、これでスッキリ >>

perlで大容量CSVのsort方法について


perlでcsvファイル100MB超のファイルをソートしたいと思ってますが、以下の方法でメモリーの関係上(と思ってます。)できません。

ソートを行う方法がありますでしょうか?
件数も11万件あるので、エクセルでソートしてからの受け渡しが出来ずに悩んでます。

(ここから)
#sortロジック
sub sort {
use warnings;
use feature ':5.10';

open my $ifh, '<', $inport or &error("Can't open $inport");
my @lines = <$ifh>;
close $ifh;

print @lines, "\n";
#csvファイル何番目?

my @sorted = map { $_->[0] }
sort { $b->[0] <=> $a->[0]}
map { [(split q{,}, $_)[0], $_] }
@lines;

@lines = @sorted;
exit;
}
(ここまで)

いつも貴重なアドバイスをありがとうございます。よろしくお願いいたします。

このQ&Aに関連する最新のQ&A

A 回答 (3件)

ファイルを1度に読み込まずに、while ループで読み込んでソートキーをハッシュのキーに割り当て、ハッシュの配列に保存して、一定数になったらファイルに保存して、最後にまとめればそれほどメモリは必要ないと思います。



my %sorted;

while (my $line = <$fh>) {
my $key = (split /,/, $line)[0];
push @{$sorted{$key}}, $line;
if (@{$sorted{$key}} == 1000) {
open OUT, ">>$key.tmp" or die "Can't open: $!";
print OUT @{$sorted{$key}};
close OUT;
@{$sorted{$key}} = ();
}
}

open OUT, ">out.txt" or die "Can't open: $!";
foreach my $key (sort { $b <=> $a } keys $sorted) {
if (-e "$key.tmp") {
open IN, "$key.tmp" or die "Can't open: $!";
print OUT while <IN>;
close IN;
}
print OUT @{$sorted{$key}} if @{$sorted{$key}};
}
close OUT;
    • good
    • 0
この回答へのお礼

早速やってみました。
すごいです!!
無事動作させることが出来ました!!
140MBを超えるデータですが、1分かからないで終わります。
こんなにパフォーマンスが向上する方法があるのかと目から鱗です。
いつも助かります。ありがとうございました。

お礼日時:2010/06/26 23:15

> foreach my $key (sort { $b <=> $a } keys $sorted) {



No2 です。1つ誤記がありました。訂正します。

foreach my $key (sort { $b <=> $a } keys %sorted) {
    • good
    • 0
この回答へのお礼

訂正ありがとうございます。
助かります。

お礼日時:2010/06/26 23:13

メモリが無理なら、ファイルに頼るしかないでしょう。



ファイルのような外部記録を使ったソートアルゴリズムには自然マージソートがあります。
この方法だと、1行ずつ処理すればいいので、メモリはそれほど使いません。

CPANのFile::Sortモジュールがmerge sortのようです。
http://search.cpan.org/~cnandor/File-Sort-1.01/S …

あるいは、Cとかのソースは見付かるので、自分で作ってもいいでしょう。
    • good
    • 0
この回答へのお礼

いつもアドバイスありがとうございます。
File::Sortモジュールについて少し調べてやってみようと思いましたが、うまくいきませんでした。
サーバーがこのモジュールがないのかもしれませんので確認をしてみようと思います。

お礼日時:2010/06/26 23:12

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q大量データから抽出する効率よいperlプログラムは

以前も質問させていただきましたが、
大量データから抽出する際の効率よいperlプログラム作成について
また、教えてください。
例)
大量データ Aファイル 3列 可変値(数値、URL、数値)タブ区切り 重複値あり
123 http://www.XX.co.jp/XX 4567
1111 http://www.XX.co.jp/XX 3333
3 http://www.XX.co.jp/YZ 4567
1111 http://www.YYY… 116

抽出対象データ Bファイル 1列(URL)重複なし
http://www.XX.co.jp/X
http://www.YYY.co.jp


BファイルにあるURLで始まるURLがAファイルにある場合 Aファイルのその行を抽出したい。
grepで実施すると すごい時間がかかってしまうため、効率よい抽出方法をおしえてください。
今回は、完全一致ではなく、Bファイルに入っているリストのURLから始まるものにしたいと考えているので、前の手法(hash連想配列)が使えないと考えております。
Aファイルが容量大きいため、grep処理では1週間たっても終わらないのです。

以前も質問させていただきましたが、
大量データから抽出する際の効率よいperlプログラム作成について
また、教えてください。
例)
大量データ Aファイル 3列 可変値(数値、URL、数値)タブ区切り 重複値あり
123 http://www.XX.co.jp/XX 4567
1111 http://www.XX.co.jp/XX 3333
3 http://www.XX.co.jp/YZ 4567
1111 http://www.YYY… 116

抽出対象データ Bファイル 1列(URL)重複なし
http://www.XX.co.jp/X
http://www.YYY.co.jp


BファイルにあるURLで始まるURLがAファイルにある場合 Aフ...続きを読む

Aベストアンサー

本当に終わるか気になったので、自分のPCで試してみました。
メモリ4Gであれこれ普通に使いながら、次のものです。
ただ、内一個は途中でやめちゃいました。

まず、こんなかんじでdummyファイルを作りました

Ruby
# dummy作成
http://ideone.com/TDxut
→1Gバイトで約2000万件の嘘データ
# フィルタ元リスト作成
→dummyの頭50件の、URL内ドメイン箇所までのリスト

Ruby
# 文字列マッチ
http://ideone.com/xPsku
→約25分

# 正規表現マッチ
http://ideone.com/kvSff
→途中でやめた為不明

GNU/grep
# grep -F -f 元リスト.txt dummy.txt
→1分弱!


ということで、少なくともRubyでは全く太刀打ちできませんでした。
でも、終わる分量ではあると思います。特にPerlならきっともっと早いんでしょう
やっぱりgrepがおすすめですね

QperlでCSVをソートする方法について

perl初心者です。いつもありがとうございます。

perlでcsvファイル(1行のカラム数は200)、総行数は約3万行のファイルを37番目のカラム(-25以上25未満の数値データ)で降順ソートしその値によって行数がだいたい均等になるよう3分割し、2番目のカラムに文字でも数字でもよいのですがその4つのグループごとにフラグ(例えば1,2,3)を入れたいと思ってます。グループ化については境目の37番カラムの値は重複している場合が多いと思うのですがその場合は下(別に上でもかまいません)に入れるものとします。

ソートロジックは過去の質問を参照して理解しましたがグループ化しフラグを入れるルーチンがうまく作れません。下記のように作ったのですがこの先同じことを何度もやらなくてはならないので先に進めません。どなたかお助けください。最終的にやりたいことはカラム37でグループ化→カラム2にフラグを立てる、次にカラム2とカラム38(-25から0までの数値)でソートし同様に同じ行数になるようにグループ化→カラム3にフラグを立てる、さらにカラム2とカラム3とカラム39(-25以上25未満の数値データ)でソートし・・・同様に繰り返し最終的に1グループが100件(行)~150件(行)になるようにしたいのです。つまり約3万件のデータを3*4*2*4*2=192分割(5列の値で分類)したい、そしてどのような範囲で分割したかという情報も得たいのです。

use strict;
use warnings;

use utf8;
use Encode;
binmode STDOUT, ':encoding(utf-8)';

my $dir = './data'; # 処理するディレクトリ
my $motoFile = 'customer.txt'; # もとファイル

open my $fh, '<:encoding(cp932)', "$dir/$motoFile" or die 'ファイルが開けません。',"$!";

my %sorted;

while (my $line = <$fh>) {
my $key = (split /,/, $line)[37];
push @{$sorted{$key}}, $line;
if (@{$sorted{$key}} == 1000) {
open OUT, '>>:encoding(cp932)', "$dir/$key.tmp" or die "Can't open: $!";
print OUT @{$sorted{$key}};
close OUT;
@{$sorted{$key}} = ();
}
}

open OUT, '>:encoding(cp932)', "$dir/out.txt" or die "Can't open: $!";
foreach my $key (sort { $b <=> $a } keys %sorted) {
if (-e "$key.tmp") {
open IN, '<:encoding(cp932)', "$dir/$key.tmp" or die "Can't open: $!";
print OUT while <IN>;
close IN;
}
print OUT @{$sorted{$key}} if @{$sorted{$key}};
}
close OUT;

#↓↓↓↓ここからフラグを作成するルーチン
# 行数を調べ3つに分けるルーチン
my @colum37;
open IN, '<:encoding(cp932)', "$dir/out.txt" or die 'ファイルが開けません。',"$!";
my @in = <IN>;
close IN;
my $gyousuu = scalar(@in);
my $amari = $gyousuu % 3;

if ($amari == 0) {
my $groupGyousuu = ($gyousuu-$amari)/3;
print "総行数は$gyousuu","で、1グループの行数は$groupGyousuu","ほど、余りは$amari\n";

# あまりが0の時、group1は@inの0行 ~$groupGyousuu-1行まで
#         group2は@inの$groupGyousuu行 ~$groupGyousuu*2-1行まで
#         group3は@inの$groupGyousuu*2行~$groupGyousuu*3-1行まで
foreach my $num (1..2) {
push @colum37, (split /,/, $in[$groupGyousuu*$num])[37]; # これは境目の先頭の37番目
}
print "@colum37\n"; #これでここまでは完成、分けるべき値がこの配列に入っている。

open OUT, '>:encoding(cp932)', "$dir/out.txt" or die "Can't open: $!";
foreach my $line (@in) {
my @line = split /,/,$line;
if ($line[37]>=$colum37[0]) {
$line[1] = 1;
}elsif ($line[37]>=$colum37[1] and $line[37]<$colum37[0]) {
$line[1] = 2;
}elsif ($line[37]<$colum37[1]) {
$line[1] = 3;
}
$line = join (',',@line);
print OUT $line;
}
close OUT;
}
elsif ($amari == 1) { この後未作成

perl初心者です。いつもありがとうございます。

perlでcsvファイル(1行のカラム数は200)、総行数は約3万行のファイルを37番目のカラム(-25以上25未満の数値データ)で降順ソートしその値によって行数がだいたい均等になるよう3分割し、2番目のカラムに文字でも数字でもよいのですがその4つのグループごとにフラグ(例えば1,2,3)を入れたいと思ってます。グループ化については境目の37番カラムの値は重複している場合が多いと思うのですがその場合は下(別に上でもかまいません)に入れるものとします。

ソートロジ...続きを読む

Aベストアンサー

## 面白そうだったので、自分流に書いてみました。
## 適当に書いたので、バグがあったらごめんなさいです。
## ← ##で始まる行は解説用コメントです

use strict;
use warnings;
use utf8;

binmode(STDOUT, ':utf8');
binmode(STDERR, ':utf8'); ## エラー出力も考慮しましょう

my $dir = './data'; # 処理するディレクトリ
my $motoFile = 'customer.txt'; # もとファイル

# データファイル読み込み
my @array;
open(my $fh, '<:encoding(cp932)', "$dir/$motoFile") or die 'ファイルが開けません。',"$!";
while(my $line = <$fh>) {
chomp $line;
## 「配列リファレンスの配列」を作る。複数カラムでのソートが楽になります
push(@array, [ split(/,/, $line) ]);
}
close($fh);

# 配列リファレンス内の指定カラム値を比較して配列をソート
## どこを使ってソートするかわからなかったので
## とりあえず[37]~[41]でソート
my @sorted = sort {
$b->[37] <=> $a->[37] ||
$b->[38] <=> $a->[38] ||
$b->[39] <=> $a->[39] ||
$b->[40] <=> $a->[40] ||
$b->[41] <=> $a->[41]
} @array;

# ソート済みデータファイル出力
## 分類用フラグは後付けで計算
open(my $fh_out, '>:encoding(cp932)', "$dir/out.txt") or die "Can't open: $!";
for(my $i=0; $i<192; $i++) {
# 192等分したブロックの先頭と終了のインデックスを求める
## 余りの分を先頭に近いブロックに寄せる方法については宿題としておきます(難しくないです)
my $start = int(@sorted * $i / 192);
my $end = int(@sorted * ($i+1) / 192) - 1;

# 分類用フラグの計算
my @flag_value = (
int($i / (4 * 2 * 4 * 2)) % 3 + 1,
int($i / (2 * 4 * 2)) % 4 + 1,
int($i / (4 * 2)) % 2 + 1,
int($i / 2) % 4 + 1,
$i % 2 + 1,
);

# 出力範囲の表示
## とりあえず標準出力に。
## データ形式に合わせて見やすいように整形するといいでしょう
printf(
"[%d, %d, %d, %d, %d] (%s, %s, %s, %s, %s) ~ (%s, %s, %s, %s, %s)\n",
@flag_value,
@{$sorted[$start]}[37..41],
@{$sorted[$end]}[37..41],
);

# ブロック毎にフラグを上書きしながら出力
for(my $j=$start; $j<=$end; $j++) {
## 分類用フラグをどこに立てるかわからなかったので
## とりあえず[2]~[6]に立てる
@{$sorted[$j]}[2..6] = @flag_value;

# 出力
print $fh_out join(',', @{$sorted[$j]}),"\n";
}
}
close($fh_out);

## 具体的な用途が不明なので以下は独り言ですが、
## 正直なところ、カラム内にインデックスフラグ立てるメリットは
## ほとんどない気がします・・。
## 結果を別ファイルに分けるならわかるのですが、それならなおさら
## カラム内にフラグを持たせる必要はないように思えます。

## 面白そうだったので、自分流に書いてみました。
## 適当に書いたので、バグがあったらごめんなさいです。
## ← ##で始まる行は解説用コメントです

use strict;
use warnings;
use utf8;

binmode(STDOUT, ':utf8');
binmode(STDERR, ':utf8'); ## エラー出力も考慮しましょう

my $dir = './data'; # 処理するディレクトリ
my $motoFile = 'customer.txt'; # もとファイル

# データファイル読み込み
my @array;
open(my $fh, '<:encoding(cp932)', "$dir/$motoFile") or die 'ファイルが開けませ...続きを読む

Qperlで容量の大きいCSVファイルを開く方法

perlで容量の大きいCSVファイルを開く方法


ファイル容量の大きいcsvファイルから、必要な項目を抜き出して別ファイルにするプログラムを作成したいと思ってます。
csvファイルが少ない場合は動作したのですが、容量が140MBを超えたデータを読み込もうとすると、ブラウザー表示で何も変化いたしません

プログラムは以下のようになってます。
-------------------------------------------------

open(IN,"$inport") || &error(" $inport を読み込みopen出来ません");
flock(IN,1);
@lines = <IN>;
foreach $lines (@lines) {
local(@val) = split("\,", $lines);
print "$val[0]";
$dat .= "$val[1]\,$val[5]\n";
}
open(OUT,">$dcsv");
flock(OUT,2);
print OUT "$dat";
close OUT;


-------------------------------------------------
件数も多いので、foreachを$lines (@lines) としないで($start .. $end)として読み込みの件数を制限して対応しようと考えてましたが、うまくいきませんでした。

ご指導いただけますと幸いです。

perlで容量の大きいCSVファイルを開く方法


ファイル容量の大きいcsvファイルから、必要な項目を抜き出して別ファイルにするプログラムを作成したいと思ってます。
csvファイルが少ない場合は動作したのですが、容量が140MBを超えたデータを読み込もうとすると、ブラウザー表示で何も変化いたしません

プログラムは以下のようになってます。
-------------------------------------------------

open(IN,"$inport") || &error(" $inport を読み込みopen出来ません");
flock(IN,1);
@lines = <IN>;
foreach $l...続きを読む

Aベストアンサー

質問者さんのコードは
> @lines = <IN>;
ここで、ファイルの全データを変数に読み込んで
> foreach $lines (@lines) {
これで、データを1つづつ取り出す

という処理になっていますので、「@lines=<IN>」の時点でメモリを大量に消費します。この2行の代わりに


> while ($lines = <IN>) {

とすれば、ファイルから1行ずつデータを読んで処理するようになりますので、
ファイルサイズが大きくても処理できるようになります。

ただし、そうやったとしても、
> $dat .= "$val[1]\,$val[5]\n";
この部分で変数 $dat のサイズがどんどん大きくなりますから、そちらの分のメモリ消費は入力ファイルサイズに比例します。

---

open(IN,"$inport") || &error(" $inport を読み込みopen出来ません");
flock(IN,1);

open(OUT,">$dcsv");
flock(OUT,2);

while ($lines = <IN>) {
local(@val) = split("\,", $lines);
print "$val[0]";
print OUT "$val[1]\,$val[5]\n";
}
close IN;
close OUT;
---
とすれば、完全に入力ファイルサイズに依存しないようになります。

質問者さんのコードは
> @lines = <IN>;
ここで、ファイルの全データを変数に読み込んで
> foreach $lines (@lines) {
これで、データを1つづつ取り出す

という処理になっていますので、「@lines=<IN>」の時点でメモリを大量に消費します。この2行の代わりに


> while ($lines = <IN>) {

とすれば、ファイルから1行ずつデータを読んで処理するようになりますので、
ファイルサイズが大きくても処理できるようになります。

ただし、そうやったとしても、
> $dat .= "$val[1]\,$val[5]\n";
この部分で変数 $dat ...続きを読む

QPerlで特定行から特定行までを抜き出したい

皆さんのお知恵をお貸し頂ければ幸いです。

Perlで以下のようなことをしたいと考えています。
例えば、次のようなテキストファイルがあったとします。

example.log
==================================
aaaa
hogehoge
test
okok
perl
script
==================================

上記ファイルを読み込んで、「hogehoge」から「perl」の間に挟まれた行だけ抜き出したいのです。
イメージとしては、読み込んだファイルを配列に入れて、一行づつ読ませ、キーワード「hogehoge」が現れたらそこでフラグを立て、それ以降の行を表示し、キーワード「perl」が現れた時点で表示を止めるという処理になるのかな?と思っています。

このような場合、どういう風にすればいいのでしょうか?
恐れ入りますが、ご教授頂ければ幸いです。

それでは、どうぞよろしくお願い致します。

Aベストアンサー

> 一行づつ読ませ、キーワード「hogehoge」が現れたらそこでフラグを立て、それ以降の行を表示し、キーワード「perl」が現れた時点で表示を止めるという処理になるのかな?と思っています。

それでいいと思いますよ?これをそのままコード化すると、こんな感じでしょうか。(No.1さんのとはちょっと結果が違います。)

open FH, "example.log" or die $!;
$flag = 0;
while ($data = <FH>) {
  chomp $data;
  if  ($data eq "hogehoge") { $flag = 1 }
  elsif ($data eq "perl")    { $flag = 0 }
  elsif ($flag) { print "$data\n" }
}
close FH;

で、もっと略したいPerlな人だとこんな感じ。Perl独特の記法がふんだんに使われているので、勉強するには不向きかもしれませんが^^;

open FH, "example.log" or die $!;
while (<FH>) {
  print if /^hogehoge$/ .. /^perl$/ and !/^(?:hogehoge|perl)$/;
}
close FH;

※インデントに全角空白を使っているので、コピーする場合はタブなどに置換して下さい。

> 一行づつ読ませ、キーワード「hogehoge」が現れたらそこでフラグを立て、それ以降の行を表示し、キーワード「perl」が現れた時点で表示を止めるという処理になるのかな?と思っています。

それでいいと思いますよ?これをそのままコード化すると、こんな感じでしょうか。(No.1さんのとはちょっと結果が違います。)

open FH, "example.log" or die $!;
$flag = 0;
while ($data = <FH>) {
  chomp $data;
  if  ($data eq "hogehoge") { $flag = 1 }
  elsif ($data eq "perl")    { $fl...続きを読む

Q数値かどうかの判定方法

$aに代入されているものが数値かどうかを判定するにはどのようにしたらよいのでしょうか?

Aベストアンサー

$a =~ /^[0-9]*$/
上記の場合、*は「直前のパターンの0回以上の繰り返し」の意味なので、0から9がなくても、つまり$aが空でもマッチしてしまいます。
なので、
$a =~ /^[0-9]+$/
としましょう。
(+は「直前のパターンの1回以上の繰り返し」)
また、0-9は\dで表すこともできるので
$a =~ /^\d+$/
と書くこともできます。

Q複数ファイルの読み込みについて

perl初心者です。

あるディレクトリから拡張子がdataであるファイルを全て読み込みたいのですが、方法がわかりません。
cshで書くと
foreach arg (*.data)
コマンド $arg

のようになりますが、perlだと
foreach $arg (@arg){
コマンド $arg

となりますよね?
引数がリストなのでよくわかりません。
そもそもperlではできないのでしょうか?


それともう一点ですが、ファイルオープンするときに
foreachループの中で
open(FILE, "$arg");
とすることは可能ですか?
上の質問と組み合わせて全てのファイルを開いて作業を行いたいので。

説明が下手ですいません。補足しますのでよろしくお願いします。

Aベストアンサー

while(<*.data>)
{
## $_には、*.DATAなファイル名が格納されている。
open(F,"$_"); ##openする。
while(<F>)
{
##読み出された内容が$_に格納されている。
print $_; ##出力してみる。
}
}

というのが最短コーディングです。

Qperlでcsvファイルを読む(ダブルコーテーション内カンマを無視したい)

perlでCSVファイルを読み込むスクリプトを作っています。

以下のようなCSVファイルがあります。

■CSVファイル
東京,よろしくお願いします。
大阪,はじめまして
九州,"5,000円でお願いします"

カンマで区切り、以下のようにすると、"5,000円"の部分が2つに分かれてしまいます。
($data1,$data2) = split(/,/,$all_data)

前後にダブルコーテーションがあった場合、中のカンマで区切らないような良い方法はないでしょうか?

環境:
Perl 5.8.5

Aベストアンサー

Text::ParseWords を使ってこんなのはどうですか。(例ではparse_lineを使っています)
もしquoteを残したければundefを1に変えてください。

use Text::ParseWords;

$" = "\t";
while (<DATA>) {
chomp;
my @words = &parse_line(',', undef, $_);
print "@words\n";
}

exit 0;
__DATA__
東京,よろしくお願いします。
大阪,はじめまして
九州,"5,000円でお願いします"

QPerlで行頭にある文字が含まれている行を全部削除して詰めたい

perl初心者です。以下のようにデータがならんでいる時、
test111 aaaaaaaaabbbbbbbbcccccc
test112 aaaaccccabbbbbbbbcccccc
test113 aaaaccaaabbbbbbbbcccccc
test114 acccaaaaabbbbbbbbcccccc

test111 aacaaaaaabbbbbbbbcccccc
test112 accaaaaaabbbbbbbbcccccc
test113 aaacccaaabbbbbbbbcccccc
test114 aaaaaccaabbbbbbbbcccccc

test112の行だけ削除して、さらにそこを詰めたい時のスクリプトを作成しています。

途中からわかりません。
行を削除する関数が調べても見つからないのです。

#!/usr/bin/perl ;
open(IN, "test.doc") or die ;

open(OUT, ">testout.doc");

while(<IN>) {
chomp ;
if (/(\S+)/) {

$name = $1 ;

if ($name =~ /^test112(\S+)/) {
#ここでマッチさせて、一気に行を削除して、しかも行を詰めたいのですが

;

}
print OUT " \n" ;
}
}
close (IN) ;
close (OUT) ;

大変困っております。宜しくお願いします。

perl初心者です。以下のようにデータがならんでいる時、
test111 aaaaaaaaabbbbbbbbcccccc
test112 aaaaccccabbbbbbbbcccccc
test113 aaaaccaaabbbbbbbbcccccc
test114 acccaaaaabbbbbbbbcccccc

test111 aacaaaaaabbbbbbbbcccccc
test112 accaaaaaabbbbbbbbcccccc
test113 aaacccaaabbbbbbbbcccccc
test114 aaaaaccaabbbbbbbbcccccc

test112の行だけ削除して、さらにそこを詰めたい時のスクリプトを作成しています。

途中からわかりません。
行を削除する関数が調べても見つからないのです。

...続きを読む

Aベストアンサー

一致しなかったときのみ出力するということで、

while(<IN>){
unless(/^test112/){
print OUT;
}
}

更に簡単に書くと、
while(<IN>){
print OUT unless(/^test112/);
}
となります。

削除にこだわるなら、
while(<IN>){
s/^test112\s.+//;
print OUT;
}
あたりでしょうか。

もしくは、明示的に削除したいなら、
while(<IN>){
if(/^test112\s.+/){
$_ = "";
}
print OUT;
}
というふうに、カラの文字列を代入してやるのも、値を削除するときの常套手段ですね。

Qファイルの行数取得

超初心者です。

いま、表計算的なスクリプトを記述しています。

あるファイルの行数を取得する関数ってあるんでしょうか?

ファイルに記述されている数値を足したり引いたりするのですが、forを使っての計算の際にファイルの行数が必要となりました。

Aベストアンサー

Perlにですね。ないはずです。
行数とはファイルに書かれた改行文字の個数ということなので
実際にファイルを全て読み込まないと行数はわかりません。
以下のように色々な方法があると思います

#### 単純な例
$a = 0;
open FD, "<file.txt" || die $!;
while (<FD>) {
$a++;
}
close FD;
print "行数:$a\n";

### 少しマニアックな方法
open FD, "<file.txt" || die $!;
@a = <FD>;
close FD;
print "行数:" . ($#a + 1) + "\n";


### 反則的方法(外部コマンド) ... UNIXの場合
print "行数:" . `wc -l file.txt` . "\n";

Qファイルからデータを読み込んで、配列に格納する方法

データファイル grep.dat があり、その中は
12345
67890
ABCDE
(EOF)
となっています。
 
このファイルの中身を読み込んで、配列 P[0]の
中に("12345","67890","ABCDE") に格納したい
のですが、どのように記述すればよいでしょうか。

Aベストアンサー

多次元配列に代入する場合

my @p;
open FILE, "grep.dat";
  @{$p[0]} = <FILE>;  ・・(a)
close FILE;

openの書式などは好みで変えてください。
結論を言えば、(a)のように書けばokです。

#細かい書式は他にもありますので調べてみるといいかもしれません。


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング