Shell脚本问题:逐行对比文件忽略最后词,补全差异行丢失最后词
解决Shell脚本对比文件时丢失最后一个单词的问题
我懂你遇到的问题了——你想写个Shell脚本对比settings.py和settings_template.py,忽略每行最后一个单词,把settings.py里有但settings_template.py没有的完整行追加到后者末尾,但现在脚本输出的内容丢了匹配行的最后一个单词。
问题根源
你当前的思路是先生成两个去掉最后一个单词的临时文件,再用awk对比临时文件的内容。但输出的时候你打印的是临时文件里的内容(已经丢了最后一个单词),而不是原文件的完整行,这就是问题所在。
修复方案:直接在awk里处理,不用临时文件
我们可以让awk直接处理原文件,在内存里生成“忽略最后一个单词”的对比键,同时保留原行内容,这样就能输出完整的行:
#!/bin/bash awk ' # 第一步:读取settings_template.py,存储所有"忽略最后一个单词"的行作为已存在标记 NR == FNR { # 生成对比键:去掉行尾最后一个单词(匹配最后一个空格到行尾的内容并替换为空) compare_key = $0 sub(/ [^ ]+$/, "", compare_key) existing_lines[compare_key] = 1 next } # 第二步:读取settings.py,检查每行是否需要追加 { # 同样生成当前行的对比键 compare_key = $0 sub(/ [^ ]+$/, "", compare_key) # 如果这个键不在已存在的集合里,就输出完整行并追加到目标文件 if (!existing_lines[compare_key]) { print $0 print $0 >> "settings_template.py" } } ' settings_template.py settings.py
更安全的版本(避免边读边写)
如果担心直接在awk里追加到正在读取的文件可能出现异常,可以先把需要追加的行存到临时文件,最后再批量追加:
#!/bin/bash # 先筛选出需要追加的行,存入临时文件 awk ' NR == FNR { compare_key = $0 sub(/ [^ ]+$/, "", compare_key) existing_lines[compare_key] = 1 next } { compare_key = $0 sub(/ [^ ]+$/, "", compare_key) if (!existing_lines[compare_key]) { print $0 } } ' settings_template.py settings.py > to_append.tmp # 批量追加到目标文件 cat to_append.tmp >> settings_template.py # 清理临时文件 rm to_append.tmp
关键逻辑说明
sub(/ [^ ]+$/, "", compare_key):用正则匹配最后一个空格到行尾的内容(也就是最后一个单词和前面的空格),替换为空,得到忽略最后一个单词的对比键- 我们只对比这个键是否存在,输出和追加的却是原文件的完整行,这样就不会丢失最后一个单词了
这样就能完美实现你的需求啦!
内容的提问来源于stack exchange,提问作者user9136763
相关产品推荐
相关产品推荐

