对布尔变量的操作

pms*_*pms 2 bash shell boolean sh

在这个问题中,已经展示了如何在bash中使用整齐的布尔变量.有没有办法用这些变量执行逻辑运算?例如,如何得到这个:

var1=true
var2=false
# ...do something interesting...
if ! $var1 -a $var2; then     <--- doesn't work correctly
   echo "do sth"
fi
Run Code Online (Sandbox Code Playgroud)

pms*_*pms 7

这确实有效:

if ! $var1 && $var2; then
   echo "do sth"
fi
Run Code Online (Sandbox Code Playgroud)

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

  • -a和-o是来自旧Bourne shell的`test`命令(你没有使用)的运算符,并且已经过时了.&&和!是bash语法的一部分. (5认同)

Sor*_*gal 5

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

执行此行时发生了什么?

if true ; then echo 1 ; fi
Run Code Online (Sandbox Code Playgroud)

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

什么if确实是在执行一个或多个命令(或者更确切地说,管道),如果从最后执行的命令的返回码是成功的,它执行后的命令then,直到fi达到.如果返回代码不成功,then则跳过该部件并在之后继续执行fi.

if 没有开关,它的行为无论如何都是不可修改的.

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

true
Run Code Online (Sandbox Code Playgroud)

它什么都不打印,但它将返回代码设置为0(又名"true").您可以通过重写上述if语句来更清楚地看到它是一个命令:

if /bin/true ; then echo 1 ; fi
Run Code Online (Sandbox Code Playgroud)

这完全等同.

始终从测试中返回true并不是很有用.通常iftest命令一起使用.test有时符号链接或以其他方式称为[.在你的系统上你可能有一个/bin/[程序,但是如果你正在使用bash [它将是一个内置命令.test是一个比一个更复杂的命令if,你可以阅读所有相关的.

help [
man [
Run Code Online (Sandbox Code Playgroud)

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

if [ 1 -lt 2 ] ; then echo one is less than two ; fi
Run Code Online (Sandbox Code Playgroud)

但同样,这总是如此,所以它不是很有用.这将是更为有用的,如果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
Run Code Online (Sandbox Code Playgroud)

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

在执行上述if语句之前,将评估变量.假设我输入了20 for first和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
Run Code Online (Sandbox Code Playgroud)

现在您可以看到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
Run Code Online (Sandbox Code Playgroud)

if评估命令时,它将成为

if ! true -a false ; then
Run Code Online (Sandbox Code Playgroud)

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

如果您要使用调用版本替换上面的内容,test它仍然无法按预期工作:

var1=true
var2=false

if ! [ $var1 -a $var2 ] ; then
    echo $var1 and $var2 are both true
fi
Run Code Online (Sandbox Code Playgroud)

因为该if行将被评估为

if ! [ true -a false ; ] then
Run Code Online (Sandbox Code Playgroud)

并且test不会将其true视为布尔关键字,而不是作为命令,而是作为字符串.由于非空字符串被视为"真",test因此if即使您说过,它也会始终返回成功

if ! [ false -a yourmom ] ; then
Run Code Online (Sandbox Code Playgroud)

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

如果您test使用此版本替换该版本

if ! $var1 && $var2 ; then
Run Code Online (Sandbox Code Playgroud)

然后它将被评估为

if ! true && false ; then
Run Code Online (Sandbox Code Playgroud)

并将像这样处理:if执行true返回成功; 被逆转的!; 因为第一个命令的返回码是失败的,&&语句短路并且false永远不会被执行.由于执行的最终命令返回失败,因此将失败传递回if不执行该then子句的错误.

我希望这一切都清楚.

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

! false && true && echo 1
Run Code Online (Sandbox Code Playgroud)

哪个不使用if但仍然检查返回代码,因为这是什么&&||适用.

有一种黑色艺术可以使用test而不会犯任何错误.通常,在使用时bash,[[应该使用较新的命令,因为它更强大并且消除了许多必须由于兼容性原因而必须保留的陷阱[.

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