
我在 Linux 系統上有一個包含 3 列的 file1 和一個包含 4 列的 file2。如何根據 file1 第 3 列中的字串將兩個檔案連接到 file2 第 2 列中的字串? File2 是一個包含許多條目的大型資料庫。 file1 和 file2 的第 3 列和第 2 列分別隻共用很少的字串。我想輸出 file1 和連接的 file2 行,以防字串匹配,並為不匹配的條目輸出破折號。
文件1:
300 100 a101
450 410 a400
670 710 a20
700 610 a340
文件2:
b30 a340 tttttttt 456
b500 a200 llllllll 567
b60 a101 uuuuuuuu 344
b40 a50 kkkkkkkk 223
輸出:
300 100 a101 b60 a101 uuuuuuuu 344
450 410 a400 -
670 710 a20 -
700 610 a340 b30 a340 tttttttt 456
答案1
使用 GNUawk
和 GNU join
,這是 Linux 上的標準(可能會或可能不會與非 GNU 版本一起使用):
$ join -a1 -1 3 -2 2 <(sort -k3,3 file1) <(sort -k2,2 file2) |
awk '$4 == "" { $4 = "-" }; {t=$1; $1=$2; $2=$3; $3=t; print}' |
sort
300 100 a101 b60 uuuuuuuu 344
450 410 a400 -
670 710 a20 -
700 610 a340 b30 tttttttt 456
這join
指令分別在欄位 3 和 2 上連接 file1 和 file2。它用流程替代確保兩個文件都按各自的關鍵字段排序。-a 1
使用該選項可以file1
列印來自 的所有行,即使它們與來自 的行不符file2
。
不幸的是,join
將 file1 的關鍵欄位放在每個記錄的開頭。透過使用一個名為 $1 的值的臨時持有者的awk
變數將欄位移回其原始順序來修復此問題。t
如果檔案之間不匹配,awk 腳本也會在欄位 $4 中加入尾部破折號字元(因為join
它本身不執行此操作)。
最後,對輸出進行排序。