将变量作为字符串或整数进行比较时有什么重大区别吗

将变量作为字符串或整数进行比较时有什么重大区别吗

出于好奇,在进行 bash 变量比较(其值为 an integer)时,可以针对某些声明为 anint或 a 的预定义值对其进行测试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
$

这两个函数的行为方式相同,所以我想知道检查整数变量时是否有首选方法?我会去检查intvs,int因为它更严格,但我想知道这样做是否有任何缺点string

在这种情况下,f2()对比较也更加严格,即传递十进制值会破坏它,而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 ]

注释内双倍的括号中,""-eq 0但不会== 0

答案3

除了已经说过的。
尽管在 shell 脚本中很少需要快速计算,但比较数字的相等性更快。

$ 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

相关内容