パイプ区切りファイルの5番目の列に一致するものを検索します

パイプ区切りファイルの5番目の列に一致するものを検索します
File 1:
Connect|20130320000023|UTC|PPP|[email protected]|[email protected]|0BCBE578|
File 2:
Connect|20130320000023|UTC|PPP|[email protected]|[email protected]|0BCBE578|
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|

ファイル 1 とファイル 2 の両方の列 5 で一致するレコードを見つける必要があります。したがって、上記から出力を返す必要があります。

Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|

どうもありがとう、

答え1

方法 1: grep と awk

次のスニペットを使用してこれを実行できます:

$ grep -f <(awk -F '|' '{print $5}' file1)  file2
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|

詳細

を使用するビットはawk、最初のファイルを解析し、file15 番目の列をすべて取り出します。これらの値は、 のリストとして使用されgrep、2 番目のファイルで一致する行がすべて出力されます。

この方法の注意点

file1このメソッドは、の5 番目の列の任意の出現に一致しますfile2

方法2: awkだけ

過去にこのサイトで使用されていた別のアプローチは、awkの FNR 機能を使用することです。これは、 がawk2 つのファイルを反復処理し、最初のファイルの各行に対して 2 番目のファイルを 1 行ずつ処理する場所です。

次のようなアプローチで実現できます。次の内容をファイルに記述しますcmds.awk

FNR == NR {
f1[$5] = $5
next
}

{ if ($5 == f1[$5]) print $0; }

これを次のように実行できます。

$ awk -F '|' -f cmds.awk file1 file2

注記:代わりにこのawkパターンを使用することもできます:

FNR == NR {
f1[$5] = $5
next
}

{ if ($5 in f1) print $0; }

$ awk -F '|' -f s.awk file1 file2
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|

この方法の注意点

このアプローチでは、 の各電子メール アドレスのインスタンスを 1 つだけ処理できますfile1。したがって、5 番目の列に同じ値を持つ 2 つの行がある場合、この方法ではそれらを区別できません。ただし、OP の要件を考慮すると、これは許容できると思われます。

結合と並べ替え

joinおよびを使用してこれを行うこともできますsort

$ join -t '|' -j 5  <(sort -k5,5 file2) <(sort -k5,5 file1) | sed 's/||.*//'

これはセパレータを使用し、ソートされたファイルを 5 列目に結合します。このアプローチはと|の両方からの一致を出力するので、 を使用して2 番目の一致を末尾から切り取ります。file1file2sed

$ join -t '|' -j 5  <(sort -k5,5 file2) <(sort -k5,5 file1) | sed 's/||.*//'
[email protected]|Connect|20130320000025|UTC|PPP|[email protected]|0BCBE578

答え2

私はすべてを Perl で実行します:

$ perl -F'\|' -ane '$k{$F[4]}++; print if $k{$F[4]}>1' file1 file2  
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|
  • -a配列への自動フィールド分割を有効にします@F
  • -F'\|'のフィールド区切り文字を に設定し-aます|
  • 処理される行ごとに、5 番目のフィールド ( 0Perl では配列インデックスは から始まります) をハッシュ キー ( として保存$k{$F[4]}++し、その値を 1 ずつ増やします。フィールドが 2 回目に表示されたときは、その値は 2 になります。
  • スクリプトは両方のファイルの各行を処理し ( file1before file2)、5 番目のフィールドが以前に見つかった場合 (つまり が$k{$F[4]}1 より大きい場合)、その行を出力します。

これは、5番目の列が重複していないことを前提としています。同じファイル。そうでない場合、同じファイル内で一部の列が重複している可能性がある場合は、代わりに以下を使用します。

perl -e 'open(A,"$ARGV[0]"); while(<A>){@F=split(/\|/);$k{$F[4]}++;}
         open(B,"$ARGV[1]"); while(<B>){@F=split(/\|/); print if $k{$F[4]} 
         }' file1 file2 

答え3

ファイルサイズが同程度の場合、最適な解決策はsort両方のファイルを興味のある列で選択し、joinそれらをその列で比較します。ファイル サイズが の場合NM漸近的な実行時間は ですO(N*log(N)+M*log(M))

ファイルの 1 つが他のファイルよりもはるかに小さい場合は、O(N*M)他の回答の解決策の方が適しています。

関連情報