文字列が左角かっこの場合のシェルブラケットテストエラー

文字列が左角かっこの場合のシェルブラケットテストエラー

私は、文字列を引用することは、文字列を解析するシェルを避けるために常に良い習慣であると確信していました。

それから私はこれを見つけました:

$ x='('
$ [ "$x" = '1' -a "$y" = '1' ]
bash: [: `)' expected, found 1

問題を切り離そうとしましたが、同じエラーが発生しました。

$ [ '(' = '1' -a '1' = '1' ]
bash: [: `)' expected, found 1

私は次のように問題を解決しました。

[ "$x" = '1' ] && [ "$y" = '1' ]

私はまだここで何が起こっているかを知る必要があります。

ベストアンサー1

[これは非常にあいまいなケースであり、テスト組み込みの定義方法にバグがあると思うかもしれませんが、これは多くの[システムで使用できる実際のバイナリの動作と一致します。私が知っている限り、、、、などの[演算子と一致する値を持つ特定のケースと変数にのみ影響します。(!=-e

Bash と POSIX シェルでこの問題を解決する理由と回避策について説明します。


説明する:

以下を考慮してください。

x="("
[ "$x" = "(" ] && echo yes || echo no

問題ありません。上記のコードはエラーや出力を生成しませんyes。これが私たちが期待する仕組みです。必要に応じて、比較文字列をおよび'1'値に変更でき、x期待どおりに機能します。

実際の/usr/bin/[バイナリも同じように動作します。たとえば、実行すると、'/usr/bin/[' '(' = '(' ']'プログラムは引数が単一の文字列比較操作で構成されていることを検出できるため、エラーは発生しません。

いつ私たちがそして2番目の表現を使用してください。有効な限り、2番目の表現が何であるかは重要ではありません。例えば、

[ '1' = '1' ] && echo yes || echo no

outputyesは明らかに有効な表現ですが、2つを組み合わせると

[ "$x" = "(" -a '1' = '1' ] && echo yes || echo no

xBash は is または の場合にのみ(式を拒否します!

実際のプログラムを使用して上記の内容を実行すると[

'/usr/bin/[' "$x" = "(" -a '1' = '1' ] && echo yes || echo no

エラーは理解できます。シェルが変数置換を実行するため、/usr/bin/[バイナリは引数( = ( -a 1 = 1と終端子のみを受け取るため、開かれている]括弧がサブ式を開始するかどうかは当然解析できません。そして 操作が含まれます。もちろん、これを2つの文字列比較で解析することは可能ですが、これを行うと、括弧で囲まれたサブ式が正しい式に適用されると問題が発生する可能性があります。

実際に問題は、シェル組み込みが式を確認する前に値を拡張したかの[ように動作するということです。x

(これらのあいまいさと変数の拡張に関するその他の点は、[[ ... ]]Bashがテスト式を実装し、テスト式を使用することを推奨する重要な理由です。)


回避策は簡単で、sh古いシェルを使用しているスクリプトによく表示されます。一般xに、式が文字列比較として認識されるように、文字列(比較される2つの値)の前に「安全な」文字を追加します。

[ "x$x" = "x(" -a "x$y" = "x1" ]

おすすめ記事