AWK技术需求:双文件匹配Field1,排除最后字段,中间字段不匹配则打印行
按首字段匹配、排除尾字段对比全不匹配行的解决方案
需求回顾
我们需要对比两个文件:
- 以每行的第一个字段作为匹配依据
- 对比时排除每行的最后一个字段,只校验首字段和尾字段之间的所有中间字段
- 若匹配到的两行(首字段相同)的所有中间字段均不匹配(包括字段数量不同的情况),则输出这两行
示例文件内容
File1
LSP0 NODE0 NODE4 NODE3 591 LSP1 NODE1 NODE2 NODE3 725 LSP2 NODE4 NODE5 515 LSP3 NODE2 NODE4 NODE3 NODE6 725
File2
LSP0 NODE0 NODE4 NODE5 NODE3 515 LSP1 NODE1 NODE2 NODE3 576 LSP2 NODE4 NODE5 615 LSP3 NODE2 NODE1 615
解决方案:使用awk脚本
awk天生适合处理这种字段级别的对比和关联匹配,下面是定制的脚本:
# 读取第一个文件,存储首字段对应的中间字段与整行内容 NR == FNR { key = $1 # 提取中间字段:从第2个字段到倒数第2个字段 mid_content = "" for (i=2; i<=NF-1; i++) { mid_content = mid_content $i " " } # 移除末尾多余的空格 sub(/ $/, "", mid_content) file1[key]["mid"] = mid_content file1[key]["full_line"] = $0 next } # 处理第二个文件,对比匹配行 { key = $1 # 提取当前行的中间字段 current_mid = "" for (i=2; i<=NF-1; i++) { current_mid = current_mid $i " " } sub(/ $/, "", current_mid) # 只处理在第一个文件中存在匹配首字段的行 if (key in file1) { # 拆分两个中间字段为数组,方便逐字段对比 split(file1[key]["mid"], ref_arr, " ") split(current_mid, curr_arr, " ") # 假设所有字段都不匹配,只要找到一个相同字段就推翻这个假设 all_fields_diff = 1 max_length = (length(ref_arr) > length(curr_arr)) ? length(ref_arr) : length(curr_arr) for (i=1; i<=max_length; i++) { # 对应位置字段相同 → 不是全不匹配 if (ref_arr[i] == curr_arr[i]) { all_fields_diff = 0 break } } # 确认全不匹配后,输出两行内容 if (all_fields_diff) { print file1[key]["full_line"] print $0 print "---" # 可选分隔符,方便区分不同匹配组 } } }
使用方法
- 将上述脚本保存为
compare_lines.awk - 终端执行命令:
awk -f compare_lines.awk File1 File2
逻辑说明
- 读取第一个文件:用关联数组
file1存储每个首字段对应的中间字段内容和完整行,方便后续快速匹配 - 处理第二个文件:对每行提取首字段和中间字段,和第一个文件中存储的对应内容对比
- 逐字段校验:把两个中间字段拆分成数组,逐个位置对比——只要有任意一个位置的字段相同,就判定不是“全不匹配”;只有所有对应位置(包括长度不同时的额外字段)都不同,才输出两行
比如如果把File2中的LSP3行改成LSP3 NODE5 NODE6 615,执行脚本后就会输出:
LSP3 NODE2 NODE4 NODE3 NODE6 725 LSP3 NODE5 NODE6 615 ---
内容的提问来源于stack exchange,提问作者user3746195
相关产品推荐
相关产品推荐

