如何编写Bash或MSDOS脚本:匹配M98P9001行后按条件删除3行
实现方案
为什么之前的Sed命令不符合需求
你之前使用的sed -e '/M98P9001/,+2d'是典型的逐行流式删除逻辑:一旦检测到匹配M98P9001的行,就会立即从当前行开始连续删除后续2行,完全没有机会校验后续两行的内容是否包含指定的保护代码,因此无法满足条件判断的要求。
核心实现逻辑(AWK,兼容Bash/Windows GNU环境)
AWK支持自定义行缓冲区,非常适合这类需要拿到连续多行内容做整体判断的场景,整体逻辑为:
- 遇到普通无匹配的行,直接输出
- 遇到
M98P9001的匹配行时,启动3行内容的缓冲区,依次存入当前行及后续2行 - 攒满3行内容后,校验后续2行是否包含任意保护代码:
M98P8050、M98P8080、M09- 若未检测到任何保护代码:直接丢弃这3行,不输出
- 若检测到至少一个保护代码:将3行内容全部正常输出
- 自动处理文件末尾的边界情况(匹配行在文件末尾、后续行不足2行的场景)
可直接运行的命令
awk ' BEGIN { buf_cnt=0; delete buf } /M98P9001/ { for(i=1;i<=buf_cnt;i++) print buf[i] delete buf; buf_cnt=1; buf[1]=$0 if(buf_cnt<3) next } buf_cnt>0 { buf_cnt++; buf[buf_cnt]=$0 if(buf_cnt==3) { has_protect=0 for(i=2;i<=3;i++) { if(buf[i] ~ /M98P8050|M98P8080|M09/) { has_protect=1; break } } if(has_protect) for(i=1;i<=3;i++) print buf[i] delete buf; buf_cnt=0 } next } { print $0 } END { if(buf_cnt>0) { has_protect=0 for(i=2;i<=buf_cnt;i++) { if(buf[i] ~ /M98P8050|M98P8080|M09/) { has_protect=1; break } } if(has_protect) for(i=1;i<=buf_cnt;i++) print buf[i] } } ' input.txt > output.txt
测试验证
针对你提供的测试输入文件,运行上述命令后的输出完全符合预期:
- 输入中
M98P9001 (OFF)****后续的两行分别为G00X20Y25、M98P8051 (FAST CUT),未包含任何指定保护代码 - 因此脚本会自动删除这连续3行内容,最终输出:
G03X22Y22.5 G01X48.5 G01X22Y34 G01X25Y33
注意事项
- 保护代码的匹配为正则模糊匹配,只要行内包含对应字符串即可识别,和原G代码的格式兼容
- 如果后续两行中任意一行出现了
M98P8050、M98P8080、M09中的任意一项,脚本会自动跳过删除逻辑,完整保留这3行内容 - 纯MSDOS批处理实现该逻辑的代码复杂度极高,推荐在Windows环境下安装GNU AWK(gawk)后运行上述跨平台命令即可
内容的提问来源于stack exchange,提问作者Philippe Chartrand
相关产品推荐
相关产品推荐

