为什么 bash 脚本中的命令 echo `echo \\\\\\\z` 打印 \\z 而不是 \\\z?

为什么 bash 脚本中的命令 echo `echo \\\\\\\z` 打印 \\z 而不是 \\\z?

命令

echo `echo \\\\\\\z`

来自这本书,我不明白为什么它会打印

\\z

当它通过 bash 脚本执行时。

我认为应该打印

\\\z

答案1

反引号有效地为您提供了对反斜杠的双重处理。 (一次是在处理主命令行时,另一次是在命令替换中的命令时。)

就像 Kusalanda 所说,这对于$(..)命令替换来说是不同的。

首先,我们要注意的是,我们似乎正在讨论 Bash 的echo,默认情况下它本身不处理反斜杠转义,因此例如echo '\\'传递\\echowhich prints \\。如果您使用了echo处理反斜杠本身的 ,(例如带有shopt -s xpg_echo、 Dash 或 zsh 的 Bash ),您将得到最后一个\\变成\\z作为输出。


Bash 的手册说:

当使用旧式反引号形式的替换时,反斜杠保留其字面含义,除非后面跟着[美元符号、反引号或反斜杠]。

所以,在命令中

echo `echo \\\\\\\z`      # 7 backslashes

这些\\对首先被简化为单个\s,并且\z保持为\z(它后面没有三个中的任何一个,因此反斜杠是字面意思)。然后反引号中的命令再次运行 shell。

所以命令替换中的命令最终为

echo \\\\z                 # 4 backslashes

其中\\对被简化为单个\s,并且参数echo变为\\z(通过两个 s 打印不变echo,请参见上面的警告)。

您可以看到带有美元符号的类似结果,例如:

var=foo
echo `echo \$var`

印刷foo

POSIX 还有一个奇怪的单引号示例:

echo `echo '\$x'`

印刷$x。 (单引号不保护$


命令替换的形式$(...)更明智,其内容仅被处理一次,因此:

echo $(echo \\\\\\\z)           # 7 backslashes

打印\\\z(3),以及

var=foo
echo $(echo \$var)

印刷$var

另请参阅:

答案2

初始 echo 命令由 shell 处理,因此它可以正确地看到倍数\并将其减少为echo \\\z.

此时,shell就不再涉及了。

echo 命令然后会看到\\\,因此它会将其简化为单个\,即您需要一个文字\

没有必要逃避最后\,这样就可以减少到\\\z

相关内容