2013-08-16 169 views
0

我需要引用行尾並使用this解決方案來替換文件有多行時完美工作的行尾。sed:替換行尾

當我嘗試使用這種方法的文件沒有\n或單行以\n結尾時出現問題。在這種情況下,sed不會取代任何內容,即使第二個s/命令也不起作用。也看起來像線的末尾永遠不會被取代。

我的命令是:

sed ':a;N;$!ba;s/\n/\\n/g;s/a/_/g' <file> 

(取代\n\\n和替換a_例如)。

我用hexdump -C在這裏顯示的文件:

有測試我做:

$ # Test1. single line without \n 
$ echo -n 'abc' | sed ':a;N;$!ba;s/\n/\\n/g;s/a/_/g' | hexdump -C 
00000000 61 62 63           |abc| 
# but expected "_bc" 

$ # Test2. single line with \n 
$ echo 'abc' | sed ':a;N;$!ba;s/\n/\\n/g;s/a/_/g' | hexdump -C 
00000000 61 62 63 0a          |abc.| 
# but expected "_bc\n" 

$ # Test3. two lines 
$ echo -e 'abc\n' | sed ':a;N;$!ba;s/\n/\\n/g;s/a/_/g' | hexdump -C 
00000000 5f 62 63 5c 6e 0a         |_bc\n.| 
# but expected "_bc\n\n" 

問題:爲什麼第二s/不能取代的Test1和Test2的東西嗎?在所有這些測試中,是否有任何方法可以修復替換s/\n/\\n/s/a/_/g

P.S .:我不想要一些解決方法,比如在sed處理之前在流尾添加換行符,並在刪除之後刪除它。

編輯:看起來像N命令不會讀取單行,即使它後跟'\ n'。任何想法如何解決它?

編輯2:看起來像這樣是expected behavior of N command。有沒有什麼方法可以取代最後一行的結尾?

+0

我最近使用過這個:sed'{:q; N; s/\ n/_/g; t q}' – svante

+0

您是否嘗試過分離sed部分? 'sed':a; N; $!ba' | sed的/ \ n/\\ n/g; s/a/_/g''或類似的。 – svante

+0

這沒有幫助,因爲它等於'cat | sed's/\ n/\\ n/g; s/a/_/g''。使用'':a; N; $!ba''連接線正在一個sed過程中工作。 – loentar

回答

0

傷心,但我沒有找到任何方法來防止sed添加新行輸出N命令時使用。我不想要一些解決方法,喜歡在處理之前添加新行並在刪除之後刪除它,但似乎沒有其他方法。

這是解決方法,最終溶液:

sed ':a;$!{N;ba};s/\n/\\n/g;s/a/_/g' <<< "$VAR" | tr -d '\n' 

<<<狀回聲增加了新的行成的輸入字符串,tr刪除它。

隨着該行所有測試都OK:

$ echo -e "abc" | sed ':a;$!{N;ba};s/\n/\\n/g;s/a/_/g' | tr -d '\n' | hexdump -C 
00000000 5f 62 63           |_bc| 

$ echo -e "abc\n" | sed ':a;$!{N;ba};s/\n/\\n/g;s/a/_/g' | tr -d '\n' | hexdump -C 
00000000 5f 62 63 5c 6e         |_bc\n| 

$ echo -e "abc\n\n" | sed ':a;$!{N;ba};s/\n/\\n/g;s/a/_/g' | tr -d '\n' | hexdump -C 
00000000 5f 62 63 5c 6e 5c 6e        |_bc\n\n| 

P.S:謝謝波東搞清楚的:a;$!{N;ba}

P.P.S .:如果有人會給出沒有tr的工作答案,我會重新接受它。

2

你可以用perl代替嗎?

$ echo -n "abc" | perl -pe 's/\n$/\\n/;' -pe 's/a/_a/;' | od -x 
0000000 615f 6362 
0000004 
$ echo "abc" | perl -pe 's/\n$/\\n/;' -pe 's/a/_a/;' | od -x 
0000000 615f 6362 6e5c 
0000006 
$ echo -e 'abc\n' | perl -pe 's/\n$/\\n/;' -pe 's/a/_a/;' | od -x 
0000000 615f 6362 6e5c 6e5c 
0000010 
+0

Bash是首選。不要只爲一個大於30的腳本添加新的依賴關係。 – loentar

+0

@loentar你有沒有出現在你的輸入中的字符:) – devnull

+0

對不起,在「期望的結果」中有錯別字,你的第二個正則表達式應該看起來像's/a/_ /;'它也可以組合成單個參數:'perl -pe's/\ n $/\\ n/g; s/a/_/g''。無論如何謝謝你的回答。 – loentar

3

這可能會爲你工作(GNU SED):

sed ':a;$!{N;ba};s/\n/\\n/g;s/a/_/g' file 

或:

sed ':a;$!N;$!ba;s/\n/\\n/g;y/a/_/' file 

邏輯上是有道理的:一個人不能得到next行,如果你在last線。

+0

謝謝你的回答。我理解這個邏輯。不幸的是,它不會替換'\\ n'(Test2和Test3)的最後一行。可能沒有辦法使'N'讀取不會跳過最後一行。 – loentar

+0

因爲它不能讀取不存在的行,只需添加一行! 'sed':a; $!{N; ba}; G; s/\/\\ n/g; s/a/_/g'文件 – potong

+0

不幸的是,這總是在源碼流中添加新行,失敗了。它也不會刪除最後一行,所以所有的測試都失敗了。 – loentar