似てて紛らわしいものシリーズ
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 )) ))
こんな使い方はやめましょう・・・
参考資料
- man bash
`
(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".
`