4

我正在尝试在 Linux 系统上使用 sed 替换多行

这是我的文件

<!-- PAGE TAG -->
DATA1
DATA2
DATA3
DATA4
DATA5
DATA6
<div id="DATA"></div>
DATA8
DATA9
<!-- PAGE TAG -->

我所做的尝试都失败了!

sed -n '1h;1!H;${;g;s/<!-- PAGE TAG -->.*<!-- PAGE TAG -->//g;p;}' 
sed -n '1!N; s/<!-- PAGE TAG -->.*<!-- PAGE TAG -->// p'
sed -i 's|<!--[^>]*-->[^+]+<!--[^>]*-->||g' 
sed -i 's|/\/\/<!-- PAGE TA -->/,/\/\/<!-- PAGE TA -->||g'

两者之间的一切都<!-- PAGE TAG -->应该被替换。

这个问题类似于 sed multiline replace

4

2 回答 2

4

根据您看到的链接中给出的答案进行调整,这应该有效:

sed '/<!-- PAGE TAG -->/,/<!-- PAGE TAG -->/d'

正则表达式的格式是[2addr]d,其中 2 个地址是/<!-- PAGE TAG -->/,并且/<!-- PAGE TAG -->/用逗号分隔。d意味着删除从匹配第一个地址的行到匹配最后一个地址的行的所有行。(这意味着标签之外的东西,但与标签在同一行的东西也会被删除)。


虽然 Tim Pote 已经回答了这个问题,但我还是把它贴在这里以防万一有人需要替换多行模式:

sed -n '1h; 1!H; ${g; s/<!-- PAGE TAG -->[^!]*<!-- PAGE TAG -->//g; p;}'

我从现有来源修改了解决方案,因此此处解释了大部分命令。

这里的正则表达式有点不完整,因为它假定!2 个页面标签之间的数据中没有字符。如果没有这个假设,我无法控制正则表达式匹配的字符数,因为没有惰性量词(据我所知)。

此解决方案不会删除标记之前的文本,即使它与标记位于同一行。

于 2012-06-15T01:06:02.190 回答
4

虽然@nhahtdh 的答案是您原始问题的正确答案,但此解决方案是您评论的答案:

sed '
  /<!-- PAGE TAG -->/,/<!-- PAGE TAG -->/ {
    1 {
      s/^.*$/Replace Data/
      b
    }
    d
  }
'

你可以这样读:

/<!-- PAGE TAG -->/,/<!-- PAGE TAG -->/-> 对于这些正则表达式之间的行

1 {-> 第一个匹配行

s/^.*$/Replace Data/-> 搜索任何内容并替换为Replace Data

b-> 分支到结束(在这种情况下表现得像 break)

d-> 否则,删除该行

您可以通过在每个命令后添加分号来使用 gnu sed 将任何一系列 sed 命令变成单行(但如果您希望以后能够阅读它,则不建议这样做):

sed '/<!-- PAGE TAG -->/,/<!-- PAGE TAG -->/ { 1 { s/^.*$/Replace Data/; b; }; d; };'

顺便说一句,您应该真正尝试在您的帖子中尽可能具体。“替换/删除”是指“替换或删除”。如果要更换,就说更换。这有助于我们这些试图回答您的问题的人以及可能遇到相同问题的未来用户。

于 2012-06-15T01:33:16.133 回答