回答:
との違いは[[ … ]]
、シングルブラケットまたはダブルブラケット-bashの使用で[ … ]
ほとんどカバーされています。重要なのは、[[ … ]]
特別な構文[
ですが、コマンドの面白い名前です。[[ … ]]
内部には特別な構文規則[ … ]
がありますが、そうではありません。
ワイルドカードのしわが追加されたため、[[ $a == z* ]]
評価方法は次のとおりです。
[[ … ]]
条件式を囲む条件構造$a == z*
です。==
、オペランド$a
とを持つ2項演算子z*
です。a
。==
演算子をます:変数の値がa
patternと一致するかどうかをテストしますz*
。方法は次のとおりです [ $a == z* ]
評価は次のとおりです。
[
単語を評価することによって形成された引数を指定して、コマンド$a
、==
、z*
、]
。$a
変数の値にa
。a
6文字の文字列であるfoo b*
(例えばによって得られたa='foo b*'
)と、現在のディレクトリ内のファイルのリストが(あるbar
、baz
、qux
、zim
、zum
)、その後、展開の結果は、単語の次のリストであります:[
、foo
、bar
、baz
、==
、zim
、zum
、]
。[
前の手順で取得したパラメーターを使用してコマンドを実行します。
[
コマンドは構文エラーを訴え、ステータス2を返します。注:では[[ $a == z* ]]
、ステップ3 a
で、単一の単語が期待されるコンテキスト(条件演算子の左側の引数)にあるため、値の単語分割とファイル名生成は行われません==
。ほとんどの場合、その位置で単一の単語が理にかなっている場合、変数の展開は二重引用符の場合と同様に動作します。ただし、そのルールには例外が[[ abc == $a ]]
ありa
ます。in の値にワイルドカードが含まれている場合a
、ワイルドカードパターンと照合されます。値は、たとえば、a
あるa*
その後、[[ abc == $a ]]
真である(なぜならワイルドカード*
の引用符で囲まれていない拡張からの$a
マッチ*
)、一方[[ abc == "$a" ]]
(偽である通常の文字ため*
の引用符で囲まれた部分の拡張は$a
一致しませんbc
)。内部は[[ … ]]
、二重引用符は、違いを確認していない文字列マッチング演算子の右側のを除いて(=
、==
、!=
および=~
)。
[
test
コマンドのエイリアスです。Unixバージョン6にはif
コマンドがありましたが、バージョン7(1979)にはif-then-else-elif-fi構成を含むいくつかのプログラミング構成を持つ新しいBourneシェルが付属し、Unixバージョン7にはほとんどのコマンドを実行するコマンドが追加されました古いバージョンのコマンドによって実行された「テスト」。test
if
[
test
Unix System III(1981)のエイリアスになり、両方ともシェルに組み込まれました。[
ただし、Unixの一部の亜種はその後ずっとコマンドを持たないことに注意する必要があります(Almquistシェルに基づく一部のBSDでは2000年代前半までsh
(test
ビルトインは常にash
ソースにが、最初は無効だったBSD))。
注意test
別名[
「テスト」を行うためのコマンドであり、そのコマンドが行うことは割り当てがありませんが、そう割り当てと等価演算子の間に明確にする理由はありませんので、等価演算子です=
。==
は、いくつかの最近の実装でのみサポートされています[
(およびの単なるエイリアスです=
)。
[
コマンドにすぎないため、シェルは他のコマンドと同じ方法で解析されます。
具体的には、あなたの例$a
では、引用されていないため、単語分割の通常の規則に従って複数の単語に分割され、各単語はファイル名生成またはグロブを経てより多くの単語になり、それぞれの単語は[
コマンドへの個別の引数。
同様z*
に、現在のディレクトリ内のファイル名のリストに展開されますz
。
あれば、たとえば、$a
あるb* = x
、とがありz1
、z2
、b1
そしてb2
現在のディレクトリ内のファイルは、[
コマンドが9つの引数を得るでしょう:[
、b1
、b2
、=
、x
、==
、z1
、z2
と]
。
[
引数を条件式として解析します。これらの9つの引数は、有効な条件式には加算されないため、おそらくエラーが返されます。
[[ ... ]]
コンストラクトは、おそらく1988年頃としてKornシェルによって導入されたksh86a
一方、1987年にそれを持っていなかったksh88
最初からそれを持っていました。
ksh(すべての実装)の他に、[[...]]
bash(バージョン2.02以降)およびzshでもサポートされていますが、3つの実装はすべて異なり、同じシェルの各バージョンには違いがありますが、変更は一般に下位互換性があります(bashの顕著な例外です)=~
特定のバージョンの動作が変更された後にいくつかのスクリプトを壊すことが知られている演算子)。[[...]]
POSIX、UnixまたはLinux(LSB)では指定されていません。数回の組み込みが検討されていますが、主要なシェルでサポートされている一般的な機能は[
コマンドとcase-in-esac
構成体ですでにカバーされているため、含まれていません。
[[ ... ]]
構造全体がコマンドを構成します。つまり、終了ステータス(条件式の評価の結果として最も重要な資産)があり、別のコマンドにパイプすることができます(有用ではありませんが)、通常はどこでも使用します他のコマンドを使用します(シェル構造であるため、シェル内のみ)が、通常の単純なコマンドのように解析されません。内部の内容はシェルによって条件式として解析され、単語分割とファイル名生成の通常の規則は異なって適用されます。
[[ ... ]]
は==
最初から認識しており、=
1と同等です。ただし、kshの失敗(および混乱と多くのバグを引き起こしている)は、=
and ==
が等号演算子ではなく、パターン一致演算子であることです(ただし、一致する側面は、引用によって無効にできますが、シェルごとに異なる不明確なルールがあります)。
上記のコード[[ $a == z* ]]
では、シェルはそれを通常のルールと同様のルールでいくつかのトークンに解析し、パターン一致比較として認識しz*
、a
変数の内容と一致するパターンとして扱います。
一般的に、足で撃つの[[ ... ]]
は、[
コマンドを使うよりも難しいです。しかし、次のようないくつかのルール
-a
or -o
演算子を使用しない(いくつかの[
コマンドと&&
and ||
シェル演算子を使用する)作る[
POSIXシェルで信頼性の高いです。
[[...]]
異なるシェルでは-nt
、正規表現マッチング演算子などの追加の演算子をサポートしていますが、リストと動作はシェルごと、バージョンごとに異なります。
そのため、スクリプトの解釈対象となるシェルとその最小バージョンがわからない限り、おそらく標準[
コマンドを使用する方が安全です。
1例外:[[...]]
バージョンでbashに追加されました2.02
。2.03
変更されるまで、[[ x = '?' ]]
trueを[[ x == '?' ]]
返し、falseを返します。つまり=
、これらのバージョンで演算子を使用する場合、引用符はパターンマッチングを防止しませんでしたが、を使用する場合は防止しました==
。
[ '!' = foo -o a = a ]
してbash
例えば。
どちらも式を評価するために使用され、[[はPOSIXの古いボーンシェルでは機能しません。また、[[はパターンマッチングと正規表現もサポートします。例これらを試してください
[ $n -eq 0 -a $y -eq 0 ] && echo "Error" || echo "Ok"
[[ $n -eq 0 && $y -eq 0 ]] && echo "Error" || echo "Ok"
[[...]]
、一部のシェルの一部のバージョンでのみ[
正規表現をサポートすることに注意してください。arithemtic比較のために、これらのシェルでサポートすることを[[
、あなたはかなり書きたい(( n == 0 && y == 0))