总评:任何新的回答,只要能够给这个问题带来新的有用见解,都将获得额外奖励。
Bash参考手册提到Bash支持以下for循环结构:
for name [ [in [words ...] ] ; ] do commands; done
for (( expr1 ; expr2 ; expr3 )) ; do commands ; done
令人惊讶的是,以下的for循环结构也是有效的:
for i in 1 2 3; { echo $i; }
for ((i=1;i<=3;++i)); { echo $i; }
这些不寻常的结构完全没有记录。无论是Bash man-pages、Bash手册还是Linux文档项目都没有提到这些结构。
当调查语法时,可以看到使用大括号(
{ commands; }
)作为do commands; done
的替代方案是一个有效的结构,适用于for循环和select语句,并追溯到Bash-1.14.7[1]。另外两个循环结构:
until test-commands; do consequent-commands; done
while test-commands; do consequent-commands; done
没有这种替代形式。
由于许多shell语言都相关,因此人们可以发现这些构造也被定义在那里并进行了轻微的文档记录。KSH手册提到:
For historical reasons, open and close braces may be used instead of
do
anddone
e.g.for i; { echo $i; }
ZSH实现并记录了其他循环结构的类似替代方案,但存在一些限制。它指出:
对于
if
、while
和until
命令,在这两种情况下,循环的测试部分也必须适当地加以限定,例如使用[[...]]
或((...))
,否则测试的结束将无法被识别。
问题:这个结构的起源是什么,为什么它没有传播到其他循环结构中?
更新1:这篇文章下面有一些非常有用和富有教育意义的评论,指出这是一个未记录的Bourne Shell功能,似乎是早期C语言与sh语言之间的一场战斗的结果。
更新 2:在向Gnu Bash邮件列表提出问题:“为什么这个语言特性没有被记录?”时,我收到了来自GNU bash的当前首席开发人员Chet Ramey的以下回答:
它从未被记录过。bash支持它(未记录)的原因是,它是我们为了兼容而实现的一种未记录的Bourne shell特性。在30多年前的那个时候,有一些脚本使用了它。我希望那些脚本已经成为历史的尘土,但谁知道现在有多少人在使用这种结构。
我将其保留为未记录的;无论如何,人们都不应该使用它。
相关问题/答案:
脚注:[1] 我并没有找到早期的版本,但我相信这篇文章的创作时间早于此。