Bash Boolean testing

送分小仙女□ 提交于 2021-02-05 20:11:51

问题


I am attempting to run a block of code if one flag is set to true and the other is set to false. ie

var1=true
var2=false
if [[ $var1 && ! $var2 ]]; then var2="something"; fi

Since that did not evaluate the way that I expected I wrote several other test cases and I am having a hard time understanding how they are being evaluated.

aa=true 
bb=false
cc="python"
if [[ "$aa" ]]; then echo "Test0" ; fi
if [[ "$bb" ]]; then echo "Test0.1" ; fi
if [[ !"$aa" ]]; then echo "Test0.2" ; fi
if [[ ! "$aa" ]]; then echo "Test0.3" ; fi
if [[ "$aa" && ! "$bb" ]]; then echo "Test1" ; fi
if [[ "$aa" && ! "$aa" ]]; then echo "Test2" ; fi
if [[ "$aa" ]] && ! [[ "$bb" ]]; then echo "test3" ; fi
if [[ "$aa" ]] && ! [[ "$cc" ]]; then echo "test4" ; fi
if [[ $aa && ! $bb ]]; then echo "Test5" ; fi
if [[ $aa && ! $aa ]]; then echo "Test6" ; fi
if [[ $aa ]] && ! [[ $bb ]]; then echo "test7" ; fi
if [[ $aa ]] && ! [[ $cc ]]; then echo "test8" ; fi

When I run the preceding codeblock the only output I get is

Test0
Test0.1
Test0.2

however, my expectation is that I would get

Test0
Test1
Test3
Test5
Test7

I have tried to understand the best way to run similar tests, however most examples I have found are set up in the format of
if [[ "$aa" == true ]];
which is not quite what I want to do. So my question is what is the best way to make comparisons like this, and why do several of the test cases that I would expect to pass simply not?

Thank you!


回答1:


Without any operators, [[ only checks if the variable is empty. If it is, then it is considered false, otherwise it is considered true. The contents of the variables do not matter.




回答2:


Your understanding of booleans in shell context is incorrect.

var1=true
var2=false

Both the above variables are true since those are non-empty strings.

You could instead make use of arithmetic context:

$ a=1
$ b=0
$ ((a==1 && b==0)) && echo y
y
$ ((a==0 && b==0)) && echo y
$
$ ((a && !(b))) && echo y;       # This seems to be analogous to what you were attempting
y



回答3:


true and false are evaluated as strings ;)

[[ $var ]] is an equivalent of [[ -n $var ]] that check if $var is empty or not.

Then, no need to quote your variables inside [[. See this reminder.

Finally, here is an explication of the difference between && inside brackets and outside.




回答4:


The shell does not have Boolean variables, per se. However, there are commands named true and false whose exit statuses are 0 and 1, respectively, and so can be used similarly to Boolean values.

var1=true
var2=false
if $var1 && ! $var2; then var2="something"; fi

The difference is that instead of testing if var1 is set to a true value, you expand it to the name of a command, which runs and succeeds. Likewise, var2 is expanded to a command name which runs and fails, but because it is prefixed with ! the exit status is inverted to indicate success.

(Note that unlike most programming languages, an exit status of 0 indicates success because while most commands have 1 way to succeed, there are many different ways they could fail, so different non-zero values can be assigned different meanings.)




回答5:


The closest you can come seems to be use functions instead of variables because you can use their return status in conditionals.

$  var1() { return 0; }
$  var2() { return 1; }  # !0 = failure ~ false

and we can test this way

$  var1 && echo "it's true" || echo "it's false"
it's true
$  var2 && echo "it's true" || echo "it's false"
it's false

or this way

$  if var1; then echo "it's true"; else echo "it's false"; fi
it's true
$  if var2; then echo "it's true"; else echo "it's false"; fi
it's false

Hope this helps.



来源:https://stackoverflow.com/questions/23320150/bash-boolean-testing

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!