在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
说明:
命令分为两部分:
- 前半部分保持 3 行移动窗口。
- 在
匹配
之后附加 5 行。
详情如下:
:a
是循环占位符$q
在文件末尾打印模式空间 (PS) 内的所有行。N
将下一行追加到 PSs/\n/&/3
替换第三个换行符本身。这是一个计数装置,用于检查 PS 中是否有 3 行。Ta
如果之前的替换失败则循环到循环占位符a
/match/!{P;D}
查看match
,如果失败,则打印到第一个换行符,然后删除该行及其换行符(这会调用新周期)。:b
是循环占位符此时已找到匹配项。$bc
如果文件结尾分支转发到占位符c
N
将下一行追加到 PSs/\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/