'$ 在 bash 中是什么意思?

9uz*_*an7 20 shell bash

我想获得一个字符的 ASCII 码,所以我有以下内容:

VAR="a"
NUM=$(printf "%d" "'$VAR")
echo $NUM
Run Code Online (Sandbox Code Playgroud)

'$在这种情况下是什么意思?有人可以指出我的文档以了解语法吗?我不明白,如果它的一部分$(...)printfbash

mur*_*uru 28

'$没有什么特别的意思。使用%din printf,它尝试将参数评估为整数表达式。'a被视为char a,或整数 97。即使您不使用变量扩展,您也会得到相同的结果:

$ printf %d\\n "'a'"
97
$ printf %d\\n "'0'"
48
$ printf %d\\n "'"$'\1'
1
Run Code Online (Sandbox Code Playgroud)

bash 文档printf(强调我的):

非字符串格式说明符的参数被视为 C 语言常量,除了允许前导加号或减号,并且如果前导字符是单引号或双引号,则值为后一个字符的 ASCII 值。

任何留下的字符都将被忽略,如注释中所述。

  • 您要添加有关 _single_ 单引号而不是平衡单引号的使用的任何信息吗?你所有的例子(除了最后一个)都使用平衡引号,但没有注释。 (6认同)
  • bash 手册页中的相关文本:“**非字符串格式说明符的参数** 被视为 C 常量,但允许使用前导加号或减号,并且**如果前导字符是单引号或双引号,该值为后面字符**的ASCII值。" (4认同)
  • 您在前两个示例中的字母后写了一个额外的撇号。所以你的第一个例子的第二个参数应该是 `"'a"` 而不是 `"'a'"`。第一个字母之后的任何字符都将被忽略,因此如果您添加额外的撇号,您将不会收到错误消息,但这是不正确的。 (2认同)

cod*_*oma 21

'是 printf 参数的一部分(请参阅此处的参数部分)。

本 $是普通的shell扩展的一部分,所以printf争论变得%d'a

最后,$(...)construct 是Command Substitution,在这种情况下意味着NUM它的值设置为printf函数的输出。

  • 在单引号成为 `printf` 获取的参数的一部分之前,同样重要的是要注意,它本身在双引号字符串中,所以就 shell 语法而言,它只是一个普通字符。(它不会像没有转义或引用它本身那样以带引号的字符串开头。) (7认同)

小智 13

正如已经说过的,'$本身并不意味着什么特别的。您"'$VAR"将扩展为'a,它将作为参数传递给printf实用程序。

然后是有趣的部分——一个晦涩但标准的特性printf(shell 实用程序,而不是 C 语言中的函数)。

根据 SuSv4标准(重点是我的):

的参数的操作数[到printf]应被视为字符串如果相应的转换说明是bc,或s,并须就好像由评价strtod()函数如果相应的转换说明是aAeEfFg,或G

否则 [例如,如果转换说明符是d],它们应被评估为无后缀的 C 整数常量,如 ISO C 标准所述,具有以下扩展:

  • 一个领先<plus-sign><hyphen-minus>应被允许。

  • 如果前导字符是单引号或双引号,则该值应为跟在单引号或双引号之后的字符的底层代码集中的数值。

  • 可能允许使用后缀整数常量。

如果您的 shell 支持多字节字符(如 UTF-8,任何现代系统的默认值),则该数值将是完整字符的数值,而不是其前导字节的数值:

% printf '%d\n' '"á' "'é"
225
233
% printf 'U+%X\n' '"??'
U+732B
Run Code Online (Sandbox Code Playgroud)

请注意,这不是字符的“ASCII 值” ——bash 联机帮助页的描述充其量只是一种误导。

但是,bash(以及除 yash 之外的大多数其他外壳程序)不符合标准,因为即使使用像forg这样的浮点说明符,它们也会执行该转换,这明显违反了上面的第一段,该段表示strtod()应该在这种情况下使用:

% bash --posix -c 'printf "%f\n" \"Q'
81.000000
Run Code Online (Sandbox Code Playgroud)