2011-07-09 52 views
4

我想在Bash中用sed做一些簡單的字符串替換。我是Ubuntu 10.10。Sed:用一個下劃線替換一系列點

只看到下面的代碼,這是不言自明:


name="A%20Google.." 
echo $name|sed 's/\%20/_/'|sed 's/\.+/_/' 

我想A_Google_但我得到A_Google..

sed 's/\.+/_/'部分顯然是錯誤的。

BTW,sed 's/\%20/_/'sed 's/%20/_/'都可以工作。哪個更好?

+0

預感:嘗試'的/\.\.*/ _ /''。你的sed可能無法正確處理'+'。 – Beta

+0

@Beta:嗨,我想知道爲什麼'sed's /\.*/_/''不會工作。謝謝。 – DocWiki

+0

因爲'\。*'會匹配任意數量的點,包括零,例如「A_Google ..」開頭的無點。 – Beta

回答

5

sed說POSIX基本正則表達式,其中不包括+作爲元字符。可移植,改寫使用*

sed 's/\.\.*/_/' 

,或者如果你將永遠關心的是Linux,你可以使用各種GNU-主義:

sed -r 's/\.\.*/_/' # turn on POSIX EREs (use -E instead of -r on OS X) 
sed 's/\.\+/_/'  # GNU regexes invert behavior when backslash added/removed 

這最後例子回答了你的另一個問題:一個字符當按照原樣使用時可以具有特殊含義,並且即使當反斜槓時,%處沒有特殊含義,未來驗證意味着不假定\%是安全的。

附加說明:您不需要在管道中有兩個單獨的sed命令。

echo $name | sed -e 's/\%20/_/' -e 's/\.+/_/' 

(?另外,你只需要做的是每行一次,或所有出現您可能希望/g修改)

+0

我不太瞭解你的'\%'部分。你的意思是'\%'沒有特別的意義,但這可能會在未來改變?所以'%'是一個更好的解決方案。我不知道什麼時候應該添加反斜槓,什麼時候不要。 – DocWiki

+0

您必須知道正在使用哪種正則表達式語言,以及'%'與'\%'的東西由POSIX的GNU解釋所複雜化,其中在BRE中不存在的ERE元字符可以被反斜槓以獲得ERE含義(所以'\ +'在大多數版本的'sed中表示一個文字'+' ',但是在GNU'sed'中,它意味着它之前的一個或多個)。不幸的是,正則表達式是隱藏地雷的噩夢,並且在可預見的未來仍然如此;你別無選擇,只能確切知道程序使用哪種正則表達式引擎,以及引擎的怪癖是什麼。 – geekosaur

2

sed命令不理解+所以你必須手工將其展開:

sed 's/\.\.*/_/' 

或者告訴sed要使用擴展的正則表達式:

sed -r 's/\.+/_/' # GNU 
sed -E 's/\.+/_/' # OSX 

哪個開關,-r-E,取決於您的sed,它可能甚至不支持擴展正則表達式,因此便攜式解決方案將使用\.\.*代替\.+。但是,因爲你在Linux上,你應該有GNU sed,所以sed -r應該做的伎倆。