基于匹配字段用awk合并文件异常:无法打印全部数组赋值
AWK文件合并脚本问题排查与修复
需求说明
需要基于匹配字段合并两个文件:
- 匹配规则:File 1的第2个字段(
Chr)匹配File 2的第1个字段(Geneid) - 输出要求:结果包含File 2的第1、2、3字段,加上File 1的第3、4字段(
Length和DP_xxx)
文件示例
File 1
Geneid Chr Length DP_D_9_8_21_B_contigs_sorted.bam c_1_1 c_161045_1 3489 1178 c_1_2 c_161045_2 216 75 c_1_3 c_161045_3 1335 425 c_1_4 c_161045_4 201 106
File 2
Geneid KO_ID KO_function c_161045_3 NA NA c_161045_4 K07733 prophage regulatory protein c_161045_6 NA NA c_161045_7 NA NA c_161045_8 NA NA
原脚本问题分析
你编写的脚本存在3个核心问题:
- 数组存储逻辑错误:
原脚本用a[$1]=$3和a[$2]=$4存储数据,但未使用匹配键(File1的第2字段)作为数组主键,反而用了File1的第1字段,导致后续无法通过File2的第1字段正确关联对应数据;同时同一数组的不同键会互相覆盖,无法同时保存Length和DP值。 - 语法错误:
FNR>1($1 in a)缺少逻辑运算符&&,正确写法应为FNR>1 && ($1 in a)。语法错误会导致脚本执行逻辑异常,出现“合并中途停止”的问题。 - 输出逻辑错误:
输出时调用a[$1]和a[$2],但实际应该根据File2的第1字段(匹配键)去获取File1对应的Length和DP值,而非错误的键值。
修复后的脚本
下面是两种可行的修复方案:
方案1:使用单个数组拼接值
awk -F '\t' 'BEGIN {OFS="\t"} NR==FNR {a[$2]=$3 OFS $4; next} # 用File1的第2字段作为键,存储第3、4字段 FNR==1 {print "Gene_ID", "KO_ID", "KO_Function", "Length", "Coverage"} # 输出自定义表头 FNR>1 && ($1 in a) {print $1, $2, $3, a[$1]}' File1 File2 > ResultFile
方案2:使用两个独立数组分别存储
awk -F '\t' 'BEGIN {OFS="\t"} NR==FNR {len[$2]=$3; dp[$2]=$4; next} # 用两个数组分别存Length和DP值 FNR==1 {print "Gene_ID", "KO_ID", "KO_Function", "Length", "Coverage"} FNR>1 && ($1 in len) {print $1, $2, $3, len[$1], dp[$1]}' File1 File2 > ResultFile
正确输出结果
执行修复后的脚本,ResultFile内容如下:
Gene_ID KO_ID KO_Function Length Coverage c_161045_3 NA NA 1335 425 c_161045_4 K07733 prophage regulatory protein 201 106
内容的提问来源于stack exchange,提问作者Linton
相关产品推荐
相关产品推荐

