在我的bash脚本中,我有一个外部(从用户那里收到的)字符串,我应该在sed模式中使用它。
REPLACE="<funny characters here>"
sed "s/KEYWORD/$REPLACE/g"
我如何转义$REPLACE
字符串,以便将其安全地接受sed
为文字替换?
注:本KEYWORD
是一个愚蠢的字符串没有匹配等,这是不是由用户提供。
outputvar="${inputvar//"$txt2replace"/"$txt2replacewith"}".
在我的bash脚本中,我有一个外部(从用户那里收到的)字符串,我应该在sed模式中使用它。
REPLACE="<funny characters here>"
sed "s/KEYWORD/$REPLACE/g"
我如何转义$REPLACE
字符串,以便将其安全地接受sed
为文字替换?
注:本KEYWORD
是一个愚蠢的字符串没有匹配等,这是不是由用户提供。
outputvar="${inputvar//"$txt2replace"/"$txt2replacewith"}".
Answers:
警告:这并没有考虑换行。有关更深入的答案,请参阅此SO问题。(感谢Ed Morton和Niklas Peter)
请注意,转义所有内容不是一个好主意。Sed需要转义许多字符才能获得其特殊含义。例如,如果您在替换字符串中转义了一个数字,它将变成反向引用。
正如本·布兰克(Ben Blank)所说,替换字符串中只需要转义三个字符(转义自身,语句末尾用正斜杠和&替换所有字符):
ESCAPED_REPLACE=$(echo $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=$(echo $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的注释以获取解释。
编辑:由于以前没有考虑某些极端情况,因此上面的命令已更改了几次。查看编辑历史记录以了解详细信息。
KEYWORD
,在GNU sed的,这里有2个字符^
,$
上面没有提到的:s/[]\/$*.^|[]/\\&/g
A='foo"bar' echo $A | sed s/$A/baz/
在bash。双引号就像在它周围的'foo'和'bar'一样对待
sed命令允许您使用其他字符代替/
分隔符:
sed 's#"http://www\.fubar\.com"#URL_FUBAR#g'
双引号不是问题。
.
,否则该转义具有特殊含义。我编辑了您的答案。
sed '/CLIENTSCRIPT="foo"/a CLIENTSCRIPT2="hello"' file
with sed '|CLIENTSCRIPT="foo"|a CLIENTSCRIPT2="hello"' file
和那不一样。
s
sed 的命令(如替换)允许您使用其他字符代替/作为分隔符。同样,这将是如何在带斜杠的URL上使用sed的答案。它没有回答OP问题,即如何转义用户输入的字符串,该字符串可以包含/,\,但是如果决定使用该字符串,还可以包含#。而且,URI也可以包含#
在replace子句中专门处理的仅有三个文字字符是/
(关闭子句),\
(转义字符,后向引用&c。)和&
(将匹配包括在替换中)。因此,您所需要做的就是逃避这三个字符:
sed "s/KEYWORD/$(echo $REPLACE | sed -e 's/\\/\\\\/g; s/\//\\\//g; s/&/\\\&/g')/g"
例:
$ export REPLACE="'\"|\\/><&!"
$ echo fooKEYWORDbar | sed "s/KEYWORD/$(echo $REPLACE | sed -e 's/\\/\\\\/g; s/\//\\\//g; s/&/\\\&/g')/g"
foo'"|\/><&!bar
基于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
man echo
),从而导致参数$1
以破折号开头时管道的行为异常。相反,您可以使用来启动管道printf '%s\n' "$1"
。
做出响应有点晚了...但是有一种更简单的方法可以执行此操作。只需更改定界符(即,分隔字段的字符)。所以,不是s/foo/bar/
你写s|bar|foo
。
而且,这是执行此操作的简单方法:
sed 's|/\*!50017 DEFINER=`snafu`@`localhost`\*/||g'
结果输出没有那个讨厌的DEFINER子句。
&
和``必须仍然转义,分隔符也必须转义,无论选择哪个。
$
在要更改的字符串中转义,并保持$
替换字符串中的含义。说我想更改$XXX
为variable的值$YYY
,sed -i "s|\$XXX|$YYY|g" file
效果很好。
原来你在问错问题。我也问错了问题。错误的原因是第一句话的开头:“在我的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"}"
$A
并且$B
未引用,但事实并非如此。内部${}
的引号与外部的引号不匹配。
var='has space'
),这OUTPUT=${INPUT//"$A"/"$B"}
是安全的。
使用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
awk
是它与几乎没有任何相似之处sed -i
,它在99%的时间内非常方便。
我对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'
(我喜欢:
作为令牌),用于转换中的标签页\t
。
不要忘记围绕“和”的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"
如果您只是想在sed命令中替换Variable value,那么只需删除Example:
sed -i 's/dev-/dev-$ENV/g' test to sed -i s/dev-/dev-$ENV/g test
一种更简单的方法是简单地事先构建字符串并将其用作参数 sed
rpstring="s/KEYWORD/$REPLACE/g"
sed -i $rpstring test.txt
REPLACE=/
了REPLACE: 提供sed: -e expression #1, char 12: unknown option to `s'