file1からパターンを読み取り、file2を繰り返し検索して一致する行と3行を印刷してから、file3に印刷したいと思います。
今私はやっています:
cat file1 | while read line; do awk '/$line/ {for(i=1; i<=3; i++) {getline; print}}' file2 > file3 ; done
これを行うより効率的な方法はありますか?私のirlファイルは巨大です(〜30GB)。
答え1
各パターンに対してファイルを一度にスキャンできます。特にファイルがキャッシュに収まらないため、ファイルを一度だけ検索する方がはるかに高速です。
あなたのサンプルコードは実際にfile1
。単一のファイルにすべての一致が必要な場合は、パターンが「OR」演算子で連結されるのと同じです。
awk '
BEGIN {
while (getline <"file1") pattern = pattern "|" $0;
pattern = substr(pattern, 2);
}
match($0, pattern) {for(i=1; i<=3; i++) {getline; print}}
' file2 > file3
また、一致する行を印刷せずに次の3行だけを印刷することに注意してください。次の3行の前に一致する行を印刷するには、ループの前に追加のprint;
項目を追加する必要がありますfor
。
実際、次の3行の前に一致する行を印刷し、grep
コマンドがその-A
パラメータをサポートしている場合は、そのパラメータを使用する必要があります。 grepのような特別なプログラムは、awkのような解釈言語よりも速いことがよくあります。追加ボーナスでコマンドははるかに簡単です。
grep -A -E -f file1 file2 >file3
grepが遅い場合は、マルチバイトロケールのGNU grepに欠陥があるためです。時には、ファイルやパターンにマルチバイト文字が含まれていなくても、非常に遅くなることがあります。 ASCII以外の文字と一致させるために文字クラスを使用しない場合(たとえば、[[:alpha:]]
すべてのUnicode文字と一致させるために文字クラスを使用しない場合)、シングルバイトロケールでgrepを実行します。
LC_ALL=C grep -A3 -E -f file1 file2 >file3
grepの出力はawkフラグメントとまったく同じではありません。これは、前の行で印刷された行の1つでパターンが見つかった場合は異なる動作をするためです。たとえば、モードがあり、a
行が、、、の場合、が印刷され、上記のa1
awkフラグメントは、追加の印刷を含むawkフラグメントは、、、、が印刷されます。a2
b
c
d
grep -A3
a1
a2
b
c
a2
b
c
print
a1
a2
b
c