GNU/Linux >> Linux の 問題 >  >> Linux

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

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を搭載した別のコンピューターにクローン/転送しますか?
Linux
  1. 2つのパターン間の(および除外する)行を印刷しますか?

  2. 2つの異なる単語が存在するテキストファイルを検索しますか(任意の順序、任意の行)?

  3. Lum – 2つの別々のファイルからの列のマージ?

  1. diff3ツールを使用してLinuxで3つのファイルを比較する方法

  2. 2 つの tarball のコンテンツを比較する方法

  3. スクリプトの同じ行で stderr と stdout を別のファイルにリダイレクトする方法は?

  1. LinuxでMeldを使用してファイルとフォルダをグラフィカルに比較する

  2. 2つのパターンの間(およびそれを含む)の線を印刷しますか?

  3. 2つのファイルを2つの列に印刷しますか?