在我的bash脚本中,我有一个外部(从用户那里收到的)字符串,我应该在sed模式中使用它。
REPLACE="<funny characters here>"
sed "s/KEYWORD/$REPLACE/g"
我如何转义$REPLACE
字符串,以便将其安全地接受sed
为文字替换?
注:本KEYWORD
是一个愚蠢的字符串没有匹配等,这是不是由用户提供。
警告:这并没有考虑换行。有关更深入的答案,请参阅此SO问题。(感谢Ed Morton和Niklas Peter)
请注意,转义所有内容不是一个好主意。Sed需要转义许多字符才能获得其特殊含义。例如,如果你在替换字符串中转义了一个数字,它将变成反向引用。
正如本·布兰克(Ben Blank)所说,替换字符串中只需要转义三个字符(转义自身,语句末尾用正斜杠和&替换所有字符):
ESCAPED_REPLACE=$(printf '%s\n' "$REPLACE" | sed -e 's/[\/&]/\\&/g')
# Now you can use ESCAPED_REPLACE in the original sed statement
sed "s/KEYWORD/$ESCAPED_REPLACE/g"
如果你需要转义KEYWORD
字符串,则需要以下内容:
sed -e 's/[]\/$*.^[]/\\&/g'
可以由以下人员使用:
KEYWORD="The Keyword You Need";
ESCAPED_KEYWORD=$(printf '%s\n' "$KEYWORD" | sed -e 's/[]\/$*.^[]/\\&/g');
# Now you can use it inside the original sed statement to replace text
sed "s/$ESCAPED_KEYWORD/$ESCAPED_REPLACE/g"
请记住,如果你使用的字符不是/
定界符,则需要在上面的表达式中替换斜杠以及正在使用的字符。请参阅PeterJCLaw的注释以获取解释。
编辑:由于以前没有考虑某些极端情况,因此上面的命令已更改了几次。查看编辑历史记录以了解详细信息。
值得注意的是,通过不将正斜杠用作分隔符,可以避免不得不转义正斜杠。sed的大多数(全部?)版本都允许您使用任何字符,只要符合模式即可:$ echo'foo / bar'| sed s _ / _:_#foo:bar
sed -e's /(\ / \ | \\\ | &&)/ \\&// g'在OSX上对我不起作用,但这样做:sed's /([\\\ /&])/ \\&/ g',它略短一些。
对于搜索模式
KEYWORD
,在GNU sed中,这里还有两个chars^
,$
上面没有提到:s/[]\/$*.^|[]/\\&/g
@Jesse:固定。实际上,这就是我在第一段中警告的错误。我想我没有练习我的讲道。
@NeronLeVelu:我不确定我是什么意思,但是“在管道或变量中没有特殊含义。它在运行结果之前由外壳程序进行解析,因此变量内的双引号是安全的。例如,尝试
A='foo"bar' echo $A | sed s/$A/baz/
在bash。双引号就像在它周围的'foo'和'bar'一样。