我有两个文件;文件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被重复的次数与在第1列中出现的次数一样多,但我不希望ARS-BFGL-BAC-11044出现在输出中,因为它从未出现在文件2中。
最近的是下面的awk命令,但是它不允许复制ARS-BFGL-BAC-10975,也就是说,我只在输出应该更长的时候合并到文件2的长度。
awk 'FNR==NR{a[$1]=$2 FS $3;next} $1 in a {print $0, a[$1]}' file2 file1 > output发布于 2016-03-14 00:51:05
这如预期的那样工作。
$ 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 29303546file1记录与file2匹配的数量没有限制,但显然file2键应该是唯一的。我不知道当你运行同样的脚本时你得到了什么。
如果您不介意丢失订单,可以使用join和sorted文件
$ 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发布于 2016-03-14 00:38:54
编辑:看到karakfa答案的第二部分,我意识到整个grep/裁剪马戏团是不需要的.一个简单的连接具有相同的结果。这只有在file1的大小足够小的情况下才是有用的,这样grepping加排序比对整个文件进行排序要便宜。如果输入文件较小,join也可能更快。
如果不局限于awk,则可以使用grep和核心实用程序(进程替换需要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将从file2提取的第一列作为grep -f的文件参数(“匹配该文件中任何行的匹配行”),-F则将这些行视为固定字符串而不是正则表达式。-w确保我们只作为一个整体查看列,而不是子字符串匹配。
结果通过管道传输到sort,因为join需要排序输入。join接受所有这些的结果,将其作为第一个文件处理,并与<(sort file2)连接。注意输出是按字母顺序排序的。如果它应该以与file完全相同的顺序出现,我们就不能使用join。
https://stackoverflow.com/questions/35977680
复制相似问题