如何用sed/perl在Shell脚本中实现多行正则替换(保留首尾内容)
批量多行正则替换:用sed/perl实现原地修改文件
问题背景
我查过Stack Overflow上的《How to use regex for multiple line pattern in shell script》一文,但无法满足需求。需要通过终端工具(sed或perl)实现原地正则替换来批量修改文件,无需依赖HTML/XML库。
原始文件内容
Some text <div class="firstClass secondClass" something="else"> Some random stuff </div> Random Text <div class="thirdClass fifthClass" something="else"> Some random stuff < is something < but not /> This </div> <div class="fourthClass"> Some random stuff </div> Final Text
期望转换结果
Some text <!-- firstClass start --> Some random stuff <!-- firstClass end --> Random Text <!-- thirdClass start --> Some random stuff < is something < but not /> This <!-- thirdClass end --> <!-- fourthClass start --> Some random stuff <!-- fourthClass end --> Final Text
尝试过的命令
sed -n '/<div class="\([^ "]*\)[^>]*>/,/<\/div>/{s/<div class="\([^ "]*\)[^>]*>/<!-- \1 start -->/;/<\/div>/d;p}' file
该命令能正确替换起始行,但无法在内容后添加对应结束标识,还会删除首尾无关行。需要保留这些行,并在内容末尾添加与起始行提取的标识对应的结束注释。
通用模式说明
此需求不限于HTML场景,通用结构如下:
原始通用结构
Some random text before my pattern PATTERN "info ... random stuffs END PATTERN Some random stuff after pattern
期望转换后结构
Some random text before my pattern NEW PATTERN - info random stuffs END NEW PATTERN - info Some random stuff after pattern
注:random stuffs中绝不会出现END PATTERN,无嵌套情况,仅需提取起始行中第一个空格或引号前的info内容,其余内容可删除。
解决方案
1. 使用sed实现(GNU sed适用)
sed -i.bak ' /<div class="\([^ "]*\)[^>]*>/{ s//<!-- \1 start -->/ h :loop n /<\/div>/{ g s/<!-- \(.*\) start -->/<!-- \1 end -->/ p d } p b loop }' file
-i.bak:原地修改文件,同时生成.bak备份文件(无需备份可直接用-i)- 逻辑:匹配起始行时,替换为注释并将提取的类名存入临时缓存;逐行读取内容,直到遇到结束标签,从缓存取出类名生成对应结束注释,替换结束标签后打印,其余行正常输出。
2. 使用perl实现(跨平台通用)
perl -i.bak -0777 -pe ' s/<div class="([^ "]+)[^>]*>\n(.*?)<\/div>/<!-- $1 start -->\n$2\n<!-- $1 end -->/gs' file
-i.bak:原地修改并生成备份文件-0777:将整个文件读入内存处理多行内容-pe:循环处理内容并输出结果s/.../.../gs:g表示全局替换,s让.匹配换行符,实现跨行匹配替换
通用模式适配(sed版)
如果是通用的PATTERN与END PATTERN结构,可将sed命令调整为:
sed -i.bak ' /PATTERN "\([^ "]*\)/{ s//NEW PATTERN - \1/ h :loop n /END PATTERN/{ g s/NEW PATTERN - \(.*\)/END NEW PATTERN - \1/ p d } p b loop }' file
内容的提问来源于stack exchange,提问作者Aram Papazian
相关产品推荐
相关产品推荐

