linux - 如何在 sed 中匹配后替换文本 block

标签 linux sed

sed中,我想在匹配后替换多行文本 block ,例如,在匹配“foo”后,假设其行号为0。我想替换从第-3行到第+5行的文本 block ,即匹配行之前的第三行和匹配行之后的第五行之间的文本 block ,由另一个文本 block bar1\nbar2组成。我希望能够在两种情况下执行此操作:

1) 保留被替换 block 后面的匹配行; 2) 删除匹配行以及-3 和+5 行。

请帮助我。

谢谢。

最佳答案

这可能有效(GNU sed):

seq 31|sed 's/5/& match/' >/tmp/file
sed ':a;$q;N;s/\n/&/3;Ta;/match/!{P;D};:b;$bc;N;s/\n/&/8;Tb;:c;s/.*/bar1\nbar2/' /tmp/file
1
bar1
bar2
11
bar1
bar2
21
bar1
bar2
31
sed ':a;$q;N;s/\n/&/3;Ta;/match/!{P;D};h;s/\([^\n]*\n\)*\([^\n]*match[^\n]*\).*/\2/;x;:b;$bc;N;s/\n/&/8;Tb;:c;s/.*/bar1\nbar2/;G' /tmp/file
1
bar1
bar2
5 match
11
bar1
bar2
15 match
21
bar1
bar2
25 match
31

说明:

命令分为两部分:

  1. 前半部分保持 3 行移动窗口。
  2. 匹配之后附加 5 行。

详情如下:

  • :a 是循环占位符
  • $q 在文件末尾打印模式空间 (PS) 内的所有行。
  • N 将下一行追加到 PS
  • s/\n/&/3 替换第三个换行符本身。这是一个计数装置,用于检查 PS 中是否有 3 行。
  • Ta 如果之前的替换失败则循环到循环占位符a
  • /match/!{P;D} 查看match,如果失败,则打印到第一个换行符,然后删除该行及其换行符(这会调用新周期)。
  • :b 是循环占位符此时已找到匹配项。
  • $bc 如果文件结尾分支转发到占位符c
  • N 将下一行追加到 PS
  • s/\n/&/8 替换第 8 个(前 3 个,后 5 个)换行符本身。这是一个计数设备,用于检查 PS 中是否附加了 5 行
  • Tb 如果之前的替换失败,则循环到循环占位符 b
  • :c 是循环占位符
  • s/.*/bar1\nbar2/ 将 PS 替换为所需的字符串。

第二个衬垫复制了 match 行并将其附加到替换的字符串中。

替代解决方案:

sed -r ':a;$!N;s/[^\n]*/&/9;$!Ta;/^([^\n]*\n){3}([^\n]*match[^\n]*)\n.*/!{P;D};c\bar1\nbar2' file

sed -r ':a;$!N;s/[^\n]+/&/9;$!Ta;/^([^\n]*\n){3}([^\n]*match[^\n]*)\n.*/!{P;D};s//\bar1\nbar2\n\2/' file

关于linux - 如何在 sed 中匹配后替换文本 block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11299701/

相关文章:

c - 为什么 getsockopt() 没有返回 TCP_MAXSEG 的预期值?

python - 使用 Python 在 RPI3 中串行丢失数据

regex - 用 sed 替换控制字符

regex - 仅使用 sed 打印二进制匹配?

regex - 如何在我的整个系统中进行查找和替换?

mysql - 使用 awk 或 sed 将 mysql.log 重新格式化为简单格式

c - 在 C 中设置 CPU 亲和性的问题

linux - 使用自定义虚拟主机在 docker 中运行 nginx

linux - Vala DBus 接口(interface)对象我应该如何注册属性更改?

bash - sed:如何将一系列行打印到文件末尾