如何修改sed脚本,遇到非##开头行时停止打印指定代码段
问题
需要提取并打印符合以下格式的注释代码段:
## FAML [ASMB] keyword,keyword ## Some text ## END OF FAML [ASMB]
现有实现仅在匹配到## END OF FAML [ASMB]时停止打印,但存在缺陷:当未遇到结束标记时,若出现不以注释前缀(##、//等)开头的非注释行,需要立即停止打印。例如下面的示例中,遇到Some code行时就应终止输出:
## FAML [ASMB] keyword,keyword ## Some text ## End OF FAL Some code
现有实现代码如下:
spc='[[:space:]]*' gph="[[:graph:]]+" cmt='//' ebl='\[' ebr='\]' local pn_ere="^[[:space:]]*([#;!]+|@c|${cmt})[[:space:]]+" local kys="(([^,]+)(,[^,]+)*)?" nfaml=${faml:-"[[:graph:]]+"} nasmb=${asmb:-"[[:graph:]]+"} beg_ere="${pn_ere}${nfaml} ${ebl}${nasmb}${ebr}${spc}${kys}$" end_ere="${pn_ere}END OF ${nfaml} ${ebl}${nasmb}${ebr}${spc}$" sed -E -n "/$beg_ere/,/$end_ere/ { /$end_ere/z; s/$pn_ere// ; p }" "$filename"
请修改上述sed脚本,满足遇到非注释行立即停止打印的需求。
解决方案
修改后的sed脚本如下:
spc='[[:space:]]*' gph="[[:graph:]]+" cmt='//' ebl='\[' ebr='\]' local pn_ere="^[[:space:]]*([#;!]+|@c|${cmt})[[:space:]]+" local kys="(([^,]+)(,[^,]+)*)?" nfaml=${faml:-"[[:graph:]]+"} nasmb=${asmb:-"[[:graph:]]+"} beg_ere="${pn_ere}${nfaml} ${ebl}${nasmb}${ebr}${spc}${kys}$" end_ere="${pn_ere}END OF ${nfaml} ${ebl}${nasmb}${ebr}${spc}$" sed -E -n "/$beg_ere/,/$end_ere/ { # 遇到非注释行时立即清空模式空间并退出sed /$pn_ere/! { z; q } /$end_ere/z; s/$pn_ere// ; p }" "$filename"
修改说明
新增的/$pn_ere/! { z; q }语句实现了需求:
/$pn_ere/!:匹配不满足注释前缀格式的行z:清空当前模式空间,避免残留内容输出q:立即退出sed进程,终止所有后续行的处理
这样一来,当区间内出现非注释行时,脚本会立刻停止输出并退出,不会继续处理后续内容。
内容的提问来源于stack exchange,提问作者Dilna
相关产品推荐
相关产品推荐

