【问题标题】:Why does [[ -eq ]] show non-numerical strings as equal in Bash?为什么 [[ -eq ]] 在 Bash 中将非数字字符串显示为相等?
【发布时间】:2017-11-24 14:37:54
【问题描述】:

我知道we should use =(或其别名==)在Bash 中比较字符串。但是我忘记了,在脚本中使用了-eq,得到了奇怪的结果,但没有错误。

我没有找到任何关于此的文档,但根据我的测试,[[ "$foo" -eq "$bar" ]] 似乎总是评估为 0,即成功,对于 any$foo$bar,前提是它们不以数字开头:

$ [[ "1" -eq "1" ]] && echo yes || echo nope
yes
$ [[ "1" -eq "0" ]] && echo yes || echo nope
nope
$ [[ "x1" -eq "0" ]] && echo yes || echo nope
yes
$ [[ "x1" -eq "x0" ]] && echo yes || echo nope
yes
$ [[ foo -eq bar ]] && echo yes || echo nope
yes
$ [[ so -eq different ]] && echo yes || echo nope
yes

当一个值以数字开头时,它确实评估为1(错误):

$ [[ 1x -eq 1 ]] && echo yes || echo nope
bash: [[: 1x : valeur trop grande pour la base (le symbole erroné est "1x")
nope

我收到的错误消息是法语“value too high for the base(错误符号是“1x””。

为什么它不返回 1 和/或在获取非数字时显示错误?当你犯了那个错误时,事情真的很难调试。

我使用了 GNU bash,版本 4.3.11(1)-release (x86_64-pc-linux-gnu)。

【问题讨论】:

  • 这个错误是因为任何以1开头的都是十进制的,所以不能有字母。
  • @MadPhysicist 是的,但我的问题更多是关于为什么在比较时出现 no 错误,例如foobar.
  • 作为一阶猜测,我假设这种行为意味着不代表有效数字的字符串被设置为 null 或类似零的东西。尝试比较"zzz" -le "kkk""zzz" -le "666"。使用 -eq 以外的运算符可能会提供信息,因为 null 显然不等于任何数字,但既不大于也不小于。

标签: bash


【解决方案1】:

在算术上下文中,bash 会首先尝试查看它是否是一个数字,然后再查看它是否是一个有效的 var 名称。如果是 var 名称但 var 为空或未定义,则值为 0。

[STEP 100] # echo $BASH_VERSION
4.4.12(1)-release
[STEP 101] # n=123
[STEP 102] # [[ n -eq 123 ]] && echo yes || echo no
yes
[STEP 103] # [[ 'n' -eq 123 ]] && echo yes || echo no
yes
[STEP 104] # varname=n
[STEP 105] # [[ $varname -eq 123 ]] && echo yes || echo no
yes
[STEP 106] # [[ notdefined -eq 123 ]] && echo yes || echo no
no
[STEP 107] # [[ notdefined -eq 0 ]] && echo yes || echo no
yes
[STEP 108] #

即使这样也有效:

[STEP 108] # expr='100 + 20 + 3'
[STEP 109] # [[ expr -eq 123 ]] && echo yes || echo no
yes
[STEP 110] #

而且展开是递归的:

[STEP 201] # a=b
[STEP 202] # b=c
[STEP 203] # c=123
[STEP 204] # [[ a -eq 123 ]] && echo yes || echo no
yes
[STEP 205] # (( a == 123 )) && echo yes || echo no
yes
[STEP 206] #

来自 bash 的手册页:

ARITHMETIC EVALUATION

Shell 变量可以作为操作数;在计算表达式之前执行参数扩展。在表达式中,shell 变量也可以通过名称引用而不使用参数扩展语法。当不使用参数扩展语法按名称引用时,为 null 或未设置的 shell 变量的计算结果为 0。 变量的值在被引用时被评估为算术表达式,或者当使用declare -i 为已赋予整数 属性的变量赋值时。空值的计算结果为 0。shell 变量不需要打开其 integer 属性即可在表达式中使用。

【讨论】:

    猜你喜欢
    • 2012-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-29
    • 1970-01-01
    • 2019-05-20
    • 2016-03-19
    相关资源
    最近更新 更多