我有一个 shell 脚本,使用 set -e 递增变量,如下例所示:
$ var=0; echo $?
0
$ ((var++)); echo $?
1
$ ((var++)); echo $?
0
$ ((var++)); echo $?
0
$ echo $var; echo $?
3
0
$ bash --version
GNU bash, version 4.2.46(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$
脚本意外退出。问题是完全相同的脚本不在 MacBook 上本地运行时以同样的方式退出。运行上面的示例时,MacBook 上的 bash shell 的行为方式完全相同。
有谁知道这里发生了什么事吗?
答案1
如果算术表达式的值非零,则算术命令成功。如果表达式的值为 0,则命令失败,状态为 1。这允许在测试中使用算术命令,因为 shell 算术表达式中的布尔运算符返回 0 表示 true,1 表示 false(如在 C 中)。例如
if ((x==3)); then …
之所以有效,是因为当等于 3((x==3))
时返回 0 ,否则返回 1。$x
后缀增量运算符返回变量的旧值。因此,如果之前为零,则((var++))
返回错误状态。var
set -e
告诉 shell 在第一个命令失败时退出。那里没有什么惊喜。
为了避免可能合法地具有值 0 的算术表达式导致不必要的错误,请不要使用算术命令,而应使用带有算术表达式的普通赋值。
var=$((var+1))
答案2
您始终可以使用算术命令,例如((var++))
.如果赋值之前 var 的值为 0,那么要强制获得成功的状态代码,您可以编写:((var++)) || true
或者你可以这样写来跳过 errexit 逻辑:! ((var++))
答案3
我使用declare -i i=0; i+=1
,退出代码为零。
之前写过一个hacki=0; ((i++)) ||true