POSIX shell:如果“$”是单词中的最后一个字符,它会失去其特殊含义吗?

POSIX shell:如果“$”是单词中的最后一个字符,它会失去其特殊含义吗?

当我跑步时,在灰烬、冲刺和猛击上

$ echo ab$

它返回

ab$

此行为是 POSIX 指定的还是只是 POSIX 兼容 shell 中的常见约定?我在 POSIX Shell 命令语言页面上找不到任何提及此行为的内容。

答案1

$本身并没有特殊含义(try echo $),只有与其后的其他字符组合形成扩展时才有特殊含义,例如$var(或${var}$(util),,$((1+2))

$“特殊”含义是在 POSIX 标准中定义扩展 部分令牌识别:

如果当前字符是不带引号的$or `,则 shell 应从其介绍性不带引号的字符序列中识别参数扩展、命令替换或算术扩展的任何候选者的开始:$or ${$(or `、 and$((。 shell 应读取足够的输入以确定要扩展的单元的末尾(正如所引用的章节中所解释的)。在处理字符时,如果在替换中发现嵌套的扩展或引用实例,则 shell 应按照为找到的构造指定的方式递归处理它们。从替换开始到结束找到的字符(允许识别嵌入结构所需的任何递归)应不加修改地包含在结果标记中,包括任何嵌入或封闭的替换运算符或引号。令牌不应由替换结束时界定。

所以,如果$不形成扩展,则其他解析规则生效:

如果前一个字符是单词的一部分,则当前字符应附加到该单词后。

那覆盖了你的ab$字符串。

在单独的情况下$(“新词”$本身就是 the):

当前字符用作新单词的开头。

意义$包含非标准扩展的生成单词的被 POSIX 明确定义为未指定。

另请注意$是 中的最后一个字符$$,但这也恰好是保存当前 shell PID 的变量。在 中bash!$可以调用历史扩展(上一个命令的最后一个参数)。所以一般来说,no,$在未引用的单词末尾并不是没有意义,但在单词末尾它至少不表示标准扩展。

答案2

根据具体情况,这要么是明确未指定的(因此实现可能会按照它们的意愿进行),要么需要按照您观察到的方式发生。在你的具体场景中echo ab$POSIX 强制输出您观察到的“ab$”这不是未指定的。最后对所有不同案例进行了快速总结。

有两个要素:首先将其标记为单词,然后解释这些单词。


代币化

POSIX 标记化要求A$不是有效的开始参数扩展,命令替换, 或者算术替换被视为WORD正在构建的令牌的字面部分。这是因为规则 5(“如果当前字符是不带引号的$or `,则 shell 应从其介绍性不带引号的字符序列中识别参数扩展、命令替换或算术扩展的任何候选者的开始:分别为$or ${$(or `、 和$((” )不适用,因为这些扩展在那里都不可行。参数扩展需要一个有效的名称出现在那里,空名称是无效的。

由于这条规则不适用,我们将继续遵循,直到找到一条适用的规则。两个候选者是#8(“如果前一个字符是单词的一部分,则当前字符应附加到该单词。”)和#10(“当前字符用作新单词的开头。”) ,分别适用于echo a$echo $

还有第三种形式的情况也echo a$+b属于同样的情况,因为+不是特殊参数的名称。我们稍后会再讨论这一点,因为它会触发规则的不同部分。

因此,规范要求从$语法上将其视为单词的一部分,然后可以在以后对其进行进一步处理。


单词扩展

以这种方式解析输入并$包含在单词中后,单词扩展应用于已读过的每个单词。每个单词都经过处理单独地

明确规定:

如果未加引号的“$”后跟的字符不是以下字符之一:

  • 一个数字字符
  • 特殊参数之一的名称(参见特殊参数
  • 变量名的有效第一个字符
  • A <left-curly-bracket>( '{' )
  • A<left-parenthesis>

结果未指定。

“未指定”是这里的一个特殊术语,意思是

  1. 在这种情况下,一致的 shell 可以选择任何行为
  2. 一个合格的应用不能依赖任何特定行为

在您的示例中echo ab$$ 后面没有任何特点,因此该规则不适用,并且不会调用未指定的结果。根本没有引起任何扩展$,因此它确实存在并打印出来。

在哪里apply 在我们上面的第三个案例中是:echo a$+b。后面$跟着+,它不是数字,特殊参数(@*#?-$!0),变量的开头姓名(下划线或字母便携式字符集),或括号之一。在这种情况下,行为未指定:一致的 shell被允许发明一个称为+展开的特殊参数,以及符合要求的应用程序不应该假设 shell 不。 shell 还可以做任何它喜欢做的事情,包括报告错误。

例如,zsh,包括其 POSIX 模式,解释$+b为“是变量b集”并用 1 或 0 代替它的位置。它同样具有~和的扩展=。这是顺应行为。

另一个可能发生这种情况的地方是echo "a$ b"。同样,shell 可以按照自己的意愿行事,并且作为脚本作者,$如果您想要文字输出,则应该转义 。如果你不这样做,它可能会起作用,但你不能依赖它。这是规范的绝对字母,但我不认为这种粒度是有意或考虑的。


总之

  • echo ab$:文字输出,完全指定
  • echo a$ b:文字输出,完全指定
  • echo a$ b$:文字输出,完全指定
  • echo a$b:参数扩展b,完全指定
  • echo a$-b:特殊参数扩展-,完全指定
  • echo a$+b:未指定的行为
  • echo "a$ b":未指定的行为

对于$单词末尾的 a,您可以依赖该行为,并且必须按字面意思对其进行处理,并将其echo作为其参数的一部分传递给命令。这是对外壳的一致性要求。

相关内容