Bashの等価演算子(==、-eq)


135

誰かがbashスクリプトの-eqとの違いを説明できますか==

以下に違いはありますか?

[ $a -eq $b ] そして [ $a == $b ]

それはそれだけである==変数は、数値が含まれている場合にのみ使用されていますか?

回答:


186

これは、他の方法で回避だ:===文字列の比較のためのもの、-eq数値のものです。-eq同じ家族の中で-lt-le-gt-ge、そして-ne、それはあなたがたのである覚えている場合に役立ちます。

==ちなみに、バシズムです。POSIXを使用することをお勧めし=ます。bashでは2つは同等であり、プレーンなshでは動作=が保証されている唯一の1つです。

$ a=foo
$ [ "$a" = foo ]; echo "$?"       # POSIX sh
0
$ [ "$a" == foo ]; echo "$?"      # bash specific
0
$ [ "$a" -eq foo ]; echo "$?"     # wrong
-bash: [: foo: integer expression expected
2

(補足:これらの変数展開を引用してください!上記の二重引用符は省略しないでください。)

#!/bin/bashスクリプトを作成している場合は、代わりにを使用[[することをお勧めます。二重化されたフォームには、より多くの機能、より自然な構文、そしてあなたをつまずく落とし穴がより少ない。の周りの二重引用符は不要になりました$a

$ [[ $a == foo ]]; echo "$?"      # bash specific
0

以下も参照してください。


1
@DJCrashdummyは[[、全体として、1980年代のksh-ismであり、bash(および他の多くのシェル)が採用されています。それは全体のポイントだ-あなたが持っている場合は[[ 、すべてで、その後、あなたが安全にすべての拡張機能は、その周りに実装(のkshと仮定することができますfnmatch()スタイルのパターンマッチング、ERE正規表現で=~、はい、文字列の分割とファイルシステムグロブの抑制)になります利用可能です。以来[[、その全体が非POSIXの構文は、それは持って生まれた機能が利用可能になると仮定には、追加の移植性の損失はありません。
Charles Duffy、

1
@DJCrashdummy、...表示するリンクは、fnmatchパターンとして解釈されるものをリテラル文字列として解釈する場合は、の右側に引用符が必要な場合があることを正しく指摘してい[[ $var = $pattern ]]ます。文字列fooは非リテラルの解釈を持たないため、引用符は完全に安全です。OPが一致したい場合foo*(たとえば、アスタリスクをリテラルとして使用し、文字列の後に来ることは何も意味しないfoo)にのみ、引用符またはエスケープが必要になります。
Charles Duffy、

@CharlesDuffy残念ながら私はあなたが何を参照しているのかわかりません。私のコメントは削除されたようで、かなり長い間思い出せません。:-(
DJCrashdummy

@DJCrashdummy、...ええと、私はあなたが自分でそれを撤回すると思っていました。基本的に、それは[[バシズムである内部の引用されていない展開についての反対でした(それがあなたが答えを+1しなかった唯一の理由であることを示しています)。
Charles Duffy、

@CharlesDuffyいいえ、それが唯一の理由ではありません:単純なタスクでbash-isms、ksh-ismsなどが好きではないという事実(それは問題を引き起こし、初心者を混乱させるだけです)に加えて、なぜシングルを混合するのかわかりません中括弧[ ... ]と二重等号==。:-/
DJCrashdummy

27

オペレーターの周りのテスト構成に依存します。オプションは、二重括弧、二重ブレース、単一ブレース、またはテストです

((...))を使用する場合は==、C と同様に算術公平性をテストします。

$ (( 1==1 )); echo $?
0
$ (( 1==2 )); echo $?
1

(注0手段trueUnixのセンスおよび非ゼロでは失敗したテストです)

-eq二重括弧の内側を使用すると、構文エラーになります。

あなたが使用している場合は、[...] (またはシングルブレース)または[[...]] (またはダブルブレース)、またはtest、あなたが-eq、-ne、-lt、-le、-gtのいずれかを使用することができますか算術比較としての-ge 。

$ [ 1 -eq 1 ]; echo $?
0
$ [ 1 -eq 2 ]; echo $?
1
$ test 1 -eq 1; echo $?
0

==中括弧(またはtestコマンド)の内側は、文字列比較演算子の 1つです。

$ [[ "abc" == "abc" ]]; echo $?
0
$ [[ "abc" == "ABC" ]]; echo $?
1

文字列演算子としては、=と同等で==あり、周囲の空白=または==その必須文字に注意してください。

あなたができる[[ 1 == 1 ]][[ $(( 1+1 )) == 2 ]]それは文字列の等価性をテストしていますが、算術的等価性ではありません。

だから、-eq結果が生成おそらくの整数値と期待さ1+1ISに等しい2RHは文字列であり、末尾のスペースを有しているにもかかわらず:

$ [[ $(( 1+1 )) -eq  "2 " ]]; echo $?
0

同じものの文字列比較は末尾のスペースを取得するため、文字列比較は失敗します。

$ [[ $(( 1+1 )) ==  "2 " ]]; echo $?
1

そして、誤った文字列比較は完全に間違った答えを生成する可能性があります。「10」は辞書式に「2」よりも小さいため、文字列比較ではtrueor が返されます0。多くの人がこのバグにかまれています。

$ [[ 10 < 2 ]]; echo $?
0

対10の算術演算が2未満であるという正しいテスト。

$ [[ 10 -lt 2 ]]; echo $?
1

コメントでは、文字列に整数を使用すると、同じではない文字列に対してTrueを返すという技術的な理由の問題があり-eqます。

$ [[ "yes" -eq "no" ]]; echo $?
0

その理由は、Bashが型付けされていないためです。これ-eqにより、可能であればベース変換を含めて文字列が整数として解釈されます。

$ [[ "0x10" -eq 16 ]]; echo $?
0
$ [[ "010" -eq 8 ]]; echo $?
0
$ [[ "100" -eq 100 ]]; echo $?
0

そして0、Bashがそれを単なる文字列であると考える場合:

$ [[ "yes" -eq 0 ]]; echo $?
0
$ [[ "yes" -eq 1 ]]; echo $?
1

だから、[[ "yes" -eq "no" ]]と等価です[[ 0 -eq 0 ]]

最後の注意:テストコンストラクトに対するBash固有の拡張機能の多くはPOSIXではないため、他のシェルでは失敗します。他のシェルは一般に[[...]]andおよび((...))orをサポートしていません==


True を返す技術的な理由に興味があり[[ "yes" -eq "no" ]]ます。bashはこれらの文字列を比較可能な整数値に強制変換する方法を教えてください。;-)
オドニー

4
bash変数は型指定されていないので[[ "yes" -eq "no" ]][[ "yes" -eq 0 ]] or と同等です[[ "yes" -eq "any_noninteger_string" ]]-すべてTrue。-eq比較整数力。"yes"整数として解釈されます0。他の整数がであるか0、文字列の結果がである場合、比較はTrue です0
dawg

ブー、ヒス・リ:==コード・サンプルで(移植不可能)を示し、=その下で(移植可能、標準化)についてのみ言及しています。
Charles Duffy

24

==はbash固有のエイリアス=で、数値比較ではなく文字列(字句)比較を実行します。eqもちろん数値比較です。

最後に、私は通常、フォームを使用することを好みます if [ "$a" == "$b" ]


15
POSIXで==のみ=指定されているため、ここでの使用は不適切です。
Charles Duffy、

9
あなたが本当に使用することを主張した場合==、その後の間にそれを置く[[]]。(そして、スクリプトの最初の行がを使用するように指定されていることを確認してください/bin/bash。)
holgero

18

みんな:いくつかの答えは危険な例を示しています。OPの例で[ $a == $b ]は、引用符で囲まれていない変数置換が具体的に使用されています(17年10月編集時点)。その[...]ため、文字列の等価性は安全です。

ただし、などの代替を列挙する場合は[[...]]、右側も引用する必要があることを通知する必要があります。引用されていない場合は、パターンマッチです。(bashのmanページから:「パターンの一部を引用符で囲んで、文字列として一致させることができます。」)

ここbashでは、「yes」を生成する2つのステートメントはパターンマッチングであり、他の3つは文字列の等価です。

$ rht="A*"
$ lft="AB"
$ [ $lft = $rht ] && echo yes
$ [ $lft == $rht ] && echo yes
$ [[ $lft = $rht ]] && echo yes
yes
$ [[ $lft == $rht ]] && echo yes
yes
$ [[ $lft == "$rht" ]] && echo yes
$

2
平等であっても信頼できるように[ "$lht" = "$rht" ] 引用符一緒にする必要があります。あなたが作成したファイルを持っている場合はtouch 'Afoo -o AB'[ $lft = $rht ]そのファイル名があるにもかかわらず、trueを返しますすべてではないと同じにAB
Charles Duffy
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.