【问题标题】:Why an unset variable gets evaluated as 0 in bash if statement为什么在 bash if 语句中未设置的变量被评估为 0
【发布时间】:2017-11-14 01:14:18
【问题描述】:

我试图理解为什么未设置的变量被评估为 0。 在我编写的某些脚本中,仅在需要时才设置变量,有时则不需要。 所以这种行为会导致输出不正确。 这是否意味着我必须预设所有变量或至少添加检查它们是否已设置?

#!/bin/bash
#myvalue=0  #comment to simulate an unset variable.

if [[ $myvalue -eq 0 ]] ; then
   echo "OK"
fi

结果正常:

bash -x test.sh
+ [[ '' -eq 0 ]]
+ echo OK
OK

【问题讨论】:

  • 试试if [ $myvalue -eq 0 ];then
  • 当然你可以用-eq[;事实上,你是否应该使用[[ ... -eq ... ]] 值得商榷,因为你可以改用可读性更强的(( ... == ... ))
  • 添加检查是否已设置很简单:if [[ ${myvalue--1} -eq 0 ]] ; then(将默认值设置为 -1...选择您喜欢的任何默认值)
  • 这么多年过去了,我觉得这个问题最讽刺的是[[是为了避免[的陷阱而引入的,但是(至少对我来说)[很好理解和[[ 令人困惑且容易出错!
  • [-eq 使用非整数操作数时会给出一个很好的错误消息,而[[ 只是默默地忽略错误。

标签: bash if-statement evaluation unset is-empty


【解决方案1】:

[[ ... ]] 中的 -eq 运算符,因为它仅适用于整数值,所以会触发对其操作数的算术评估。在算术表达式中,未设置的变量默认为 0。算术评估的更明显演示:

$ if [[ 3 -eq "1 + 2" ]]; then echo equal; fi
equal

请注意,在您的示例中,您甚至不需要先扩展参数;算术评估将为您完成:

$ if [[ myvalue -eq 0 ]]; then echo equal; fi
equal
$ myvalue=3
$ if [[ myvalue -eq 3 ]]; then echo equal; fi
equal

此外,这是特定于 bash [[ ... ]] 命令的。对于 POSIX [-eq 不会触发算术评估。

$ if [ "$myvalue" -eq 0 ]; then echo equal; fi
bash: [: : integer expression expected
$ if [ myvalue -eq 0 ]; then echo equal; fi
bash: [: myvalue: integer expression expected

【讨论】:

  • 我猜这就是你写的答案“在算术表达式中,未设置的变量默认为 0”。我不知道。也在 man bash 中寻找此类信息,但没有找到。
  • 在手册页的 ARITHMETIC EVALUATION 部分中,有一句话“在不使用参数扩展语法的情况下按名称引用时,为 null 或未设置的 shell 变量的计算结果为 0。”不过,据我所知,数字比较运算符触发算术评估这一事实实际上并没有记录在案。
  • (我认为$myvalue,而不仅仅是myvalue,在未设置时被视为0这一事实可能是$myvalue未根据内部通常规则扩展的无意的副作用[[ ... ]].)
  • 它也让我觉得也许我应该总是使用 [ ] 而不是 [[ ]] 。这样至少我会看到可能使我预设一个重要值的错误,以反对获得不需要的结果。
  • [[ 在非算术测试中明显优于[;应该只使用(( ... )) 进行算术运算。 (我刚刚看过;[[ 被记录为对其运算符的操作数应用算术扩展;但是,这仅适用于期望整数的运算符。[[ -f "1+2" ]],例如,正确检查名为 1+2 的文件,而不是 3。)
【解决方案2】:

如果您希望文字值作为比较值,请使用 = 而不是 -eq

if [[ $myvalue = 0 ]] ; then
    echo "OK"
fi

算术二元运算符 (-eq) 如果 arg1 等于 0,则返回 true,$myvalue 是,无论设置为 0 还是根本不设置...'' 为 null,这等于零。

【讨论】:

    猜你喜欢
    • 2014-05-11
    • 2015-12-07
    • 2015-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多