首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Linux合并文件awk命令

Linux合并文件awk命令
EN

Stack Overflow用户
提问于 2016-03-14 00:26:17
回答 2查看 136关注 0票数 0

我有两个文件;文件1:

代码语言:javascript
复制
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:

代码语言:javascript
复制
ARS-BFGL-BAC-10975 10 21225382
ARS-BFGL-BAC-11025 10 84516867
ARS-BFGL-BAC-11193 1 29303546

期望的输出:

代码语言:javascript
复制
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的长度。

代码语言:javascript
复制
awk 'FNR==NR{a[$1]=$2 FS $3;next} $1 in a {print $0, a[$1]}' file2 file1 > output
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-03-14 00:51:05

这如预期的那样工作。

代码语言:javascript
复制
$ 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键应该是唯一的。我不知道当你运行同样的脚本时你得到了什么。

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

代码语言:javascript
复制
$ 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

只需一点点额外的杂耍,你就可以把订单拿回来(装饰/取消装饰)。

代码语言:javascript
复制
$ 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
票数 3
EN

Stack Overflow用户

发布于 2016-03-14 00:38:54

编辑:看到karakfa答案的第二部分,我意识到整个grep/裁剪马戏团是不需要的.一个简单的连接具有相同的结果。这只有在file1的大小足够小的情况下才是有用的,这样grepping加排序比对整个文件进行排序要便宜。如果输入文件较小,join也可能更快。

如果不局限于awk,则可以使用grep和核心实用程序(进程替换需要Bash ):

代码语言:javascript
复制
$ 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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35977680

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档