5

更准确地说,为什么

"`command "$variable"`"

将外部引号视为包含内部引号,而不是将变量扩展到任何引号之外?

我用来测试这个的确切命令类似于另一个 stackoverflow 问题中提出的关于使用命令替换时正确引用方法的示例:

fileName="some path with/spaces"
echo "`dirname "$fileName"`"

它正确地呼应了“some path with”,而不是因为参数数量无效而抱怨。

我阅读了 Bash 的手册页,其中在“扩展”一章的“命令替换”部分中指出,新型 $() 替换保留了括号之间任何字符的含义,但是,关于反引号,它只提到反斜杠有效以有限的方式:

当使用旧式反引号形式的替换时,反斜杠保留其字面含义,除非后面跟着$,`\。前面没有反斜杠的第一个反引号终止命令替换。

我的第一个想法是反引号也一样,除了提到的例外,因此“引用”内部双引号,但是,我被告知事实并非如此。指出我这个方向的第二个观察是

a=\$b
b=hello
echo `echo $a`

打印“$b”。如果反引号让美元符号得到解释,那么第一个变量替换应该在调用子shell之前发生,子shell扩展字符串“$b”,结果是“hello”。根据手册页的上述摘录,我什至可以通过使用确保美元符号实际被引用

echo `echo \$a`

结果仍然是一样的。

第三个观察结果让我有些怀疑:

echo `echo \\a`

结果:“\a”

echo \a

结果:一个

在这里,似乎两个反斜杠都被保留了,直到 subshel​​l 发挥作用,即使手册页指出反引号中的反斜杠在后面跟着另一个反斜杠时没有其字面意义。编辑: ^ 在这方面一切都按预期工作,我一定使用了错误的 shell(我的另一个终端中的 tcsh,并且字符与“a”不同)。

虽然我无法找出实际发生的情况,但在我寻找答案时,我遇到一些人提到关于命令替换的术语“引用上下文”,但没有任何解释它的含义或位置它被描述。我在 Bash 引用(gnu.org、tldp、man bash)或通过 DuckDuckGo 中都没有找到对“引用上下文”的任何真正引用。

除了了解正在发生的事情之外,我更希望获得一些关于如何从中辨别这种行为的参考或指导,因为我认为我可能未能将一些部分放在一起,而这些部分是自然产生的。否则我会忘记答案。

对于那些建议人们使用新式美元符号和括号替换的人:在 ca。具有数十或数百种不同专有环境的 50 年历史的 Unix 机器(不能为更新的环境丢弃 shell),当必须编写与大多数人可能使用的 shell 兼容的脚本时,这不是一种选择。

感谢任何可以帮助我的人。

4

1 回答 1

3

POSIX在 2.2.3 中有这样的说法(强调我的):

`(反引号)

反引号应保留其特殊含义,引入其他形式的命令替换(请参阅命令替换)。从初始反引号和直到下一个反引号之前没有<反斜杠>的字符的引用字符串部分,已删除转义字符,定义了该命令,当单词是扩大。以下任何一种情况都会产生未定义的结果:

  • 在“`...`”序列中开始但不结束的单引号或双引号字符串

  • 在同一个双引号字符串中开始但不结束的“`...`”序列

对我来说,这几乎定义了其他人可能(非正式地?)称为引用上下文的内容,该上下文包含两个连续反引号中的所有内容。

在某种程度上,反引号是除了单引号、双引号和反斜杠之外的第四个引号。请注意,在双引号中,单引号也失去了引用功能,因此反引号会改变其中双引号的功能也就不足为奇了。

我用其他 shell 尝试了你的例子,比如 FreeBSD 和 zsh 上的 Almquist shell。正如预期的那样,他们输出some path with.

于 2018-07-12T19:24:37.733 回答