在我的bash脚本中,我有一个外部(从用户接收)字符串,我应该在sed模式中使用。

REPLACE="<funny characters here>"
sed "s/KEYWORD/$REPLACE/g"

我如何转义$REPLACE字符串,以便它被sed安全地接受为文字替换?

注意:KEYWORD是一个哑子字符串,没有匹配等。不是用户提供的。


当前回答

我有一个改进sedeasy功能,这将打破特殊字符,如制表符。

function sedeasy_improved {
    sed -i "s/$(
        echo "$1" | sed -e 's/\([[\/.*]\|\]\)/\\&/g' 
            | sed -e 's:\t:\\t:g'
    )/$(
        echo "$2" | sed -e 's/[\/&]/\\&/g' 
            | sed -e 's:\t:\\t:g'
    )/g" "$3"
}

那么,有什么不同呢?$1和$2用引号括起来,以避免shell展开并保留制表符或双空格。

附加管道| sed -e 's:\t:\\t:g'(我喜欢:as令牌)转换\t中的制表符。

其他回答

更简单的方法是预先构建字符串,并将其用作sed的参数

rpstring="s/KEYWORD/$REPLACE/g"
sed -i $rpstring  test.txt

下面是我之前用过的一个AWK的例子。它是一个AWK,打印新的AWKS。AWK和SED相似,可能是一个很好的模板。

ls | awk '{ print "awk " "'"'"'"  " {print $1,$2,$3} " "'"'"'"  " " $1 ".old_ext > " $1 ".new_ext"  }' > for_the_birds

这看起来有点过分,但不知何故,引号的组合可以保持“打印为字面量”。然后,如果我没记错的话,变量只是用引号括起来:“$1”。试试吧,让我知道它对SED的效果如何。

基于钢琴龙的正则表达式,我做了一个bash函数,逃脱关键字和替换。

function sedeasy {
  sed -i "s/$(echo $1 | sed -e 's/\([[\/.*]\|\]\)/\\&/g')/$(echo $2 | sed -e 's/[\/&]/\\&/g')/g" $3
}

下面是如何使用它:

sedeasy "include /etc/nginx/conf.d/*" "include /apps/*/conf/nginx.conf" /etc/nginx/nginx.conf

我有一个改进sedeasy功能,这将打破特殊字符,如制表符。

function sedeasy_improved {
    sed -i "s/$(
        echo "$1" | sed -e 's/\([[\/.*]\|\]\)/\\&/g' 
            | sed -e 's:\t:\\t:g'
    )/$(
        echo "$2" | sed -e 's/[\/&]/\\&/g' 
            | sed -e 's:\t:\\t:g'
    )/g" "$3"
}

那么,有什么不同呢?$1和$2用引号括起来,以避免shell展开并保留制表符或双空格。

附加管道| sed -e 's:\t:\\t:g'(我喜欢:as令牌)转换\t中的制表符。

如果您只是想替换sed命令中的变量值,那么只需删除 例子:

sed -i 's/dev-/dev-$ENV/g' test to sed -i s/dev-/dev-$ENV/g test