2つの間に違いはありますか?
[[ $a == z* ]]
そして
[ $a == z* ]
異なる出力が出てくる例を見てもいいですか?
[[ ]]
また、どのように異なる動作をしますか[ ]
?
答え1
[[ … ]]
との違いは[ … ]
主に次に反映されます。引用符なしの空白パラメータ拡張が二重括弧 "[["内では機能しますが、単一括弧"["内では機能しないのはなぜですか?。重要なのは[[ … ]]
特別な構文では[
ありません。[[ … ]]
内部コンテンツの特別な文法規則はありません[ … ]
。
ワイルドカードを追加した後の[[ $a == z* ]]
計算は次のようになります。
[[ … ]]
構文解析コマンド:条件式の条件付き構成$a == z*
。- 条件式解析:
==
オペランドが$a
sumの二項演算子ですz*
。 - 最初のオペランドを変数値に拡張します
a
。 - 評価
==
演算子:変数の値がパターンa
と一致するかどうかをテストしますz*
。 - 条件式を評価します。結果は条件演算子の結果です。
- コマンドが評価され、条件式が true の場合は状態が 0 で、条件式が false の場合は 1 になります。
[ $a == z* ]
評価方法は次のとおりです。
- Parseコマンド:、、、
[
単語を評価して引数が形成されたコマンドです$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
ワイルドカード文字が含まれている場合、abc
ワイルドカードパターンと比較されます。たとえば、a
isの値がa*
true(引用符付き拡張子の[[ abc == $a ]]
ワイルドカード文字が一致するため)で、値がfalse(引用符付き拡張子の一般文字が一致しないため)の場合です。内部で二重引用符は違いはありません。*
$a
bc
[[ abc == "$a" ]]
*
$a
bc
[[ … ]]
文字列一致演算子の右側に追加(=
、、、==
そして!=
)=~
。
答え2
[
はコマンドのエイリアスですtest
。 Unixバージョン6にはif
コマンドがありますが、バージョン7(1979)には新しいコマンドが含まれています。ボンシェル何個ありますか?プログラムの作成構文には if-then-else-elif-fi 構文が含まれ、Unix バージョン 7 が追加されました。test
if
このコマンドは、以前のバージョンでこのコマンドで実行されたほとんどの「テスト」を実行します。
[
別名として使用され、test
両方ともUnix System III(1981)シェルに組み込まれています。。一部のUnixバリアント[
にははるかに後にまでコマンドがないことに注意する必要があります(2000年代初頭まで、一部のBSDはsh
Almquistシェルに基づいていました。(test
組み込み機能は常にash
ソースコードに含まれていましたが、これらのBSDでは最初は無効になっています。)
test
akaは割り当てを実行しない「テスト」を実行するコマンドであるため、割り当て[
演算子と恒等演算子、つまり恒等演算子を区別する理由はありません=
。==
いくつかの最近の実装でのみサポートされています[
(エイリアスとしてのみ=
)。
[
これは単なるコマンドなので、シェルはそれを他のコマンドと同じように解析します。
具体的には、あなたの例で$a
は引用されていないので、一般的な単語分割規則に従って複数の単語に分割され、各単語はファイル名の生成(別名globbing)を経て可能な限り多くの単語を生成します。各単語は、次の個別の引数を生成します。コマンド[
。
同様にz*
、現在のディレクトリに展開されますz
。
たとえば、$a
現在のディレクトリに、およびファイルがb* = x
ある場合、コマンドは、、、、、、、および9つのパラメータを取得します。z1
z2
b1
b2
[
[
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の1つのバグ(混乱と多くのバグにつながる)は、等価演算子ではなくパターンマッチング演算子です(たとえ=
=
==
マッチ側面は参照で無効にできますが、ルールは明確ではなく、シェルによって異なります。
上記のコードでは、[[ $a == z* ]]
シェルはそれを一般的な規則に似た規則のいくつかのトークンに解析し、それをパターン一致比較として認識し、変数のz*
内容に一致するパターンとして扱いますa
。
[[ ... ]]
通常、命令を出すよりも足に銃を撃つのは難しいです[
。しかし、次のようないくつかのルールがあります。
- 常に参照変数
-a
or演算子を使用しないでください-o
(複数の[
コマンドを使用して&&
ください。||
シェルオペレーター)
[
POSIXシェルを使用して安定性を向上させます。
[[...]]
追加の演算子は他のシェルでサポートされています(たとえば-nt
、正規表現一致演算子...)。ただし、リストと動作はシェルとバージョンによって異なります。
したがって、スクリプトが解釈されるシェルと最小バージョンを知らない限り、[
標準コマンドを使用する方が安全です。
11つの例外:[[...]]
バージョンのbashに追加されました2.02
。2.03
変更されるまでは[[ x = '?' ]]
trueが返され、[[ x == '?' ]]
falseが返されます。つまり、=
これらのバージョンで演算子を使用する場合は、引用のためパターンマッチングは防止されませんが、使用する場合はそうです==
。
答え3
どちらも式を評価するために使用されます。 [[ は POSIX 以前の bourn シェルでは動作しません。 [[ また、パターンマッチングと正規表現もサポートしています。次の例を試してください。
[ $n -eq 0 -a $y -eq 0 ] && echo "Error" || echo "Ok"
[[ $n -eq 0 && $y -eq 0 ]] && echo "Error" || echo "Ok"