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

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

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

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


当前回答

不要忘记所有的快乐发生在壳的限制'和'

所以(ksh)

Var=">New version of \"content' here <"
printf "%s" "${Var}" | sed "s/[&\/\\\\*\\"']/\\&/g' | read -r EscVar

echo "Here is your \"text\" to change" | sed "s/text/${EscVar}/g"

其他回答

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

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

sed命令允许你使用其他字符代替/作为分隔符:

sed 's#"http://www\.fubar\.com"#URL_FUBAR#g'

双引号不是问题。

使用awk -它更干净:

$ awk -v R='//addr:\\file' '{ sub("THIS", R, $0); print $0 }' <<< "http://file:\_THIS_/path/to/a/file\\is\\\a\\ nightmare"
http://file:\_//addr:\file_/path/to/a/file\\is\\\a\\ nightmare

现在回复有点晚了……但有一种更简单的方法。只需更改分隔符(即分隔字段的字符)。所以不是s/foo/bar/而是s|bar|foo。

这里有一个简单的方法:

sed 's|/\*!50017 DEFINER=`snafu`@`localhost`\*/||g'

结果输出没有那个讨厌的DEFINER子句。

我有一个改进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中的制表符。