kjo*_*kjo 35 shell bash quoting command-substitution
超过 3.5K 票的StackOverflow答案具有用于分配给DIR当前 bash 脚本目录的单行:
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
Run Code Online (Sandbox Code Playgroud)
我对嵌套的双引号感到困惑。据我所知,以下片段是双引号的:
"$( cd "
"${BASH_SOURCE[0]}"
" && pwd )"
Run Code Online (Sandbox Code Playgroud)
...以及=(即$( dirname和))右侧的所有其他内容均未加引号。换句话说,我假设第 2、第 4 和第 6 个"字符分别“关闭”第 1、第 3 和第 5 个"字符。
我明白双引号的作用"${BASH_SOURCE[0]}",但是另外两对双引号的目的是什么?
另一方面(尽管投票得分很高),如果上面的片段不正确,那么实现其名义意图的正确方法是什么?
(名义意图我的意思是:将pwdfirst cd-ing后返回的值收集到 返回的目录中dirname "${BASH_SOURCE[0]}",并cd在子 shell 中执行-ing,以便$PWD父 shell 的 保持不变)。
Joh*_*024 29
一旦进入$(...),引用从头开始。
换句话说,"..."和$(...)罐巢内彼此。命令替换 ,$(...)可以包含一个或多个完整的双引号字符串。此外,双引号字符串可能包含一个或多个完整的命令替换。 但是,它们不交错。 因此,在命令替换内开始的双引号字符串永远不会扩展到它之外,反之亦然。
因此,请考虑:
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
Run Code Online (Sandbox Code Playgroud)
内部$(...)是:
dirname "${BASH_SOURCE[0]}"
Run Code Online (Sandbox Code Playgroud)
上面${BASH_SOURCE[0]}是双引号。$(...)在确定${BASH_SOURCE[0]}双引号时,除 之外的任何双引号或单引号都无关紧要。
外层$(...)包含:
cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd
Run Code Online (Sandbox Code Playgroud)
这里,表达式$( dirname "${BASH_SOURCE[0]}" )是双引号的。$(...)在考虑内部内容时,外部外部有引号这一事实无关紧要。内部有引号的事实$(...)也无关紧要。
cuo*_*glm 17
你的谜题是关于如何bash(以及一般的外壳)解析输入的。在:
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
Run Code Online (Sandbox Code Playgroud)
首先,bash将赋值的右侧解析为一个长字符串,$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )因为双引号可以出现在双引号内。
之后,bash开始解析命令替换。因为在左括号后面的所有字符都用于在命令替换中构造命令,您将得到:
cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd
Run Code Online (Sandbox Code Playgroud)
shell 继续解析该复合命令,将其分为两部分:
cd "$( dirname "${BASH_SOURCE[0]}" )"然后对 应用相同的解析规则cd "$( dirname "${BASH_SOURCE[0]}" )",但这一次,双引号不是多余的,而是有意义的。它们可以防止 的结果上的字段拆分$( dirname "${BASH_SOURCE[0]}" ),以及 的扩展${BASH_SOURCE[0]}(与最外面的双引号相比,在变量赋值的 RHS 中不需要防止split+glob)。
此规则适用于所有 POSIX shell 中的命令替换。您可以在POSIX 规范的 Token Recognition 部分阅读更多细节难题。