`==`がzshとbashの `[…]`内で異なる動作をするのはなぜですか?


9

私がこれを行うときに私が期待したものを得ますbash

[ "a" == "a" ] && echo yes

それは私を与えましたyes

しかし、これをで行うとzsh、次のようになります。

zsh: = not found

同じコマンド(/usr/bin/[)が異なるシェルで異なる動作をするのはなぜですか?


5
同じコマンドではありません-以前に見つかった組み込みコマンド$PATHが検索されます。そして、アウェイの==有効なtest構文ではありません/usr/bin/[。ただ、=結構です。
mikeserv 2016年

回答:


18

/usr/bin/[どちらのシェルにもありません。Bashでは、組み込みのtest/ [コマンドを使用しており、同様にzshでも使用しています。

違いはあるのzshも有する=拡張=fooパスに展開foo実行します。つまり==、で呼び出さ=れたコマンドを見つけようとするものとして扱われますPATH。そのコマンドは存在しないため、エラーが発生します

zsh: = not found

(実際にを使用していても、同じことが起こります/usr/bin/[)。


あなたは、することができます使用し==、あなたが本当にしたい場合はこちら。これは、zshで期待どおりに機能します。

[ "a" "==" "a" ] && echo yes

引用は=word拡張の実行を妨げるためです。でequalsオプションを無効にすることもできますsetopt noequals


ただし、次のいずれかをお勧めします。

  • 単一=のPOSIX互換同等性テストを使用します。または
  • Bashzshの両方で条件を使用すると[[==さらに良いです。一般的には、内部に特別な解析ルールを設定することで、この種の問題(およびその他の問題)を回避することを含め、すべての点で優れており、安全です。[[

間の正確な違いは何だ[とは[[?(Googleで検索すると、検索[ vs [[結果vsのみが表示されます、LOL)
Johnson Steward '15年

2
[[はどちらの場合もより広い範囲のテストをサポートし、変数や演算子などを引用する必要をなくすカスタム解析ルールを備えています。特にBashまたはzshを使用している場合は、を使用してください[[。移植可能なスクリプトを作成している場合は、POSIX互換の[/ testコマンドに書き込みます(実行中のシステムで実際のコマンドである場合とそうでない場合があります)。
Michael Homer

1
ちょうど[[そこに使用して、存在を忘れてください[
Michael Homer

1
あなたが知っている...私はあなたの推薦に同意しません。[[機能は異なります。これを試してみてくださいfor f in *; do [ -e "$f" ] && for a in f d h p S b c; do [ "-$a" "$f" ] && for p in r w x u g; do [ "-$p" "$f" ] || p=-; a=$a$p; done && break; done && printf "%s:\t%s\n" "$a" "$f"; done
mikeserv '15年

3
まあ、=/ ==間違いなく一つのケースである[[よりも良好ではない[として、[[ a == b ]]ある「」「B」のパターンと一致しないし、ではない「」「B」に等しく、あなたが期待通り。それは[[ $a == "$b" ]]、例えばあなたが書く必要があることを意味します。少なくとも、この[コマンドを使用すると、コマンドの解析がどのように機能するかがわかっていれば[ "$a" = "$b" ]、他のコマンドのようにsplit + glob演算子を回避するためにそれを記述する必要があることがわかります。これを念頭に置き、-aまたは-oを使用しない場合[は、POSIX準拠の実装で安全です。
ステファンChazelas

2

そしてzshとbashは同じ答えを出します(type両方のシェルにも組み込みです):

$ type -a [
[ is a shell builtin
[ is /usr/bin/[

2

[ bashおよびzshのシェル組み込みコマンドです。

$ type [
[ is a shell builtin

以下からのシェルの組み込みコマンドのドキュメント

組み込みコマンドはシェル自体に含まれています。組み込みコマンドの名前が単純コマンドの最初の単語として使用されている場合(単純コマンドを参照)、シェルは別のプログラムを呼び出さずにコマンドを直接実行します。組み込みコマンドは、別個のユーティリティで取得することが不可能または不便な機能を実装するために必要です。

公式ドキュメント($ help test)でのみ使用できます=

STRING1 = STRING2

文字列が等しい場合はTrue。

したがって、正しい式は次のようになります。

$ [ "a" = "a" ] && echo yes
yes

何が起こるかというと、bashは少し厳密ではありません。での==オペレーターのサポートは[ bash拡張機能のようであり、使用することはお勧めしません。

string1 == string2

string1 = string2

文字列が等しい場合はTrue。[[コマンドと一緒に使用すると、上記のようにパターンマッチングが実行されます(条件付き構成体を参照)。

'='は、POSIX準拠のテストコマンドで使用する必要があります。

を使用する==場合は、次の[[キーワードを使用する必要があります。

$ [[ "a" == "a" ]] && echo yes
yes

覚えておいてください[[あまりポータブルである(POSIXではありません)。しかし、bashとzshの両方がサポートしています。


1

両方のシェルでは、bashzsh[ユーティリティは、シェルの組み込みです。これはそのツールのシェル実装であり、バイナリよりも優先的に使用されます/usr/bin/[。異なる結果は、実装によって異なります。


ではbash[ユーティリティは複合コマンドCONDITIONAL EXPRESSIONSとして受け入れます[[。bashs manページによると、両方===有効です。

string1 == string2
string1 = string2
        True if the strings are equal.  = should be used with the test command for POSIX
        conformance.

ではzsh[ユーティリティはPOSIXとその拡張が指定されている場合、それらを実装しようとします。POSIXテストユーティリティの仕様全く存在しない==オペレータ定義されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.