关于bash:如何在shell脚本中声明和使用布尔变量?

How to declare and use boolean variables in shell script?

我尝试使用以下语法在shell脚本中声明布尔变量:

1
2
3
variable=$false

variable=$true

这是正确的吗?另外,如果我想更新这个变量,我会使用相同的语法吗?最后,使用布尔变量作为表达式的语法是否正确:

1
2
3
if [ $variable ]

if [ !$variable ]


答案(2月12日,2014年修订)

1
2
3
4
5
the_world_is_flat=true
# ...do something interesting...
if ["$the_world_is_flat" = true ] ; then
    echo 'Be careful not to fall off!'
fi

原始的答案

警告:http:/ / / / / 89391 21210966 stackoverflow.com

1
2
3
4
5
the_world_is_flat=true
# ...do something interesting...
if $the_world_is_flat ; then
    echo 'Be careful not to fall off!'
fi

从布尔变量:使用bash

原因是这里是原始的答案,因为没有复习的评论在2014年2月12日,pertain只原始的答案,和许多的评论是错误的,当与修订相关的答案。例如,丹尼斯威廉姆森的评论关于bash builtin trueon Jun 2010年第2个答案只适用于原始的,没有修改。


铊;博士

1
2
3
bool=true

if ["$bool" = true ]

未来的问题和答案(原创)

我不建议answer1公认。它的语法是漂亮的,但它有一些获得。

说我们有下面的状态。

1
2
3
if $var; then
  echo 'Muahahaha!'
fi

在下面的cases2状态评估,这是真正的和想的嵌套执行的命令。

1
2
3
4
5
# 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。对于成本的情况下,都是别人的!

最后的案例(特别是顽皮的# 5),因为它要执行的命令中包含的变量(这就是为什么一个有效状态evaluates为commands3,4)。

这里是一个例子:无害的

1
2
3
4
5
6
7
8
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。在上述情况下,你应该得到一个警告,这是不存在的指挥。但我们还可以做的更好(我在湖上的建议)。

所以迈克解释海浩特初音的原版的答案。

问题的答案在HBAR

因此,本方法有意外的行为。

1
2
3
4
5
6
7
var=false
if [ $var ]; then
  echo"This won't print, var is false!"
fi

# Outputs:
# This won't print, var is false!

你会期望上述状态评估是假,因此不执行循环中的语句。惊喜!

引证的值("false")引证的变量("$var"),或使用test[[而不[,有所作为。

我所做的是:

这是我建议你检查你的方式"booleans"。他们的工作是可能的。

1
2
3
4
5
6
7
8
9
10
11
12
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

他们所有的当量相当多。你有一个keystrokes型更多的方法比其他的answers5但代码将更多的防守。

脚注

  • 安切洛蒂自初音的回答是编辑和不再包含(二)获得。
  • 需要exhaustive列表。
  • 一个有效的命令在这个上下文的均值a命令是存在。它不物,如果是正确的,或命令。例如man woman会被视为一个有效的无声命令,搜索页,即使没有你的存在。
  • 为无效的(不存在的)简单的bash命令,想抱怨,命令没找到。
  • 如果你在乎的是长度,第一推荐是最短的。

  • 这里似乎有一些关于bash内置的true的误解,更具体地说,关于bash如何扩展和解释括号内的表达式。好的。

    Miku答案中的代码与bash内置的true/bin/true或任何其他风格的true命令完全无关。在这种情况下,true只是一个简单的字符串,无论是通过变量赋值还是通过条件表达式的计算,都不会调用true命令/内置。好的。

    以下代码在功能上与Miku答案中的代码相同:好的。

    1
    2
    3
    4
    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的命令或builtin,也没有(在miku的例子中)在bash解析令牌true时进行任何特殊处理。它只是一个字符串,而且是一个完全任意的字符串。好的。

    更新(2014-02-19):在跟踪了Miku答案中的链接之后,现在我看到了一些混乱的来源。Miku的答案使用单括号,但他链接到的代码片段不使用括号。只是:好的。

    1
    2
    3
    4
    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命令(根据bash版本,可以是内置的,也可以是/bin/true)。
  • 比较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相同。好的。

    只需考虑以下两个代码片段,就可以将这一点带回家:好的。

    此代码(如果使用根权限运行)将重新启动计算机:好的。

    1
    2
    3
    4
    var=reboot
    if $var; then
      echo 'Muahahaha! You are going down!'
    fi

    这段代码只是打印"很好的尝试"。没有调用reboot命令。好的。字母名称(P)Update(2014-04-14)to answer the question in the comments regarding the difference between EDOCX1 penal 0 and EDOCX1 penal 1:afaik,there is no difference.The EDOCX1 commercial operator is a bash-specific synonym for EDOCX1 original 0,and as far as I've seen,they work exactly the same in all context.好的,好的。(P)Note,however,that I'm specifically talking about the EDOCX1 penal 0 and EDOCX1 penal 1 string comparison operators used in either EDOCX1 penalthy 6I'm not suggesting that EDOCX1 plography 0 ocol and EDOCX1 plus 1 is interchangeable everywhere in Bash.好的,好的。(P)For example,you obviously can't do variable assignment with EDOCX1 commercial,such as EDOCX1 commercial 11(well technically you can do this,but the value of EDOCX1 individual 12 commercial will be EDOCX1 13 commercial,because bash isn't seeing an EDOCX1Ch just becomes "=foo"好的,好的。(P)Also,although EDOCX1 pental 0 and EDOCX1 commercial 1 are interchangeable,you should keep in mind that how those tests work does depended on whether you're using it inside EDOCX1 penographic 6 or EDOCX1 penographic 7,and also on whether or not the operations are quoted.You can read more about that in advanced bash scripting guide:7.3 other comparison operators(scroll down to the discussion of EDOCX1 discussion of weocx1 penal 0 and EDOCX1 universal).好的,好的。好吧。


    使用算术表达式。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #!/bin/bash

    false=0
    true=1

    ((false)) && echo false
    ((true)) && echo true
    ((!false)) && echo not false
    ((!true)) && echo not true

    输出:

    true
    not false


    长话短说:

    巴什没有布尔人

    bash所具有的,是在比较和条件方面的布尔表达式。也就是说,可以在bash中声明和比较的是字符串和数字。就是这样。

    在bash中,无论您在何处看到truefalse,它要么是字符串,要么是仅用于其退出代码的命令/内置。

    这个语法…

    1
    if true; then ...

    本质上是…

    1
    if COMMAND; then ...

    当命令返回退出代码0时,条件为真。truefalse是bash内置的,有时也是独立的程序,只返回相应的退出代码。

    上述条件相当于:

    1
    COMMAND && ...

    当使用方括号或test命令时,您依赖于该构造的退出代码。请记住,[ ][[ ]]也是命令/内置的,就像其他命令/内置的一样。所以…

    1
    if [[ 1 == 1 ]]; then echo yes; fi

    对应于

    1
    if COMMAND; then echo yes; fi

    这是COMMAND,这是[[ 1 == 1 ]]

    if..then..fi结构只是句法上的糖分。您始终可以运行由双符号分隔的命令,以获得相同的效果:

    1
    [[ 1 == 1 ]] && echo yes

    在这些测试结构中使用truefalse时,实际上您只是将字符串"true""false"传递给测试命令。这里有一个例子:

    信不信由你,但这些条件都会产生同样的结果:

    1
    2
    3
    4
    if [[ false ]]; then ...
    if [["false" ]]; then ...
    if [[ true ]]; then ...
    if [["true" ]]; then ...

    总是与字符串或数字比较

    为了向未来的读者阐明这一点,我建议始终使用围绕truefalse的引号:

    1
    2
    3
    if [["${var}" =="true" ]]; then ...
    if [["${var}" =="false" ]]; then ...
    if [[ -n"${var:-}" ]]; then echo"var is not empty" ...

    不要

    1
    2
    3
    4
    if [ ... ]; then ...  # always use double square brackets in bash!
    if [["${var}" ]]; then ...  # this is not as clear or searchable as -n
    if [["${var}" != true ]]; then ...  # creates impression of booleans
    if [["${var}" -eq"true" ]]; then ...  # `-eq` is for numbers and doesn't read as easy as `==`

    也许吧

    1
    if [["${var}" !="true" ]]; then ...  # creates impression of booleans. Can be used for strict checking of dangerous operations. This condition is false for anything but the literal string"true".


    龙前,当我们在处理有什么内容sh,booleans red on a会展酒店计划在testtest归来false退出运行状态,如果一个没有参数。这允许一个智囊团,这是一个变量的设置和unset变假为真的任何价值。今天,是一个测试和一bashbuiltin通常通过一个字符[其别名(或缺乏它的壳可使用AS的石棚,Notes):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    FLAG="up or <set>"

    if ["$FLAG" ] ; then
        echo 'Is true'
    else
        echo 'Is false'
    fi

    # unset FLAG
    #    also works
    FLAG=

    if ["$FLAG" ] ; then
        echo 'Continues true'
    else
        echo 'Turned false'
    fi

    因为引证会议,作家喜欢使用脚本命令,但[[复合mimics test安切洛蒂更好的语法:变量与空间不需要引号,可以使用作为一个逻辑算子和||&&Weird precedence POSIX和没有限制的数量的术语。

    例如,如果一个确定的标志是一个集和计数数大于1。

    1
    2
    3
    4
    5
    6
    7
    8
    FLAG="u p"
    COUNT=3

    if [[ $FLAG  && $COUNT -gt '1' ]] ; then
        echo 'Flag up, count bigger than 1'
    else
        echo 'Nope'
    fi

    这些空间可以得到机会的时候,零长度字符串和变量都是零,所以当你需要和需要与一些shell脚本。


    How to declare and use boolean variables in shell script?

    与许多其他编程语言不同,bash不按"type"分隔变量。

    所以答案很清楚。巴什没有boolean variable。然而:

    使用DECLARE语句,我们可以限制变量的值赋值。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #!/bin/bash
    declare -ir BOOL=(0 1) #remember BOOL can't be unset till this shell terminate
    readonly false=${BOOL[0]}
    readonly true=${BOOL[1]}
    #same as declare -ir false=0 true=1
    ((true)) && echo"True"
    ((false)) && echo"False"
    ((!true)) && echo"Not True"
    ((!false)) && echo"Not false"

    declarereadonly中的r选项用于明确说明变量是只读的。希望目标明确。


    "faking a布尔离开A陷阱和未来的读者,为什么不只是使用一个更好的价值比的真实和虚假的?

    例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    build_state=success
    if something-horrible; then
      build_state=failed
    fi

    if [["$build_state" == success ]]; then
      echo go home, you are done
    else
      echo your head is on fire, run around in circles
    fi


    POSIX(便携式操作系统接口)

    我想这里的关键点是便携性。这就是为什么我的头文件本身就有POSIX。

    从本质上讲,所有投票的答案都是正确的,但它们太过具体化了。

    基本上,我只想添加更多关于可移植性的信息。

  • []中的括号(如["${var}" = true ]中的括号)是不必要的,可以省略它们直接使用test命令:

    1
    test"${var}" = true && CodeIfTrue || CodeIfFalse

    注意,我不再推荐这个,因为它正在慢慢被否决。

  • 想象一下这些单词truefalse对shell意味着什么,自己测试一下:

    1
    echo $(( true ))
    1
    0
    1
    echo $(( false ))
    1
    1

    但使用引号:

    1
    echo $(("true" ))
    1
    2
    bash:"true": syntax error: operand expected (error token is""true"")
    sh (dash): sh: 1: arithmetic expression: expecting primary:""true""

    同样适用于:

    1
    echo $(("false" ))

    shell只能解释字符串。我希望你能理解使用不带引号的关键字有多好。

    但在之前的回答中没有人说过。

  • 这是什么意思?嗯,有几件事。

    • 你应该习惯布尔关键字被当作数字来对待,也就是说,true=0false=1,记住所有非零值都被当作false

    • 因为它们被视为数字,所以您也应该这样对待它们,也就是说,如果定义变量,请说:

      1
      2
      var_bool=true
      echo"${var_bool}"
      1
       true

      您可以通过以下方式创建它的相反值:

      1
      2
      var_bool=$(( 1 - ${var_bool} ))
      echo"${var_bool}"
      1
      1

      正如您自己看到的,shell第一次使用它时会打印true字符串,但从那时起,它都通过分别代表true1的数字0工作。

  • 最后,你应该如何处理这些信息

    • 首先,一个好习惯是指定0代替true;指定1代替false

    • 第二个好习惯是测试变量是否等于零:

      1
      if ["${var_bool}" -eq 0 ]; then YourCodeIfTrue; else YourCodeIfFalse; fi

    比尔·帕克被否决了,因为他的定义与普通的代码约定相反。通常,真的定义为0,假的定义为非零。1表示假,9999和-1表示假。与函数返回值相同-0表示成功,任何非零表示失败。对不起,我还没有投票或直接回复他的街头信誉。

    Bash建议现在使用双括号代替单括号,MikeHolt给出的链接解释了它们工作方式的不同。7.3。其他比较运算符

    一方面,-eq是一个数字运算符,因此拥有代码

    1
    2
    3
    #**** NOTE *** This gives error message *****
    The_world_is_flat=0;
    if ["${The_world_is_flat}" -eq true ]; then

    将发出错误语句,应为整数表达式。这适用于任一参数,因为两者都不是整数值。然而,如果我们在它周围加上双括号,它将不会发出错误语句,但会产生错误的值(好吧,在可能的排列中有50%)。它将评估为[[0-eq真]]=成功,也将评估为[[0-eq假]]=成功,这是错误的(hmmm…)。那内置的是一个数值吗?).

    1
    2
    3
    #**** NOTE *** This gives wrong output *****
    The_world_is_flat=true;
    if [["${The_world_is_flat}" -eq true ]]; then

    条件的其他排列也会产生错误的输出。基本上,任何将变量设置为数值并将其与真/假内置进行比较的内容(上面列出的错误条件除外),或将变量设置为真/假内置并将其与数值进行比较的内容。此外,任何将变量设置为真/假内置函数并使用-eq进行比较的内容。因此,避免在布尔比较中使用-eq,避免在布尔比较中使用数值。以下是将产生无效结果的排列的摘要:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    #With variable set as an integer and evaluating to true/false
    #*** This will issue error warning and not run: *****
    The_world_is_flat=0;
    if ["${The_world_is_flat}" -eq true ]; then

    #With variable set as an integer and evaluating to true/false
    #*** These statements will not evaluate properly: *****
    The_world_is_flat=0;
    if ["${The_world_is_flat}" -eq true ]; then
    #
    if [["${The_world_is_flat}" -eq true ]]; then
    #
    if ["${The_world_is_flat}" = true ]; then
    #
    if [["${The_world_is_flat}" = true ]]; then
    #
    if ["${The_world_is_flat}" == true ]; then
    #
    if [["${The_world_is_flat}" == true ]]; then


    #With variable set as an true/false builtin and evaluating to true/false
    #*** These statements will not evaluate properly: *****
    The_world_is_flat=true;
    if [["${The_world_is_flat}" -eq true ]]; then
    #
    if ["${The_world_is_flat}" = 0 ]; then
    #
    if [["${The_world_is_flat}" = 0 ]]; then
    #
    if ["${The_world_is_flat}" == 0 ]; then
    #
    if [["${The_world_is_flat}" == 0 ]]; then

    所以,现在来看看什么有效。在比较和评估中使用真/假内置(如Mike Hunt所指出的,不要将它们括在引号中)。然后使用单或双等号(=或==)和单或双括号([]或[])。就我个人而言,我喜欢双等号,因为它让我想起了其他编程语言中的逻辑比较,而双引号只是因为我喜欢输入。所以这些工作:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #With variable set as an integer and evaluating to true/false
    #*** These statements will work properly: *****
    #
    The_world_is_flat=true/false;
    if ["${The_world_is_flat}" = true ]; then
    #
    if [["${The_world_is_flat}" = true ]]; then
    #
    if ["${The_world_is_flat}" = true ]; then
    #
    if [["${The_world_is_flat}" == true ]]; then

    给你。


    在许多编程语言中,布尔类型是或实现为整数的子类型,其中true的行为类似于1false的行为类似于0

    • C中的布尔

    • python中的布尔值

    • Java中的布尔

    在数学上,布尔代数类似于整数算术模2。因此,如果语言不提供本机布尔类型,最自然和最有效的解决方案是使用整数。这几乎适用于任何语言。例如,在bash中,您可以执行以下操作:

    1
    2
    3
    4
    # val=1; ((val)) && echo"true" || echo"false"
    true
    # val=0; ((val)) && echo"true" || echo"false"
    false

    男子狂欢:

    ((expression))

    The expression is evaluated according to the rules described below under ARITHMETIC EVALUATION. If the value of the expression is non-zero, the return status is 0; otherwise the return status is 1. This is exactly equivalent to let"expression".


    以下是对Miku原始答案的改进,解决了Dennis Williamson对案例的担忧,其中变量没有设置:

    1
    2
    3
    4
    5
    the_world_is_flat=true

    if ${the_world_is_flat:-false} ; then
        echo"Be careful not to fall off!"
    fi

    并测试变量是否为false

    1
    2
    3
    if ! ${the_world_is_flat:-false} ; then
        echo"Be careful not to fall off!"
    fi

    对于变量中包含有害内容的其他情况,这是向程序提供的任何外部输入的问题。

    在信任任何外部输入之前,必须对其进行验证。但是,当接收到输入时,必须只进行一次验证。

    它不必像丹尼斯·威廉姆森建议的那样,通过对变量的每次使用来影响程序的性能。


    下面是一个对我有用的简单示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    temp1=true
    temp2=false

    if ["$temp1" = true ] || ["$temp2" = true ]
    then
        echo"Do something."
    else
        echo"Do something else."
    fi

    这里是一个短手if true的实现。

    1
    2
    3
    4
    5
    6
    7
    # Function to test if a variable is set to"true"
    _if () {
        ["${1}" =="true" ] && return 0
        ["${1}" =="True" ] && return 0
        ["${1}" =="Yes" ] && return 0
        return 1
    }

    例1

    1
    2
    3
    4
    5
    6
    7
    my_boolean=true

    _if ${my_boolean} && {
        echo"True Is True"
    } || {
        echo"False Is False"
    }

    例2

    1
    2
    my_boolean=false
    ! _if ${my_boolean} && echo"Not True is True"

    我发现现有的答案令人困惑。

    就我个人而言,我只想拥有一些看起来像C的东西。

    这段代码在生产中一天工作多次:

    1
    2
    3
    4
    5
    6
    snapshotEvents=true

    if ($snapshotEvents)
    then
        # do stuff if true
    fi

    为了让大家开心,我测试了:

    1
    2
    3
    4
    5
    6
    snapshotEvents=false

    if !($snapshotEvents)
    then
        # do stuff if false
    fi

    也很管用。

    $snapshotEvents评估变量值的内容。所以你需要的是$

    你不需要括号,我觉得它们很有用。

    • 测试日期:GNUBash,版本4.1.11(2)-发布

    • Bash初学者指南,Machtlet Garrels,2008年1月11日


    我的发现和建议与其他帖子有些不同。我发现我基本上可以像任何"常规"语言那样使用真/假,而不需要"跳铁环"的提示…不需要进行[]或显式字符串比较…我尝试了多个Linux发行版,我测试了bash、dash和busybox。我和她一起跑,没有一声巨响…结果总是一样的。我不知道最初的投票结果最高的帖子是怎么说的。也许时代已经改变了,这就是一切?

    如果将变量设置为true,则在条件中它的计算结果为true。设置为false,计算结果为false。非常直!唯一要注意的是,未定义的变量的计算结果也是真的!如果它做了相反的事情,那就太好了,但这就是诀窍——你只需要明确地将你的胸部设置为"真"或"假"。

    请参见下面的示例bash和结果。如果你想确认…

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #!/bin/sh

    #not yet defined...
    echo"when set to ${myBool}"
    if ${myBool}; then echo"it evaluates to true"; else echo"it evaluates to false"; fi;

    myBool=true
    echo"when set to ${myBool}"
    if ${myBool}; then echo"it evaluates to true"; else echo"it evaluates to false"; fi;

    myBool=false
    echo"when set to ${myBool}"
    if ${myBool}; then echo"it evaluates to true"; else echo"it evaluates to false"; fi;

    产量

    1
    2
    3
    4
    5
    6
    when set to
    it evaluates to true
    when set to true
    it evaluates to true
    when set to false
    it evaluates to false


    巴什真的把这个问题和[[[(($((等混淆了。

    所有处理彼此的代码空间。我想这主要是历史性的,巴什有时不得不假装成江户。

    大多数时候,我可以选择一种方法并坚持下去。在这种情况下,我倾向于声明(最好是在公共库文件中,我可以在实际脚本中包含.)。

    1
    TRUE=1; FALSE=0

    然后我可以使用(())算术运算符,用于测试。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    testvar=$FALSE

    if [[ -d ${does_directory_exist} ]]
    then
        testvar=$TRUE;
    fi

    if (( testvar == TRUE )); then
        # do stuff because the directory does exist
    fi
  • 你必须有纪律。您的testvar必须随时设置为$TRUE$FALSE

  • ((中…))比较器,您不需要前面的$,这使得它更易读。

  • 我可以用(())是因为$TRUE=1$FALSE=0是数值。

  • 缺点是有时必须使用$

    1
    testvar=$TRUE

    不是很漂亮。

  • 这不是一个完美的解决方案,但它涵盖了所有的情况,我需要这样一个测试。