- ベストアンサー
ファイルからある文字列の個数を数えたい
perl5でunixの"wc"や"grep -c"みたいに1つのファイルの中からある文字列の個数を カウントするスクリプトを作ろうとしています。 ファイルは256文字×10万行くらいのテキストで、 検索する文字列は15文字前後×40個(例えば「apple-000001」「lemon_orange」など)です。 どのようなスクリプトを組んだら効率よく各文字列をカウントできるのでしょうか? それよりwcやgrep -cを40回行った方が早いのでしょうか?
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
最終的な速度については分かりませんが,Perl で効率良く実現しようというのであれば,配列(下の例では @pattern)に照合する文字列を入れておいて,ファイルから一行読むごとに, foreach $pattern (@pattern) { $count{$pattern} += /$pattern/g; #行の内容は $_ に入っていると仮定 } とかしてやればよいのではないでしょうか。 一行にパターンが必ず一回しか現れないのであれば,2行目は, $count{$pattern}++ if (/$pattern/); とかすることも可能でしょう。 上記コードでは,パターン照合回数は grep を使ったときと同じですが,ファイルI/Oの回数は 1/パターン数 で済みます。が,パターン照合の速度そのものは grep のほうが速いでしょうから,最終的にどちらが速いかはやってみないと分かりません。 ちなみに,Perl のパターンマッチング処理は,一般に sed と同等或いはより高速だと言われているので,sed を使う意味はあまりないと思います。
その他の回答 (2)
- a-kuma
- ベストアンサー率50% (1122/2211)
> また、systemコマンドでgrepを呼んだとすると、その結果をperlで処理するのはどうするのでしょうか? パイプを使います。perl は普段使わないので、怪しいのですが、こんな感じになるはず。 open IN, "grep なんとかかんとか |" or die "error\n"; while ( <IN> ) { 何か $_ を使った処理。例えば… print; } close IN; > ファイルは1つです。その中で検索する文字列が40個あります。 ああ、そういうことなのね。ちょっと迷いますね。 sed で、一行一単語にばらしつつ、検索する文字列を含む行だけを抽出しておいて、その出力を perl で 処理してカウントして行くのが一番軽いかな?
お礼
さらなるご回答ありがとうございます。 パイプの使い方大変参考になりました。 sedのほうは、atonさんが回答していただいた処理と比較検討してみたいと思います。
- a-kuma
- ベストアンサー率50% (1122/2211)
直接の回答にはならないかもしれません。 > それよりwcやgrep -cを40回行った方が早いのでしょうか? wc や grep は、複数のファイルを一度に処理できますから、起動は一回だけで 済みます。 # 特定の単語を探すのであれば、wc には無理ですね。 perl もかなり早いんですが、(環境にもよりますが)grep なんかは、それなりに 速さを要求されてきて育ってきたプログラムですから、下手なスクリプトを書くよりは ずーっと早いです。 もし探す文字が、固定で構わない(つまり、正規表現を使わない)のであれば、 fgrep を使うのが一番早いんじゃないかと思います。
補足
回答ありがとうございます。 >grep は、複数のファイルを一度に処理できますから、起動は一回だけで済みます。 > ファイルは1つです。その中で検索する文字列が40個あります。 それぞれの個数を調べるにはやはり40回のgrepが必要ですか? あと、その前後の処理をperlで書いてしまっているので、perl上で処理できるように したいというのがあります。 また、systemコマンドでgrepを呼んだとすると、その結果をperlで処理するのはどうするのでしょうか? grepの結果をファイルに一度結果を出力する必要があるのでしょうか?
お礼
ご回答ありがとうございました。 まさにperlやりたかった内容です! grepと比較検討してみたいと思います。 #見た目的にはperl処理かな ^ ^;)
補足
1000行25パターンのテストデータでやってみたところ grep(25回)はperlの1.5倍処理時間がかかりました。 ということでperlで処理したいと思います。 ありがとうございました。