如何在shell脚本中声明和使用布尔变量?
我尝试使用以下语法在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日只适用于原有的答案,而不是修改。
TL; DR
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
通常,只有当您的“布尔”变量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
if "$var"; then
。 在上述情况下,您应该会收到警告,指出找不到该命令。 但是我们仍然可以做得更好(见底部的我的建议)。
另请参阅麦克霍尔特对美库原始答案的解释。
Hbar的答案存在问题
这种方法也有意想不到的行为。
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
他们几乎相当。 与其他答案中的方法相比,您将不得不输入更多的按键,但是您的代码将更具防御性。
脚注
man woman
仍然会被视为有效的命令。 似乎这里大约内建bash的一些误解true
,更具体地说,有关庆典是如何扩展和解释括号内的表达式。
miku的回答中的代码与bash内建的true
, /bin/true
以及true
命令的任何其他风格完全没有关系。 在这种情况下, true
只不过是一个简单的字符串,并且不会调用true
命令/内建函数,既不是通过变量赋值也不是通过对条件表达式的求值。
以下代码在功能上与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
时进行的任何特殊处理。 这只是一个字符串,而且完全是任意的。
更新(2/19/2014):在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”。 重新启动命令不被调用。
var=reboot
if [ $var ]; then
echo 'Nice try.'
fi
更新(2014年4月14日)要回答评论中关于=
和==
AFAIK之间差异的问题,没有区别。 ==
运算符是=
的特定于bash的同义词,就我所见,它们在所有上下文中都完全相同。 但是,请注意,我正在专门讨论在[ ]
或[[ ]]
测试中使用的=
和==
字符串比较运算符。 我并不是建议=
和==
在bash中随处可以互换。 例如,你显然不能用==
做变量赋值,比如var=="foo"
(技术上你可以这样做,但是var
的值将是"=foo"
,因为bash没有看到==
运算符在这里,它看到一个=
(赋值)运算符,后面是字面值="foo"
,它变成了"=foo"
)。
此外,尽管=
和==
可以互换,但您应该记住,这些测试的工作方式取决于您在[ ]
还是[[ ]]
使用它,以及操作数是否被引用。 你可以在这里阅读更多关于它的信息:7.3其他比较运算符(向下滚动到讨论=
和==
)。
上一篇: How to declare and use boolean variables in shell script?