異なるファイルの2つの列を比較し、一致した場合に印刷します。

異なるファイルの2つの列を比較し、一致した場合に印刷します。

私はSolaris 10を使用しているので、-fに関連するgrepオプションは機能しません。

パイプで区切られた2つのファイルがあります。

ファイル1:

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|

私のファイルは約400,000行を含む大容量なので、実行速度を速くしたいと思います。

ベストアンサー1

これが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は現在のファイルのライン番号です。両方のファイルは、最初のファイルを読み取る場合にのみ同じです。
  • c[$1$2]++; next:最初のファイルの場合は、最初の2つのフィールドをc配列として保存します。次に、最初のファイルにのみ適用されるように、次の行に移動します。

  • c[$1$2]>0:elseブロックはこれが2番目のファイルの場合にのみ実行されるため、そのファイルのフィールド1と2がすでに表示されていることを確認し(c[$1$2]>0)、表示されている場合はその行を印刷します。のデフォルトのawkジョブは行を印刷することであるため、c[$1$2]>0trueの場合は行が印刷されます。


またはPerlタグを使用しているので:

perl -e 'open(A, "file2"); while(<A>){/.+?\|[^|]+/ && $k{$&}++};
         while(<>){/.+?\|[^|]+/ && do{print if defined($k{$&})}}' file1

説明する

最初の行が開き、2行目()file2までのすべての内容が読み取られ、ハッシュ(最後の一致演算子の結果)に保存されます。|.+?\|[^|]+$&%k

2行目は、同じ正規表現を使用して最初の2つの列を抽出し、その行を印刷する方法でfile1を処理します(その列がハッシュで定義されている場合)%k


上記の両方の方法で、file2の最初の2列をメモリに保存する必要があります。問題にならない行は数十万行だけですが、そうであればそうすることができます。

cut -d'|' -f 1,2 file2 | while read pat; do grep "^$pat" file1; done

しかし、速度は遅くなります。

おすすめ記事