在这个问题中,已经展示了如何在 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执行一个或多个命令(或者更确切地说,管道),并且如果执行的最后一个命令的返回代码成功,它会在达到thenuntil之后执行命令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)。
但是testnut run 命令本身。如果要检查命令的退出代码,则不能使用test.