2014-09-29 135 views
0

我想匹配一些文本,包括换行符。命令如下差不多的作品,但它不匹配的第一行简单的多行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 

回答

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

3

对于涉及多行的任何事情来说,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)以上或谈论“空格”你有错误的做法。

0

这里有一个解决方法

sed 's/$/\\n/' | tr -d '\n' | sed 's/foo.*bar/zap\\nbar/g' | sed 's/\\n/\n/g' 
+0

如果字符串'\原始文件N'存在上述不希望会用一个换行符替换它。 – 2014-09-30 02:07:23

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