在 bash 脚本中使用反引号进行命令替换的奇怪输出

Chr*_*ski 2 shell bash quoting command-substitution

echo "testing:"
PROXY_URL="/proxyurl/"
proxyUrlSedEscaped=`echo "$PROXY_URL" | sed -e 's/[\/&]/\\&/g'`
echo                     "$PROXY_URL" | sed -e 's/[\/&]/\\&/g'
echo "$proxyUrlSedEscaped"

echo "???"
Run Code Online (Sandbox Code Playgroud)

上面有以下输出:

testing:
\/proxyurl\/
&proxyurl&
???
Run Code Online (Sandbox Code Playgroud)

为什么最后的回声输出与之前的回声输出不同?

此命令通过命令行正常工作: PROXY_URL="/proxyurl/"; echo "$PROXY_URL" | sed -e 's/[\/&]/\\&/g',输出:\/proxyurl\/

Mic*_*mer 5

根据 Bash 手册以及 POSIX):

当使用旧式反引号替换形式时,反斜杠保留其字面含义,除非后跟$, `, 或\

这意味着`echo "$PROXY_URL" | sed -e 's/[\/&]/\\&/g'`导致sed执行的命令为sed -e 's/[\/&]/\&/g',因为双反斜杠已转义为单个反斜杠。\&然后&在 sed 中生成文字。

您可以使用$(...)-style 命令替换来避免这种情况:

proxyUrlSedEscaped=$(echo "$PROXY_URL" | sed -e 's/[\/&]/\\&/g')
Run Code Online (Sandbox Code Playgroud)

新式替换允许任何具有其通常解释的命令。

如果您必须使用,`那么相当怪异的双重转义也适用:

proxyUrlSedEscaped=`echo "$PROXY_URL" | sed -e 's/[\/&]/\\\\&/g'`
Run Code Online (Sandbox Code Playgroud)

,轮流\\\\\\,其中的sed则变成\你。