繁体   English   中英

Linux合并文件awk命令

[英]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键应该是唯一的。 我不确定在运行相同脚本时会得到什么。

如果您不介意丢失订单,可以使用joinsort文件

$ 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 | sortfile2提取第一列,并将其作为grep -f的文件参数(“匹配与该文件中的任何行匹配的行”),- -F将这些行视为固定字符串而不是正则表达式。 -w确保只将整个列视为整体,没有子串匹配。

    结果通过管道传递给sort ,因为join需要排序的输入。

  • 然后join将获得所有结果,将其视为第一个文件,然后与<(sort file2)联接。

注意,输出按字母顺序排序。 如果出现的顺序与file顺序完全相同,我们不能使用join

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM