我希望匹配包含换行符在内的一些文字。下面的命令几乎可以工作,但它与第一行不匹配
(echo foo; echo foo; echo bar) | sed '1!N; s/foo.*bar/zap\nbaz/'
foo
zap
baz
这里有同样的问题:
(echo foo; echo bar; echo bar) | sed '1!N; s/foo.*bar/zap\nbaz/'
foo
bar
bar
我发现了一个更复杂的sed命令,它在两种情况下都能正常工作,但我宁愿修复简单的命令(如果可能的话),或者至少理解为什么它不起作用。
(echo foo; echo bar; echo bar) | sed -n '1h;1!H;${g;s/foo.*bar/zap\nbaz/p}'
zap
baz
答案 0 :(得分:3)
$ (echo foo; echo bar; echo bar) |
awk -v RS= '{sub(/foo.*bar/,"zap\nbaz"); print}'
zap
baz
任何时候你发现自己在sed中使用的不仅仅是s,g和p(和-n),或者在谈论“空格”时,你的方法是错误的。
答案 1 :(得分:0)
您的简单方法一次最多可以在模式空间中保存两行文本,因此无法匹配三行模式。
特别是:
(echo foo; echo foo; echo bar) | sed '1!N; s/foo.*bar/zap\nbaz/'
foo
zap
baz
它读取第一行(foo
),找不到匹配项,并打印foo
。然后它读取第二个(foo
),追加下一个(bar
),找到匹配并执行替换,然后打印zap\nbaz
。
在第二轮中:
(echo foo; echo bar; echo bar) | sed '1!N; s/foo.*bar/zap\nbaz/'
foo
bar
bar
它读取第一行(foo
),找不到匹配项,并打印foo
。然后它读取第二个(bar
),追加下一个(bar
),找不到匹配并打印bar\nbar
。
答案 2 :(得分:0)
这是一个解决方法
sed 's/$/\\n/' | tr -d '\n' | sed 's/foo.*bar/zap\\nbar/g' | sed 's/\\n/\n/g'
答案 3 :(得分:0)
这可能适合你(GNU sed):
sed '/foo/{:a;N;/foo.*bar/!ba;s//zap\nbaz/}' file
如果当前行包含foo
,则附加换行符和下一行,然后查找foo
后跟bar
(包括换行符在内的任意数量的字符)。如果找到此模式,请将其替换为zap\nbaz
并打印出结果。如果没有循环回:a
并重复直到找到它或文件结束(在这种情况下,模式空间中的整个字符串将被打印出来而没有任何变化)。
N.B。 N
命令不允许您读取传递文件结尾并尝试拯救它。命令s//zap\nbaz/
将当前正则表达式替换为zap\nbaz
,其中当前正则表达式是此/.../
中的最后一个/foo.*baz/
。
没有大括号的替代方案:
sed '/foo/!b;:a;N;/foo.*bar/!ba;s//zap\nbaz/' file