如何用awk匹配两个文件指定三列并将匹配行追加到新文件
多文件字段匹配拼接问题解决方案
问题背景
排查数小时仍未解决该问题,它看起来逻辑简单但始终调试不通过,特来求助。
涉及文件内容
文件1
tig00000005 15310 16162 XP_012153921.1 NW_003797090.1 LOC105664333 PREDICTED: elastin-like tig00000005 23339 23974 XP_012152584.1 NW_003797083.1 LOC100878991 PREDICTED: LOW QUALITY PROTEIN tig00000005 24600 25138 XP_012143166.1 NW_003797196.1 LOC100881279 PREDICTED: ankyrin-2 isoform X2 tig00000005 2685 4511 XP_012144644.1 NW_003797249.1 LOC105662970 PREDICTED: fibrinogen alpha chain-like isoform X2 tig00000005 28923 29432 XP_012148395.1 NW_003797444.1 LOC100881617 PREDICTED: eukaryotic translation initiation factor 4 gamma 3-like isoform X12 tig00000005 32415 34324 XP_012153921.1 NW_003797090.1 LOC105664333 PREDICTED: elastin-like
文件2
tig00000005 maker gene 15310 16162 . + . ID=snap_masked-tig00000005-processed-gene-0.2;Name=snap_masked-tig00000005-processed-gene-0.2 tig00000005 maker gene 16764 17237 . + . ID=snap_masked-tig00000005-processed-gene-0.3;Name=snap_masked-tig00000005-processed-gene-0.3 tig00000005 maker gene 23339 23974 . + . ID=snap_masked-tig00000005-processed-gene-0.4;Name=snap_masked-tig00000005-processed-gene-0.4 tig00000005 maker gene 24600 25138 . - . ID=snap_masked-tig00000005-processed-gene-0.10;Name=snap_masked-tig00000005-processed-gene-0.10 tig00000005 maker gene 25472 26900 . + . ID=snap_masked-tig00000005-processed-gene-0.5;Name=snap_masked-tig00000005-processed-gene-0.5
需求说明
将文件1的第1、2、3列与文件2的第1、4、5列进行匹配,匹配成功时将文件2的对应行追加到文件1的对应行末尾,预期输出示例:
tig00000005 15310 16162 XP_012153921.1 NW_003797090.1 LOC105664333 PREDICTED: elastin-like tig00000005 maker gene 15310 16162 . + . ID=snap_masked-tig00000005-processed-gene-0.2;Name=snap_masked-tig00000005-processed-gene-0.2
原有错误代码及问题
尝试的两段awk代码均未达到预期:
awk 'OFS="\t"; FS="\t"; NR==FNR{a[$1,$2,$3]=$0; next} (($1,$4,$5) in a){print $0,a[$0]}' file1 file2 awk 'OFS="\t"; FS="\t"; NR==FNR{a[$1,$2,$3]=($1,$4,$5)} {print $0,a[$0]}' file1 file2
问题点:
- FS/OFS赋值未放在BEGIN块中,第一行处理时分隔符未生效
- 键映射逻辑颠倒,且查询时误用整行内容$0作为查询键
- 多列组合键未用分隔符,存在误匹配风险
- 文件传入顺序错误,导致输出顺序不符合要求
可行解决方案
代码实现
awk 'BEGIN{FS=OFS="\t"} NR==FNR{k=$1 SUBSEP $4 SUBSEP $5;a[k]=$0;next} {k=$1 SUBSEP $2 SUBSEP $3;print $0,(k in a?a[k]:"")}' file2 file1
说明
- 先读取文件2,以第1、4、5列组合为键存储整行内容
- 再读取文件1,以第1、2、3列组合为键查询,匹配成功则拼接输出,未匹配则仅输出文件1原有内容
- SUBSEP为awk内置的多键分隔符,避免不同列内容拼接导致的误匹配
- 不需要保留未匹配的行时,将打印语句修改为
if(k in a) print $0,a[k]即可
内容的提问来源于stack exchange,提问作者user2472414
相关产品推荐
相关产品推荐

