为什么$bar
在这里作为文字打印,甚至认为外部子外壳应该根据bash命令行处理规则扩展其参数?
$ foo='$bar' bar=expanded
$ echo $(echo $(echo $foo))
$bar
内部子外壳会显示 $ bar ,但是为什么外部子外壳不会展开它? bash是否隐式地将其作为文字传递,如果是,为什么以及如何传递?据我所知,参数扩展发生在新进程内部子shell的每个分支之后。对于嵌套子外壳,命令替换是从内向外进行的,内部子外壳在派生发生并且命令行(字符串)被拆分,扩展之前,打印出外壳命令行的文字,原始文本表示形式并由新外壳处理。现在的问题是,为什么即使在文本$ bar中实际上不包含引号的情况下,它也不会在子外壳中展开呢? 是什么导致它在此处被隐式引用?
这里是没有嵌套壳的相同逻辑和预期输出的示例
$ foo='$bar' bar=expanded
$ echo $foo
$bar
$ echo $bar
expanded
此外,通过添加eval
,我得到了第一个示例中期望的结果,但是我并没有理解为什么它是必要的以及它如何运行。
$ echo $(eval echo $(echo $foo))
expanded
答案 0 :(得分:1)
Bash manual解释了订购shell的扩展:(为清晰起见,已重新格式化)
扩展顺序为:
括号扩展;
波浪线扩展,参数和变量扩展,算术扩展和命令替换(以从左到右的方式完成);
分词;
和文件名扩展。
在可以支持它的系统上,还有一个附加的扩展:进程替换。这与代字号,参数,变量以及算术扩展和命令替换同时执行。
执行这些扩展后,除非单词本身已被引号引起,否则将删除原始单词中存在的引号字符(引号删除)。
这本质上与Posix shell specification相呼应,并增加了一些特定于bash的扩展。
请注意,第二组扩展(包括命令替换($(...)
)从左至右仅执行一次。它们不会重复执行,因此命令替换的结果不会受到参数扩展的影响。除非加引号,否则它会进行分词,文件名扩展和引号删除。
确实,在子外壳中评估的命令是由内而外评估的,但是在每个级别上,内部命令的替换仅需进行单词拆分,文件名扩展和引号删除(在本示例中均不适用)。
因此,唯一的参数扩展是用其值替换$foo
。