如何理解扩展之间的顺序?

如何理解扩展之间的顺序?

从 POSIX 7 开始:

单词扩展的顺序如下:

  1. 波形符扩展(参见第 2.6.1 节)、参数扩展(参见第 2.6.2 节)、命令替换(参见第 2.6.3 节)和算术扩展(参见第 2.6.4 节)应从头到尾执行。请参阅第 2.3 节中的第 5 项。

  2. 除非 IFS 为空,否则应对步骤 1 生成的字段部分执行字段拆分(参见第 2.6.5 节)。

  3. 除非 set -f 有效,否则应执行路径名扩展(参见第 2.6.6 节)。

  4. 报价删除(参见第 2.6.7 节)应始终最后执行。

  1. 波形符扩展、参数扩展、命令替换和算术扩展是否按指定顺序执行?

    它们之间的顺序重要吗?如果是,我们如何理解为什么顺序是这样的?

  2. 为什么路径名扩展发生在字段分割之后,而其他扩展发生在字段分割之前?

    特别是,波浪号扩展和路径名扩展都与路径名和文件名有关,为什么它们在字段分割方面的放置方式不同?

  3. POSIX 中没有大括号扩展吗?

  4. 我注意到“单词扩展”。扩展是否仅适用于具有令牌标识符 WORD 的令牌,而不适用于具有其他令牌标识符(例如 NAME、特定运算符、NEWLINE、IO_NUMBER、ASSIGNMENT)的令牌?

答案1

波形符扩展、参数扩展、命令替换和算术扩展列在同一步骤中。这意味着它们被执行同时。波形符扩展的结果不进行参数扩展,参数扩展的结果不进行波形符扩展,等等。例如,如果 的值为foo$(bar) qux则该单词在步骤 1 处$foo扩展为;$(bar) qux参数扩展产生的文本不会在步骤 1 中进行任何进一步的转换,但随后会被步骤 2 分割。

“开始到结束”意味着从左到右的处理,这很重要,例如当发生赋值时:a=1; echo $a$((a=2))$a打印,因为在第一个参数扩展和第二个参数扩展之间执行122算术扩展,设置为2 。$((a=2))a$a$a

该顺序的原因是历史使用情况。 POSIX 通常遵循现有的实现,很少指定新的行为。周围有多个贝壳;在大多数情况下,POSIX 遵循科恩壳但省略了大多数不存在的功能伯恩外壳(由于 Bourne shell 基本上已被废弃,因此 POSIX 的下一版本可能会包含新的 ksh 功能)。

Bourne shell 执行参数扩展、字段分割、通配符的原因是它允许将通配符存储在变量中:您可以设置ato *.txt *.pdf,然后使用$a代表匹配的文件名列表*.txt,后跟名称列表匹配*.pdf(假设两个模式匹配)。 (我并不是说这是最好的设计,只是说它就是这样设计的。)我不太清楚为什么人们希望将命令替换放置在 Bourne shell 的特定步骤中;在 Korn shell 中,其语法$(…)接近于参数扩展,${…}因此将它们一起执行是有意义的。

波形符扩展的位置是一个历史怪事。稍后放置它会更有意义,这样您就可以编写~$some_user并将其扩展到名称为变量值的用户的主目录some_user。我不知道为什么不这样做。这个命令甚至需要一个特殊的声明,即波浪号扩展的结果不会进行其他扩展(根据您引用的段落,如果HOME/foo bar则那么~将扩展为两个单词/foobar由于字段分割,但没有 shell 这样做,并且 POSIX.2008明确指出“由波形符扩展产生的路径名应被视为带引号”)。

POSIX 中没有大括号扩展,否则规范会说明这一点。

单词扩展仅在 WORD 上执行,并在以下部分中提到注意事项(例如,字段分割和路径名生成仅在允许多个单词的上下文中执行,例如在双引号之间不执行)。 NAME、NEWLINE、IO_NUMBER 等不包含任何可以扩展的内容。

答案2

关于(1),该顺序基于现有实施。如果参与编写的人知道不同 shell 的不同顺序被认为是标准,他们会在措辞中提供一些余地以允许这样做。如中所述2.6 词扩展,没有任何迹象表明其他订购可以符合该标准。

再次,对于 (2),请记住这是基于现有的实现。最初实施的原因不一定能在标准中找到,尽管对于一些有趣的分歧领域(例如,BSD 与 SVr4),理由本节总结了委员会选择其中一个相互冲突的替代方案的原因。

对于(3),你提到的“大括号扩展”可能与2.6.2 参数扩展(尽管还有其他可能性,但不一定在 POSIX 中)。

最后(4),记起那一个NAME是某种类型的WORD。词扩展适用于名字

答案3

  1. 前四个扩展顺序:

每个扩展的触发器都是不同的:波形符扩展~、参数扩展$name${name}、命令替换$()` `以及算术扩展$((...)))。因此,顺序并不重要,因为无法将一个扩展与另一个混淆,并且每个扩展仅执行一次。已进行参数扩展的令牌将不会进行命令替换(例如)。
一种可能令人困惑的扩展是算术扩展,因为(在其内部)可能存在参数扩展、扩展、字符串扩展、命令替换和引号删除。并且,算术扩展可以嵌套。但所有这些都发生在已经检测到的算术展开式内部,而不是外部。

最重要的顺序是从左到右。

毕竟,上述扩展的结果(如果没有引用)将受到字段分割和路径名扩展(按顺序)的影响。

所有扩展最终都将被删除报价。

  1. 不,POSIX 中没有大括号扩展。
  2. 在这种情况下,单词和标记通常表示相同的想法。

相关内容