【问题标题】:"test -v $TESTENV" always false, even when TESTENV is defined"test -v $TESTENV" 总是假的,即使定义了 TESTENV
【发布时间】:2018-08-13 16:54:39
【问题描述】:

我在 Fedora 27 下运行 Bash 4.4.19,我有一个简单的脚本:

#!/bin/bash
TESTENV="Hello"
echo "$TESTENV"
if [ -v $TESTENV ]; then
    echo "Yup"
fi
echo "Done"

当我运行它时,它会打印:

Hello
./myscript: line 3: [: Hello: binary operator expected
Done

所以,我将额外的括号添加到第 3 行,现在看起来像:

if [[ -v $TESTENV ]]; then

但产生:

Hello
Done

什么给了?我希望看到上述一项/两项的“是”。我尝试将 "$TESTENV" 用引号括起来,我也尝试使用 -z 运算符来代替 - 但 行为是相同的。

【问题讨论】:

  • Re: “尝试了-z 运算符” -- 你为什么期望[ -z Hello ] 永远是真的?根据定义,它是错误的。当你的变量 isn't 设置,没有引号的扩展,[ -z ] 等价于[ -n "-z" ],这是真的(因为-n 是测试的默认操作,当只给出一个单操作数)。如果您希望 -z 有帮助,则需要更多引号:[ -z "$TESTENV" ],因此如果变量为空,您可以调用 [ -z '' ]
  • ...这是一个使用set -x 启用日志记录的地方会使问题立即变得明显。
  • 感谢@CharlesDuffy,我以前从未使用过set -x

标签: bash shell if-statement


【解决方案1】:

我知道这是一个老问题,但我认为最重要的问题没有得到解答。单括号[ 实际上是test 命令的别名。这意味着[ 不是语法。

因此,当[ 有一个或多个操作数试图计算返回一个空字符串时,它会抱怨它期待两个操作数(二进制)(“缺少操作数”问题)。这就是为什么您会看到开发人员使用[ x$foox = x$blahx ]xx 保证操作数永远不会计算为空字符串。

双括号[[ ]],另一方面,是一种语法,比[ ]更有能力。但是,重要的是要注意并非所有 POSIX shell 都支持 [[ ]]。此外,它没有 “缺少操作数” 问题,并且它允许使用 >, <, >=, <=, !=, ==, &&, || 运算符的更多类似 C 的语法。

我的建议如下:如果您的解释器是#!/bin/bash,则使用[[,但如果您想要可移植性,请使用[

所以在这种情况下,POSIX 兼容选项将是:

#!/bin/bash
TESTENV="Hello"
echo "$TESTENV"
if [ -v TESTENV ]; then
    echo "Yup"
fi
echo "Done"

【讨论】:

    【解决方案2】:

    测试变量是否存在且不为空的最简单方法:

    if [[ $TESTENV ]]; then ...
    

    【讨论】:

      【解决方案3】:

      对于$,您使用的是变量的,而不是变量名本身。您可能的意思是:

      if [[ -v TESTENV ]]; then
          echo "Yup"
      fi
      

      如果您定义了名为Hello 的变量(例如Hello=hi),那么if 条件就会成功,您可能根本没有注意到这个问题:)

      【讨论】:

      • 如果你要假设-v已经实现,你也可以使用[[而不是[
      • 这正是我的意思 - 在我比较脚本的每个参考/教程中,我都错过了这一点。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-23
      • 1970-01-01
      • 1970-01-01
      • 2014-06-20
      相关资源
      最近更新 更多