Shell脚本中的布尔类型

7

我在while循环中遇到了布尔值问题,因此我改用for循环。但是,即使在满足条件之后,我仍然无法改变布尔值的值。

doFirst= true
    for (( j=1; j<=7; j++))
    do
            letter="A"
            seatChoses=$letter$j

            flagRand=$(echo $flightSeatBooked | awk -v flseatRand=$flightSeatBooked -v orseatRand=$seatChoses '{print match(flseatRand, orseatRand)}')
            if  $doFirst ; then
            **$doFirst= false** // Here is the error!
                if [ $flagRand -eq 0 ]; then
                    echo "System generated a slot, "$seatChoses" for you. [Y or N]"
                fi
            fi

    done

1
尝试移除 $ 吗? doFirst = false - Anders Lindahl
在你的echo中,你不需要在$seatChoses周围加上引号。 - siride
嗨,Anders,实际上我正在访问与第一行声明的相同变量... 我仍然可以删除$吗? - Bryan Wong
标记为“here is the error”的那行应该写成(无空格)doFirst=false,没有$。这仍然是一种非常规的做法,但它至少可以工作。 - Jonathan Leffler
2个回答

21

在 shell 脚本中,没有布尔值这样的东西(也就是说,在变量中存储和处理布尔值是不可能的)。truefalse是命令;true 的退出值是0,而false的退出值是非零。Bash 中的if语句接受一个命令;如果该命令返回0,则执行then子句,否则执行else子句。

doFirst= true

这一行并不会按你的期望执行。在 shell 脚本中,等号后面不能有空格。空格意味着你结束了赋值操作,现在正在编写一个命令。这相当于:

doFirst="" true

此外,如果你在一个命令之前有一个赋值语句(像这样),那么它并不会在shell中执行赋值操作。它只在该命令的环境中设置该环境变量;该赋值对命令之外的任何东西都没有影响。

if  $doFirst ; then

这会展开$doFirst变量,并尝试将结果解释为命令。奇怪的是,如果$doFirst未定义(就像我上面解释的那样),它将进入then分支。在这一点上,您再次犯了第一个错误,试图将变量设置为false,但仍然没有发生任何事情; $doFirst保持未定义状态。您进一步犯了一个错误,试图分配$doFirst;在设置变量时,使用裸名而不是$来获取变量的值。

我的建议是不要在Bash中尝试使用布尔值;只需使用字符串,并检查字符串的值即可。请注意,我删除了空格,因此现在将其设置为确切的字符串;并且没有命令,因此这将在shell中设置变量,而不是为单个命令设置环境:

doFirst=true
# ...
   if [ $doFirst = true ]; then
       doFirst=false
   # ...

嗨@Brian,感谢你的指导。然而,在你的第三行出现了这个错误。我该如何解释?[: true: 需要整数表达式 - Bryan Wong
1
@BryanWong 抱歉,请使用 == 而不是 -eq-eq 用于数字,== 用于字符串。我已编辑了我的答案。 - Brian Campbell
@BrianCampbell:实际上,Bash确实有布尔类型。起初我还持怀疑态度,但是我进行了一些调查。你可以自己试试。if语句的行为就像一个布尔值,而不是一个已设置或未设置的字符串。 - siride
1
@siride if语句作用于布尔值,但作用于传入命令的返回值,而不是变量的字符串值。因此,Bash具有布尔返回值(尽管0映射为true,任何非零值映射为false,这有点违反直觉),但不能将返回值存储在变量中,然后直接用if测试它;你需要使用if [ $var -eq 0 ]来执行[test命令,并检查该命令的返回值。基本上,Bash具有布尔退出码,但没有布尔变量。 - Brian Campbell
@siride 这可能有点令人困惑,因为它确实有 truefalse,以及像 &&|| 这样的运算符。truefalse 是命令,它们返回 0 和非零;而 &&|| 基于命令的退出代码进行操作。所以你可以写 if true && false; then ...,它是有效的。但你不能存储它。foo=$(true) 存储了 true 的标准输出到 foo 中,而不是返回值。true; foo=$? 存储了返回值;但你不能说 if $foo; then ... - Brian Campbell

2
你是否真的在=和"true"/"false"之间放了一个空格,还是这是格式错误?这是你的问题之一。
另外,如评论中Anders Lindahl所提到的,当你在shell脚本中设置变量时,不能在前面使用$。你必须这样说:
doFirst=false

请注意,等号周围不应该有空格。


嗨,siride,我实际上正在访问在第一行声明的相同变量... 我仍然可以删除$吗? - Bryan Wong
3
在读取变量时使用 $,而不是在赋值变量时使用。例如,将 doFirst=falseif $doFirst 区分开来。 - Barmar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接