シェルの比較における単一の等号 (=) と二重の等号 (=) の違いは何ですか?

シェルの比較における単一の等号 (=) と二重の等号 (=) の違いは何ですか?

内部の文字列を比較するには、if二重の角括弧を使用する必要があると読んでください。 一部の書籍では、 で比較を行うことができると書かれています=。 しかし、 でも機能します==

#!/bin/bash
a="hello"
b="world"
if [[ $a == $b ]];then
    echo "equal"
fi

比較すると=との間に違いはありますか?==

答え1

ではbash(その構文をコピーした のようにksh) bash[[ $a == $b ]]比較ではなく、パターン マッチングです。[[ $a == "$b" ]]バイト間の等価比較には が必要です。は、 をサポートする任意のシェル=と同じです。==[[...]]

[[...]]shは標準的な構文ではありません。[ 指示標準であり、標準比較演算子は存在します=(ただし、一部の[実装では==¹ も認識されます)。

あらゆるコマンドの引数と同様に、変数の展開は引用符で囲む必要があります。分割+グロブおよび空の削除(後者のみが で実行されるzsh)なので、次のようになります。

[ "$a" = "$b" ]

標準ではsh、パターン マッチングは次のように行われますcase

case $a in
  ($b) ...
esac

完全を期すために、他の平等のようなシェル スクリプトで遭遇する可能性のある演算子:

  • [ "$a" -eq "$b" ]: [10 進整数を比較する標準演算子。[実装によっては、数値の前後に空白を入れることも、任意の算術式を入れることもできますが、これは移植性がありません。移植性のために、 を使用することができます。また、 の標準的な同等物 (POSIX では、動作はと に整数定数が含まれている場合にのみ指定されます)[ "$(($a))" -eq "$(($b))" ]も参照してください。[ "$((a == b))" -ne 0 ]$a$b

  • ((a == b))ksh の であり、 および にも含まれる はzshbashに格納されている算術式の評価が のもの$aと同じ数値を生成する場合に true を返します$b。通常、これは数値の比較に使用されます。算術式の評価方法とサポートされている数値についてはシェル間で違いがあることに注意してください (たとえば、bash および一部の ksh の実装/バージョンは浮動小数点をサポートしておらず、先頭にゼロがある数値を 8 進数として扱います)。

  • expr "$a" = "$b"両方のオペランドが 10 進整数として認識された場合 (数値の前後に空白が入る場合もあります)、数値比較を行い、それ以外の場合は 2 つの文字列オペランドのソート順序が同じかどうかを確認します。 または の値が、、$aなどの演算子$bである場合も失敗します。expr(substr

  • awk -- 'BEGIN{exit !(ARGV[1] == ARGV[2])}' "$a" "$b"$a:および が数値として認識される場合$b(少なくとも 10 進整数と 1.2、-1.5e-4 などの浮動小数点数、先頭の末尾の空白は無視され、16 進数、8 進数、または で認識されるものも認識されますstrtod())、数値比較が実行されます。それ以外の場合は、実装に応じて、バイト対バイトの文字列比較、または の比較 (つまり、 と が同じ順序であるかどうか) のいずれかexprになりますstrcoll()$a$b

参照:


¹ GNU と 、 、 、一部の ベースのシェルと の組み込みが含まれています[[、では、kshbashyashashzshzsh=cmd特別なファイル名拡張演算子です(そのままのコンテキストで展開されます~user)対応するコマンドのパスに展開されるため、equalsその機能を無効にするオプションをオフにしない限り、それを記述する必要があります。そうしないと、コマンドが見つからない[ "$a" '==' "$b" ]というエラーが発生します。=[ "$string" '=~' "$regexp" ]

答え2

これらは bash では同等です:

[[ $x == "$y" ]]
[[ $x = "$y" ]]
[ "$x" == "$y" ]
[ "$x" = "$y" ]

最初の 2 つの $x 変数は引用符で囲む必要はありません。Bash は [ 内では単語の分割とパス名の展開を実行しますが、[[ 内では実行しません。

$ x='a b'
$ [ -s $x ]
-bash: [: a: binary operator expected
$ [[ -s $x ]]
$ ls
$ [ a = * ]
-bash: [: a: unary operator expected
$ [[ a = * ]]
$ 

[[ $x = "$y" ]]文字列の比較ですが、[[ $x = $y ]]パターン マッチング式です。

$ y='a*'; [[ aa = "$y" ]]; echo $?
1
$ y='a*'; [[ aa = $y ]]; echo $?
0

-eq は整数のみで使用することを目的としています:

$ [[ x.x -eq x.x ]]
-bash: [[: x.x: syntax error: invalid arithmetic operator (error token is ".x")
$ x=9; [[ "x" -eq 9 ]]; echo $?
0

参照BashFAQ/031: test、[、[[ の違いは何ですか?

答え3

=と はどちらも==演算子です。一部の言語 (C など) では、一方は変数に値を割り当てるために使用され、もう一方は値 (算術式の結果) を比較するために使用されます。実際、算術評価内では両方の演算子がまさにそのとおりです。A$((a=23))は割り当て、a$((a==23))は算術比較です。

$ echo "$((a=11)) $((a==23))" "$((a=23))" "$((a==23))"
11 0 23 1

しかし、テスト構造(テストそして[…]そして[[…]]) 両方の演算子は同じ意味を持ち、同じ操作を実行します。

つまり、これらすべてのオプションは次のようになります。

test "$a" =  "$b"
   [ "$a" =  "$b" ]
  [[ "$a" =  "$b" ]]
test "$a" == "$b"
   [ "$a" == "$b" ]
  [[ "$a" == "$b" ]]

同等の内部バッシュバイナリ等価性をテストします (変数は引用符で囲みます)。右の変数が引用符で囲まれていない場合は、パターンとして解釈され、それに応じて一致します。つまり、リテラル文字列ではなくパターンとして一致します。

引用符で囲まれた演算子\=および も、\==test および 内で使用される場合は同等です[…]。ただし、引用符で囲まれた演算子は\==内では失敗します[[…]]

他のシェルの場合、結果はさまざまです (正しい結果はY -(true false) であるはずですが、0 (true) および 1 (false) 以外の終了コードは で失敗として報告されます¤)。一部のシェルは で失敗します- -(終了コードは常に 1 です)。

                     | dash  ksh   bash  zsh   
  test a  =  "$b"    | Y -   Y -   Y -   Y -    
     [ a  =  "$b" ]  | Y -   Y -   Y -   Y -    
    [[ a  =  "$b" ]] | ¤ ¤   Y -   Y -   Y -    
  test a  == "$b"    | ¤ ¤   Y -   Y -   - -    
     [ a  == "$b" ]  | ¤ ¤   Y -   Y -   - -    
    [[ a  == "$b" ]] | ¤ ¤   Y -   Y -   Y -    
  test a \=  "$b"    | Y -   Y -   Y -   Y -    
     [ a \=  "$b" ]  | Y -   Y -   Y -   Y -    
    [[ a \=  "$b" ]] | ¤ ¤   Y -   - -   - -    
  test a \== "$b"    | ¤ ¤   Y -   Y -   Y -    
     [ a \== "$b" ]  | ¤ ¤   Y -   Y -   Y -    
    [[ a \== "$b" ]] | ¤ ¤   Y -   - -   - -

すべてのオプションは ksh で機能しますが、引用符で囲まれた演算子は bash と zsh ( の内部[[…]]) では失敗し、引用符で囲まれていない\=\==も zsh ( の外部[[…]]) では失敗します。

関連情報