反转布尔变量

bre*_*ish 34 scripting bash

我想尝试简单的脚本

flag=false
while !$flag
do
   read x
   if [ "$x" -eq "true" ]
   then
     flag=true
   fi
   echo "${x} : ${flag}"
done
Run Code Online (Sandbox Code Playgroud)

但是当我运行它时,如果我输入true,我会看到那个x="true"and flag="true",但循环并没有结束。脚本有什么问题?如何正确反转布尔变量?

Gil*_*il' 25

您的脚本中有两个错误。第一个是您需要在!和之间留一个空格$flag,否则shell 会查找名为 的命令!$flag。第二个错误是-eq用于整数比较,但您在字符串上使用它。根据您的外壳,您将看到一条错误消息并且循环将永远继续,因为条件[ "$x" -eq "true" ]不能为真,或者每个非整数值都将被视为 0,如果您输入任何字符串(包括false),循环将退出不同于 0 的数字。

虽然! $flag是正确的,但将字符串视为命令是一个坏主意。它可以工作,但它对脚本中的更改非常敏感,因为您需要确保它$flag永远不会是truefalse。最好在这里使用字符串比较,就像下面的测试一样。

flag=false
while [ "$flag" != "true" ]
do
   read x
   if [ "$x" = "true" ]
   then
     flag=true
   fi
   echo "${x} : ${flag}"
done
Run Code Online (Sandbox Code Playgroud)

可能有更好的方式来表达您所追求的逻辑。例如,您可以创建一个无限循环并在检测到终止条件时中断它。

while true; do
  read -r x
  if [ "$x" = "true" ]; then break; fi
  echo "$x: false"
done
Run Code Online (Sandbox Code Playgroud)


ack*_*ack 12

虽然 Bash 中没有布尔变量,但使用算术评估很容易模拟它们。

flag= # False
flag=0 # False
flag=1 # True (actually any integer number != 0 will do, but see remark below about toggling)
flag="some string" # Maybe False (make sure that the string isn't interpreted as a number)

if ((flag)) # Test for True
then
  : # do something
fi

if ! ((flag)) # Test for False
then
  : # do something
fi

flag=$((1-flag)) # Toggle flag (only works when flag is either empty or unset, 0, 1, or a string which doesn't represent a number)
Run Code Online (Sandbox Code Playgroud)

这也适用于 ksh。如果它适用于所有符合 POSIX 的 shell,我不会感到惊讶,但还没有检查标准。

  • -1 | 在 POSIX sh 中,standalone ((..)) 是未定义的;请删除对它的引用 (2认同)

小智 12

如果您可以绝对确定变量将包含 0 或 1,则可以使用按位异或等于运算符在两个值之间翻转:

$ foo=0
$ echo $foo
0
$ ((foo ^= 1))
$ echo $foo
1
$ ((foo ^= 1))
$echo $foo
0
Run Code Online (Sandbox Code Playgroud)