为什么 while [ 0 ] 进入无限循环?

use*_*107 23 shell bash test

我看到下面循环的行为与带有while [ 1 ]. 为什么呢?

while [ 0 ]; do
    echo "hello"
done
Run Code Online (Sandbox Code Playgroud)

win*_*ner 33

shell 中的单方括号是test(单独的命令或 shell 内置的)的同义词,因此[ 0 ]test 0. test用于进行比较和测试文件的属性,您可以在其联机帮助页中阅读。当它没有给出一个看起来像比较、文件测试或它可以执行的其他操作之一的表达式时,它会测试参数是否存在并且是非空字符串。无论是01用于测试真正适当的投入,并作为非空字符串测试是成功,while循环循环下去。

你可能想试试

while false; do
  echo "hello"
done
Run Code Online (Sandbox Code Playgroud)

可能替换falsetrue. 或者也许你想要的是使用(( ))

while (( 0 )); do
  echo "hello"
done
Run Code Online (Sandbox Code Playgroud)

其行为与大多数语言一样,其中 0 表示失败/假,1 表示成功/真。

  • 正如@ruakh 解释的那样,这个语句是错误的:*当它没有给出一个看起来像比较、文件测试或它可以执行的其他操作之一的表达式时,它就成功了。* 要测试的任何单个参数(任何如果参数不是空字符串,并且“0”和“1”都不是空字符串,则方括号内的单个参数)被认为是 TRUE。新的 shell 程序员经常写 `if [ 1=2 ]` 而不是 `if [ 1 = 2 ]` 并且想知道为什么前者总是正确的。这是真的,因为它是单个参数,而不是空字符串。 (3认同)

Kaz*_*Kaz 10

此处的值 0 不是用作数字常量,而是用作字符串。这些测试在产生成功终止状态的效果方面都是等效的:

[ A ]
[ "XYZ" ]
[ 0 ]
Run Code Online (Sandbox Code Playgroud)

这些会产生一个失败的终止状态:

[ ]
[ "" ]
Run Code Online (Sandbox Code Playgroud)

有一个非空参数,其计算结果为逻辑真。这允许您执行以下操作:

if [ $UNDER_NUCLEAR_ATTACK ] ; then
  launch-missiles -a $DRY_RUN  # $DRY_RUN set to "-n" during testing
fi
Run Code Online (Sandbox Code Playgroud)

该变量UNDER_NUCLEAR_ATTACK设置为任何非空值以表示真,或者未设置或为空以表示假。

我们可以应用!运算符来反转逻辑:

[ ! a ]  # fails: a is nonblank so true; and not true is false.
[ ! ]    # succeeds: blank is false, not blank is true.
Run Code Online (Sandbox Code Playgroud)

要评估数字条件,您必须使用数字测试运算符:

 while [ $A -gt $B ] ; do ...
Run Code Online (Sandbox Code Playgroud)

如果AB包含看起来像十进制整数的字符串,则将它们作为数字进行比较,如果A大于B,则循环执行。所以假设这UNDER_NUCLEAR_ATTACK不是一个空白或非空白的字符串类型布尔值,而是一个实际上是0(false) 或其他值 (true)的数字布尔值。在这种情况下,我们会像这样编写测试:

 if [ $UNDER_NUCLEAR_ATTACK -ne 0 ] ; then ...
Run Code Online (Sandbox Code Playgroud)