为什么 bash 大括号扩展在某些算术表达式中有效,但在其他算术表达式中无效?

Jak*_*kub 4 bash shell arithmetic-expressions brace-expansion

我正在编写一个非常简单的 bash 脚本,但我无法理解为什么已弃用的 $[] 可以完美地工作,而 $(()) 似乎破坏了整个事情。

我所指的代码是:

for i in {1..10};
do 
    printf %4d $[{1..10}*i]
    echo
done
Run Code Online (Sandbox Code Playgroud)

在此版本中,我没有遇到任何问题,但我不想使用已弃用的 bash 元素,这就是我想切换到 $(()) 的原因。

不幸的是,一旦我将代码更改为:

printf %4d $(({1..10}*i))
Run Code Online (Sandbox Code Playgroud)

我收到一个错误:

./script_bash.sh: line 8: {1..10}*i: syntax error: argument expected (error token is "{1..10}*i")
Run Code Online (Sandbox Code Playgroud)

我会很感激在这方面提供一些帮助......

bis*_*hop 5

将机器设置为 1990 年。

Bash$[]按照 POSIX P1003.2d9(大约 1990 年)实现了语法,该语法是已发布的 P1003.2-1992 的草案。在草案和标准之间的两年时间里,POSIX 转而采用了 ksh88$(())语法和行为。Chet Ramey(bash 维护者)早在 2012 年就说过这样的话:

Bash...实现了 $[...] 因为当时没有其他语法,并且为了在 shell 中获得一些算术扩展的操作经验。Bash-1.14... 列出了算术展开的两种形式,但到 1995 年 bash-2.0 发布时,手册仅提到 $((...)) 形式。

这对我来说表明该$[]形式是实验性的,并且它具有某些行为(例如大括号扩展),当 POSIX 采用该语法时,这些行为被指定为遗忘$(())。这些实验行为被保留下来,因为已经有依赖它们的脚本(记住已经过去了两年多)。

Chet 在同一线程中明确表示该$[]形式已过时,但并未弃用:

现在,继续使用 $[...] 语法几乎没有任何问题。只需要几十个字节的代码。我没有删除它的计划。

当前的 POSIX标准C.2.6 Word Expansions > Arithmetic Expansion提到了语法(重点是我的):

在早期的提案中,使用了 $[表达式] 形式。它在功能上等同于当前文本的“$(())”,但有人提出反对意见,认为 1988 年的 KornShell 已经实现了“$(())”,并且没有令人信服的理由发明另一种语法。此外,“$[]”语法在涉及 case 语句中的模式时存在轻微的不兼容性。

因此,bash 中实现的行为并不完全符合规范,但由于没有计划删除它,如果它能巧妙地解决您的问题,我认为没有理由放弃它的好处。然而,正如 @Barmar 的评论所指出的,评论代码并将其链接到此处是一个好主意,这样未来的开发人员就知道你到底是什么意思!