Bash嵌套子Shell参数扩展

时间:2018-08-15 05:02:24

标签: bash shell scripting

为什么$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

1 个答案:

答案 0 :(得分:1)

Bash manual解释了订购shell的扩展:(为清晰起见,已重新格式化)

  

扩展顺序为:

     
      
  • 括号扩展;

  •   
  • 波浪线扩展,参数和变量扩展,算术扩展和命令替换(以从左到右的方式完成);

  •   
  • 分词;

  •   
  • 和文件名扩展。

  •   
     

在可以支持它的系统上,还有一个附加的扩展:进程替换。这与代字号,参数,变量以及算术扩展和命令替换同时执行。

     

执行这些扩展后,除非单词本身已被引号引起,否则将删除原始单词中存在的引号字符(引号删除)。

这本质上与Posix shell specification相呼应,并增加了一些特定于bash的扩展。

请注意,第二组扩展(包括命令替换($(...))从左至右仅执行一次。它们不会重复执行,因此命令替换的结果不会受到参数扩展的影响。除非加引号,否则它会进行分词,文件名扩展和引号删除。

确实,在子外壳中评估的命令是由内而外评估的,但是在每个级别上,内部命令的替换仅需进行单词拆分,文件名扩展和引号删除(在本示例中均不适用)。

因此,唯一的参数扩展是用其值替换$foo

相关问题