[英]Linux merge files awk command
我有两个文件; 文件1:
ARS-BFGL-BAC-10975 0.9303 688423261 1 01/04/2015 0.9983763305
ARS-BFGL-BAC-11025 0.9092 688423261 1 01/04/2015 0.9983763305
ARS-BFGL-BAC-11044 0.9626 688423261 2 01/04/2015 0.9983763305
ARS-BFGL-BAC-11193 0.9544 688423261 1 01/04/2015 0.9983763305
ARS-BFGL-BAC-10975 0.9303 688423263 1 01/04/2015 0.9983763000
ARS-BFGL-BAC-11025 0.9082 688423263 1 01/04/2015 0.9983763000
ARS-BFGL-BAC-11044 0.9926 688423263 2 01/04/2015 0.9983763000
ARS-BFGL-BAC-11193 0.9144 688423263 1 01/04/2015 0.9983763000
第二个文件,文件2:
ARS-BFGL-BAC-10975 10 21225382
ARS-BFGL-BAC-11025 10 84516867
ARS-BFGL-BAC-11193 1 29303546
所需的输出:
ARS-BFGL-BAC-10975 0.9303 688423261 1 01/04/2015 0.9983763305 10 21225382
ARS-BFGL-BAC-11025 0.9092 688423261 1 01/04/2015 0.9983763305 10 84516867
ARS-BFGL-BAC-11193 0.9544 688423261 1 01/04/2015 0.9983763305 1 29303546
ARS-BFGL-BAC-10975 0.9303 688423263 1 01/04/2015 0.9983763000 10 21225382
ARS-BFGL-BAC-11025 0.9992 688423263 1 01/04/2015 0.9983763000 10 84516867
ARS-BFGL-BAC-11193 0.9144 688423263 1 01/04/2015 0.9983763000 1 29303546
因此,文件1的行比文件2的行多。我只想基于第一列在输出中保留文件2中的行,所以我希望ARS-BFGL-BAC-10975
重复多次。出现在文件2中的第1列中,但我不希望输出中出现ARS-BFGL-BAC-11044
,因为它从未出现在文件2中。
我拥有的最接近的命令是以下awk命令,但它不允许复制ARS-BFGL-BAC-10975
,即当输出应ARS-BFGL-BAC-10975
,我仅合并到文件2的长度。
awk 'FNR==NR{a[$1]=$2 FS $3;next} $1 in a {print $0, a[$1]}' file2 file1 > output
这按预期工作
$ awk 'NR==FNR{a[$1]=$2 FS $3; next} $1 in a{print $0, a[$1]}' file2 file1
ARS-BFGL-BAC-10975 0.9303 688423261 1 01/04/2015 0.9983763305 10 21225382
ARS-BFGL-BAC-11025 0.9092 688423261 1 01/04/2015 0.9983763305 10 84516867
ARS-BFGL-BAC-11193 0.9544 688423261 1 01/04/2015 0.9983763305 1 29303546
ARS-BFGL-BAC-10975 0.9303 688423263 1 01/04/2015 0.9983763000 10 21225382
ARS-BFGL-BAC-11025 0.9082 688423263 1 01/04/2015 0.9983763000 10 84516867
ARS-BFGL-BAC-11193 0.9144 688423263 1 01/04/2015 0.9983763000 1 29303546
多少个file1记录将匹配到file2没有限制,但是显然file2键应该是唯一的。 我不确定在运行相同脚本时会得到什么。
如果您不介意丢失订单,可以使用join
和sort
文件
$ join <(sort file1) <(sort file2)
ARS-BFGL-BAC-10975 0.9303 688423261 1 01/04/2015 0.9983763305 10 21225382
ARS-BFGL-BAC-10975 0.9303 688423263 1 01/04/2015 0.9983763000 10 21225382
ARS-BFGL-BAC-11025 0.9082 688423263 1 01/04/2015 0.9983763000 10 84516867
ARS-BFGL-BAC-11025 0.9092 688423261 1 01/04/2015 0.9983763305 10 84516867
ARS-BFGL-BAC-11193 0.9144 688423263 1 01/04/2015 0.9983763000 1 29303546
ARS-BFGL-BAC-11193 0.9544 688423261 1 01/04/2015 0.9983763305 1 29303546
几乎没有多余的杂耍,您可以带回订单(装饰/取消装饰)
$ join -12 <(cat -n file1 | sort -k2) <(sort file2) |
sort -k2,2 | cut -d' ' -f2 --complement
ARS-BFGL-BAC-10975 0.9303 688423261 1 01/04/2015 0.9983763305 10 21225382
ARS-BFGL-BAC-11025 0.9092 688423261 1 01/04/2015 0.9983763305 10 84516867
ARS-BFGL-BAC-11193 0.9544 688423261 1 01/04/2015 0.9983763305 1 29303546
ARS-BFGL-BAC-10975 0.9303 688423263 1 01/04/2015 0.9983763000 10 21225382
ARS-BFGL-BAC-11025 0.9082 688423263 1 01/04/2015 0.9983763000 10 84516867
ARS-BFGL-BAC-11193 0.9144 688423263 1 01/04/2015 0.9983763000 1 29303546
编辑 :看到karakfa的答案的第二部分,我意识到不需要整个grep / cut马戏团...简单的连接具有相同的结果。 仅当grepping减小了file1
的大小,以便grepping加排序比对整个文件进行排序便宜时,这才有用。 如果输入文件较小,则join
也可能更快。
如果您不限于awk,则可以使用grep和core utils(需要Bash进行进程替换):
$ join <(grep -wFf <(cut -d ' ' -f 1 file2) file1 | sort) <(sort file2)
ARS-BFGL-BAC-10975 0.9303 688423261 1 01/04/2015 0.9983763305 10 21225382
ARS-BFGL-BAC-10975 0.9303 688423263 1 01/04/2015 0.9983763000 10 21225382
ARS-BFGL-BAC-11025 0.9082 688423263 1 01/04/2015 0.9983763000 10 84516867
ARS-BFGL-BAC-11025 0.9092 688423261 1 01/04/2015 0.9983763305 10 84516867
ARS-BFGL-BAC-11193 0.9144 688423263 1 01/04/2015 0.9983763000 1 29303546
ARS-BFGL-BAC-11193 0.9544 688423261 1 01/04/2015 0.9983763305 1 29303546
从里到外:
cut -d ' ' -f 1 file2
提取的第一列file2
。 grep -wFf <(cut -d ' ' -f 1 file2) file1 | sort
grep -wFf <(cut -d ' ' -f 1 file2) file1 | sort
从file2
提取第一列,并将其作为grep -f
的文件参数(“匹配与该文件中的任何行匹配的行”),- -F
将这些行视为固定字符串而不是正则表达式。 -w
确保只将整个列视为整体,没有子串匹配。
结果通过管道传递给sort
,因为join
需要排序的输入。
join
将获得所有结果,将其视为第一个文件,然后与<(sort file2)
联接。 注意,输出按字母顺序排序。 如果出现的顺序与file
顺序完全相同,我们不能使用join
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.