转义字符串以获取sed替换模式

时间:2009-01-02 17:44:16

标签: string sed escaping

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

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

如何逃避$REPLACE字符串,以便sed作为文字替代品安全地接受它?

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

15 个答案:

答案 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