字符串与 [[ 测试中的整数的比较

Ser*_*nyy 7 command-line bash posix

我一直在寻找Kusalananda和xhienne之间的讨论在这里,在这里它提到[ "" -ge 2 ]不是一个有效的测试产生的错误bash --posix和其他POSIX兼容的炮弹。

bash-4.3$ [ "" -gt 10 ]
bash: [: : integer expression expected
bash-4.3$ [ '' -gt 10 ]
bash: [: : integer expression expected
Run Code Online (Sandbox Code Playgroud)

那里一切都很好。出于好奇,我对[[.

bash-4.3$ [[ "" -gt 10 ]] && echo "YES"
bash-4.3$ [[ "" -gt 0 ]] && echo "YES"
bash-4.3$ [[ "" -gt -1 ]] && echo "YES"
YES
bash-4.3$ [[ "" -eq 0 ]] && echo "YES"
YES
Run Code Online (Sandbox Code Playgroud)

如您所见,没有错误,它实际上被评估为数字表达式,其中 "" 等于 0。那么这里到底发生了什么?难道[[仅仅是不符合旧test或POSIX?它只是执行字符串比较而不是数字比较吗?

Joh*_*024 14

之间的一个区别[,并[[[不是做算术评估,但[[作用:

$ [ "2 + 2" -eq 4 ] && echo yes
bash: [: 2 + 2: integer expression expected
$ [[ "2 + 2" -eq 4 ]] && echo yes
yes
Run Code Online (Sandbox Code Playgroud)

第二个微妙之处在于,无论在 bash 下执行算术计算的任何地方,空字符串的计算结果都为 0。例如:

$ x=""; echo $((0 + x))
0
$ [[ "" -eq 0 ]] && echo yes
yes
Run Code Online (Sandbox Code Playgroud)

文档

来自man bash

允许外壳变量作为操作数;在计算表达式之前执行参数扩展。在表达式中,shell 变量也可以通过名称引用而不使用参数扩展语法。在不使用参数扩展语法的情况下按名称引用时,为 null 或未设置的 shell 变量的计算结果为 0。变量的值在被引用时被计算为算术表达式,或者当使用声明 -i 赋予整数属性的变量被赋值时。 空值的计算结果为 0。shell 变量不需要打开其整数属性即可在表达式中使用。[强调]

旁白:安全问题

请注意,bash 的算术评估是一个潜在的安全问题。例如,考虑:

x='a[$(rm -i *)]'
[[ x -eq 0 ]] && echo yes
Run Code Online (Sandbox Code Playgroud)

随着 -i选项,以上是安全的,但一般的教训是不要对未净化的数据使用 bash 的算术评估。

相比之下, with[不执行算术评估,因此,该命令从不尝试删除文件。相反,它会安全地生成一个错误:

$ x='a[$(rm -i *)]'
$ [ "$x" -eq 0 ] && echo yes
bash: [: a[$(rm -i *)]: integer expression expected
Run Code Online (Sandbox Code Playgroud)

有关此问题的更多信息,请参阅此答案