set -e 在 i=0 时退出;让 i++

问题描述 投票:0回答:3

以下带有调试选项的脚本

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))

有什么想法吗?

bash shell set operator-keyword increment
3个回答
24
投票

我的问题的答案不是使用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,但我不会有任何其他方式。


10
投票
如果

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

1
投票

查看 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
,退出状态变为零。
我希望这是有道理的。 

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.