不思議なことに、bash変数の比較(値はan)を実行するときに、integer
anまたはaと宣言された事前定義さint
れた値についてテストできますstring
。
サンプルスクリプト:
#!/bin/bash
f1()
{
[ "$1" == "1" ] && echo "$FUNCNAME: \"1\" compared as string"
}
f2()
{
[[ "$1" -eq 1 ]] && echo "$FUNCNAME: \"1\" compared as int"
}
f1 $1
f2 $1
出力:
$ ./param.sh 1
f1: "1" compared as string
f2: "1" compared as int
そして
$ ./param.sh blah
$
どちらの関数も同じように動作するので、整数変数をチェックするときに好む方法があるかどうか疑問に思います。もっと厳しいので、int
vsを確認したいのですが、これint
は欠点があるかどうか疑問に思いますstring
。
この場合、f2()
比較もさらに厳しくなる。つまり、10進値を渡すと値が壊れますが、渡すとf1()
問題はありません。
答え1
はい、多くの違いがあります。たとえば、=
文字列がまったく同じであることを確認し、-eq
同じであることを確認する前に、両方の式に対して算術を実行します。
$ [ " 1 " -eq 1 ] && echo equal || echo not
equal
$ [ " 1 " = 1 ] && echo equal || echo not
not
$ [ +1 -eq 1 ] && echo equal || echo not
equal
$ [ +1 = 1 ] && echo equal || echo not
not
$ [ "0+1" -eq 1 ] && echo equal || echo not
equal
$ [ "0+1" = 1 ] && echo equal || echo not
not
さらに、空の文字列は数値で正確にゼロに等しくなります。
$ [ "" -eq 0 ] && echo equal || echo not
equal
$ [ "" = 0 ] && echo equal || echo not
not
比較演算子を導入すると、別の種類の違いが発生します。たとえば、<
vsを考えてみましょう。-lt
$ [[ 2 -lt 10 ]] && echo less || echo not
less
$ [[ 2 < 10 ]] && echo less || echo not
not
これは、文字列「2」が文字列「10」の後にアルファベット順に続くが(1が2よりも前にあるため)、数字「2」が数字「10」より数値的に小さいためです。
答え2
整数と文字列の比較は、以下より大きいか小さい場合に最も重要です。
#!/bin/bash
eleven=11
nine=9
[[ $nine < $eleven ]] && echo string # fail
[[ "$nine" -lt "$eleven" ]] && echo integer # pass
辞書式で並べ替えると、9が11の後に来るため、最初は失敗します。
引用符を使用して文字列を比較するか数値を比較するかを決定するのではなく、演算子が決定します。上記の引用符を追加または削除できますが、違いはありません。 Bash は二重括弧内に定義されていない変数をキャプチャするため、引用符は必要ありません。数値テストに小括弧で引用符を使用すると、次の理由でコストが節約されません。
[ "" -lt 11 ]
とにかくエラーです(「整数式が必要です」)。引用符は、単一の括弧内の文字列比較に対する効果的な保護です。
[ "" \< 11 ]
コメント内ダブル括弧内は""
will-eq 0
ですがwill notです== 0
。
答え3
言ったことに加えて。
シェルスクリプトでは速い計算はほとんど必要ありませんが、数値が等しいかどうかを比較する方が高速です。
$ b=234
$ time for ((a=1;a<1000000;a++)); do [[ $b = "234" ]]; done
real 0m13.008s
user 0m12.677s
sys 0m0.312s
$ time for ((a=1;a<1000000;a++)); do [[ $b -eq 234 ]]; done
real 0m10.266s
user 0m9.657s
sys 0m0.572s