bash でインクリメント

  • 25
    Like
  • 2
    Comment

算術式展開というやつです。タイトルにはインクリメントとありますが、デクリメントでも同じことです。

1. expr

外部コマンドです。ゆえに bash に依存しません。ただ for 文の中で算術式計算を多数実行したりすると、目に見えて遅くなります。

count=1
count=$(expr $count + 1) # => 2

また、インクリメントに ++ は使用できません。前置も後置も不可です。

2. $(())

bash 組み込みの機能です。

count=1
count=$((++count))    # => 2
count=$((count++))    # => 2
count=$((count += 1)) # => 3

$(()) ではインクリメント演算子が使えます。前置は評価前にインクリメントした値を返し、後置は評価後です。実行例から見て取れます。また、$(()) 内の変数は $ を無視して記述できます。$var のように記述することも可能です。

+= で書くこともできます。前置と同じ動作です。

3. let

bash の builtin コマンドとして定義されています。$(()) とほぼ等価です。let コマンドの後ろに取るものを算術式として評価します。

count=1
let ++count    # => 2
let count++    # => 3

$(()) との違いは、

  • 実行後の変数自体をインクリメントする (変数自体に代入不要)
  • 終了ステータスが非ゼロのときがある

let arg [arg ...]

Each arg is an arithmetic expression to be evaluated (see ARITHMETIC EVALUATION above). If the last arg evaluates to 0, let returns 1; 0 is returned otherwise.

マニュアルにある通り、最後に評価したときにゼロであったとき 1 が返ります。

count=0
let count++ # => 1 (後置なのでこの時点では 0)
echo $?     # => 1
let count++ # => 2 (後置なのでこの時点では 1)
echo $?     # => 0
let count++ # => 3 (後置なのでこの時点では 2)
echo $?     # => 0

前置の場合、

count=0
let ++count # => 1
echo $?     # => 0
let ++count # => 2
echo $?     # => 0
let ++count # => 3
echo $?     # => 0

となります。後置のカウンタが 0 スタートのとき (count=0; let count++) は 1 で終わるので注意しましょう。

スクリプト内で set -e などをしていると予期せぬところで落ちてしまいます。