我试图了解 bash 中的 shell 扩展(GNU bash,版本 4.4.20(1)-release (i686-pc-linux-gnu))。
键入我的交互式 bash shell
x='$(id)'
$x
$(echo $x)
我期望从最后两行中的任何一行都会出现表单错误
bash: uid=xxx(user): command not found
但得到了
bash: $(id): command not found
.
我不明白为什么这里没有发生命令替换。不应该在变量扩展之后实现吗?我的猜测是它与此处描述的 Shell 操作有关https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Shell-Operation
有人可以解释这种行为吗?
我只是对更准确地理解 bash 扩展感兴趣。我对在我的问题中运行实际脚本不感兴趣。
$(…)
是命令替换(“进程替换”<(…)
等)。变量替换和命令替换发生在同一遍中,在字符串中从左到右。这些替换结果中唯一发生的事情是分词和通配符。所以
x='$(id)'
设置x
为 5-character string$(id)
。然后,为了运行$x
,shell 替换$x
为 value$(id)
。这不包含任何空格或通配符,因此它被视为命令名称。对比:
假设该文件
/none/id
不存在但/usr/bin/id
存在,该echo
命令将扩展为三个单词:(echo
显然),/none/@(id)
(glob 模式/none/@(id)
不匹配任何内容,因此保持不变)和/usr/bin/id
(glob 模式/usr/bin/@(id)
匹配一个文件,因此将其替换为匹配的单元素列表)。在 bash 手册中,相关语句位于Shell Expansions部分的开头。
两个分号之间的所有内容都是一次。每次传递都基于前一次传递的结果。
请注意,单个句子(即使是像我上面引用的那样复杂的句子)也无法讲述整个故事。Shell 语义很复杂。我怀疑任何外壳的手册都包含所有角落案例的详细信息。POSIX 规范更正式,但没有涵盖特定于 bash 的扩展,甚至还留下了一些未定义的非常奇怪的情况。
就是引用。单引号 (
'
) 定义文字字符串,不能发生插值或转义。双引号 ("
) 允许插值和转义。这是一个例子:
这是另一个基于单引号和双引号的插值和转义示例: