为什么反引号中的嵌套引号在bash中起作用?

时间:2017-12-13 22:53:58

标签: linux bash shell unix command-substitution

更确切地说,为什么

"`command "$variable"`"

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

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

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

通过"正确地回应"某些路径,而不是因为参数数量无效而抱怨。

我阅读了Bash的手册页,其中在章节" EXPANSION&#34 ;, section" Commmand Substitution"新式$()替换保留括号之间任何字符的含义,但是,关于反引号,它只提到反斜杠以有限的方式工作:

  

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

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

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

打印" $ b"。如果反引号让美元符号被解释,第一个变量替换应该在调用子shell之前发生,子shell扩展字符串" $ b",导致"你好。&#34 ; 根据手册页的上述摘录,我甚至可以确保使用

实际引用美元符号。
echo `echo \$a`

结果仍然相同。

第三次观察让我有些怀疑:

echo `echo \\a`

结果:" \ a"

echo \a

结果:a

这里似乎两个反斜杠都被保留,直到子shell发挥作用,即使手册页指出反引号中的反斜杠在后面跟着另一个反斜杠时没有字面含义。 编辑:^在这方面,一切都按预期工作,我必须使用错误的shell(在我的另一个终端中使用tcsh,并使用#34; a"中的不同字符)。

虽然我一直无法找到实际发生的事情,但在我寻找答案的过程中,我发现有些人提到了术语"引用语境"关于命令替换,但没有任何解释它的含义或描述的位置。 我没有找到任何真正的引用"引用上下文"在Bash引用(gnu.org,tldp,man bash)或通过DuckDuckGo。

除了知道发生了什么之外,我最好还是想对如何从中辨别出这种行为有一些参考或指导,因为我认为我可能没有将这些行为放在一起自然而然。否则,我只会忘记答案。

对那些建议人们使用新式美元符号和括号替换的人:在ca.具有数十或数百种不同专有环境的50年历史的Unix机器(不能为新的机器抛出一个shell),当必须编写任何人可能正在使用的大多数shell之间兼容的脚本时,它不是一个选项

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

1 个答案:

答案 0 :(得分:0)

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

  

`(反引号)

     

反引号应保留其特殊含义,引入另一种形式的命令替换(请参见命令替换)。 带引号的字符串的一部分,从最初的反引号开始,直到到下一个反引号为止的字符,都没有<反斜杠>,并且删除了转义字符,定义该命令,当扩展单词时,其输出将替换为“`...`”。以下两种情况中的任何一种都会产生不确定的结果:

     
      
  • 以单引号或双引号开头的字符串,但不以“ ......”序列结尾

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

  •   

在我看来,这几乎定义了其他人可能会(非正式地称呼)什么叫引用上下文,该上下文包含两个连续的反引号中的所有内容。

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

我尝试了其他shell的示例,例如FreeBSD和zsh上的Almquist shell。如预期的那样,它们输出some path with