在这个问题中,已经展示了如何在 bash 中使用简洁的布尔变量。有没有办法用这些变量执行逻辑运算?例如如何得到这个:
var1=true
var2=false
# ...do something interesting...
if ! $var1 -a $var2; then <--- doesn't work correctly
echo "do sth"
fi
这确实有效:
if ! $var1 && $var2; then
echo "do sth"
fi
也许有人可以解释为什么 -a 和 -o 运算符不起作用和 &&, ||, ! 做?
好的男孩和女孩,上课时间。
执行此行时发生了什么?
if true ; then echo 1 ; fi
这里发生的是if
命令正在执行。之后发生的一切都是if
命令的一部分。
它的作用是if
执行一个或多个命令(或者更确切地说,管道),并且如果执行的最后一个命令的返回代码成功,它会在达到then
until之后执行命令fi
。如果返回代码不成功,then
则跳过该部分并在之后继续执行fi
。
if
不带开关,它的行为无论如何都不可修改。
在上面的示例中,我告诉if
执行的命令是true
. true
不是语法或关键字,它只是另一个命令。尝试自己执行它:
true
它不会打印任何内容,但会将其返回码设置为0
(又名“true”)。if
将上面的语句改写成这样,可以更清楚地看出它是一个命令:
if /bin/true ; then echo 1 ; fi
这是完全等价的。
总是从测试中返回 true 并不是很有用。它通常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
语句之前,对变量进行评估。假设我输入了 20 forfirst
和 25 for second
,评估后脚本将如下所示:
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
被执行时,它将是 testing 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
因此它总是会成功返回if
,即使您说过
if ! [ false -a yourmom ] ; then
由于两者都是非空字符串-a
,测试都为真,返回成功,它被反转!
并传递给if
,它不执行then
语句。
如果你test
用这个版本替换版本
if ! $var1 && $var2 ; then
然后它将被评估为
if ! true && false ; then
并且会这样处理:if
执行true
返回成功;由!
;反转 因为第一个命令的返回码是失败的&&
语句短路并且false
永远不会被执行。因为最后执行的命令返回了失败,失败被传回if
不执行then
子句的那个。
我希望这一切都清楚了。
或许值得指出的是,您可以使用这样的结构:
! false && true && echo 1
哪个不使用if
但仍然检查返回码,因为那是什么&&
和||
用途。
test
在不犯任何错误的情况下使用是一种黑色艺术。通常,bash
在[[
使用[
.
由于原始海报没有提供他正在努力完成的实际示例,因此很难就最佳解决方案提供任何具体建议。希望这对他有足够的帮助,他现在可以找出正确的做法。
您在这里混合了两种不同的语法。
这将起作用:
if ! [ 1 -a 2 ]; then
echo "do sth"
fi
注意表达式周围的括号。
您需要test
命令([
在较新的语法中)才能使用这些键(-a
等-o
)。
但是test
nut run 命令本身。如果要检查命令的退出代码,则不能使用test
.