これは非常に曖昧なコーナーケースであり、テスト[
組み込みの定義方法のバグを考慮する場合があります。ただし、[
多くのシステムで使用可能な実際のバイナリの動作と一致します。私の知る限り、それだけで特定のケースと一致する値持つ変数に影響する[
ようなオペレータ(
、!
、=
、-e
、などを。
BashとPOSIXシェルでその理由と回避方法を説明します。
説明:
以下を考慮してください。
x="("
[ "$x" = "(" ] && echo yes || echo no
問題ない; 上記はエラーを生成せず、を出力しますyes
。これは、私たちが何かを機能させることを期待する方法です。'1'
必要に応じて比較文字列との値を変更するとx
、期待どおりに機能します。
実際の/usr/bin/[
バイナリは同じように動作することに注意してください。たとえば、実行すると'/usr/bin/[' '(' = '(' ']'
エラーは発生しません。これは、引数が単一の文字列比較操作で構成されていることをプログラムが検出できるためです。
ときに我々はバグが発生すると、第二の発現と。有効である限り、2番目の式が何であるかは関係ありません。例えば、
[ '1' = '1' ] && echo yes || echo no
出力yes
、および明らかに有効な式です。しかし、2つを組み合わせると、
[ "$x" = "(" -a '1' = '1' ] && echo yes || echo no
バッシュは、以下の場合に式を拒否した場合にのみx
です(
か!
。
実際の[
プログラムを使用して上記を実行する場合、すなわち
'/usr/bin/[' "$x" = "(" -a '1' = '1' ] && echo yes || echo no
エラーが理解できるであろう:シェルは変数置換を行うため、/usr/bin/[
バイナリのみパラメータを受信(
=
(
-a
1
=
1
し、終端が]
そこにいる、オープン括弧サブ表現を開始するかどうか、それは当然のことながら解析に失敗したかどうかと 関係する動作を制御します。確かに、2つの文字列比較として解析することは可能ですが、そのように貪欲に行うと、括弧で囲まれた部分式を持つ適切な式に適用すると問題が発生する可能性があります。
問題は、実際には、[
組み込みのシェルx
が式を調べる前に値を拡張した場合と同じように動作することです。
(これらのあいまいさ、および変数展開に関連する他の理由は、Bashが実装された大きな理由であり、[[ ... ]]
代わりにテスト式の使用を推奨しています。)
回避策は簡単で、古いsh
シェルを使用するスクリプトでよく見られます。多くの場合x
、文字列の前に「安全な」文字を追加し(両方の値が比較される)、式が文字列比較として認識されるようにします。
[ "x$x" = "x(" -a "x$y" = "x1" ]
[[ "$x" = '1' && "$y" = '1' ]]