私はif
に関するbashの例を読んでいますが、いくつかの例は単一の角括弧で書かれています:
if [ -f $param ]
then
#...
fi
その他の二重角かっこ:
if [[ $? -ne 0 ]]
then
start looking for errors in yourlog
fi
違いはなんですか?
単一の[]
は、posix Shell準拠の条件テストです。
Double [[]]
は、標準[]
の拡張であり、bashおよびその他のシェル(zsh、kshなど)でサポートされています。追加の操作(および標準のposix操作)をサポートします。例:||
の代わりに-o
および=~
と一致する正規表現。相違点のより完全なリストは、 条件付き構文に関するbash手動セクション にあります。
スクリプトをシェル間で移植できるようにする場合は、[]
を使用します。 [[]]
でサポートされない条件式が必要で、移植性を必要としない場合は、[]
を使用します。
行動の違い
Bash 4.3.11でテスト済み:
POSIX対Bash拡張機能:
通常コマンドvsマジック
[
は、奇妙な名前の通常のコマンドです。
]
は[
の単なる引数であり、これ以上の引数が使用されないようにします。
Ubuntu 16.04には、coreutilsが提供する/usr/bin/[
に実際に実行可能ファイルがありますが、bashの組み込みバージョンが優先されます。
Bashがコマンドを解析する方法に変更はありません。
特に、<
はリダイレクト、&&
および||
は複数のコマンドを連結し、( )
は\
でエスケープされない限りサブシェルを生成し、Wordの展開は通常どおり行われます。
[[ X ]]
は、X
を魔法のように解析する単一の構成体です。 <
、&&
、||
、および()
は特別に処理され、Wordの分割ルールは異なります。
=
や=~
などの違いもあります。
Basheseの場合:[
は組み込みコマンドであり、[[
はキーワードです。 https://askubuntu.com/questions/445749/whats-the-difference-between-Shell -builtin-and-Shell-keyword
<
[[ a < b ]]
:辞書編集の比較[ a \< b ]
:上記と同じ。 \
が必要です。または、他のコマンドと同様にリダイレクトを行います。バッシュ拡張。expr a \< b > /dev/null
:POSIX同等²、参照: Bashで辞書式の文字列をテストする方法?&&
および||
[[ a = a && b = b ]]
:true、論理and[ a = a && b = b ]
:構文エラー、&&
ANDコマンド区切りとして解析cmd1 && cmd2
[ a = a -a b = b ]
:同等ですが、POSIX³で非推奨[ a = a ] && [ b = b ]
:POSIXおよび同等の信頼できる(
[[ (a = a || a = b) && a = b ]]
:false[ ( a = a ) ]
:構文エラー、()
はサブシェルとして解釈されます[ \( a = a -o a = b \) -a a = b ]
:同等ですが、()
はPOSIXで非推奨になりました{ [ a = a ] || [ a = b ]; } && [ a = b ]
POSIXと同等5展開時の単語分割とファイル名生成(split + glob)
x='a b'; [[ $x = 'a b' ]]
:true、引用符は不要x='a b'; [ $x = 'a b' ]
:構文エラー、[ a b = 'a b' ]
に展開x='*'; [ $x = 'a b' ]
:現在のディレクトリに複数のファイルがある場合の構文エラー。x='a b'; [ "$x" = 'a b' ]
:POSIXと同等=
[[ ab = a? ]]
:true パターンマッチング (* ? [
は魔法)を行うため。現在のディレクトリ内のファイルに展開しません。[ ab = a? ]
:a?
globが展開されます。したがって、現在のディレクトリ内のファイルに応じて、trueまたはfalseになる場合があります。[ ab = a\? ]
:glob展開ではなくfalse=
と==
は[
と[[
の両方で同じですが、==
はBash拡張機能です。case ab in (a?) echo match; esac
:POSIXと同等[[ ab =~ 'ab?' ]]
:false4、''
で魔法を失います[[ ab? =~ 'ab?' ]]
:true=~
[[ ab =~ ab? ]]
:true、POSIX 拡張正規表現 一致、?
はグロブ展開しません[ a =~ a ]
:構文エラー。同等のbashはありません。printf 'ab\n' | grep -Eq 'ab?'
:POSIX同等(単一行データのみ)awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?'
:POSIXと同等。推奨事項:常に[]
を使用します。
私が見たすべての[[ ]]
コンストラクトに対応するPOSIXがあります。
[[ ]]
を使用する場合:
[
は、奇妙な名前を持つ通常のコマンドであり、特別なセマンティクスは含まれていません。¹Kornシェルの同等の[[...]]
コンストラクトに触発された
²ただし、a
またはb
の一部の値(+
またはindex
など)で失敗し、a
とb
が似ている場合は数値比較を行います。 10進整数。 expr "x$a" '<' "x$b"
は両方を回避します。
³また、!
や(
のようなa
またはb
の一部の値でも失敗します。
4 bash 3.2以降では、bash 3.1との互換性が提供されていません(BASH_COMPAT=3.1
など)
5 ただし、グループ化(ここでは、不要なサブシェルを実行する{...;}
の代わりに(...)
コマンドグループ)は、||
および&&
シェル演算子としては必要ありません( ||
および&&
[[...]]
演算子または-o
/-a
[
演算子)の優先順位は同じです。したがって、[ a = a ] || [ a = b ] && [ a = b ]
は同等です。
条件テスト用の単一の角かっこ(つまり[...])内では、単一の=
などの一部の演算子はすべてのシェルでサポートされていますが、演算子==
の使用は一部の古いシェルではサポートされていません。
条件テストの二重括弧([[...]])内では、古いシェルと新しいシェルで=
または==
を使用しても違いはありません。
編集:私も注意する必要があります:bashでは、可能であれば常に二重角括弧[[...]]を使用してください。単一角括弧よりも安全です。次の例でその理由を説明します。
if [ $var == "hello" ]; then
$ varがnull /空の場合、スクリプトは次のように表示されます。
if [ == "hello" ]; then
スクリプトが壊れます。解決策は、二重角括弧を使用するか、変数を常に引用符で囲むことです("$var"
)。二重括弧は、より防御的なコーディングの実践です。
[[
は、[
コマンドに似た(ただしより強力な)bashキーワードです。
見る
http://mywiki.wooledge.org/BashFAQ/031 および http://mywiki.wooledge.org/BashGuide/TestsAndConditionals
POSIX sh用に書いているのでない限り、[[
をお勧めします。
Bashマニュアル 言う:
[[と共に使用すると、「<」および「>」演算子は現在のロケールを使用して辞書式にソートされます。テストコマンドは、ASCII順序を使用します。
(テストコマンドは[]と同じです)
軽い正規表現のマッチングに二重角括弧を使用できます。 :
if [[ $1 =~ "foo.*bar" ]] ; then
(使用しているbashのバージョンがこの構文をサポートしている限り)