如何在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会简单地抱怨命令没有找到。
  • 如果你在意长度,第一个建议是最短的。

  • 似乎这里大约内建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表示成功,其他任何代码表示失败。
  • 由于退出代码为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其他比较运算符(向下滚动到讨论=== )。

    链接地址: http://www.djcxy.com/p/4129.html

    上一篇: How to declare and use boolean variables in shell script?

    下一篇: How do I split a string on a delimiter in Bash?