それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

bashの似てて紛らわしいもの (( / $(( の丸括弧

似てて紛らわしいものシリーズ (( / $((

bash の記述で初心者泣かせの、似てて紛らわしかったり、どう使っていいかわからなかったり、読み方を間違えてパニックになる記号について

(( / $(( の違い

(( / $(( は数字を計算する方法です。どちらも同じ機能を持ちますが・・・

  • (( はコマンド
  • $(( は展開表現

コマンドとは実行されるもの、展開表現とは実行される前に置換されるもの。

$(( {1..10}$varname と同じく、インタプリタが解釈した時点で評価され文字に置き換わります。

(( はコマンド として実行され、終了ステータスを返します。

どちらも数値計算をする点は同じ

(( / $((は、どちらも次のように、代入を解釈したり、四則演算や比較評価をする点においては同じです。次のような計算ができます。

i++
i=0
i=i+1
i%=10
i==9

実行前に解釈される $((

$(( 実行前に計算されて文字列として結果を返します。 *1

$(( の例

$ echo $(( 1 + 1 )); echo $?#=>0
2

よくある間違い

$  $(( 1 + 1 )) # コレは間違い

とくにわけがわからなくなるのが、この間違いの記述。実行前に解釈されて文字列に置き換わる、そして出力結果を実行しようとする。

$  $(( 1 + 1 )) # コレは
$  2 # こうなって
$  2 # コマンドが見つからない・・・

$((の意味は $( に近いです。 echo $( command ) が先にcommandが実行され、結果に置き換わるのと同じです。

echo $(( 1+1)) と書いたときも、 先に (( が実行され、結果の文字列 に置換されます。その結果echo 2 となりコレが実行されるのです。

コマンドとしての ((

(( はコマンドとして実行されます。

正しく数値計算ができたら終了ステータス0、比較結果がfalse なときも終了ステータス1を返します。

あと、ゼロ除算など数値計算が出来ない時は終了ステータス1を返します。

コマンドなので、コマンドが書ける所なら、どこにでも記述できます。つまり if 文や while などの条件(コマンド)として使えるのです。

コレは間違い
$ echo (( 1 + 1  )) # 間違い echo はコマンドを引数に取らない
コレらは全て正しい記述
## 足し算
$ (( 1 + 1 ))  ; 
## 変数の計算
$  i=0; (( i++ ))  ; echo $i ; 
## 変数の比較
$ (( i = 1 )); (( i > 0 )) && echo $i; 
## while 内で加算と比較
$ i=0; while (( i++ , i < 10 )); do echo $i ; done ;

true と false に注意

(( expression )) の 比較は(( 1 > 0 )) true になるが、終了ステータスは0である。文字は返ささない

$(( expression )) の比較は$(( 1 > 0 )) は true になり、文字列として1が返ってくる。

補足すると、$(( expression ))は展開されるので終了ステータスは存在しない

true の扱いについては油断してると頭の中を持っていかれるので注意が必要。

*1: 実行前という表現が正しいかわかりませんが、コマンドとして実行される前という意味です。