对布尔变量的操作

时间:2012-06-18 08:06:56

标签: bash shell boolean sh

在这个question中,已经展示了如何在bash中使用整齐的布尔变量。有没有办法用这些变量执行逻辑运算?例如。怎么弄这个:

var1=true
var2=false
# ...do something interesting...
if ! $var1 -a $var2; then     <--- doesn't work correctly
   echo "do sth"
fi

3 个答案:

答案 0 :(得分:7)

这确实有效:

if ! $var1 && $var2; then
   echo "do sth"
fi

也许有人可以解释为什么-a和-o运算符不起作用&amp;&amp;,|| ,!办?

答案 1 :(得分:5)

好的男孩和女孩,上课时间。

执行此行时会发生什么?

if true ; then echo 1 ; fi

这里发生的是if命令正在执行。之后发生的一切都是if命令的一部分。

if执行的是一个或多个命令(或管道),如果执行的最后一个命令的返回代码成功,则执行then之后的命令直到{{达到了1}}。如果返回代码不成功,则会跳过fi部分,并在then之后继续执行。

fi 不接受任何切换,其行为无论如何都无法修改。

在上面的示例中,我告诉if执行的命令是iftrue不是语法或关键字,它只是另一个命令。尝试自己执行:

true

它不会打印任何内容,但会将其返回码设置为true (又称“true”)。您可以通过重写上面的0语句来更清楚地看到它是一个命令:

if

这完全等同。

始终从测试中返回true并不是很有用。通常将if /bin/true ; then echo 1 ; fi if命令结合使用。 test有时会与test进行符号链接或称为[。在您的系统上,您可能有一个/bin/[程序,但如果您使用的是bash [,那么它将是一个内置命令。 test是一个比if更复杂的命令,您可以阅读所有相关信息。

help [
man [

但是现在让我们说test根据您提供的选项执行一些测试,并返回成功的返回码(0)或不成功的返回码。这允许我们说

if [ 1 -lt 2 ] ; then echo one is less than two ; fi

但同样,总是是真的,所以它不是很有用。如果12是变量

,那会更有用
read -p' Enter first number: ' first
read -p' Enter second number: ' second
echo first: $first
echo second: $second
if [ $first -lt $second ] ; then
     echo $first is less than $second
fi

现在你可以看到test正在发挥作用。这里我们传递test四个参数。第二个参数是-lt,它是一个告诉test的开关,应该测试第一个参数和第三个参数,以查看第一个参数是否小于第三个参数。第四个论点什么也没做,只是标志着命令的结束;将test称为[时,最终参数必须始终为]

在执行上述if语句之前,将评估变量。假设我为first输入了20,为second输入了25,在评估之后,脚本将如下所示:

read -p' Enter first number: ' first
read -p' Enter second number: ' second
echo first: 20
echo second: 25
if [ 20 -lt 25 ] ; then
     echo 20 is less than 25
fi

现在您可以看到执行test时它将测试is 20 less than 25?,这是真的,因此if将执行then语句。

回到手头的问题:这里发生了什么?

var1=true
var2=false

if ! $var1 -a $var2 ; then
    echo $var1 and $var2 are both true
fi

评估if命令时,它将变为

if ! true -a false ; then

这是指示if执行true并将参数-a false传递给true命令。现在,true不接受任何开关或参数,但如果您不需要它们也不会产生错误。这意味着它将执行,返回成功,-a false部分将被忽略。 !将取消成功失败,then部分将不会被执行。

如果您要使用调用test的版本替换上述版本,则仍然无法正常工作:

var1=true
var2=false

if ! [ $var1 -a $var2 ] ; then
    echo $var1 and $var2 are both true
fi

因为if行将被评估为

if ! [ true -a false ; ] then

并且test会将true视为布尔关键字,而不是命令,而是字符串。由于test将非空字符串视为“true”,因此即使您说过

,也会将成功返回if
if ! [ false -a yourmom ] ; then

由于两者都是非空字符串-a,因此测试为true,返回成功与!相反并传递给if,后者不执行then言。

如果您将test版本替换为此版本

if ! $var1 && $var2 ; then

然后它将被评估到

if ! true && false ; then

将按照以下方式处理:if执行true,返回成功;由!逆转;因为第一个命令的返回码失败,&&语句短路并且false永远不会被执行。由于执行的最终命令返回失败,因此失败将传递回if,而不执行then子句。

我希望这一切都清楚。

或许值得指出的是,你可以使用这样的结构:

! false && true && echo 1

哪个不使用if但仍会检查返回代码,因为这是&&||的用途。

使用test而不犯任何错误有一种黑色艺术。通常,在使用bash时,应该使用较新的[[命令,因为它更强大并且消除了许多陷阱,出于兼容性原因,这些问题必须保存在[中。

由于原始海报没有提供他试图完成的实际例子,因此很难就最佳解决方案提出任何具体建议。希望这足以帮助他现在能够找到正确的事情。

答案 2 :(得分:1)

你在这里混合了两种不同的语法。

这将有效:

if ! [ 1 -a 2 ]; then
   echo "do sth"
fi

注释表达式。

您需要test命令(在较新的语法中为[)才能使用这些密钥(-a-o等等。)

但是test会自行运行命令。 如果要检查命令的退出代码,则不得使用test