使用awk跳过注释行并比对两文件指定列,输出匹配与不匹配结果
解决基于指定列比对两个文本文件的AWK脚本问题
需求说明
编写AWK脚本,跳过以#开头的注释行,基于第1、2、4、5列比对1234.txt(file1)和5678.txt(file2),输出以下制表符分隔的内容:
- 两文件间的匹配行(保留file1中的完整行)
- 仅存在于单一文件的行,并标注所属文件
预期输出示例
Match between 1234.txt and 5678.txt: chr1 1013466 . T TA 11438.1 PASS chr1 1013490 . C G 14137 PASS Not Found in 1234.txt: chr1 1014600 . C A 2000 PASS Not Found in 5678.txt: chr1 1013600 . T TAA 1140 PASS
输入文件内容
file1(1234.txt)
##.... #.... chr1 1013466 . T TA 11438.1 PASS chr1 1013490 . C G 14137 PASS chr1 1013600 . T TAA 1140 PASS
file2(5678.txt)
##... #.... chr1 1013466 . T TA 10914 PASS chr1 1013490 . C G 13785.1 PASS chr1 1014600 . C A 2000 PASS
现有脚本问题
原脚本存在多处语法错误和逻辑缺陷:
- 条件判断
/^[^#]/ FNR==1 { next }写法错误,未用逻辑运算符连接条件 - 数组命名错误:
$f1、$f2是引用变量值的字段,而非合法数组名 - 仅存储了用于比对的列,未保留完整行内容
- 输出格式不符合预期,缺少文件归属标注,匹配行未保留原完整行
修正后的AWK脚本
f1=1234.txt f2=5678.txt awk -F'\t' ' # 跳过所有以#开头的注释行 /^#/ { next } # 处理第一个文件:用第1、2、4、5列拼接成唯一键,存储完整行 FNR == NR { key = $1 FS $2 FS $4 FS $5 file1[key] = $0 next } # 处理第二个文件:存储完整行,标记匹配项 { key = $1 FS $2 FS $4 FS $5 file2[key] = $0 if (key in file1) { matched[key] = 1 } } # 按要求输出结果 END { # 输出两文件匹配行(取file1的内容) print "Match between 1234.txt and 5678.txt:" for (key in matched) { print file1[key] } # 输出仅存在于file2的行 print "\nNot Found in 1234.txt:" for (key in file2) { if (!(key in file1)) { print file2[key] } } # 输出仅存在于file1的行 print "\nNot Found in 5678.txt:" for (key in file1) { if (!(key in file2)) { print file1[key] } } } ' OFS='\t' "$f1" "$f2"
脚本说明
- 用
/^#/ { next }跳过所有注释行,包括多行注释开头的##行 - 处理第一个文件时,将指定列拼接成唯一键,把完整行存入数组,确保后续能输出原始内容
- 处理第二个文件时,同步标记与第一个文件匹配的键,方便后续归类输出
- END块按预期格式分三部分输出内容,严格对应需求中的标注要求
内容的提问来源于stack exchange,提问作者justaguy
相关产品推荐
相关产品推荐

