在这个question中,已经展示了如何在bash中使用整齐的布尔变量。有没有办法用这些变量执行逻辑运算?例如。怎么弄这个:
var1=true
var2=false
# ...do something interesting...
if ! $var1 -a $var2; then <--- doesn't work correctly
echo "do sth"
fi
答案 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
执行的命令是if
。 true
不是语法或关键字,它只是另一个命令。尝试自己执行:
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
但同样,总是是真的,所以它不是很有用。如果1
和2
是变量
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
。