回答:
これは、他の方法で回避だ:=
と==
文字列の比較のためのもの、-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
以下も参照してください。
[[ $var = $pattern ]]
ます。文字列foo
は非リテラルの解釈を持たないため、引用符は完全に安全です。OPが一致したい場合foo*
(たとえば、アスタリスクをリテラルとして使用し、文字列の後に来ることは何も意味しないfoo
)にのみ、引用符またはエスケープが必要になります。
[[
バシズムである内部の引用されていない展開についての反対でした(それがあなたが答えを+1しなかった唯一の理由であることを示しています)。
[ ... ]
と二重等号==
。:-/
オペレーターの周りのテスト構成に依存します。オプションは、二重括弧、二重ブレース、単一ブレース、またはテストです
((...))を使用する場合は==
、C と同様に算術公平性をテストします。
$ (( 1==1 )); echo $?
0
$ (( 1==2 )); echo $?
1
(注0
手段true
Unixのセンスおよび非ゼロでは失敗したテストです)
-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+1
ISに等しい2
RHは文字列であり、末尾のスペースを有しているにもかかわらず:
$ [[ $(( 1+1 )) -eq "2 " ]]; echo $?
0
同じものの文字列比較は末尾のスペースを取得するため、文字列比較は失敗します。
$ [[ $(( 1+1 )) == "2 " ]]; echo $?
1
そして、誤った文字列比較は完全に間違った答えを生成する可能性があります。「10」は辞書式に「2」よりも小さいため、文字列比較ではtrue
or が返されます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をサポートしていません==
。
[[ "yes" -eq "no" ]]
ます。bashはこれらの文字列を比較可能な整数値に強制変換する方法を教えてください。;-)
==
コード・サンプルで(移植不可能)を示し、=
その下で(移植可能、標準化)についてのみ言及しています。
==
はbash固有のエイリアス=
で、数値比較ではなく文字列(字句)比較を実行します。eq
もちろん数値比較です。
最後に、私は通常、フォームを使用することを好みます if [ "$a" == "$b" ]
==
のみ=
指定されているため、ここでの使用は不適切です。
==
、その後の間にそれを置く[[
と]]
。(そして、スクリプトの最初の行がを使用するように指定されていることを確認してください/bin/bash
。)
みんな:いくつかの答えは危険な例を示しています。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
$
[ "$lht" = "$rht" ]
引用符と一緒にする必要があります。あなたが作成したファイルを持っている場合はtouch 'Afoo -o AB'
、[ $lft = $rht ]
そのファイル名があるにもかかわらず、trueを返しますすべてではないと同じにAB
。
[[
、全体として、1980年代のksh-ismであり、bash(および他の多くのシェル)が採用されています。それは全体のポイントだ-あなたが持っている場合は[[
、すべてで、その後、あなたが安全にすべての拡張機能は、その周りに実装(のkshと仮定することができますfnmatch()
スタイルのパターンマッチング、ERE正規表現で=~
、はい、文字列の分割とファイルシステムグロブの抑制)になります利用可能です。以来[[
、その全体が非POSIXの構文は、それは持って生まれた機能が利用可能になると仮定には、追加の移植性の損失はありません。