我尝试使用以下语法在 shell 脚本中声明一个布尔变量:
variable=$false
variable=$true
它是否正确?另外,如果我想更新该变量,我会使用相同的语法吗?最后,使用布尔变量作为正确的表达式是以下语法:
if [ $variable ]
if [ !$variable ]
修订回答(2014 年 2 月 12 日)
the_world_is_flat=true
# ...do something interesting...
if [ "$the_world_is_flat" = true ] ; then
echo 'Be careful not to fall off!'
fi
原始答案
警告: https : //stackoverflow.com/a/21210966/89391
the_world_is_flat=true
# ...do something interesting...
if $the_world_is_flat ; then
echo 'Be careful not to fall off!'
fi
From: 在 Bash 中使用布尔变量
这里包含原始答案的原因是因为 2014 年 2 月 12 日修订前的评论仅适用于原始答案,并且许多评论在与修订后的答案相关时是错误的。例如,丹尼斯 · 威廉姆森的有关 bash 的评论内置true
在 2010 年 6 月 2 日只适用于原有的答案,而不是修改。
bool=true
if [ "$bool" = true ]
我不推荐接受的答案1 。它的语法很漂亮,但它有一些缺陷。
假设我们有以下条件。
if $var; then
echo 'Muahahaha!'
fi
在以下情况2 中 ,此条件将评估为true并执行嵌套命令。
# Variable var not defined beforehand. Case 1
var='' # Equivalent to var="". Case 2
var= # Case 3
unset var # Case 4
var='<some valid command>' # Case 5
通常,当您的 “boolean” 变量(在此示例中为var
)显式设置为 true 时,您只希望将条件计算为 true。所有其他案件都具有危险的误导性!
最后一种情况(#5)尤其顽皮,因为它将执行变量中包含的命令(这就是为什么条件对于有效命令3,4评估为真的原因)。
这是一个无害的例子:
var='echo this text will be displayed when the condition is evaluated'
if $var; then
echo 'Muahahaha!'
fi
# Outputs:
# this text will be displayed when the condition is evaluated
# Muahahaha!
引用变量更安全,例如if "$var"; then
。在上述情况下,您应该收到一条警告,指出找不到该命令。但我们仍然可以做得更好(请参阅我在底部的建议)。
另请参阅 Mike Holt 对 Miku 原始答案的解释。
这种方法也有意想不到的行为。
var=false
if [ $var ]; then
echo "This won't print, var is false!"
fi
# Outputs:
# This won't print, var is false!
您可能希望上述条件计算为 false,因此从不执行嵌套语句。惊喜!
引用值( "false"
),引用变量( "$var"
),或使用test
或[[
而不是[
,不要有所作为。
以下是我建议您查看 “布尔” 的方法。他们按预期工作。
bool=true
if [ "$bool" = true ]; then
if [ "$bool" = "true" ]; then
if [[ "$bool" = true ]]; then
if [[ "$bool" = "true" ]]; then
if [[ "$bool" == true ]]; then
if [[ "$bool" == "true" ]]; then
if test "$bool" = true; then
if test "$bool" = "true"; then
它们几乎都是等价的。你需要输入比其他答案中的方法更多的键击5但你的代码将更具防御性。
man woman
仍将被视为有效命令。 这里似乎存在一些误解,关于 Bash 内置的true
,更具体地说,关于 Bash 如何扩展和解释括号内的表达式。
miku 的答案中的代码与 Bash builtin true
,nor /bin/true
以及true
命令的任何其他风格完全无关。在这种情况下, true
只不过是一个简单的字符串,并且不会通过变量赋值或条件表达式的求值来调用true
命令 / builtin。
以下代码在功能上与 miku 的答案中的代码相同:
the_world_is_flat=yeah
if [ "$the_world_is_flat" = yeah ]; then
echo 'Be careful not to fall off!'
fi
这里唯一的区别是被比较的四个字符是'y','e','a' 和'h' 而不是't','r','u' 和'e'。而已。没有尝试调用命令或内置命名为yeah
,也没有(在 miku 的例子中)当 Bash 解析令牌为true
时进行任何类型的特殊处理。它只是一个字符串,而且是一个完全随意的字符串。
更新(2014-02-19):按照 miku 的回答中的链接后,现在我看到了一些混乱的来源。 Miku 的答案使用单括号,但他链接到的代码片段不使用括号。只是:
the_world_is_flat=true
if $the_world_is_flat; then
echo 'Be careful not to fall off!'
fi
两个代码片段的行为方式都相同,但括号完全改变了引擎盖下的内容。
这是 Bash 在每种情况下所做的事情:
没有括号:
$the_world_is_flat
扩展为字符串"true"
。 "true"
解析为命令。 true
命令(内置或/bin/true
,具体取决于 Bash 版本)。 true
命令的退出代码(始终为 0)与 0 进行比较。回想一下,在大多数 shell 中,退出代码为 0 表示成功,其他任何表示失败。 if
语句的then
子句括号:
$the_world_is_flat
扩展为字符串"true"
。 string1 = string2
。 =
运算符是 bash 的字符串比较运算符 。所以... "true"
和"true"
进行字符串比较。 if
语句的then
子句。 无括号代码有效,因为true
命令返回退出代码 0,表示成功。括号中的代码有效,因为$the_world_is_flat
的值与=
右侧的字符串文字true
相同。
只是为了推动这一点,请考虑以下两段代码:
此代码(如果以 root 权限运行)将重新启动您的计算机:
var=reboot
if $var; then
echo 'Muahahaha! You are going down!'
fi
这段代码只打印 “Nice try”。不会调用 reboot 命令。
var=reboot
if [ $var ]; then
echo 'Nice try.'
fi
更新(2014-04-14)要回答关于=
和==
:AFAIK 之间差异的评论中的问题,没有区别。 ==
运算符是=
的特定于 Bash 的同义词,就我所见,它们在所有上下文中的工作方式完全相同。
但请注意,我特别谈到在[ ]
或[[ ]]
测试中使用的=
和==
字符串比较运算符。我并不是说在 bash 中到处都可以互换=
和==
。
例如,您显然无法使用==
进行变量赋值,例如var=="foo"
(从技术上讲,您可以执行此操作,但var
的值将为"=foo"
,因为 Bash 没有看到==
运算符在这里,它看到一个=
(赋值)运算符,后面是文字值="foo"
,它只是变成"=foo"
)。
此外,虽然=
和==
是可以互换的,但你应该记住,这些测试的工作方式取决于你是在[ ]
或[[ ]]
使用它,还是取决于是否引用了操作数。您可以在Advanced Bash Scripting Guide 中阅读更多相关内容:7.3 其他比较运算符 (向下滚动到=
和==
的讨论)。