tl;dr
[ ! $bar ] 将$bar 视为字符串,并且任何非空 字符串都被视为“真” - 包括文字false ;换句话说:[ ! 'true' ] && [ ! 'false' ] both 评估为“false”,因为在这两种情况下操作数都是非空字符串,! 否定结果。
因此,必须使用字符串比较:
bar=false
if [ ! "$bar" = 'true' ]; then # same as: [ "$bar" != 'true' ]
echo 'bar is false'
else
echo 'bar is true'
fi
在 Bash 中,您还可以使用 [[ ! $bar == 'true' ]] 或 [[ $bar != 'true' ]];除非你需要保持 POSIX 兼容,I suggest using [[ ... ]]。
在[ ... ] 和[[ ... ]](特定于Bash)的上下文中,默认情况下变量值是字符串,并且通常是POSIX-像 shell没有明确的布尔数据类型。
一元运算符!将其操作数隐式解释为布尔值,字符串在布尔上下文中解释如下:
- 只有一个空字符串被认为是“false”(退出代码
1(!))
-
任何非空字符串 - 包括文字
false - 被视为“真”(退出代码0( !))
因此,! $bar 的计算结果为“假”,因为 $bar - 包含非空字符串 'false' - 计算结果为“真”,而 ! 将其反转。
!也可以用在条件之外直接否定命令的成功状态(包括[)。
由于false 和true 也以命令名 的形式存在(通常作为shell 内置命令),您可以 执行以下操作,但请注意它只能按预期工作变量值可以是文字 false 或 true:
bar=false
if ! "$bar"; then
echo 'bar is false'
else
echo 'bar is true'
fi
背景资料
类似 POSIX 的 shell 只有 2 种基本(标量)数据类型:
-
字符串(默认):
- 在
[ ... ] 和[[ ... ]] 条件句中,运算符=(Bash 中的==),,,>,>=` 执行字符串 em> 比较。
-
整数:
注意:根据 POSIX,您不能将变量键入为整数(因为没有办法声明 shell 变量),所以它只是隐式 在使用算术运算符的比较中/在算术上下文中视为一个。
然而,在 Bash 中,您可以使用declare -i / local -i声明整数变量,但在条件/算术上下文中,它仍然是运算符/算术上下文的选择,它决定了值是否被视为字符串或整数。
Shell 中的布尔值隐式表示为退出代码,在通常的布尔到整数映射的反转中:
- “true”映射到退出代码
0(!)
- “false”表示为退出代码
1(!) 或任何其他非零退出代码。