You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 19:31:24