shell中的命令替换和字段拆分

shell中的命令替换和字段拆分,shell,posix,Shell,Posix,我理解以下命令失败的原因 $ a=foo bar -bash: bar: command not found 它尝试先执行a=foo,然后执行bar,但失败,因为没有名为bar的命令 但我不明白为什么会这样。我希望下面的命令也会失败 $ a=$(echo foo bar) $ echo "$a" foo bar 根据第一个命令,发生替换,然后发生字段拆分 2.6个单词扩展 本节介绍在上执行的各种扩展 话。并非对每个字都执行所有扩展,如中所述 以下各节 波浪形展开、参数展开、命令替换、, 算术

我理解以下命令失败的原因

$ a=foo bar
-bash: bar: command not found
它尝试先执行
a=foo
,然后执行
bar
,但失败,因为没有名为
bar
的命令

但我不明白为什么会这样。我希望下面的命令也会失败

$ a=$(echo foo bar)
$ echo "$a"
foo bar
根据第一个命令,发生替换,然后发生字段拆分

2.6个单词扩展

本节介绍在上执行的各种扩展 话。并非对每个字都执行所有扩展,如中所述 以下各节

波浪形展开、参数展开、命令替换、, 算术展开,以及在单个 word扩展到单个字段。它只是字段拆分或路径名 可从单个单词创建多个字段的扩展。这个 这条规则的唯一例外是特殊规则的扩展 双引号内的参数“@”,如特殊说明中所述 参数

单词扩展顺序如下:

  • 波浪形展开(参见波浪形展开)、参数展开(参见参数展开)、命令替换(参见命令替换), 算术展开式(见算术展开式)应为 表演,从头到尾。参见令牌识别中的第5项

  • 除非IFS为空,否则应在步骤1生成的字段部分执行字段拆分(参见字段拆分)

  • 除非set-f有效,否则应执行路径名扩展(参见路径名扩展)

  • 报价删除(见报价删除)应始终在最后执行

  • 因此,在指挥部替代之后

    a=$(echo foo bar)
    
    变成

    a=foo bar
    
    然后在to字段拆分之后,应该首先执行
    a=foo
    ,然后执行
    bar
    ,然后我们应该有相同的错误,即
    bar:command not found
    。那么为什么
    a=$(echo foo bar)
    工作得很好呢?

    答案在我看来

    具体而言,第1点和第4点:

    一,。根据Shell语法规则被识别为变量赋值或重定向的单词将保存起来,以便在步骤3和4中进行处理

    四,。在赋值之前,应展开每个变量赋值,以进行波浪线展开、参数展开、命令替换、算术展开和引号删除

    或在bash参考手册中:

    变量可以通过以下形式的语句赋值

    名称=[值]

    如果未给定值,则为变量分配空字符串。所有值都经过波浪线展开、参数和变量展开、命令替换、算术展开和引号删除(详细信息如下)


    关键是在变量赋值中不会出现分词。(也就是说,“分词”不会出现在应用的扩展列表中。)在您使用
    $(echo foo=bar)
    给出的示例中,没有变量赋值。有一个进程替换生成字符串“foo=bar”,然后该字符串被视为一个简单命令,因此shell尝试(但失败)查找名为
    foo=bar的命令。正如我所指出的和你所重申的,这是因为它不在任务扩展列表中。我认为,要理解这一点在这里如何适用,就需要理解我的后一点。即,初始令牌/字扫描不同于此处讨论的扩展。(假设我清楚地了解这种情况)威廉·珀塞尔给了你正确的答案。但是,如果你想更好地理解为什么会发生这种情况,请看同一节中的第1点:
    根据Shell语法规则被识别为变量赋值或重定向的单词将被保存,以便在步骤3和4中进行处理。
    这意味着整个命令替换将被保存,以供以后处理,第4点告诉您不会发生单词拆分。@davideb我一点也不担心当然,关于正确答案的评论是关于什么的,但你是正确的,第1点正是我在上一段中试图表达的观点,只是写得更好。@Etan Reisner:我当时在使用我的平板电脑,由于屏幕尺寸有限和滚动问题,我错误地认为你是问这个问题的人。很抱歉给您带来不便。