6

のオプションackとして使用して、あるファイルのパターン(パターンのリスト)を別のファイルから取得する方法はありますか?にオプションがあるようですが、 inとは異なります。-fgrep-fack-fgrep

おそらく、例はあなたにもっと良い考えを与えるでしょう。file1があるとします。

file1:
a
c
e

そしてfile2:

file2:
a  1
b  2
c  3
d  4
e  5

そして、file2からfile1のすべてのパターンを取得して、次のようにします。

a  1
c  3
e  5

これはできackますか?awkそれ以外の場合、両方のファイルに数百万のレコードがあり、本当に効率的な方法で完了する必要があるため、ジョブを処理するためのより良い方法(ハッシュなど)はありますか?ありがとう!

4

5 に答える 5

8

これは、ハッシュを使用してfile2の行での反復ごとのO(1)(償却時間)ルックアップのためにfile1から必要なキーのセットを保持するPerlワンライナーです。したがって、O(m + n)時間で実行されます。ここで、mはキーセットの行数、nはテストしているファイルの行数です。

perl -ne'BEGIN{open K,shift@ARGV;chomp(@a=<K>);@hash{@a}=()}m/^(\p{alpha}+)\s/&&exists$hash{$1}&&print' tkeys file2

file2がキーに対して行ごとにテストされている間、キーセットはメモリに保持されます。

Perlの-aコマンドラインオプションを使用した場合も同じです。

perl -ane'BEGIN{open G,shift@ARGV;chomp(@a=<G>);@h{@a}=();}exists$h{$F[0]}&&print' tkeys file2

2番目のバージョンはおそらく目には少し簡単です。;)

ここで覚えておかなければならないことの1つは、プロセッサバウンドよりもIOバウンドである可能性が高いということです。したがって、目標はIOの使用を最小限に抑えることです。ルックアップキーセット全体が、O(1)の償却ルックアップを提供するハッシュに保持されている場合。このソリューションが他のソリューションよりも優れている点は、一部の(低速の)ソリューションは、file2の各行に対して1回だけキーファイル(file1)を実行する必要があることです。この種のソリューションはO(m * n)になります。ここで、mはキーファイルのサイズ、nはfile2のサイズです。一方、このハッシュアプ​​ローチはO(m + n)時間を提供します。それは大きな違いです。キーセットを介した線形検索を排除することでメリットがあり、IOを介してキーを1回だけ読み取ることでさらにメリットがあります。

于 2012-03-30T04:49:51.283 に答える
6

コメントから回答に切り替えたら...;-)

これは、DavidOのperlone-linerと同じように動作するawkone-linerですが、awkです。AwkはPerlよりも小さく、おそらくスリムです。しかし、awkにはいくつかの異なる実装があります。あなたのパフォーマンスが他のパフォーマンスよりも優れているのか、perlよりも優れているのかわかりません。ベンチマークを行う必要があります。

awk 'NR==FNR{a[$0]=1;next} {n=0;for(i in a){if($0~i){n=1}}} n' file1 file2

これは何をする(すべき)のですか?

awkスクリプトの最初の部分は、file1の行(現在のファイルのレコード番号が合計のレコード番号と等しい)のみに一致し、配列にデータを入力します。2番目の部分(後続のファイルで実行)は、配列内の各項目をステップスルーし、現在の入力行と一致する正規表現として使用できるかどうかを確認します。

コードの2番目のブロックは、前のブロックで0または1に設定された「n」で始まります。awkでは、「1」はtrueと評価され、欠落している中括弧ブロックはと同等と見なされる{print}ため、前のブロックで一致が見つかった場合、このブロックは現在の行を出力します。

file1に正規表現ではなく文字列が含まれている場合は、最初の比較を。に置き換えることで、これを変更して実行速度を上げることができますif(index($0,i))...

注意して使用してください。あなたのマイレージは異なる場合があります。ナッツが含まれている可能性のある施設で作成されました。

于 2012-03-30T05:01:28.263 に答える
1

TXRは、要件を処理するためのもう1つのオプションです。私はあなたがそれに必要なものを書くにはあまりにも新しいですが、作者はStackOverflowに頻繁に寄稿しています。TXRで必要なことができると確信していますが、パフォーマンスが向上するかどうかはわかりません。テストする必要があります。

パターンマッチングに専念する言語全体に興味がある場合は、一見の価値があります。:)

于 2012-03-30T06:13:29.837 に答える
1
nawk 'FNR==NR{a[$0];next}($1 in a)' file3 file4

テスト済み:

pearl.384> cat file3
a
c
e
pearl.385> cat file4
a  1 
b  2 
c  3 
d  4 
e  5
pearl.386> nawk 'FNR==NR{a[$0];next}($1 in a)' file3 file4
a  1 
c  3 
e  5
pearl.387>
于 2012-03-30T05:41:53.310 に答える
1

trを使用して、ファイルをackの正規表現に変換できます。sedを使用して、末尾のパイプ文字を削除しました。

ack "` tr'\ n''|' <patts | sed's/.$//' `"

これにはいくつかのプロセスが必要であるため、awkソリューションの方がおそらく効率的ですが、これは非常に覚えやすいことに注意してください。

于 2013-06-20T11:01:52.793 に答える