递增变量会触发bash 4中的EXIT,但不会触发bash 3中的EXIT

eom*_*nis 9 bash version increment exit

考虑这个(示例性)bash脚本:

#!/bin/bash -e
errorExit() {
    echo "" >&2
    echo "ERROR (${var_scriptfilename}):" >&2
    echo "An unhandled error occurred." >&2
    intentionalExit 1
}
intentionalExit () {
    trap - EXIT # Unregister the EXIT trap
    exit $1
}
trap errorExit EXIT # Trap script errors
var_scriptfilename="$(basename "$0")"
# ==== START OF TEST ====
var_counter=0
((var_counter++))
echo "var_counter is $var_counter" >&2
# ===== END OF TEST =====
intentionalExit 0
Run Code Online (Sandbox Code Playgroud)

如果我在Cygwin的bash中运行它会产生预期的输出:

var_counter is 1
Run Code Online (Sandbox Code Playgroud)

但是,如果我在我的Debian Squeeze盒子上运行它,这是它的预定目的地,我最终进入了EXIT陷阱:

ERROR (test.increment.sh):
An unhandled error occurred.
Run Code Online (Sandbox Code Playgroud)

...这是为什么?

如果我删除了-e选项,它在两个系统上都按预期工作,但显然我想保持-e使用.

稍微麻烦的"通用"变体,var_counter=$(($var_counter+1))在两个shell上都设置了-e,但是我更喜欢使用第一种符号(或类似的东西),因为它在读取代码时明显地作为增量操作.

bash --version 在Cygwin bash上说:

GNU bash, version 3.2.51(24)-release (i686-pc-cygwin)
Copyright (C) 2007 Free Software Foundation, Inc.
Run Code Online (Sandbox Code Playgroud)

在Debian上,它是:

GNU bash, Version 4.1.5(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
Run Code Online (Sandbox Code Playgroud)

我很感兴趣为什么会这样.有人知道这种行为的原因吗?

另外,是否有人知道在bash中增加变量的类似方法我可以使用?

jw0*_*013 12

来自Debian的bash4手册页:

((expression))
    The expression is evaluated according  to  the  rules  described
    below  under ARITHMETIC EVALUATION.  If the value of the expres?
    sion is non-zero, the return status is 0; otherwise  the  return
    status is 1.  This is exactly equivalent to let "expression".
Run Code Online (Sandbox Code Playgroud)

并且 ...

-e      Exit  immediately  if a pipeline (which may consist of a
        single simple command),  a subshell command enclosed  in
        parentheses,  or one of the commands executed as part of
        a command list enclosed by  braces  (see  SHELL  GRAMMAR
        above) exits with a non-zero status.
Run Code Online (Sandbox Code Playgroud)

所以发生的是((var++))增量var从0到1并返回0,导致整个表达式返回非零,触发 errexit.

现在,对于两个不同的bash版本之间的区别:这种((行为的变化似乎发生在4.0和4.1之间.在4.0 (( 显然没有触发errexit.有关详细信息,请参阅此NEWS文件.你必须向下滚动到135行左右.源分发中的更改日志似乎证实了这一点.

如果您只想在不使用退出状态的情况下增加变量,则有多种方法可以执行此操作.也许其他人可以给出最好的建议,但有些可能性是:

  • var="$((var+1))",便携式POSIX sh方法
  • ((var++)) || true,强制语句始终具有零退出状态(仅限bash)

  • 非常感谢,这肯定会为那个人提供很多信息。我想,看到 EXIT 只是因为我从 0 开始计数而被调用,我可以使用前增量而不是后增量,即`((++var_counter))`而不是`((var_counter++))`。然后计算结果从 1 开始,返回值将始终为零。我现在已经在提到的两个 shell 上成功地测试了这个。 (3认同)
  • @FelipeAlvarez`(())`是一个独立的命令,就像在其他编程语言中执行语句一样.`((2 + 2))`只会运行,返回0给shell.`$(())`是一个扩展 - 表达式的结果被插回到命令行中代替`$(())`表达式.它通常用作较长命令行的一部分. (2认同)