mike-neckのブログ

Java or Groovy or Swift or Golang

Bash で (( で 0 になっている変数をインクリメントしてたら終了ステータスが 1 になってた

Bash で go のテストコードを生成していたら、mac では動くけど、 github actions では動かないテストが出力されていた。

仕方無しに、 set -x をつけて動かしたところ、 (( count++ )) という処理でスクリプトが終了していた。


ということで、以下のコマンドで動作を確認

bash -c '
declare -i count=0
(( count++ ))
echo "${?} ${count}"
(( count++ ))
echo "${?} ${count}"

実行結果は以下の通り。


結果から考えると、以下のような動きをとっていると考えられる

  • (( count++ ))count の値が演算結果とされる(つまり計算結果は 0)
  • (( 演算の終了ステータスはパースエラーあるいは計算結果が 0 の場合に 1
  • (( の終了ステータスを決定した後、 ++ の結果が反映される

一応、 count を最初に -1 にしておいて、インクリメントした場合の結果も上記で説明がつく…


念の為にソースコードでも確認してみる

変数の評価結果に 1 を加えてる箇所

git.savannah.gnu.org

変数の評価結果を返す

git.savannah.gnu.org

関数の戻り値が 0 の場合は失敗と判断…

git.savannah.gnu.org


以上から、 Bash0 からインクリメント (( count++ )) を実行する場合、以下の対処が必要になる

  • (( count=count+1 )) のように ++ 演算子を避ける
  • (( count++ )) || true のように終了ステータス 1 になっても落ちないようにする
  • set +e をつけて通す