2014-02-11 37 views
1

我想在下面的上下的方式來使用SED任意變量:的sed與可能包含斜線

VAR=`echo $STRING | sed s/$TOKEN/$REPLACEMENT/` 

不幸的是,我已經臨到其中$更換有可能會包含斜線的情況下。這將導致bash的抱怨,因爲它(殼)可能會擴展爲這樣的事情:

#given $VAR=I like bananas, $TOKEN=bananas, and $REPLACEMENT=apples/oranges 
VAR=`echo I like bananas | sed s/bananas/apples/oranges/` 

所以,現在的sed被賦予了太多的/的無效參數。有沒有什麼好的方法來處理?

+0

,就應該替換舊的和過時的背抽動帶括號'$(...)'例如:'VAR = $(回聲$ STRING | sed s/$ TOKEN/$ REPLACEMENT /)' – Jotne

+0

可能重複的[sed命令:如何使用變量](http://stackoverflow.com/questions/19151954/sed-command-how-to-use-變量) – devnull

+0

比這更糟糕。如果$ TOKEN包含RE元字符('.','*'等),那麼sed也會評估這些元字符。那是你要的嗎? –

回答

3

你可以使用任何你喜歡的分隔符。 "s!$TOKEN!$REPLACEMENT!""s%$TOKEN%$REPLACEMENT%"是流行的替代品。

當然,在一般情況下,如果輸入可能包含任何字符,則可以回到原來的一個。您可以切換到一種不會混淆代碼和數據的語言,這實際上就是shell本身;

echo "${VAR/$TOKEN/$REPLACEMENT}" 

(。這是一個bash的擴展,雖然這是在其他一些炮彈可用,但不是在經典的Bourne shell)

+0

另一個不錯的選擇是不可打印的ascii控制字符,這些字符特別不會出現在字符串中:'printf -v foo's \ x01's \ x01%s \ x01'「searchstring」「replacsestring」;回聲「$字符串」| sed -e「$ foo」' –

+1

@thatotherguy有趣的想法,但我很猶豫建議,因爲它必然會在各種各樣的'sed'實現中斷裂。 – tripleee

+0

我對此表示懷疑。這將違反POSIX,並且在C中執行起來會比簡單地執行起來更困難。 –

0

你不能可靠地使用的sed此爲:

  1. 你通常找不到這是保證不被 在任何$令牌或$替換字符串的字符,
  2. 的sed不能搜索字符串 - 它始終搜索正則表達式和 所以$ TOKEN中的任何RE元字符都將被評估爲這樣,並且您的 無法可靠地實現代碼以逃避它們(儘管有許多 人嘗試過)。

所以,僅僅用awk:

VAR=$(echo "$STRING" | awk -v t="$TOKEN" -v r="$REPLACEMENT" 'idx=index($0,t) {$0 = substr($0,1,idx-1) r substr($0,idx+length(t))} 1') 

將爲絕對在任何3串除了在$ STRING換行符任何字符工作。

沒有echo將在$ STRING過處理換行符:

VAR=$(awk -v s="$STRING" -v t="$TOKEN" -v r="$REPLACEMENT" ' 
BEGIN { 
    if (idx = index(s,t)) 
     s = substr(s,1,idx-1) r substr(s,idx+length(t)) 
    print s 
}')