堆栈溢出回答拥有 > 3.5K 票的人使用此单行代码来分配DIR
当前 bash 脚本的目录:
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
我对嵌套的双引号感到困惑。据我所知,以下片段是用双引号引起来的:
"$( cd "
"${BASH_SOURCE[0]}"
" && pwd )"
=
... (即$( dirname
和)右侧的所有其他内容)
均未加引号。换句话说,我假设第二个、第四个和第六个"
字符分别“关闭”第一个、第三个和第五个"
字符。
我明白双引号的作用是什么"${BASH_SOURCE[0]}"
,但是另外两对双引号的目的是什么?
另一方面,如果(尽管得票率很高)上述代码片段不正确,那么实现其名义意图的正确方法是什么?
(经过名义意图pwd
我的意思是:收集第一个-ing返回的值到cd
返回的目录dirname "${BASH_SOURCE[0]}"
,并在子 shell 中执行 -ing cd
,这样$PWD
父 shell 的 保持不变)。
答案1
一旦进入$(...)
,引用就从头开始。
换句话说,"..."
并且$(...)
可以巢彼此之内。命令替换, $(...)
, 可以包含一个或多个完全的双引号字符串。另外,双引号字符串可以包含一个或多个完全的命令替换。 但是,它们并不交织。 因此,在命令替换内部开始的双引号字符串永远不会扩展到命令替换之外,反之亦然。
所以,考虑:
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]}" )
是用双引号引起来的。$(...)
当考虑内部的内容时,外部外部的引号这一事实是无关紧要的。事实上,内部有引号$(...)
也是无关紧要的。
答案2
bash
您的困惑与如何(以及一般的 shell)解析输入的问题不正确。在:
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 规范的令牌识别部分。