基于Awk实现匹配行后第二行批量替换及脚本错误修复
问题描述
我有一个仅包含一个匹配字符串的主文件,希望将匹配短语后第二行的某列值替换,并根据参考文件(第一列为输出文件名、第二列为替换值)生成多个独立输出文件。
示例文件
主文件 (main_file)
some words here This is the 'MATCH LINE' # this is just a comment This NUMBER to be updated and other words here
参考文件 (ref_file)
Out1 ONE Out2 TWO Out3 THREE
预期输出
Out1
some words here This is the 'MATCH LINE' # this is just a comment This ONE to be updated and other words here
Out2
some words here This is the 'MATCH LINE' # this is just a comment This TWO to be updated and other words here
Out3
some words here This is the 'MATCH LINE' # this is just a comment This THREE to be updated and other words here
尝试的脚本
awk 'FNR==NR {fn[$2]=$1; vals[$2]=$2; next} {for (f in fn) {$0~/This is the '\''MATCH LINE'\''/{getline;getline;$2=vals[f]}}; print $0 > fn[f]}' ref_file main_file
错误信息
awk: file "[command line]": line 1: Syntax error Context is: >>> >>> {for (f in fn) {$0~/This is the 'MATCH LINE'/{ <<<
解决方法
错误原因分析
- 单引号转义问题:shell环境下调用awk时,原脚本对正则表达式内的单引号转义方式错误,导致awk无法正确解析正则表达式。
- 变量存储逻辑颠倒:参考文件第一列是输出文件名、第二列是替换值,但原脚本把替换值作为键、文件名作为值存储,逻辑完全搞反。
- 行处理逻辑错误:循环中直接修改
$0并滥用getline,会导致主文件行丢失,无法完整复制内容到每个输出文件。
修正后的Awk脚本
# 读取参考文件,存储每个输出文件对应的替换值 FNR == NR { replacements[$1] = $2 next } # 处理主文件,为每个输出文件生成对应内容 { for (out_file in replacements) { # 保存当前行副本,避免修改影响其他文件的输出 curr_line = $0 # 匹配到目标行时,处理后续两行 if (curr_line ~ /This is the '\''MATCH LINE'\''/) { print curr_line > out_file # 读取并打印注释行 getline print $0 > out_file # 读取待修改行,替换第二列后打印 getline $2 = replacements[out_file] print $0 > out_file # 跳过当前循环,继续读取主文件下一行 next } # 非目标行直接打印到输出文件 print curr_line > out_file } }
使用方式
将脚本保存为script.awk后,在终端执行:
awk -f script.awk ref_file main_file
也可以直接在命令行运行单行命令:
awk 'FNR == NR {replacements[$1] = $2; next} {for (out_file in replacements) {curr_line = $0; if (curr_line ~ /This is the '\''MATCH LINE'\''/) {print curr_line > out_file; getline; print $0 > out_file; getline; $2 = replacements[out_file]; print $0 > out_file; next} print curr_line > out_file}}' ref_file main_file
脚本说明
- 读取参考文件:通过
FNR == NR判断当前处理的是参考文件,将输出文件名作为键、替换值作为值存入replacements数组。 - 处理主文件:遍历每个输出文件,逐行处理主文件内容:
- 若当前行是匹配行,先打印该行,再依次读取注释行、待修改行,修改待修改行的第二列后打印。
- 非匹配行直接原样打印到对应输出文件。
内容的提问来源于stack exchange,提问作者EverLearner
相关产品推荐
相关产品推荐

