以下带有调试选项的脚本
set -e -v
仅当变量的先前值为零时,增量运算符才会失败。
#!/bin/bash
set -e -v
i=1; let i++; echo "I am still here"
i=0; let i++; echo "I am still here"
i=0; ((i++)); echo "I am still here"
bash(GNU bash,版本 4.0.33(1)-release (x86_64-apple-darwin10),还有 GNU bash,版本 4.2.4(1)-release (x86_64-unknown-linux-gnu))
有什么想法吗?
我的问题的答案不是使用let(或shift,或...),而是使用
i=$((i+1))
尝试通过使用 设置“非零状态代码退出
”来检查 bash 脚本时set -e
bash 手册指出 set -e 具有“如果简单命令以非零状态退出则立即退出。”的效果。
不幸的是,let(以及shift和...)返回计算结果(“如果最后一个参数计算结果为0,则let返回1;否则返回0”)。因此,我们得到的是某种返回值,而不是状态代码。有时这个返回值为零,有时为一,具体取决于计算。因此 set -e 将导致脚本退出,具体取决于您的计算结果!除非您永远不使用它或求助于,否则对此无能为力
let i++ || true
正如 arnaud576875 所指出的,顺便说一句,这增加了额外的 CPU 负担。
使用
let ++i
仅适用于 i 不为 -1 的特定情况,就像
let i++ 一样,仅适用于 i 不为 0 时。因此是半解。
虽然我喜欢 Unix,但我不会有任何其他方式。
let
的最后一个参数计算为
0
,则 let 返回
1
(因此,非零状态):
来自手册:
let arg [arg ...]
每个arg都是一个要计算的算术表达式。如果最后一个参数的值为 0,let 返回 1;否则返回 0。
当
i++
为
i
时,
0
计算为零(因为它是后置增量,所以返回 i
之前的值),因此 let
返回 1
,并且由于 set -e
, bash 存在。
以下是一些解决方案:
let ++i # pre-increment, if you expect `i` to never be -1
let i++ 1 # add an expression evaluating to non-zero
let i++ || true # call true if let returns non-zero
查看 set -e
上的
BASH 手册页:
如果一个简单命令(参见上面的 SHELL GRAMMAR)以非零状态退出,则立即退出。 [...]
因此,如果任何语句返回非零退出代码,shell 将退出。
查看 BASH 手册页,关于
let
命令:
如果最后一个参数的值为 0,则 let 返回 1;否则返回 0。
但是等等!
i++
的答案是一而不是零!应该有效!
同样,答案是关于增量运算符的 BASH 手册页:
id++ id--:变量后自增和后自减
好吧,不太清楚。试试这个 shell 脚本:
#!/bin/bash
set -e -v
i=1; let ++i; echo "I am still here"
i=0; let ++i; echo "I am still here"
i=0; ((++i)); echo "I am still here"
嗯...按预期工作,我所做的就是将每行中的
i++
更改为 ++i
。
i++
是一个后自增运算符。这意味着,在 i
语句返回一个值之后,它会递增 let
。由于 i
在 递增之前为零,因此
let
语句返回非零值。
但是,
++i
是一个预自增运算符
。这意味着它在返回退出状态之前会递增
i
。由于 i
递增到
1
,退出状态变为零。
我希望这是有道理的。