当let或expr的值为0时,bash -e退出


19

我有一个设置-e的bash脚本,因此该脚本将在任何退出状态!= 0时退出。

我试图做一些分配给变量的基本Shell算术运算,有时表达式等于0,这会使let或expr命令的退出状态为“ 1”。

这是一个例子:

#!/bin/bash -ex
echo "Test 1"
Z=`expr 1 - 1` || true
echo "Z will print"
let "A=4 - 4"
echo "A WILL NEVER PRINT $A"
Y=`expr 1 - 1`
echo "Y WILL NEVER PRINT $Y"
X=$(expr 2 - 2)
echo "X WILL NEVER PRINT $X"

输出为:

$ ./test_error.sh 
+ echo 'Test 1'
Test 1
++ expr 1 - 1
+ Z=0
+ true
+ echo 'Z will print'
Z will print
+ let 'A=4 - 4'

我的问题是什么是惯用的bash脚本编写方式,允许该脚本在实际退出错误而不是在等于0的基本算术上失败。我可以在所有这些表达式后缀:

A=`expr $C - $D`    || true

但这似乎很hack。

Answers:


16

不要expr用于算术。长期以来它已经过时了:现在,shell已使用$((…))构造(POSIX)或let内置(ksh / bash / zsh)或((…))构造(ksh / bash / zsh)内置了算术。

let((…))如果最后计算的表达式为0 ,则返回1(失败状态代码)。为避免这种情况导致脚本在下退出set -e,请安排最后一个表达式不返回0,例如:

let "a = 2 - 2" 1
((a = 2 - 2, 1))

或者,使用|| true成语:

((a = 2 - 2)) || true

或者,在内部进行算术运算,在$((…))外部进行赋值运算。赋值返回值中最后一个命令替换的状态,如果没有命令替换,则返回0,因此很安全。这具有在任何POSIX Shell(例如破折号)中工作的额外好处。

a=$((2 - 2))

1

$(( $C - $D ))改用您的算术。效率也更高。


是什么让它比说的更有效率(( A = $C - $D ))
主教

1

我有同样的问题。tl; dr:

如果[let的]最后一个ARG的值为0,则let返回1;否则,let返回1。let否则返回0。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.