如何用Awk对比两个文件并输出指定格式的匹配内容?
需求与问题
现有两个输入文件,需提取两者共有的:name条目,同时输出file1中该条目下的./name/of/file行,且保留file2中对应:name的完整行。已尝试一段Awk代码,但输出不符合预期,相关信息如下:
已尝试代码
awk 'FNR==NR { a[$1]; next }NF<=1{ flag=0 }$1 in a { print; flag=1; delete a[$1]; next }flag{ printf "%s\n",$0 }' file1 file2
当前输出
:name1 ./name/of/file [logfile] [ error in file coming since Day : 1 ] ./name/of/file [logfile] [ error in file coming since Day : 1 ] :name3 ./name/of/file [logfile] [ error in file coming since Day : 24 ] ./name/of/file [logfile] [ error in file coming since Day : 24 ] :name4 ./name/of/file [logfile] [ error in file coming since Day : 3 ] ./name/of/file [logfile] [ error in file coming since Day : 3 ] ./name/of/file [logfile] [ error in file coming since Day : 3 ] ./name/of/file [logfile] [ error in file coming since Day : 3 ]
输入文件file1
:name1 ./name/of/file [logfile] [ error in file coming since Day : 1 ] ./name/of/file [logfile] [ error in file coming since Day : 1 ] :name2 ./name/of/file [logfile] [ error in file coming since Day : 1 ] :name3 ./name/of/file [logfile] [ error in file coming since Day : 24 ] ./name/of/file [logfile] [ error in file coming since Day : 24 ] :name1 ./name/of/file [logfile] [ error in file coming since Day : 40] ./name/of/file [logfile] [ error in file coming since Day : 40 ] :name4 ./name/of/file [logfile] [ error in file coming since Day : 3 ] ./name/of/file [logfile] [ error in file coming since Day : 3 ] ./name/of/file [logfile] [ error in file coming since Day : 3 ] ./name/of/file [logfile] [ error in file coming since Day : 3 ] :name5 ./name/of/file [logfile] [ error in file coming since Day : 6 ] ./name/of/file [logfile] [ error in file coming since Day : 6 ] :name4 ./name/of/file [logfile] [ error in file coming since Day : 10 ] ./name/of/file [logfile] [ error in file coming since Day : 10 ] ./name/of/file [logfile] [ error in file coming since Day : 10 ] ./name/of/file [logfile] [ error in file coming since Day : 10 ]
输入文件file2
:name1 ABC123 12345 :name3 EFG789 67898 :name4 HIJ547 01234
期望输出
:name1 ABC123 12345 ./name/of/file [logfile] [ error in file coming since Day : 1 ] ./name/of/file [logfile] [ error in file coming since Day : 1 ] :name3 EFG789 67898 ./name/of/file [logfile] [ error in file coming since Day : 24 ] ./name/of/file [logfile] [ error in file coming since Day : 24 ] :name4 HIJ547 01234 ./name/of/file [logfile] [ error in file coming since Day : 3 ] ./name/of/file [logfile] [ error in file coming since Day : 3 ] ./name/of/file [logfile] [ error in file coming since Day : 3 ] ./name/of/file [logfile] [ error in file coming since Day : 3 ]
解决方案
原代码的问题在于处理顺序错误、未处理:name前导空格、未保留file2完整行。修正后的Awk代码如下:
# 读取file2,存储每个:name对应的完整行 FNR == NR { name = $1 name_line[name] = $0 next } # 处理file1中的:name行 /^[[:space:]]*:name/ { gsub(/^[[:space:]]*/, "") current_name = $0 collect = (current_name in name_line) ? 1 : 0 # 仅输出一次file2中的对应行 if (collect && !printed[current_name]) { print name_line[current_name] printed[current_name] = 1 } next } # 收集并输出file1中的目标文件行(添加缩进) collect { printf " %s\n", $0 }
执行命令:
awk -f script.awk file2 file1
代码说明
- 先读取file2,用
name_line数组保存每个:name对应的完整行 - 处理file1时,去除
:name行的前导空格,判断是否属于file2中的目标条目 - 首次匹配目标条目时,输出file2中的完整行
- 后续的
./name/of/file行在标记开启时,添加缩进后输出
内容的提问来源于stack exchange,提问作者aastha
相关产品推荐
相关产品推荐

