所有 POSIX shell 都以相同的方式实现算术扩展 $((...)) 吗?

zra*_*ajm 2 dash posix

我正在尝试编写一个可以在任何 POSIX shell 下工作的 shell 脚本,并且我发现了dash. 我想知道这是否是我可以在其他 POSIX 兼容 shell 下工作的依赖,或者它是否只是 shell 的一个无意的功能dash

\n\n

在算术扩展中,变量可以带有或不带有初始美元符号(位置参数除外,它必须始终带有美元符号$1,,$2

\n\n

但我发现 的行为有所"$((X))"不同,因为"$(($X))""$(($X))"似乎扩展了两次,而不是仅仅一次。即,如果我的变量X包含另一个变量的名称( X=Y),而该变量又包含一个数值 ( Y=1),"$(($X))"则将返回1,而"$((X))"只会产生“非法数字:Y”错误。

\n\n

我可以相信这种行为在其他 POSIX shell 中是相同的吗?

\n\n

奇怪的行为

\n\n

"$((X))"并且"$(($X))"行为不一样。

\n\n
$ X=Y; Y=1\n$ echo "$((X))"\ndash: 1: Illegal number: Y\n$ echo "$(($X))"\n1\n
Run Code Online (Sandbox Code Playgroud)\n\n

预期行为

\n\n

为了完整起见,我在这里包括了没有间接和两层间接的内容。没有间接的情况下,一切都按预期工作:

\n\n
$ X=1\n$ echo "$((X))"\n1\n$ echo "$(($X))"\n1\n
Run Code Online (Sandbox Code Playgroud)\n\n

正如预期的那样,两层间接不起作用(尽管请注意错误消息引用了不同的值)。

\n\n
$ X=Y; Y=Z; Z=1\n$ echo "$((X))"\ndash: 6: Illegal number: Y\n$ echo "$(($X))"\ndash: 7: Illegal number: Z\n
Run Code Online (Sandbox Code Playgroud)\n\n

这个问题与关于算术扩展和参数扩展的问题有些相关,但它\xe2\x80\x99s不一样,因为它处理的是更高级的shell的行为bash,但我想知道预期的POSIX行为。

\n

Ste*_*itt 6

由于您的问题是 POSIX 通用的,并且相关问题似乎涉及更高级的 shell,因此我\xe2\x80\x99 将单独回答这个问题。

\n\n

您看到的行为来自两种不同的扩展:参数扩展和算术扩展,POSIX 按该顺序指定。和

\n\n
$ X=Y; Y=1\n
Run Code Online (Sandbox Code Playgroud)\n\n

您的第一个示例仅使用算术扩展:

\n\n
$ echo "$((X))"\n
Run Code Online (Sandbox Code Playgroud)\n\n

尝试将X\xe2\x80\x99s 值解释为算术表达式,但失败,因为 \xe2\x80\x9cY\xe2\x80\x9d 不是 \xe2\x80\x99t 数字。

\n\n

您的第二个示例同时使用:

\n\n
$ echo "$(($X))"\n
Run Code Online (Sandbox Code Playgroud)\n\n

被扩展(参数扩展)为

\n\n
$ echo "((Y))"\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后算术扩展使用Y\xe2\x80\x99s 值 1。

\n\n

另请参阅了解算术表达式Bash 中使用间接扩展进行变量扩展的两个示例:算术扩展、参数扩展和逗号运算符等。

\n