2014-09-29 92 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