Bash布尔测试

15

我希望在一个标志被设置为true而另一个标志被设置为false时运行一段代码。即

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

由于那个测试结果并没有如我所预期的那样,我写了几个其他的测试用例,但是我很难理解它们是如何被评估的。

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
当我运行上面的代码块时,我唯一得到的输出是:

Test0
Test0.1
Test0.2

然而,我的期望是获取以下输出:

Test0
Test1
Test3
Test5
Test7

我尝试过理解运行类似测试的最佳方式,但我发现大多数示例都以以下格式设置:
if [[ "$aa" == true ]];
这并不是我想做的。因此,我的问题是什么是进行此类比较的最佳方法,为什么我期望通过的几个测试用例竟然没有通过?
谢谢!
5个回答

18

您对Shell上下文中的布尔值的理解是不正确的。

var1=true
var2=false

由于这些变量都是非空的字符串,因此上述变量均为true

您也可以使用算术上下文:

$ 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

2
您可以将此与 readonly true=1 yes=1 no=0 false=0 结合使用,以在算术表达式中创建可靠的 truefalse 常量。 - Henk Langeveld

18

没有任何操作符,[[ 只能检查变量是否为空。如果是空的,则被认为是 false,否则被认为是 true。变量的内容并不重要。


谢谢。在我将bb=false这行注释掉后重新运行脚本,我明白了它的工作原理,输出结果与我预期更一致。 - JLMarks
作为一个奇怪的旁白,这是我在stackoverflow上提出的第二个问题,第一个问题是两年多前。在那个问题中,你是唯一回答我的用户。我现在才来接受你的答案,所以再次感谢! - JLMarks
你可以把可复制的答案放在这里吗?还有修正过的代码吗?谢谢。 - Walrus the Cat

13

Shell本身并没有布尔类型的变量。但是,有两个名为truefalse的命令,它们的退出状态分别为0和1,因此可以类比布尔值来使用。

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

不同之处在于,你将var1的测试是否被设置为真值扩展为一个命令的名称,并运行和成功。同样,var2被扩展为一个运行失败的命令名称,但由于其前缀是!,因此退出状态被反转以表示成功。

(请注意,与大多数编程语言不同,退出状态为0表示成功,因为大多数命令只有一种成功的方式,而它们可能失败的方式有很多,因此可以分配不同的非零值来表示不同的含义。)


8

0

最接近的方法似乎是使用函数而不是变量,因为您可以在条件语句中使用它们的返回状态。

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

我们可以用这种方式进行测试

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

或者这样

$  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

希望这能有所帮助。

请参考上面的@chepner:https://dev59.com/questions/JWAg5IYBdhLWcg3wrMh4#23324368,true/false函数被构建为布尔值。 - Bradmage

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接