用sed逐行替换模式范围



我需要替换按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 '/==OPEN==/{:loop;N;/= = = =/!b循环;/id: class8/{s/。*/需要重写/}}'/example

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

我得到的最接近的代码是这个,但是我必须重写整个范围和价格都不合理:

sed -e '/==OPEN==/{:loop;N;/= = = =/!b循环;/id: class8/{s/。*/需要重写/}}'/example

还不错。

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

是的,POSIXsed和GNUsed默认情况下,^只匹配模式空间的开头。但是,您可以匹配换行符本身:

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

特别注意:

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

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

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

对于GNUsed,s命令中的m标志使^在模式空间的开始和每个换行符之后匹配。这个标志不是POSIX指定的。

相关内容

  • 没有找到相关文章

最新更新