使用awk对比多列文件,按字段匹配状态输出Y/N标记
用awk对比两文件对应字段并输出匹配状态
这里有个精准匹配你需求的awk脚本,能快速完成两个竖线分隔文件的字段对比:
核心脚本
先把这段代码存成compare.awk文件:
BEGIN { FS=OFS="|" } # 读取第一个文件,存储field1对应的各列值 NR==FNR { for(i=2; i<=NF; i++) { map[$1,i] = $i } next } # 处理第二个文件,对比输出结果 { printf "%s", $1 for(i=2; i<=NF; i++) { if(map[$1,i] == $i) { printf "%sY", OFS } else if(map[$1,i] != "") { printf "%sN", OFS } else { printf "%s%s", OFS, $i } } print "" }
运行方式
在终端里执行这条命令,替换成你的实际文件名:
awk -f compare.awk file1.txt file2.txt
或者直接用单行命令(适合快速测试):
awk 'BEGIN{FS=OFS="|"} NR==FNR{for(i=2;i<=NF;i++)map[$1,i]=$i;next} {printf "%s",$1;for(i=2;i<=NF;i++){if(map[$1,i]==$i)printf "%sY",OFS;else if(map[$1,i]!="")printf "%sN",OFS;else printf "%s%s",OFS,$i} print ""}' file1.txt file2.txt
脚本工作原理
- BEGIN块:设置输入输出分隔符为
|,让awk正确识别每一列的边界。 - 处理第一个文件(NR==FNR):
- 用关联数组
map存储每个field1对应的各列值,键格式是$1,i($1是field1的值,i是列号),这样能精准对应到每一列的内容。 next关键字让awk跳过后续逻辑,专心处理第一个文件。
- 用关联数组
- 处理第二个文件:
- 先打印第一列
field1作为基准。 - 从第二列开始循环对比:
- 如果第一个文件中存在该
field1对应列的内容,且和当前列完全匹配 → 输出|Y。 - 如果存在但不匹配 → 输出
|N。 - 如果第一个文件里没有这个
field1的行 → 保留原列内容。
- 如果第一个文件中存在该
- 最后打印换行符,保证每行格式完整。
- 先打印第一列
测试验证
用你给出的示例文件测试:
- 文件1内容:
field1|field2|field3| abc|123|234 def|345|456 hij|567|678
- 文件2内容:
field1|field2|field3| abc|890|234 hij|567|658
运行命令后,输出完全符合你的期望:
field1|field2|field3| abc|N|Y def|345|456 hij|Y|N
注意事项
- 确保两个文件的列数一致,否则可能出现列匹配错位的问题。
- 脚本兼容末尾带竖线的行(比如示例里的表头),不会影响对比逻辑。
- 如果你的文件分隔符不是竖线,只需要修改
BEGIN块里的FS=OFS="|"为对应的分隔符即可。
内容的提问来源于stack exchange,提问作者Kushal Rastogi
相关产品推荐
相关产品推荐

