Bash退出状态的简写增量符号

15

我注意到bash的(( ))符号返回状态存在一些表面上的不一致性。
考虑以下示例:

$> A=0
$> ((A=A+1))
$> echo $? $A
0 1

然而,使用另一种众所周知的简写增量符号会产生以下结果:

$> A=0
$> ((A++))
$> echo $? $A
1 1

如果脚本中有内置的set -e,则第二种表达式会导致脚本退出,因为((A++))的退出状态返回了非零值。类似问题在这个相关问题中已经得到解答。但它似乎没有解释两种表达式((A=A+1))((A++))之间的退出状态差异。

((A++))似乎仅在A等于0时返回1。(免责声明:我没有进行全面的测试。在bash 4.1.2和4.2.25中进行了测试)。因此,最终问题可以归结为:

为什么A=0; ((A++))返回1

2个回答

9

a++是后增量:它在语句评估后递增。相比之下,++a在递增之前递增。 因此:

$ a=0 ; ((a++)) ; echo $a $?
1 1
$ a=0 ; ((++a)) ; echo $a $?
1 0

在第一种情况下,表达式((a++))先被计算,而此时a仍为零,得到的值为零(因此返回状态非零)。然后,a被增加。
在第二种情况下,a被增加到1,然后((...))被计算。由于在计算算术表达式时a非零,所以返回状态为零。
来自man bash:
   id++ id--
          variable post-increment and post-decrement
   ++id --id
          variable pre-increment and pre-decrement

3
现在看起来很明显,谢谢。然而,这似乎意味着每当使用set -e时,如果期望计数器可能取值为-10,就无法安全地使用缩写符号。 是否有方法可以解决这个问题?还是应该放弃缩写符号? - Pankrates
@Pankrates,#bash 中的许多人建议放弃使用 set -e。请参阅 http://mywiki.wooledge.org/BashFAQ/105。话虽如此,您也可以运行 (( a++ )) ||: - Charles Duffy
@Charles非常有用的链接,谢谢。然而文章的结论仍未确定。一方面是“不要使用它,使用自己的错误检查”,另一方面是“使用它但要注意陷阱”,正如我最初的问题所示。我更喜欢使用set -e(我想这是方便),但前提是有一个详尽的陷阱列表。由于我没有这样的列表(如果真的存在这样的列表),我想我会听从你的建议 :) - Pankrates
是的--我说的是“很多”,而不是“全部”,因为意见分歧--实际上,我站在“如果熟悉注意事项就使用它”的一边。另一方面,维护FAQ的维基托管的主要维护者Greg则持“最好避免”的立场。 - Charles Duffy

3
< p > (()) 表示的算术表达式为非零值时退出状态为零,反之亦然。 < /p >
A=A+1

您将1分配给A,因此表达式计算为1,退出状态为零。
A++

POST递增运算符。表达式计算结果为零,退出状态为1,然后A递增。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接