在管道 delim 檔案中尋找第五列的符合項

在管道 delim 檔案中尋找第五列的符合項
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|

我需要在第 5 列的文件 1 和文件 2 中找到匹配的記錄。

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解析第一個文件,file1提取所有第五列。然後將這些值用作 的列表grep,它將列印第二個文件中包含任何匹配項的行。

使用此方法的注意事項

file1此方法將匹配中出現的任何第五列file2

方法#2:只需 awk

過去該地點使用的另一種方法是使用 的awkFNR 設施。這裡awk將迭代 2 個文件,逐行遍歷第二個文件,找出第一個文件中的每一行。

像這樣的方法就可以做到。將以下內容放入文件中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|

使用此方法的注意事項

此方法只能處理來自 的每個電子郵件地址的單一實例file1。因此,如果有 2 行的第 5 列值相同,則無法區分它們。考慮到您在 OP 中的要求,這似乎是可以接受的。

加入並排序

您也可以使用join和來執行此操作sort

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

這將使用分隔符號|並將排序後的檔案連接到第五列。這種方法會列印file1和中的匹配項file2,因此我們使用sed從末尾刪除第二個匹配項。

例子

$ 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'\|'設定 to 的欄位分隔-a符號|
  • 對於處理的每一行,將第 5 個欄位(在 Perl 中從陣列索引開始0)儲存為雜湊鍵($k{$F[4]}++並將其值遞增 1。第二次看到某個欄位時,該值將為 2。
  • 該腳本將處理兩個文件的每一行(file1before file2),如果之前已經看到第 5 個字段,即 if$k{$F[4]}大於 1,則列印該行。

這假設第五列在相同的文件。如果情況並非如此,並且某些列可能在同一文件中重複,請改用:

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))

如果其中一個文件比另一個文件小得多,那麼O(N*M)其他答案中的解決方案會更好。

相關內容