在Unix中使用AWK、Join工具实现两个文件的自然连接
在Unix环境下用
join和awk实现两个文件的自然连接 首先先明确下你提供的两个文件的内容(我帮你整理成更易读的格式):
File_a 内容
1 MIR6859-1 2340 DDX11L1 3222 2 MIR6859-1 4860 WASH7P 7074 3 WASH7P 326 MIR1302-2 670 4 FAM138A 15 MIR1302-2 5730 8 LOC729737 7270 OR4F5 64205 9 LOC729737 3070 OR4F5 68405 10 LOC729737 88330 LOC100132287 94996 11 LOC100132287 86996 LOC729737 96330 12 LOC100132287 80196 LOC729737 103130 13 LOC100132287 72396 LOC729737 110930 14 LOC100132287 61196 LOC729737 122130 15 LOC100132287 56596 LOC729737 126730
File_b 内容
10 LOC7 883 15 TYUI 678 8 LOC123 764 40 QWER 456 8 LOC125 783
自然连接通常指内连接:只保留两个文件中连接键(这里是第一列的数字)同时存在的行,将对应行的内容合并。下面分别用join和awk两种工具实现:
方法一:使用join命令
join是Unix专门用于文件连接的工具,但它要求两个文件必须按照连接键排序(默认按第一列排序)。
实现步骤
- 先对两个文件按第一列排序(可以用管道直接处理,不用生成临时文件)
- 执行
join命令完成自然连接
具体命令
join <(sort File_a) <(sort File_b)
如果你的系统不支持进程替换(<(...)),可以先生成排序后的临时文件:
sort File_a > sorted_a sort File_b > sorted_b join sorted_a sorted_b
预期输出
join会按连接键的升序输出,合并后的内容是「键 + File_a对应行的其他列 + File_b对应行的其他列」,结果如下:
8 LOC729737 7270 OR4F5 64205 LOC123 764 8 LOC729737 7270 OR4F5 64205 LOC125 783 10 LOC729737 88330 LOC100132287 94996 LOC7 883 15 LOC100132287 56596 LOC729737 126730 TYUI 678
方法二:使用awk命令
awk不需要预先排序文件,灵活性更强,适合处理未排序的数据源。思路是先把其中一个文件的内容存入数组,再遍历另一个文件匹配连接键。
实现命令
下面的脚本先读取File_b,把第一列作为键存储整行内容,然后遍历File_a,匹配到相同键时合并两行:
awk 'NR==FNR { arr[$1] = arr[$1] " " $0; next } $1 in arr { print $0 arr[$1] }' File_b File_a
如果想要让File_b的内容在前,可以调整打印顺序:
awk 'NR==FNR { arr[$1] = arr[$1] " " $0; next } $1 in arr { print arr[$1] " " $0 }' File_b File_a
脚本解释
NR==FNR:当处理第一个输入文件(File_b)时执行的逻辑arr[$1] = arr[$1] " " $0:把File_b中同一键的所有行都存在数组里(因为File_b里有两个键为8的行)next:跳过后续逻辑,继续处理下一行$1 in arr:当处理File_a时,如果当前行的第一列存在于数组中,就打印合并后的内容
预期输出(按File_a的行顺序)
8 LOC729737 7270 OR4F5 64205 8 LOC123 764 8 LOC125 783 10 LOC729737 88330 LOC100132287 94996 10 LOC7 883 15 LOC100132287 56596 LOC729737 126730 15 TYUI 678
注意事项
- 如果文件的列分隔符不是空格,需要指定分隔符:
join用-t参数,比如join -t',' <(sort -t',' File_a) <(sort -t',' File_b)awk用-F参数,比如awk -F',' 'NR==FNR { ... }'
内容的提问来源于stack exchange,提问作者ipj
相关产品推荐
相关产品推荐

