Bashシェルスクリプト上での”[..]”と”[[..]]”の違い
はじめに
Bash上で作業を行ったり、Bashのシェルスクリプトを書いたりする場合に条件分岐を使うケースがあります。
if [ -f $FILE ]; then
と記述する場合もあれば、 if [[ -f $FILE ]]; then
のように [ を2つ続けて記述する場合もあります。
両者の違いについて、知っている範囲でまとめました。
検証環境
かんたんな文字列比較処理を書いてみる
変数 X
の値が想定通りの場合に ok
と出力するだけのかんたんな条件分岐を記述してみます。
ちなみに、上記の処理は以下と同義です。
[...]
を使用した場合も [[...]]
を使用した場合もこの場合には結果は変わりません。
限られた条件における挙動の違い( 後述 )はありますが、基本的に同じように利用できます。
[
や [[
の実態はどこにある?何者なの?
[
や [[
が何者であるか?普通にLinuxを利用していると考えることは少ないでしょう。
調べてみます。
さて、ここからわかることをまとめます。
[ | [[ | |
---|---|---|
実行ファイルはある? | o | |
ビルトインコマンドである? | o | |
予約語である? | o |
実行ファイルがあったとしても、Bashを利用している限りは「ビルトインコマンド」や「予約語」の呼び出しが優先されます。
したがって、 /usr/bin/[
が呼ばれることはほぼありません。
おそらく、 /usr/bin/[
は Bash以外のシェルを想定したPOSIX標準のコマンドなのでしょう。
ちなみに /usr/bin/[ --help
を実行すると、忘れがちな条件分岐記述時に利用可能なオプションを確認できます。
( 長いので一部抜粋 )
[...]
と [[...]]
で挙動が異なるケース
ここからは、パッと思いつく両者の挙動の違いについて紹介します。
1. 正規表現が利用できるかどうか
[[...]]
では正規表現による変数のチェックが可能です。
[...]
の場合は、 =~
は不正な演算子と言われています。
2. ワイルドカードが利用できるかどうか
[[...]]
ではワイルドカードによる変数のチェックが可能です。
「正規表現」とごちゃごちゃになりそうですが、「正規表現」の場合には比較演算子 =~
を使い、「ワイルドカード」の場合には通常の文字列比較と同じように比較演算子 ==
を使います。
否定の比較演算子 !=
でも利用できます。
3. 変数が空でない判定を行う際の -n
オプションの挙動
[ -d $変数 ]
あるいは [[ -d $変数 ]]
を使って、変数が空でない条件分岐を記述できますが、 変数の状態によって挙動が変わります 。
変数が空ではない場合 は同じ挙動をします。
変数が空文字(0バイト文字)の場合 は [...]
を利用すると 変数が空ではない と判定されてしまいます。
変数が未定義の場合 も、やはり [...]
を利用すると 変数が空ではない と判定されてしまいます。
[[...]]
の挙動のほうが、直感的ではないでしょうか?
ちなみに [...}
を利用した場合でも、変数を参照する際にダブルクォートをつけると問題が解消します。
今回のケースに限らず、変数参照時はできる限り "${Y}"
のように記述する癖をつけましょう。
ひとこと
Bashでシェルスクリプトを作成している前提であれば、迷わず [[...]]
構文で条件分岐を記述したほうが良いでしょう。
ディスカッション
コメント一覧
まだ、コメントがありません