Solaris 10を使用しているため、-fを含むgrepオプションが機能しません。
パイプで区切られたファイルが2つあります:
file1:
abc|123|BNY|apple|
cab|234|cyx|orange|
def|kumar|pki|bird|
ファイル2:
abc|123|
kumar|pki|
cab|234
file2の最初の2列をfile1と比較します(最初の2列でfile1の内容全体を検索します)。一致する場合は、file1の一致する行を印刷します。次に、ファイル2の2行目を検索します。
期待される出力:
abc|123|BNY|apple|
cab|234|cyx|orange|
私が持っているファイルは巨大で、約40万行含まれているので、実行を高速化したいと思います。
承認された回答:
これがawkの設計目的です:
$ awk -F'|' 'NR==FNR{c[$1$2]++;next};c[$1$2] > 0' file2 file1
abc|123|BNY|apple|
cab|234|cyx|orange|
説明
-
-F'|'
:フィールドセパレータを|
に設定します 。 -
NR==FNR
:NRは現在の入力行番号であり、FNRは現在のファイルの行番号です。 2つは、最初のファイルが読み取られている間のみ等しくなります。 -
c[$1$2]++; next
:これが最初のファイルの場合は、最初の2つのフィールドをc
に保存します 配列。次に、次の行にスキップして、これが最初のファイルにのみ適用されるようにします。 -
c[$1$2]>0
:elseブロックは、これが2番目のファイルである場合にのみ実行されるため、このファイルのフィールド1と2がすでに表示されているかどうかを確認します(c[$1$2]>0
)そして、もしそうなら、私たちはその行を印刷します。awk
で 、デフォルトのアクションは行を印刷することです。したがって、c[$1$2]>0
trueの場合、行が印刷されます。
または、Perlでタグ付けしたので:
perl -e 'open(A, "file2"); while(<A>){/.+?|[^|]+/ && $k{$&}++};
while(<>){/.+?|[^|]+/ && do{print if defined($k{$&})}}' file1
説明
最初の行はfile2
を開きます 、2番目までのすべてを読む|
(.+?|[^|]+
)そしてそれを保存します($&
%k
の最後の一致演算子の結果です) ハッシュ。
2行目はfile1を処理し、同じ正規表現を使用して最初の2列を抽出し、それらの列が%k
で定義されている場合はその行を出力します。 ハッシュ。
上記の両方のアプローチでは、file2の最初の2列をメモリに保持する必要があります。数十万行しかない場合は問題ありませんが、問題がある場合は、次のようなことができます
cut -d'|' -f 1,2 file2 | while read pat; do grep "^$pat" file1; done
しかし、それは遅くなります。
関連:インストールされているすべてのプログラムとファイルをハードディスク(32ビットのWindows 7を搭載)にコピーし、64ビットのWindows 7を搭載した別のコンピューターにクローン/転送しますか?