为什么在bash中$((true == false))的结果是1?

47

为什么bash会有以下行为?

echo $((true == false))
1

我本以为这会打印出0,但它却打印出1

以下事实进一步增加了复杂性:

> echo $((true))
0
> echo $((false))
0
> echo $((true == true))
1
> echo $((false == false))
1
2个回答

57
所有谈论0为真,1为假的帖子都错了。在这种情况下,由于$(())引起的算术评估上下文,1是真的,0是假的,与通常的布尔意义相反。 $(())中的==操作不是Bash中返回状态的相等性,它使用给定的文字进行数字相等性比较,其中"false"和"true"被视为变量但尚未绑定,因为它们没有赋值,所以都被解释为0:
$ echo $((true))
0
$ echo $((false))
0

如果你想比较true和false的返回状态,你需要这样做:

true
TRUE=$?
false
FALSE=$?
if (( $TRUE == $FALSE )); then echo TRUE; else echo FALSE; fi

但我不确定你为什么想要这样做。

编辑:更正了原回答中关于“true”和“false”被解释为字符串的部分。它们被视为变量,但尚未绑定任何值。


此外,echo $(( $TRUE == $FALSE )) 将会报告 0,正如你所期望的那样。echo $(( $TRUE == $TRUE ))echo $(( $FALSE == $FALSE )) 也将会报告 1 - zostay
这是正确的。在Bash中,“true”和“false”作为布尔值不存在,因此在$(())内部没有特殊含义。 - sorpigal
2
+1,对于其他所有答案都是-1...还有其他人读了问题吗? - Random832
很抱歉,但这是不正确的。首先:如果 (( $TRUE == $FALSE )); then echo TRUE; else echo FALSE; fi(( 上是语法错误。然后 $((...)) 对其操作数执行算术运算。 $((true)) 返回0的事实是因为环境中没有名为 true 的变量,并且操作数的算术运算对于任何字符串都会产生0。 - fge
@fge,您的观点是错误的,因为您误解了变量插入。因为在您的shell中未定义TRUEFALSE,所以该行代码会被解释为if (( == ));....,这当然是语法错误。要查看正确的结果,请在尝试if语句之前添加TRUE=1; FALSE=0 - Izkata
1
@fge,你部分正确,但并非完全正确。的确,$((true)) 返回 0,因为 $true 在本地环境中没有被赋值(这一点在我的解释中没有完全正确),我马上会进行更正。我相信 @izkata 已经解释了你不完全正确的部分,因为在我的 Mac 上使用全新的环境,在 Bash 3.2 上运行 if (( $TRUE == $FALSE )); ... 是可以正常运行的。在旧版本的 Bash 上可能是语法错误。 - zostay

22

好的,似乎有很多人对$((...)) 真正的作用感到困惑。

它执行操作数的算术运算,裸词是变量,不是命令或字符串字面量(即 true 实际上是 $true),而任何不是数字的内容都为0== 运算符比较两个数字,如果它们相等则返回1。

这就是为什么$((true == false)) 为1的原因:环境中没有 truefalse 环境变量,这意味着 $true$false 都在算术环境下计算为空字符串,因此结果为0!

要完整,您还可以在算术上下文中使用命令替换...例如:

$ echo $((`echo 2`))
2
$ echo $((3 + $(echo 4)))
7
$ a=3
$ echo $((a + $(echo 4)))
7
# undefine a
$ a=
$ echo $((a + $(echo 4)))
4
$ a="Hello world"
$ echo $((a + 1))
1
# undefine a again
$ a=
$ echo $(($(echo $a)))
0

我已经给这个答案点赞,因为你说的和@zostay完全相同,只是你没有理解他的例子。你之所以收到语法错误,是因为在你的shell中没有定义TRUE和FALSE; 他的完整示例将它们定义为true和false命令的数字返回代码(请仔细查看其他答案中它上面的4行; TRUE = $? 定义了变量$ TRUE等)。 - Izkata
我对这个例子的说法已经纠正了。但是,我并没有说和@zostay一样的话:@zostay说truefalse被视为字符串——这不是事实!它们被视为环境变量,这是完全不同的东西,而$true$false会被计算为空字符串,而不是字面值。尝试执行echo $(($(echo $a))),其中a未定义:它不会产生语法错误,但返回0。他说得对,字符串会被计算为0。但实际上,在这种情况下,任何非数字的东西都会被计算为0。 - fge

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