Bashの[ ] vs [[ ]]: シングル vs ダブルブラケット

bashの[ ](test)と[[ ]]の違いを理解。それぞれの使い分け、POSIX互換性、== vs =の一般的な間違いを解説します。

Deprecated Syntax

詳細な説明

シングルブラケット[ ] vs ダブルブラケット[[ ]]

[ ][[ ]]の選択は、シェルスクリプトで最も混乱しやすい側面の一つです。見た目は似ていますが、動作はかなり異なります。

[ ] — testコマンド

[ ]は実際にはtestコマンドです。シェル構文ではなく、通常のコマンドです:

# これらは同等:
[ "$var" = "hello" ]
test "$var" = "hello"

[ ]のルール:

  • 変数は必ずクォート: [ "$var" = "value" ]
  • 文字列比較には=を使用(==ではない)
  • 数値比較には-eq-lt-gtを使用
  • パターンマッチングや正規表現なし
  • &&||は外側に: [ cond1 ] && [ cond2 ]

[[ ]] — Bashキーワード

[[ ]]はBash/Zsh/Kshの組み込みキーワードで、追加機能があります:

# ワードスプリッティングなし — クォートはオプション(推奨はする)
[[ $var = "hello" ]]

# ==でパターンマッチング
[[ $file == *.txt ]]

# =~で正規表現マッチング
[[ $email =~ ^[a-zA-Z]+@[a-zA-Z]+\.[a-zA-Z]+$ ]]

# 内部で論理演算子
[[ $a -gt 0 && $b -lt 100 ]]

よくある間違い: [ ]での==

# 間違い: ==は[ ]ではPOSIXではない
if [ "$var" == "value" ]; then  # bashでは動作するがshでは動作しない

# [ ]での正解:
if [ "$var" = "value" ]; then

# [[ ]]での正解:
if [[ "$var" == "value" ]]; then

比較表

機能 [ ] [[ ]]
POSIX互換 はい いいえ(bash/zsh/ksh)
ワードスプリッティング あり(クォート必須) なし
パターンマッチング なし == *.txt
正規表現 なし =~ regex
論理演算子 外部&&/`
文字列比較 = =または==

推奨

  • Bashスクリプトでは[[ ]]を使用(#!/bin/bashシェバン付き)
  • POSIX互換性が必要な場合のみ[ ]を使用(#!/bin/sh
  • [ ]では常に変数をクォートしてワードスプリッティングを防止

ユースケース

シェルスクリプトでの条件ロジックの記述、ユーザー入力の検証、ファイルの存在と種類のチェック、文字列のパターンマッチング。ポータブルまたは高度なマッチングを使用するシェルスクリプトを書く人にとって、違いを理解することが不可欠です。

試してみる — Shell Script Linter

フルツールを開く