300,000行以上のFILE_Aと30,000行以上のFILE_Bがあります。 FILE_Aの各行をFILE_Bにgrepし、grepの結果を新しいファイルに書き込むbashスクリプトを作成しました。
全体のプロセスは5時間以上かかります。
私のスクリプトのパフォーマンスを向上させる方法があると思うなら、どんな提案でも探しています。
grep コマンドとして grep -F -m 1 を使用します。 FILE_Aは次のとおりです。
123456789
123455321
FILE_Bは次のようになります。
123456789,123456789,730025400149993,
123455321,123455321,730025400126097,
したがって、bashには、FILE_Aで次の行を選択し、FILE_Bでgrepするwhileループがあります。 FILE_Bでパターンを見つけたら、result.txtに書き込みます。
while read -r line; do
grep -F -m1 $line 30MFile
done < 300KFile
ご協力ありがとうございます。
ベストアンサー1
パフォーマンスの鍵は、大容量ファイルを一度だけ読むことです。
複数のパターンを別々の行に配置して grep に渡すことができます。これは通常、grepにファイルからパターンを読み取るように指示することによって行われます。
grep -F -f 300KFile 30MFile
これにより、大きなファイル全体で一致を順番に出力し、複数のパターンに一致する行のみを一度だけ印刷します。また、これは行のどこでもパターンを探します。たとえば、パターンファイルに含まれている場合と1234
などの行が一致します。123456,345678,2348962342
478912,1211138,1234
前処理パターンにより、正確な列の一致を制限できます。たとえば、パターンに特殊文字が含まれていない場合()?*+\|[]{}
:
<300KFile sed -e 's/^/(^|,)/' -e 's/$/($|,)/' |
grep -E -f - 30MFile
各パターンの最初の一致のみを維持することが重要な場合は、最初のパスを作成して上記の関連行のみを抽出し、awkまたはPerlで2番目のパスを作成してどのパターンが表示されたかを追跡します。
<300KFile sed -e 's/^/(^|,)/' -e 's/$/($|,)/' |
grep -E -f - 30MFile |
perl -l -F, -ape '
BEGIN {
open P, "300KFile" or die;
%patterns = map {chomp; $_=>1} <P>;
close P;
}
foreach $c (@F) {
if ($patterns{$c}) {
print;
delete $patterns{$c};
}
}
'