それマグで!

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

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

bashの似てて紛らわしいもの ( / ((

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

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

(((

全然意味が違うので、間違えると大変。また見た目は似ているので似たようなものだろうと、タカをくくってると痛い目を見ます。

  • (( は算術計算。
  • ( はサブプロセスで実行(サブシェル起動)

とそれぞれ、全然意味が違います。

(( は算術計算

C言語のようなスタイルで、「算術計算」や「比較」「変数の加算」が出来ます。((計算結果を表示しません

不可能な計算をすると 終了ステータス1を投げてエラー・メッセージを出します。

(( の記述の例
((  i=0, i++ )) 
((  i%10 )) 
(( i > 0 ))
(( i +1  > 0 ))
(( i << 1 ))

((は if 文の中で使われるとは限りません。変数をインクリメント・デクリメントしたり let と同等なので算術計算にも使えます。

他にも

  • 四則計算と剰余* / % + -
  • 数値比較< > <= >= == !=
  • ビット演算 ~ << >> & ^ |
  • インクリメント 系id++ id-- ++id --id
  • 三項演算子 num = num ? var : num
    などが使えます。さすがに多いので、すべての例は別の記事にまとめようと思います。

( はサブシェルを起動

( の中に書かれるのは、コマンドです。コマンドはbash とは違う環境で実行される。サブ・プロセスのbash中で起動されます。

変数は引き継がれますが、サブ・プロセス中での変数変更は呼び出し元には影響しません。

これはパイプライン処理で変数の変更を維持できないのと同じこと(プロセス起動による)だと考えられます。

$ echo i=$i ;  ( ((i++));echo i=$i ; ) ; echo i=$i ;
i=1
i=2
i=1

cd なども同じです。

( を使うとよくハマるのが、ワーキングディレクトリの変更です。サブシェルの中での変更は、メインに戻ってきたとには捨てられています。

 $ pwd; ( cd /etc ; pwd ) ; pwd
/Users/takuya
/etc
/Users/takuya

((( を組み合わせたらどうなるのか

(( 1+1 ))
((( 1+1 )))
(((( 1+1 ))))

もうわけがわからないよ!!!

(( 1+1 ))      # (( 1+1 ))
((( 1+1 )))    # ((  ( 1+1 )  ))
(((( 1+1 ))))  # ((  (( 1+1 ))  ))

こんな使い方はやめましょう・・・

参考資料

`

   (list) list  is  executed in a subshell environment (see COMMAND EXECUTION ENVIRONMENT below).  Vari-
          able assignments and builtin commands that affect the shell's environment  do  not  remain  in
          effect after the command completes.  The return status is the exit status of list.
   ((expression))
          The  expression  is  evaluated according to the rules described below under ARITHMETIC EVALUA-
          TION.  If the value of the expression is non-zero, the  return  status  is  0;  otherwise  the
          return status is 1.  This is exactly equivalent to let "expression".

`