在我的bash脚本中,我有一个外部(从用户接收)字符串,我应该在sed模式中使用。
REPLACE="<funny characters here>"
sed "s/KEYWORD/$REPLACE/g"
如何逃避$REPLACE
字符串,以便sed
作为文字替代品安全地接受它?
注意: KEYWORD
是一个没有匹配等的哑子字符串。它不是由用户提供的。
答案 0 :(得分:238)
答案 1 :(得分:78)
sed命令允许您使用其他字符而不是/
作为分隔符:
sed 's#"http://www\.fubar\.com"#URL_FUBAR#g'
双引号不是问题。
答案 2 :(得分:41)
在replace子句中专门处理的唯一三个文字字符是/
(关闭子句),\
(以转义字符,反向引用和&amp; c。)和{{ 1}}(在替换中包含匹配)。因此,您需要做的就是逃避这三个字符:
&
示例:
sed "s/KEYWORD/$(echo $REPLACE | sed -e 's/\\/\\\\/g; s/\//\\\//g; s/&/\\\&/g')/g"
答案 3 :(得分:31)
基于Pianosaurus的正则表达式,我创建了一个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
答案 4 :(得分:16)
回复有点迟了......但是有一个更简单的方法可以做到这一点。只需更改分隔符(即分隔字段的字符)。因此,您需要s/foo/bar/
而不是s|bar|foo
。
而且,这是简单的方法:
sed 's|/\*!50017 DEFINER=`snafu`@`localhost`\*/||g'
结果输出没有那个令人讨厌的DEFINER子句。
答案 5 :(得分:11)
事实证明你提出了错误的问题。我也问了一个错误的问题。错误的原因是第一句话的开头:&#34;在我的 bash 脚本中......&#34;。
我有同样的问题&amp;犯了同样的错误。如果您正在使用bash,则不需要使用sed来执行字符串替换(并且它的很多清除程序来使用bash中内置的替换功能)。< / p>
而不是像,例如:
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"}"
答案 6 :(得分:1)
使用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
答案 7 :(得分:0)
这是我前一段时间使用的AWK示例。这是一款打印新AWKS的AWK。 AWK和SED相似,可能是一个很好的模板。
ls | awk '{ print "awk " "'"'"'" " {print $1,$2,$3} " "'"'"'" " " $1 ".old_ext > " $1 ".new_ext" }' > for_the_birds
看起来过分,但不知何故,引号的组合可以保持'打印为文字。然后,如果我没记错的话,vaiables就会被这样的引号所包围:“$ 1”。试试吧,让我知道它如何与SED一起使用。
答案 8 :(得分:0)
我对sedeasy功能有了改进,它会突破像tab这样的特殊字符。
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'
(我喜欢:
作为令牌),它会转换\t
中的标签。
答案 9 :(得分:0)
echo '1.2+3*[4]|5' | sed -r 's#([().+$*\[\]|])#\\&#g;s#\|#\\|#g'
答案 10 :(得分:-1)
不要忘记围绕“和'
的shell限制所带来的所有乐趣所以(在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"
答案 11 :(得分:-1)
如果情况恰好是您生成随机密码以传递给sed
替换模式,那么您选择要小心随机字符串中的哪组字符。如果您选择通过将值编码为base64而生成的密码,则只有在base64中可能存在的字符,并且在sed
替换模式中也是一个特殊字符。该字符为“/”,可以从您生成的密码中轻松删除:
# password 32 characters log, minus any copies of the "/" character.
pass=`openssl rand -base64 32 | sed -e 's/\///g'`;
答案 12 :(得分:-1)
如果您只是想在sed命令中替换Variable值,那么只需删除即可 例如:
sed -i 's/dev-/dev-$ENV/g' test to sed -i s/dev-/dev-$ENV/g test
答案 13 :(得分:-1)
这些是我发现的转义代码:
* = \x2a
( = \x28
) = \x29
" = \x22
/ = \x2f
\ = \x5c
' = \x27
? = \x3f
% = \x25
^ = \x5e
答案 14 :(得分:-3)
更简单的方法是手工构建字符串并将其用作sed
的参数
rpstring="s/KEYWORD/$REPLACE/g"
sed -i $rpstring test.txt