linux - 用 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 '/==打开==/ {:loop; N; /==关闭==/!b 循环;/id: class8/ {s/.*/NEEDS REWRITE/}}' /example
如果我告诉它重写开头(^),它只重写范围的第一行,我认为这是因为它将整个模式视为一行。
解决方案
我得到的最接近的代码是这样的,但我必须重写整个范围,而且它负担不起:
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
特别注意:
- 被替换的文本表示为 group
\(^\|\n\)
,表示模式空间开头的零长度子字符串或换行符,它被捕获为一个组。 - 匹配的文本通过 回显到替换中
\1
。当它是匹配的替代时,这没有明显的效果^
,但它避免了在其他替代匹配时消除换行符。 - 逗号 (
,
) 用作模式分隔符,因此/
替换文本中的斜线 ( ) 不需要转义。 - 该
g
标志用于导致模式的所有外观被替换,而不仅仅是第一个。
如果你愿意依赖 GNU 扩展,那么你可以做的更简单一点:
sed -e '/==OPEN==/ {:loop; N; /==CLOSE==/! b loop; /id: class8/ {s,^,// ,gm}}' \
/example
对于 GNU sed
,命令m
中的标志会导致在模式空间的开头和每个换行符之后立即匹配。POSIX 未指定此标志。s
^
推荐阅读
- swift - 本地通知横幅持续时间
- php - 如何在 Ionic 中使用 php 上传文件?
- appium - 我如何启动已经使用 appium 安装的 iOS 应用程序
- python - 在 matplotlib 中调整 x 轴
- python - Pandas:如何在 python3 中对混合类型的多索引使用切片?
- java - 执行 Jar 文件时出现 NullPointerException。没有任何效果
- powershell - 获取在 vm 中运行的应用程序的 CPU、磁盘、内存和网络使用情况
- python - 如何在 3D 数组中运行迭代互相关?
- ios - 如何快速将 iPhone 设备注册令牌传递给 Web 服务?
- unit-testing - SpringBoot2.0单元测试缺少依赖