letまたはexprが0と評価されると、bash -eは終了します


19

-eを設定するbashスクリプトがあるので、スクリプトは終了ステータス!= 0で終了します。

変数に割り当てられた基本的なシェル算術演算を実行しようとしていますが、式が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'

私の質問は、0に等しい基本的な算術ではなく、実際の終了エラーでスクリプトを失敗させる慣用的なbashスクリプトの方法は何ですか。

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

しかし、それはハッキーなようです。

回答:


16

expr算術には使用しないでください。それは長い間時代遅れでした:シェルには、$((…))コンストラクト(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シェル(ダッシュなど)で作業するという追加の利点があります。

a=$((2 - 2))

1

$(( $C - $D ))代わりに算術に使用してください。より効率的です。


何が言うよりも効率的(( A = $C - $D ))ですか?
ビショップ

1

私が持っていた同じ問題を。tl; dr:

[let]の最後のARGが0と評価された場合、letは1を返します。それ以外の場合、letは0を返します。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.