Lar*_*rry 5 unix linux bash shell command-substitution
更准确地说,为什么
"`command "$variable"`"
Run Code Online (Sandbox Code Playgroud)
将外部引号视为包含内部引号,而不是将变量扩展到任何引号之外?
我用来测试的确切命令类似于另一个 stackoverflow 问题中关于使用命令替换时正确引用方法的示例:
fileName="some path with/spaces"
echo "`dirname "$fileName"`"
Run Code Online (Sandbox Code Playgroud)
它正确地回应了“some path with”,而不是因为参数数量无效而抱怨。
我阅读了 Bash 的手册页,它在“扩展”一章的“命令替换”部分中指出,新样式的 $() 替换保留了括号之间任何字符的含义,但是,关于反引号,它只提到反斜杠起作用以有限的方式:
当使用旧式反引号替换形式时,反斜杠保留其字面意义,除非后跟
$,`, 或\。前面没有反斜杠的第一个反引号终止命令替换。
我的第一个想法是反引号做同样的事情,除了提到的例外,因此“引用”内部双引号,但是,我被告知事实并非如此。将我指向这个方向的第二个观察是
a=\$b
b=hello
echo `echo $a`
Run Code Online (Sandbox Code Playgroud)
打印“$b”。如果反引号让美元符号被解释,那么第一个变量替换应该在调用子shell之前发生,子shell扩展字符串“$b”,产生“hello”。根据手册页的上述摘录,我什至可以确保美元符号确实被引用,通过使用
echo `echo \$a`
Run Code Online (Sandbox Code Playgroud)
结果还是一样。
不过,第三个观察结果让我有些怀疑:
echo `echo \\a`
Run Code Online (Sandbox Code Playgroud)
结果:“\a”
echo \a
Run Code Online (Sandbox Code Playgroud)
结果:一个
在这里,似乎两个反斜杠都被保留了,直到子外壳发挥作用,即使手册页指出反引号中的反斜杠在后面跟另一个反斜杠时没有其字面意义。编辑:^ 在这方面,一切都按预期工作,我一定使用了错误的 shell(在我的另一个终端中使用了 tcsh,并且字符与“a”不同)。
虽然我无法找出实际发生的情况,但在我寻找答案时,我遇到了一些人提到了有关命令替换的术语“引用上下文”,但没有对其含义或位置进行任何解释它被描述。我在 Bash 参考资料(gnu.org、tldp、man bash)或通过 DuckDuckGo 中都没有找到任何对“引用上下文”的真正参考。
除了了解正在发生的事情之外,我更希望获得一些关于如何从中辨别这种行为的参考或指导,因为我认为我可能没有将一些自然产生的部分放在一起。否则我会忘记答案。
对于那些建议人们使用新式美元符号和括号替换的人:在大约。具有数十或数百种不同专有环境的 50 年老 Unix 机器(不能为更新的环境扔掉外壳),当必须编写在任何人可能使用的大多数外壳之间兼容的脚本时,这不是一种选择。
感谢任何可以帮助我的人。
POSIX在 2.2.3 中有这样的说法(强调我的):
`(反引号)
反引号应保留其特殊含义,引入其他形式的命令替换(请参阅命令替换)。从初始反引号到下一个反引号之前的字符(前面没有 <反斜杠>)的带引号字符串部分(已删除转义字符)定义了当单词是时其输出替换“`...`”的命令。扩大了。以下任一情况都会产生未定义的结果:
在“`...`”序列中开始但不结束的单引号或双引号字符串
在同一个双引号字符串中开始但不结束的“`...`”序列
对我来说,这几乎定义了其他人可能(非正式地?)所谓的引用上下文,其中包含两个连续反引号内的所有内容。
从某种意义上来说,反引号是除了单引号、双引号和反斜杠之外的第四种引号。请注意,在双引号内,单引号也会失去其引用功能,因此反引号改变其中双引号的功能也就不足为奇了。
我用其他 shell 尝试了您的示例,例如 FreeBSD 和 zsh 上的 Almquist shell。正如预期的那样,他们输出了some path with.