在我的bash脚本中,我有一个外部(从用户接收)字符串,我应该在sed模式中使用。
REPLACE="<funny characters here>"
sed "s/KEYWORD/$REPLACE/g"
我如何转义$REPLACE字符串,以便它被sed安全地接受为文字替换?
注意:KEYWORD是一个哑子字符串,没有匹配等。不是用户提供的。
在我的bash脚本中,我有一个外部(从用户接收)字符串,我应该在sed模式中使用。
REPLACE="<funny characters here>"
sed "s/KEYWORD/$REPLACE/g"
我如何转义$REPLACE字符串,以便它被sed安全地接受为文字替换?
注意:KEYWORD是一个哑子字符串,没有匹配等。不是用户提供的。
当前回答
看来你问错问题了。我也问错了问题。错误的原因是第一句话的开头:“在我的bash脚本中…”。
我也有同样的问题,犯了同样的错误。如果您正在使用bash,则不需要使用sed来进行字符串替换(使用bash中内置的替换特性要干净得多)。
而不是像这样,例如:
function escape-all-funny-characters() { UNKNOWN_CODE_THAT_ANSWERS_THE_QUESTION_YOU_ASKED; }
INPUT='some long string with KEYWORD that need replacing KEYWORD.'
A="$(escape-all-funny-characters 'KEYWORD')"
B="$(escape-all-funny-characters '<funny characters here>')"
OUTPUT="$(sed "s/$A/$B/g" <<<"$INPUT")"
你可以专门使用bash特性:
INPUT='some long string with KEYWORD that need replacing KEYWORD.'
A='KEYWORD'
B='<funny characters here>'
OUTPUT="${INPUT//"$A"/"$B"}"
其他回答
如果您正在生成一个随机密码以传递给sed替换模式,那么您应该注意随机字符串中的哪一组字符。如果您选择一个由base64编码的值组成的密码,那么在base64中只有一个字符是可能的,而且在sed replace模式中也是一个特殊字符。这个字符是“/”,很容易从你生成的密码中删除:
# password 32 characters log, minus any copies of the "/" character.
pass=`openssl rand -base64 32 | sed -e 's/\///g'`;
基于钢琴龙的正则表达式,我做了一个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
sed命令允许你使用其他字符代替/作为分隔符:
sed 's#"http://www\.fubar\.com"#URL_FUBAR#g'
双引号不是问题。
更简单的方法是预先构建字符串,并将其用作sed的参数
rpstring="s/KEYWORD/$REPLACE/g"
sed -i $rpstring test.txt
警告:不考虑换行。要获得更深入的答案,请参阅这个so问题。(谢谢Ed Morton和Niklas Peter)
请注意,逃避一切是一个坏主意。Sed需要对许多字符进行转义,以获得它们的特殊含义。例如,如果转义替换字符串中的一个数字,它将转换为反向引用。
正如Ben Blank所说,在替换字符串中只有三个字符需要转义(转义本身,正斜杠表示语句结束,&表示replace all):
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的评论以获得解释。
编辑:由于以前没有考虑到的一些极端情况,上面的命令已经更改了几次。详细信息请查看编辑历史记录。