HOWTO · Linux

Bash でインクリメントとデクリメント演算を行う方法

Bash で変数のインクリメントとデクリメントを行うには、+ と - 演算子や += と -= 演算子を使用します。また、単項演算子を使ってインクリメントとデクリメントを行うこともできます。++ と -- です。

このページの内容

インクリメントとデクリメントは、整数変数を一定量だけ増減させます。Bashでは、算術展開、算術コマンド、let、複合代入、単項演算子を使って変数を更新できます。増減する量と、その後に使う値が読み取りやすい書き方を選びましょう。

+ と - によるインクリメントとデクリメント

$((...)) と書く算術展開は、代入や表示に使える値を生成します。((...)) と書く算術コマンドは式を評価し、変数を直接更新できます。組み込みの let でも算術式を評価できます。シェルが式全体を1つの引数として渡すように、式を引用符で囲みましょう。

次の例を実行します。

このセクションのコードと表示されるラベルや出力は英語のままです。

x=3
y=3
z=3
x=$((x + 1))
((y = y + 1))
let "z=z+1"
printf 'x: %s\ny: %s\nz: %s\n' "$x" "$y" "$z"
x=$((x - 1))
((y = y - 1))
let "z=z-1"

最初の3つの更新では、異なる算術式を使って値を1増やし、最後の3つでは値を1減らします。式の値が必要なときは算術展開が便利です。算術コマンドと let は、変数の更新に手軽に使えます。Bashの算術演算では整数を扱います。

算術更新には += と -= を使う

複合代入 x+=amount と x-=amount は、右辺の整数を左辺の変数に加算または減算します。それぞれ x=x+amount と x=x-amount に相当します。更新量が1より大きい場合や、更新量をひと目で分かるようにしたい場合に使いましょう。

このセクションのコードと表示されるラベルや出力は英語のままです。

count=10
((count += 3))
printf 'after adding 3: %s\n' "$count"
((count -= 2))
printf 'after subtracting 2: %s\n' "$count"

これらの式は count の値をその場で更新します。算術コマンドの終了ステータスは、式の評価結果がゼロかどうかで決まります。そのため、変数更新の成功を示す値として終了ステータスに頼らないでください。

1ずつ変更するには ++ と -- を使う

単項演算子 ++ と -- は、値を正確に1だけ増減させます。単独の算術コマンドとして使うと、((count++))、((++count))、((count--))、((--count)) はいずれも変数を更新します。

式の中で演算子の値を使う場合、前置と後置では結果が異なります。++count は先に更新し、新しい値を返します。count++ は古い値を返してから更新します。-- でも同じ順序になります。更新後の変数の値だけが必要なら、曖昧さを避けるため、更新を独立した文にしましょう。

このセクションのコードと表示されるラベルや出力は英語のままです。

count=4
old=$((count++))
printf 'old: %s, count: %s\n' "$old" "$count"
new=$((++count))
printf 'new: %s, count: %s\n' "$new" "$count"

ループでインクリメントとデクリメントを使う

ループの条件によって終了時点が決まり、更新処理によってカウンターがその終了条件に近づきます。この2つの向きをそろえましょう。カウンターを増やすなら上限を条件にし、減らすなら下限を条件にします。

このセクションのコードと表示されるラベルや出力は英語のままです。

for ((count = 1; count <= 3; count++)); do
  printf '%s\n' "$count"
done

count=3
while ((count >= 1)); do
  printf '%s\n' "$count"
  ((count--))
done

for ループでは、初期化、条件、増分処理をヘッダーにまとめます。while ループでは、条件を本体の前に置き、減分処理を本体の中に置きます。どのループでも、更新を続けると最終的に条件が偽になることを確認してください。

Bashの算術演算の制限とよくある質問

Bashの算術演算は整数を扱い、浮動小数点数の計算には対応していません。小数の計算には、適切な外部計算ツールか浮動小数点演算に対応する言語を使い、そのツールを別の依存関係として考慮してください。

++ と += 1 は、どちらも変数を1増やします。単項演算子は簡潔で、複合代入は増やす量が明確になり、より大きな更新にも使えます。前置と後置の違いが関係するのは、前述のとおり式の値を使う場合だけです。

算術コマンドは、式の評価結果がゼロなら終了ステータス1を返し、それ以外なら0を返します。((count--)) では、減算前の値が式の評価に使われます。count を1から0にすると終了ステータスは0ですが、0から始めた場合は変数が-1になっても終了ステータスは1です。((--count)) と ((count -= 1)) では減算後の値が使われるため、1から0にすると終了ステータスは1になります。この違いは、算術コマンドを if や while の条件として使う場合や、set -e が有効な状態で単独のコマンドとして実行する場合に重要です。ゼロ以外の終了ステータスは、制御フローに影響することがあります。上の減算ループでは、((count--)) は1から0への更新で終了ステータス0を返し、その次に明示された ((count >= 1)) の条件によってループが終了します。