我想在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/_/'
都可以工作。哪個更好?
我想在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/_/'
都可以工作。哪個更好?
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
修改)
我不太瞭解你的'\%'部分。你的意思是'\%'沒有特別的意義,但這可能會在未來改變?所以'%'是一個更好的解決方案。我不知道什麼時候應該添加反斜槓,什麼時候不要。 – DocWiki
您必須知道正在使用哪種正則表達式語言,以及'%'與'\%'的東西由POSIX的GNU解釋所複雜化,其中在BRE中不存在的ERE元字符可以被反斜槓以獲得ERE含義(所以'\ +'在大多數版本的'sed中表示一個文字'+' ',但是在GNU'sed'中,它意味着它之前的一個或多個)。不幸的是,正則表達式是隱藏地雷的噩夢,並且在可預見的未來仍然如此;你別無選擇,只能確切知道程序使用哪種正則表達式引擎,以及引擎的怪癖是什麼。 – geekosaur
的sed
命令不理解+
所以你必須手工將其展開:
sed 's/\.\.*/_/'
或者告訴sed
要使用擴展的正則表達式:
sed -r 's/\.+/_/' # GNU
sed -E 's/\.+/_/' # OSX
哪個開關,-r
或-E
,取決於您的sed
,它可能甚至不支持擴展正則表達式,因此便攜式解決方案將使用\.\.*
代替\.+
。但是,因爲你在Linux上,你應該有GNU sed
,所以sed -r
應該做的伎倆。
預感:嘗試'的/\.\.*/ _ /''。你的sed可能無法正確處理'+'。 – Beta
@Beta:嗨,我想知道爲什麼'sed's /\.*/_/''不會工作。謝謝。 – DocWiki
因爲'\。*'會匹配任意數量的點,包括零,例如「A_Google ..」開頭的無點。 – Beta