bash 布尔变量的操作

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11079017/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 02:31:22  来源:igfitidea点击:

Operations on boolean variables

bashshellbooleansh

提问by pms

In this questionit has been shown how to use neat boolean variables in bash. Is there a way of performing logic operations with such variables? E.g. how to get this:

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

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

回答by pms

This does work:

这确实有效:

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

Maybe somebody can explain why -a and -o operators don't work and &&, ||, ! do?

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

回答by sorpigal

Okay boys and girls, lesson time.

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

What's happening when you execute this line?

执行此行时发生了什么?

if true ; then echo 1 ; fi

What's happening here is that the ifcommand is being executed. After that everything that happens is part of the ifcommand.

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

What ifdoes is it executes one or more commands (or rather, pipelines) and, if the return code from the last command executed was successful, it executes the commands after thenuntil fiis reached. If the return code was not successful the thenpart is skipped and execution continues after fi.

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

iftakes no switches, its behavior is not modifiable in anyway.

if没有开关,它的行为无论如何都不能修改。

In the example above the command I told ifto execute was true. trueis not syntax or a keyword, it's just another command. Try executing it by itself:

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

true

It will print nothing, but it set its return code to 0(aka "true"). You can more clearly see that it is a command by rewriting the above ifstatement like this:

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

if /bin/true ; then echo 1 ; fi

Which is entirely equivalent.

这是完全等效的。

Always returning true from a test is not very useful. It is typical to use ifin conjunction with the testcommand. testis sometimes symlinked to or otherwise known as [. On your system you probably have a /bin/[program, but if you're using bash[will be a builtin command. testis a more complex command than ifand you can read all about it.

总是从测试中返回 true 不是很有用。通常iftest命令结合使用。test有时符号链接到或以其他方式称为[. 在您的系统上,您可能有一个/bin/[程序,但如果您使用的bash[是内置命令。test是一个更复杂的命令if,您可以阅读所有相关内容。

help [
man [

But for now let us say that testperforms some tests according to the options you supply and returns with either a successful return code (0) or an unsuccessful one. This allows us to say

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

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

But again, this is alwaystrue, so it's not very useful. It would be more useful if 1and 2were variables

但同样,这总是正确的,所以它不是很有用。如果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

Now you can see that testis doing its job. Here we are passing testfour arguments. The second argument is -ltwhich is a switch telling testthat the first argument and third argument should be tested to see if the first argument is less than the third argument. The fourth argument does nothing but mark the end of the command; when calling testas [the final argument must always be ].

现在您可以看到它test正在发挥作用。这里我们传递了test四个参数。第二个参数是-ltwhich 是一个开关,告诉test第一个参数和第三个参数应该被测试以查看第一个参数是否小于第三个参数。第四个参数只标记命令的结束;当test作为[最后一个参数调用时,必须始终是].

Before the above ifstatement is executed the variables are evaluated. Suppose that I had entered 20 for firstand 25 for second, after evaluation the script will look like this:

在执行上述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

And now you can see that when testis executed it will be testing is 20 less than 25?, which is true, so ifwill execute the thenstatement.

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

Bringing it back to the question at hand: What's going on here?

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

var1=true
var2=false

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

When the ifcommand is evaluated it will become

if命令被评估时,它将变成

if ! true -a false ; then

This is instructing ifto execute trueand passing the arguments -a falseto the truecommand. Now, truedoesn't take any switches or arguments, but it also will not produce an error if you supply them without need. This means that it will execute, return success and the -a falsepart will be ignored. The !will reverse the success in to a failure and the thenpart will not be executed.

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

If you were to replace the above with a version calling testit would still not work as desired:

如果你用一个调用test它的版本替换上面的内容,它仍然不能按预期工作:

var1=true
var2=false

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

Because the ifline would be evaluated to

因为该if行将被评估为

if ! [ true -a false ; ] then

And testwould see truenot as a boolean keyword, and not as a command, but as a string. Since a non-empty string is treated as "true" by testit will always return success to if, even if you had said

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

if ! [ false -a yourmom ] ; then

Since both are non-empty strings -atests both as true, returns success which is reversed with !and passed to if, which does not execute the thenstatement.

由于两者都是非空字符串,因此-a测试都为真,返回成功,它被反转!并传递给if,它不执行then语句。

If you replace the testversion with this version

如果你test用这个版本替换版本

if ! $var1 && $var2 ; then

Then it will be evaluated in to

然后它将被评估为

if ! true && false ; then

And will be processed like this: ifexecutes truewhich returns success; which is reversed by !; because the return code of the first command was failure the &&statement short circuits and falsenever gets executed. Because the final command executed returned a failure, failure is passed back to ifwhich does not execute the thenclause.

并会像这样处理:if执行true返回成功;这被逆转了!; 因为第一个命令的返回码失败,&&语句短路并且false永远不会被执行。因为最后执行的命令返回一个失败,失败被传递回if不执行then子句的那个。

I hope this is all clear.

我希望这一切都清楚。

It is perhaps worth pointing out that you can use constructs like this:

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

! false && true && echo 1

Which does not use ifbut still checks return codes, because that is what &&and ||are for.

哪个不使用if但仍然检查返回码,因为这是什么&&||也是为了。

There is kind of a black art to using testwithout making any mistakes. In general, when using bash, the newer [[command should be used instead because it is more powerful and does away with lots of gotchas which must, for compatibility reasons, be kept in [.

test不犯任何错误的情况下使用有一种黑色艺术。一般来说,当使用 时bash[[应该使用较新的命令,因为它更强大,并且消除了许多出于兼容性原因必须保留在[.

Since the original poster did not supply a realistic example of what he's trying to accomplish it's hard to give any specific advice as to the best solution. Hopefully this has been sufficiently helpful that he can now figure out the correct thing to do.

由于原始海报没有提供他正在努力完成的现实示例,因此很难就最佳解决方案提供任何具体建议。希望这已经足够有帮助,他现在可以找出正确的做法。

回答by Igor Chubin

You have mixed here two different syntaxes.

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

This will work:

这将起作用:

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

Note brackets around the expressions.

注意表达式周围的括号。

You need the testcommand ([in newer syntax) to use these keys (-a, -oand so on).

您需要test命令([以较新的语法)来使用这些键(-a-o等等)。

But testdoes nut run commands itself. If you want to check exit codes of commands you must not use test.

但是testnut run 命令本身。如果要检查命令的退出代码,则不得使用test.