web-dev-qa-db-ja.com

変数を文字列または整数として比較するときに大きな違いはありますか

好奇心から、bash変数の比較(その値はinteger)を行うときに、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
$
_

両方の関数は同じように動作するので、整数変数をチェックするときに好ましい方法があるかどうか疑問に思っていますか?より厳密なので、intintの比較に行きますが、stringを使用してそれを実行するドローバックがあるかどうか疑問に思います。

この場合、f2()も比較についてより厳密です。つまり、10進数の値を渡すと壊れますが、f1()では問題ありません。

23
fduff

うん、たくさんの違い。例えば、 =は文字列が完全に等しいかどうかをチェックしますが、-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

そして、比較演算子を導入すると、他のクラスの違いがすべて現れます-<-lt、 例えば:

$ [[ 2 -lt 10 ]] && echo less || echo not
less
$ [[ 2 < 10 ]] && echo less || echo not
not

これは、文字列 "2"が文字列 "10"の後にアルファベット順である(1が2の前にあるため)が、数値 "2"は数値的に "10"よりも小さいためです。

19
godlygeek

整数と文字列の比較は、次の値よりも大きいか小さい場合に最も重要になります。

#!/bin/bash

eleven=11
nine=9

[[ $nine < $eleven ]] && echo string   # fail

[[ "$nine" -lt "$eleven" ]] && echo integer # pass

辞書式に並べ替えると、9が11の後に来るため、最初の方法は失敗します。

演算子を使用すると、引用符を使用しても、文字列と数値のどちらを比較するかが決まるわけではないことに注意してください。上記の引用を追加または削除できますが、違いはありません。 Bashは未定義の変数を二重括弧内でキャッチするため、引用符は必要ありません。数値テストに単一の括弧を付けた引用符を使用しても、次の理由で節約できません。

[ "" -lt 11 ]

とにかくエラーです(「整数式が必要です」)。引用符は、単一の括弧内の文字列比較による効果的な保護手段です。

[ "" \< 11 ]

double括弧内のメモ、""意志-eq 0 だがしかし == 0

7
goldilocks

言われたことに加えて。
シェルスクリプトでは高速な計算が必要になることはめったにありませんが、数値の方が等しいかどうかの比較は高速です。

$ 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
2
Emmanuel