为什么 Bash 在“if”语句中将未定义的变量视为 true?

Jef*_*eff 61 bash

在下面的简单示例中,如果脚本中未设置CONDITION ,则运行脚本将打印“True”。然而,人们会期望它打印“False”。这种行为的原因是什么?

# Set CONDITION by using true or false:
# CONDITION=true or false

if $CONDITION; then
    echo "True"
else
    echo "False"
fi
Run Code Online (Sandbox Code Playgroud)

Bar*_*mar 80

的参数if是要执行的语句,并测试其退出状态。如果退出状态为,则条件为真,并且执行0中的语句。then

$CONDITION未设置时,该语句是一个空语句,并且空语句的退出状态始终为零,表示成功。所以if条件成功。

POSIX shell 规范对此行为进行了解释:

如果没有命令名称,但该命令包含命令替换,则该命令应以上次执行的命令替换的退出状态完成。否则,该命令应以零退出状态完成。

  • 这确实是一个奇怪的边缘情况,因为`if ; 然后回显是;fi` 是一个语法错误,但是 `if $unset; 然后回显是;fi` 没问题。我想区别在于前者_不是_“给定一个要执行的语句”;后者被赋予一个,但它恰好为空。 (22认同)
  • 正确的。区别在于第一个错误是在解析期间检测到的,而第二个错误是在语句解析和变量替换之后执行的。 (11认同)
  • 如果你这样做“if“$CONDITION”,你会得到同样的错误 (5认同)
  • 因为这不是一句空话。它试图找到一个名称为空字符串的程序。 (4认同)
  • [2.9.1 简单命令](https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/utilities/V3_chap02.html#tag_18_09_01),最后一部分:_“如果没有命令名称,但命令包含命令替换时,该命令应以上次执行的命令替换的退出状态完成。否则,该命令应以零退出状态完成。"_ 您还可以有类似 `if "$@"; 的内容。then ...` 如果没有位置参数,这将导致空命令。语法确实需要至少一些东西,但是简单的重定向也可以...... (3认同)