2014-02-11 36 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 
}')