[シェル] カッコの意味と役割まとめ [Bash, Linux]

[シェル] カッコの意味と役割まとめ [Bash, Linux]

シェルスクリプトで使用されるカッコいろいろ

シェルスクリプト(コマンド)で使われるカッコにはそれぞれ異なる文法上の意味があります。ここでは8種類のカッコの使い方についてまとめます。

  • [] 角括弧、bracket、ブラケット
  • [[]] 二重角括弧、double bracket、ダブルブラケット
  • () 丸括弧、parenthesis、パーレン
  • (()) 二重丸括弧、double parenthesis、ダブルパーレン
  • $() ドル丸括弧、ドルパーレン
  • $(()) ドル二重丸括弧、ドルダブルパーレン
  • {} 波括弧、brace、ブレース
  • ${} ドル波括弧、ドルブレース

[] 角括弧、bracket、ブラケット

[] ブラケットは test コマンドど等価のコマンドです。

【 test 】コマンド(基礎編)――ファイルの有無などを判定する:Linux基本コマンドTips(221) – @IT

test コマンドは if 文を書く時の条件式を書くときに使用されることが多いコマンドです。

# [] ブラケットで条件式を記述して判定できる
$ if [ 1 -eq 1 ]; then echo 'equal'; fi
equal

# test と等価です。
$ if test 1 -eq 1; then echo 'equal'; fi
equal

test 1 -eq 11==1 の条件判定をしています。絶対に true なので 'equal' が出力されます。

ブラケットを使用するメリットは if 文の条件式が見やすくなる点です。

括弧の前後にはスペースを挿入しないと怒られます。[ はコマンドの1つなのでスペースで区切ると覚えておきましょう。

[[]] 二重角括弧、double bracket

[[]][] ブラケットと同じような機能を持ちます。つまり test と等価ですが Bash でしか使えません。

[[]] は Bash で追加された組み込みのコマンドで [] の機能を拡張したコマンドになります。

$ if [[ (1==1) && (1==2 || 3==1+2) ]]; then echo 'true'; fi
true

こんな感じで使います。[] だとうまく動きません。

[[ はBash の組み込みコマンドなので help [[ とすればヘルプが確認できます。

( EXPRESSION )    Returns the value of EXPRESSION
! EXPRESSION      True if EXPRESSION is false; else false
EXPR1 && EXPR2    True if both EXPR1 and EXPR2 are true; else false
EXPR1 || EXPR2    True if either EXPR1 or EXPR2 is true; else false

こんな感じの機能が使えるようになります。プログラミング言語で基本的な条件式の書き方ができるようになります。否定、論理和、論理積などがよくある記号で使えるので便利です。その他機能はヘルプを確認してください。

() 丸括弧、parenthesis、パーレン

() パーレンはサブシェルでコマンドを実行します。

$ HOGE='1'
$ echo "サブシェル実行前: $HOGE"
サブシェル実行前: 1

$ (echo "変更前: $HOGE"; HOGE='2'; echo "変更後: $HOGE")
変更前: 1
変更後: 2

$ echo "サブシェル実行後: $HOGE"
サブシェル実行後: 1

サブシェルの実行は、カレントシェルの環境(シェル変数など)を引き継ぎます。カレントシェルにはサブシェル内のシェル変数の定義内容変更が影響しません。それが上のスクリプトで確認できます。

サブシェル実行結果をリダイレクト

() パーレンでサブシェル実行の結果をリダイレクトして使うこともできます。

# サブシェルでの echo 結果を標準入力にリダイレクト
$ sort <(echo hoge; echo foo; echo bar;)
bar
foo
hoge

使い勝手の良いコマンドです。

(()) 二重丸括弧、double parenthesis、ダブルパーレン

(()) 二重丸括弧は単体の丸括弧 () と全く違う意味を持ちます。(())for 文でC言語スタイルの条件を書くために使います。forwhile と組み合わせるとC-Styleの条件で書けます。

Bash で使えます。help 'for ((' でヘルプが見れます。

以下for文の一例です。

$ for (( i=0; i<3; i++)); do echo $i; done
0
1
2

ワンライナーで書くならこのように for 文が書けます。

スクリプトとして定義する場合には複数行でいい感じになります。

my_script.sh

#!/bin/bash

# 2以上10以下の偶数を出力するfor文
for ((i=2; i<=10; i+=2)); do
    echo $i
done

そのほかの for 文との比較

シェルスクリプトで for in を使えば for (( と同じことができますが、幾つか方法があるので参考にまとめておきます。

$ for ((i=0; i<3; i++)); do echo $i; done
$ for i in {0..2}; do echo $i; done
$ for i in `seq 0 2`; do echo $i; done
$ for i in $(seq 0 2); do echo $i; done
$ for i in 0 1 2; do echo $i; done

全部出力は 0, 1, 2 の3行です。

単純な区間のループなら for i in {0..2} みたいな書き方のほうがわかりやすいし安全な気がするのですが、少し複雑な繰り返し条件を書くなら C-Style で書くのもよいですね。

while 文の条件にも使える

while 文の条件式にも (()) 二重丸括弧が使えます。

$  while ((1==1)); do echo hello; sleep 1; done
hello
hello
..

上記コマンドでは、1秒ごとに echo が繰り返し実行されます。

$() ドル丸括弧、ドルパーレン

$() ドルパーレンは、カッコ内のコマンドを実行して実行結果を文字列として展開します。つまりバッククォートと同じ機能です。

シェルスクリプトのクォートの使い方と変数埋め込みの方法まとめ │ Web備忘録

# date コマンドの実行結果が文字列内に展開される
$ HOGE="today is $(date)"

# 結果確認
$ echo $HOGE
today is Mon Mar 1 23:50:27 JST 2021

バッククォートに置き換えても同じ結果になります。

入れ子にして実行

$() は入れ子にして実行することができます。例えばカレントディレクトリのディレクトリ名を取得するには以下のように入れ子の記述が可能です。バッククォートだと入れ子で記述できませんが、$() なら可能です。

$ echo "current directory name: $(basename $(pwd))"
current directory name: sample

$(()) ドル二重丸括弧、ドル二重パーレン

$(()) ドル二重パーレンは算術演算を実行し結果を展開します。

$ echo "1 + 2 = $((1 + 2))"
1 + 2 = 3

こんな感じで加減算などの算術演算を実行し、その結果を文字列内に展開してくれます。

算術計算のを実行するためには expr コマンドで数式を評価することでも可能です。

$ expr 1 + 2
3

# echo "1 + 2 = $((1 + 2))" と等価
$ echo "1 + 2 = `expr 1 + 2`"
1 + 2 = 3

expr で実行した計算結果をバッククォートで埋め込めば $(()) と同じ機能が実現できます。$(()) のほうがわかりやすいですね。

{} 波括弧、ブレース

{} ブレースは2つの文脈で異なる意味を持つ記号になります。

{} カレントシェルでコマンドを1グループとして事項

{} ブレースはカレントシェルで一連の処理を1まとまりのグループとして実行します。() パーレンがサブシェルで一連の処理を実行するのに対して、カレントシェルで実行するのが {} ブレースです。

{ もコマンドです。なので { の前後はスペースが必要です。help { でヘルプが見れます。

使い方は以下の通りです。

# echo を3回実行する処理をカレントディレクトリで実行
$ { echo hoge; echo foo; echo bar; } > output.txt

$ cat output.txt
hoge
foo
bar

{} で複数のコマンドは末尾に ; を付けなければ実行時にエラーになります。一連のコマンドをグループ化して実行します。一連の処理が1グループとして実行されるのでリダイレクト結果も1つになります。したがってリダイレクト結果も1まとまりです。

サブシェルで実行する () パーレンと同じように使えますが、() の前後のスペースと、コマンド末尾にを ; を付けることを忘れないようにしましょう。

{} ブレース展開

bash の機能の1つです。

{} ブレースの中に複数の値を指定することで、それぞれの値を展開した結果を得ることができます。意味合い的には * を使ったワイルドカードと同じような位置づけです。

複数の値を展開する

展開結果は以下のようになります。

$ echo data_{a,b,c}
data_a data_b data_c

# カンマだけなら空文字として展開
$ echo hoge{x,y,z,}
hogex hogey hogez hoge

例えば複数のディレクトリを連番で一気に作成したいときは以下のように記述できます。

# dir_1, dir_2, dir_3 を作成する
$ mkdir dir_{1,2,3}
$ ls
dir_1  dir_2  dir_3

# dir_1, dir_2, dir_3 を削除する
$ rm -d dir_{1,2,3}

連続してブレース展開を使用すると組み合わせが列挙されます。

# 2通りx3通り=6通りの組み合わせ
$ echo {0,1}{A,B,C}
0A 0B 0C 1A 1B 1C

これは面白い使い方ですね。

連番を展開するなら以下のようにしたほうがわかりやすいです。

連番やアルファベットを展開する

{[start]..[end]}start 以上 end 以下の範囲の整数をスペース区切りで出力します。start >= end であれば逆順になります。1ずつインクリメントされます。

$ echo {1..10}
1 2 3 4 5 6 7 8 9 10

# 逆順もOK
$ echo {10..1}
10 9 8 7 6 5 4 3 2 1

アルファベットでも範囲指定が可能です。

$ echo {A..Z}
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
$ echo {Z..A}
Z Y X W V U T S R Q P O N M L K J I H G F E D C B A
$ echo {a..z}
a b c d e f g h i j k l m n o p q r s t u v w x y z
$ echo {z..a}
z y x w v u t s r q p o n m l k j i h g f e d c b a

インクリメントする値を指定することも可能です。{[start]..[end]..[value]}value だけインクリメントしてくれます。

# 1以上10以下で2ずつインクリメントした結果 => 奇数
$ echo {1..10..2}
1 3 5 7 9

# Aから1文字飛ばしでアルファベットを出力
$ echo {A..Z..2}
A C E G I K M O Q S U W Y

この展開の使い方はfor文でよく使います。

$ for i in {1..5}; do echo $i; done
1
2
3
4
5

${} ドル波括弧、ドルブレース

${} ドルブレースは、変数の埋め込みを行うときに使用します。例えば $HOGE で変数を文字列内に埋め込んだ時に、変数名の区切りがうまく処理できない場合には ${HOGE} のようにして使用すると埋め込みがうまくいきます。

# 変数HOGE の直後に 'HOGE' と出力したい
$ echo "${HOGE}HOGE"
HOGEHOGE

# これだと HOGEHOGE という変数を埋め込もうとする
$ echo "$HOGEHOGE"

以上。

参考URL

Linuxカテゴリの最新記事