出于好奇,在进行 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
$
这两个函数的行为方式相同,所以我想知道检查整数变量时是否有首选方法?我会去检查int
vs,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