我在 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
它本身不执行此操作)。
最后,对输出进行排序。