次の例に示すように、set -e を使用して変数をインクリメントするシェルスクリプトがあります。
$ var=0; echo $?
0
$ ((var++)); echo $?
1
$ ((var++)); echo $?
0
$ ((var++)); echo $?
0
$ echo $var; echo $?
3
0
$ bash --version
GNU bash, version 4.2.46(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$
スクリプトが予期せず終了しました。問題は同じスクリプトですいいえMacBookでローカルで実行している場合も同じ方法で終了します。 MacBookのbashシェルは、上記の例を実行するのとまったく同じ方法で動作します。
ここで何が起こっているのか知っている人はいますか?
答え1
算術式の値がゼロでない場合、算術コマンドは成功します。式が 0 と評価されると、コマンドは状態 1 で失敗します。シェル算術式のブール演算子が真の場合は0を、偽の場合は1を返すので(Cのように)算術コマンドをテストに使用できます。例えば
if ((x==3)); then …
((x==3))
これは、3に等しい場合は0を返し、それ以外の場合は1を返すので機能します。$x
後位増加演算子は変数の前の値を返します。したがって、以前にゼロであった場合、((var++))
エラー状態が返されます。var
set -e
最初のコマンドが失敗した場合、シェルを終了するように指示します。そこには驚くべきことはありません。
正当に値がゼロになる可能性のある算術式が原因で発生する不要なエラーを回避するには、算術コマンドを使用せず、代わりに算術式に一般的な割り当てを使用します。
var=$((var+1))
答え2
たとえば、常に算術コマンドを使用できます((var++))
。割り当て前にvarの値が0の場合、成功ステータスコードを強制します。((var++)) || true
あるいは、以下を作成してエラー終了ロジックをスキップすることもできます。! ((var++))
答え3
を使用してdeclare -i i=0; i+=1
終了コードは0です。
前にハッキングを書いたi=0; ((i++)) ||true