为什么bash会有以下行为?
echo $((true == false))
1
我本以为这会打印出0
,但它却打印出1
。
以下事实进一步增加了复杂性:
> echo $((true))
0
> echo $((false))
0
> echo $((true == true))
1
> echo $((false == false))
1
为什么bash会有以下行为?
echo $((true == false))
1
我本以为这会打印出0
,但它却打印出1
。
以下事实进一步增加了复杂性:
> echo $((true))
0
> echo $((false))
0
> echo $((true == true))
1
> echo $((false == false))
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”被解释为字符串的部分。它们被视为变量,但尚未绑定任何值。
好的,似乎有很多人对$((...))
真正的作用感到困惑。
它执行操作数的算术运算,裸词是变量,不是命令或字符串字面量(即 true
实际上是 $true
),而任何不是数字的内容都为0。 ==
运算符比较两个数字,如果它们相等则返回1。
这就是为什么$((true == false))
为1的原因:环境中没有 true
或 false
环境变量,这意味着 $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
TRUE = $?
定义了变量$ TRUE等)。 - Izkatatrue
和false
被视为字符串——这不是事实!它们被视为环境变量,这是完全不同的东西,而$true
和$false
会被计算为空字符串,而不是字面值。尝试执行echo $(($(echo $a)))
,其中a
未定义:它不会产生语法错误,但返回0。他说得对,字符串会被计算为0。但实际上,在这种情况下,任何非数字的东西都会被计算为0。 - fge
echo $(( $TRUE == $FALSE ))
将会报告0
,正如你所期望的那样。echo $(( $TRUE == $TRUE ))
和echo $(( $FALSE == $FALSE ))
也将会报告1
。 - zostay$(())
内部没有特殊含义。 - sorpigal(( $TRUE == $FALSE )); then echo TRUE; else echo FALSE; fi
在((
上是语法错误。然后$((...))
对其操作数执行算术运算。$((true))
返回0的事实是因为环境中没有名为true
的变量,并且操作数的算术运算对于任何字符串都会产生0。 - fgeTRUE
和FALSE
,所以该行代码会被解释为if (( == ));....
,这当然是语法错误。要查看正确的结果,请在尝试if语句之前添加TRUE=1; FALSE=0
。 - Izkata$((true))
返回 0,因为$true
在本地环境中没有被赋值(这一点在我的解释中没有完全正确),我马上会进行更正。我相信 @izkata 已经解释了你不完全正确的部分,因为在我的 Mac 上使用全新的环境,在 Bash 3.2 上运行if (( $TRUE == $FALSE )); ...
是可以正常运行的。在旧版本的 Bash 上可能是语法错误。 - zostay