【问题标题】:Replace a pattern range line by line with sed用 sed 逐行替换模式范围
【发布时间】:2021-08-25 17:14:13
【问题描述】:

我需要替换按 ID 排序的模式范围的每一行的开头,我正在使用 sed 但欢迎使用其他语言!

这是带有目标的示例文本

...
==OPEN==
  data: blabla
  id: class1
  moredata: blabla
==CLOSE==

==OPEN==
  id: class2
  boringdata: blabla
==CLOSE==

...extra info

==OPEN==
  id: class8
  data: ...
==CLOSE==

...more info

==OPEN==
  data: ...
  boringdata: ...
  id: class10
==CLOSE==
...

如果我要注释掉 id 为 8 的模式,预期的输出将是:

...
==OPEN==
  data: blabla
  id: class1
  moredata: blabla
==CLOSE==

==OPEN==
  id: class2
  boringdata: blabla
==CLOSE==

...extra info

// ==OPEN==
//   id: class8
//   data: ...
// ==CLOSE==

...more info

==OPEN==
  data: ...
  boringdata: ...
  id: class10
==CLOSE==
...

我得到的最接近的代码是这样的,但我必须重写整个范围,而且负担不起:

sed -e '/==打开==/ {:loop; N; /==关闭==/! b 循环; /id: class8/ {s/.*/NEEDS REWRITE/}}' /example

如果我告诉它重写开头(^),它只重写范围的第一行,我认为这是因为它将整个模式视为一行。

【问题讨论】:

    标签: linux awk sed gnu bsd


    【解决方案1】:

    我得到的最接近的代码是这个,但我必须重写 整个范围,它是买不起的:

    sed -e '/==打开==/ {:loop; N; /==关闭==/! b 循环; /id: class8/ {s/.*/NEEDS REWRITE/}}' /example

    其实还不错。

    如果我告诉它重写开头 (^),它只会重写第一个 范围的线,我认为这是因为它考虑了整个 模式为一条线。

    是的,对于 POSIX sed 和 GNU sed 默认情况下,^ 仅匹配模式空间的开头。但是,您可以自己匹配换行符:

    sed -e '/==OPEN==/ {:loop; N; /==CLOSE==/! b loop; /id: class8/ {s,\(^\|\n\),\1// ,g}}' \
      /example
    

    特别注意:

    • 被替换的文本表示为组@98​​7654325@,表示模式空间开头的零长度子字符串或作为一组捕获的换行符。
    • 匹配的文本通过\1 回显到替换中。当匹配的是 ^ 替代项时,这没有明显的效果,但它避免了在其他替代项匹配时消除换行符。
    • 逗号 (,) 用作模式分隔符,因此替换文本中的斜线 (/) 不需要转义。
    • g 标志用于替换模式的所有个外观,而不仅仅是第一个。

    如果你愿意依赖 GNU 扩展,那么你可以做得更简单一点:

    sed -e '/==OPEN==/ {:loop; N; /==CLOSE==/! b loop; /id: class8/ {s,^,// ,gm}}' \
      /example
    

    对于 GNU seds 命令中的 m 标志会导致 ^ 在模式空间的开头和每个换行符之后立即匹配。 POSIX 未指定此标志。

    【讨论】:

    • 完美的回应,我需要多读几遍才能正确,但你成功了!非常感谢^^!
    • 只是为了确定,m 标志确保它读取为多行而不是一行,g 标志确保它将继续影响每一行,对吗?所以我的问题实际上是我在一行上使用s 命令。再次感谢!
    • @M.X,这不是我用来描述它的措辞,但是是的,我想你已经明白了。
    • 注:正则表达式/地址后面的单个 sed 命令不需要用大括号括起来 {...}{} 是实际的 sed 命令),s/.*/REPLACE/mg 将用 REPLACE 替换模式空间中的每一行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-04
    • 2018-01-16
    • 1970-01-01
    • 2021-03-15
    • 2021-12-07
    相关资源
    最近更新 更多