嵌套的双引号在投票很高的单行代码中


20

一个具有> 3.5K票数的StackOverflow 答案具有此一类功能,可用于分配给DIR当前bash脚本的目录:

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

我对嵌套的双引号感到困惑。据我所知,以下片段被双引号括起来:

"$( cd "
"${BASH_SOURCE[0]}"
" && pwd )"

...,而=()$( dirname和())右边的其他所有内容均未引用。换句话说,我假设第二,第四和第六个"字符分别“关闭”了第一,第三和第五个"字符。

我知道"${BASH_SOURCE[0]}"实现了双引号,但是其他两对双引号的目的是什么?

另一方面,(尽管获得较高的投票分数)上述片段不正确,那么实现其名义意图的正确方法是什么?

(按名义意图,我的意思是:将pwd第一个cd-ing 之后的返回值收集到由返回的目录中dirname "${BASH_SOURCE[0]}",并cd在子外壳中执行-ing,以便$PWD父外壳的保持不变。)


1
这是因为$(...)的功能:$( here, it's a subshell, but you are writing code as if you were writing it on the "first level" of the shell .... )
奥利维尔·杜拉克

我是因为docker安装脚本来到这里的。要查找发行版的名称:lsb_dist="$(. /etc/os-release && echo "$ID")"; echo "$lsb_dist"
David Tonhofer,

请注意,行中不需要空格:DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"也可以使用。
David Tonhofer,

Answers:


12

您的难题与如何bash(通常是外壳)解析输入不正确。在:

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

首先,bash将赋值的右侧解析为一个长字符串,$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )因为双引号可以出现在双引号内

然后,bash开始解析命令替换。因为在开括号后到括号后的所有字符都用于在命令替换内构造命令,所以您将获得:

cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd

Shell继续解析该复合命令,将其分为两部分:

  • cd "$( dirname "${BASH_SOURCE[0]}" )"
  • 密码

然后对施加相同的解析规则cd "$( dirname "${BASH_SOURCE[0]}" )",但是这次双引号不是多余的,而是有意义的。它们防止在的结果上发生字段分裂$( dirname "${BASH_SOURCE[0]}" ),并且防止的扩展${BASH_SOURCE[0]}(与最外面的双引号相反,在变量分配的RHS中为防止split+glob没有必要)。


此规则适用于所有POSIX shell中的命令替换。您可以在POSIX规范的“令牌识别”部分中阅读更多详细的难题。


21

一旦进入内部$(...),报价便从头开始。

换句话说,"..."$(...)内彼此。进程替换$(...)可以包含一个或多个完整的双引号字符串。另外,双引号字符串可能包含一个或多个完整的字符串过程替换。 但是,它们不会交错。 因此,在流程替换内部开始的双引号字符串永远不会在其外部扩展,反之亦然。

因此,请考虑:

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

内部的$(...)是:

dirname "${BASH_SOURCE[0]}"

以上${BASH_SOURCE[0]}是双引号。引号之外的任何双引号或单引号$(...)确定均无关紧要${BASH_SOURCE[0]}

外部$(...)包含:

cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd

在此,表达式用$( dirname "${BASH_SOURCE[0]}" )双引号引起来。外部有引号的事实$(...)考虑内部的内容时是无关紧要的。内层内部有引号的事实$(...)也无关紧要。

这是双引号匹配的方式:

在此处输入图片说明


你是什么意思irrelevant?除了最外面的括号外,所有其他括号都有其自身的含义。
cuonglm '16

4
并且,这就是为什么您不应该使用反引号的原因:引用规则极其怪异且不直观。
通配符

句子“ $(...)比……更紧"..."”没有任何意义。它们不是中缀运算符,并且它们之间没有层次结构(如果存在,则意味着引号不能在括号内,或者括号不能在引号内,但事实并非如此)。技术术语是那$(…)"…"巢。
吉尔斯(Gillles)“所以-别再邪恶了”

@吉尔斯很好。我只是重新措辞,希望能更好地抓住这个概念。
John1024 '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.