web-dev-qa-db-ja.com

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

-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

しかし、それはハックのようです。

21
Dougnukem

演算に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))
_

同じ問題 がありました。 tl; dr:

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

2
l0b0

この構文は私にとってはうまくいきます:

a=$((b + c))
1
Mark Sawers

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

1
tylerl