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


17

在跑步时在灰,破折号和bash上

$ echo ab$

它返回

ab$

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


4
更好的问题是“ 如果它是单词中的最后一个字符,是否会$ 获得特殊含义?” 没有分配任何单一的特殊含义$;它用于引入多个但截然不同的扩展,例如参数扩展${...},命令替换$(...)和算术表达式$((...))。一些shell引入了其他上下文,例如ksh的command-substitution变体x=${ echo foo; echo bar;}(与标准不同,它$(...)不执行subshel​​l中的命令)。
chepner

@chepner您是否愿意权衡一下Issac和Michael Homer之间的意见分歧?他们的回答显然彼此矛盾
Harold Fischer

1
我同意迈克尔·荷马的解释。直到解析完成后,shell才开始担心扩展,因此在单个单词中ab$,没有字符跟随$,无论它是“跟随”原始输入字符串中的空字符还是用空格分隔喜欢echo ab$ foo; 原始未加引号的空格已在解析后被识别并丢弃。
chepner

Answers:


10

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

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

如果当前字符是一个无引号$`:,外壳应确定任何候选参数扩展,命令替换,或从它们的介绍性无引号字符序列算术扩展的开始$${$(`,和$((分别。外壳应读取足够的输入以确定要扩展的单元的末端(如引用部分中所述))。在处理字符时,如果发现替换中嵌套了扩展或引号的实例,则外壳程序应以为找到的结构指定的方式递归处理它们。从替换开始到结束为止发现的字符,允许进行任何识别嵌入式构造的必要递归,都应未经修改地包含在结果标记中,包括任何嵌入式或封闭的替换运算符或引号。令牌不得在替换结束时定界。

因此,如果$不构成扩展,则其他解析规则将生效:

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

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

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

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

POSIX未明确定义所生成的包含非标准扩展名的单词的含义$

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


7

根据实际情况,这可能是未明确指定的(因此实现可能会按其意愿进行),也可能需要按照您观察到的那样进行。在您的实际情况下echo ab$POSIX会强制您观察到输出“ ab $”,并且该输出并非未指定。最后是所有不同情况的快速摘要。

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


代币化

POSIX断词要求一个$是不是一个有效的起始参数扩展命令替换,或算术取代被认为是的文本部分WORD构造令牌之中。这是因为,规则5(“如果当前字符是一个无引号$`,壳必从介绍无引号字符序列识别任何候选参数扩展,命令替换,或算术膨胀开始:$${$(`,和$((,分别为” )不适用,因为这些扩展均不可行。参数扩展要求在其中显示有效名称,并且无效名称无效。

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

echo a$+b由于+不是特殊参数的名称,因此也存在第三种情况,即同一形式的裂纹。我们将在稍后返回到这一条,因为它会触发规则的不同部分。

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


词扩展

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

规定

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

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

结果不确定。

“未指定”是此处的特定术语,表示

  1. 在这种情况下,合格的外壳可以选择任何行为
  2. 合格的应用程序不能依赖任何特定行为

在你的榜样,echo ab$中,$ 后面没有任何字符,所以这条规则不适用,未指定的结果不会被调用。根本没有引起的扩展$,因此它确实存在并已打印出来。

应用在我们的第三种情况从上面:echo a$+b。这里$后面是+,这不是数字,特殊参数(@*#?-$!,或0),启动一可变的名称(下划线或从字母便携式字符集),或支架中的一个。在这种情况下,行为是不确定的:允许+合格的shell 发明一个称为expand 的特殊参数,合格的应用程序不应假定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其作为参数的一部分传递给命令。这是对外壳的一致性要求。


评论不作进一步讨论;此对话已转移至聊天
terdon

@MichaelHomer echo $还会是字面意义并完全指定吗?
哈罗德·菲舍尔

@HaroldFischer是的
迈克尔·荷马

在哪里echo "$"echo "a b$"下跌呢?
哈罗德·菲舍尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.