我想编写一个脚本“test.sh”,它将接受用户的输入并用“\”+字符替换所有特殊字符。我的脚本:
#!/bin/bash
echo 'input='"$1"
arg=`echo "$1" | sed 's:[]\[\^\$\.\*\/]:\\&:g'`
echo 'modified input='"$arg"
我的命令适用于字符串“xy”,它没有任何特殊字符。我在终端中运行此命令:
test.sh xy
我得到:
input=xy
modified input=xy
但是,当我运行这个时:
test.sh x.y
我得到:
input=x.y
modified input=x&y
我不明白为什么这个脚本不起作用。我期望得到:
input=x.y
modified input=x\.y
我认为问题出在这个 sed 命令上,但我不确定在哪里:
sed 's:[]\[\^\$\.\*\/]:\\&:g'
答案1
我认为你没有正确捕获该组。尝试这个?
sed 's:\([]\[\^\$\.\*\/]\):\\\1:g'
编辑:没关系,我不知道 & 的相关性。问题是由于解析并传递到子 shell,您需要额外转义替换中的斜杠。
sed 's:[]\[\^\$\.\*\/]:\\\\&:g'
另外,如果您使用 $(command) 而不是反引号,则不需要额外的 \'s
答案2
因此,任务是编写一个替换,以转义字符串中的sed
所有特殊字符(定义为字符[]^$.*/
,我也添加了)。\
替换可能看起来像
s/[][\^$.*/]/\\&/g
请注意,我们实际上不必转义[...]
集合中的任何字符(\
也按字面意思处理,因此我们不能逃脱那里的任何东西),而我们唯一要确保的是,这]
是在它的一开始。
所以脚本(重写为 shell 函数,并以其他方式修改)变成
function escape
{
printf '%s\n' "$1" | sed 's/[][\^$.*/]/\\&/g'
}
测试:
$ escape 'hello world'
hello world
$ escape '*.*'
\*\.\*
$ escape '\/'
\\\/
$ escape '/\'
\/\\
$ escape 's/[][\^$.*/]/\\&/g'
s\/\[\]\[\\\^\$\.\*\/\]\/\\\\&\/g