简单的多行sed命令不太有效

简单的多行sed命令不太有效,sed,multiline,Sed,Multiline,我想匹配一些文本,包括换行符。下面的命令几乎可以工作,但与第一行不匹配 (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 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

您的简单方法一次最多可以在模式空间中容纳两行文本,因此它无法匹配三行模式

特别是:

(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
,您的简单方法一次最多可以在模式空间中容纳两行文本,因此它无法匹配三行模式

特别是:

(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
,您的简单方法一次最多可以在模式空间中容纳两行文本,因此它无法匹配三行模式

特别是:

(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
,您的简单方法一次最多可以在模式空间中容纳两行文本,因此它无法匹配三行模式

特别是:

(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

sed对于涉及多行的任何事情都不是合适的工具,因为它是面向行的,因此设计为一次处理一行。sed所有用于处理多行输入的语言结构在20世纪70年代中期awk发明时都已过时,因为awk是面向记录的而不是面向行的,因此它可以像处理任何其他字符一样处理记录中的换行。例如:

$ (echo foo; echo bar; echo bar) |
    awk -v RS= '{sub(/foo.*bar/,"zap\nbaz"); print}'
zap
baz

每当您发现自己在sed中使用了多于s、g和p(带-n)或谈论“空格”时,您就有了错误的方法。

sed对于涉及多行的任何事情都不是正确的工具,因为它是面向行的,因此设计为一次处理一行。sed所有用于处理多行输入的语言结构在20世纪70年代中期awk发明时都已过时,因为awk是面向记录的而不是面向行的,因此它可以像处理任何其他字符一样处理记录中的换行。例如:

$ (echo foo; echo bar; echo bar) |
    awk -v RS= '{sub(/foo.*bar/,"zap\nbaz"); print}'
zap
baz

每当您发现自己在sed中使用了多于s、g和p(带-n)或谈论“空格”时,您就有了错误的方法。

sed对于涉及多行的任何事情都不是正确的工具,因为它是面向行的,因此设计为一次处理一行。sed所有用于处理多行输入的语言结构在20世纪70年代中期awk发明时都已过时,因为awk是面向记录的而不是面向行的,因此它可以像处理任何其他字符一样处理记录中的换行。例如:

$ (echo foo; echo bar; echo bar) |
    awk -v RS= '{sub(/foo.*bar/,"zap\nbaz"); print}'
zap
baz

每当您发现自己在sed中使用了多于s、g和p(带-n)或谈论“空格”时,您就有了错误的方法。

sed对于涉及多行的任何事情都不是正确的工具,因为它是面向行的,因此设计为一次处理一行。sed所有用于处理多行输入的语言结构在20世纪70年代中期awk发明时都已过时,因为awk是面向记录的而不是面向行的,因此它可以像处理任何其他字符一样处理记录中的换行。例如:

$ (echo foo; echo bar; echo bar) |
    awk -v RS= '{sub(/foo.*bar/,"zap\nbaz"); print}'
zap
baz
每当您发现自己在sed中使用了超过s、g和p(带-n)的字符或谈论“空格”时,您就有了错误的方法。

这里有一个解决方法

sed 's/$/\\n/' | tr -d '\n' | sed 's/foo.*bar/zap\\nbar/g' | sed 's/\\n/\n/g'
这里有一个解决办法

sed 's/$/\\n/' | tr -d '\n' | sed 's/foo.*bar/zap\\nbar/g' | sed 's/\\n/\n/g'
这里有一个解决办法

sed 's/$/\\n/' | tr -d '\n' | sed 's/foo.*bar/zap\\nbar/g' | sed 's/\\n/\n/g'
这里有一个解决办法

sed 's/$/\\n/' | tr -d '\n' | sed 's/foo.*bar/zap\\nbar/g' | sed 's/\\n/\n/g'
这可能适用于您(GNU-sed):

如果当前行包含
foo
,则添加一个换行符和下一行,然后查找
foo
,后跟
bar
(除了换行符以外的任意字符数)。如果发现此模式,则将其替换为
zap\nbaz
并打印结果。如果没有,则循环回到
:a
,并重复,直到找到它或文件结束(在这种情况下,将打印出图案空间中的整个字符串,而不进行任何更改)

注意:
N
命令将不起作用