如何在外壳脚本中声明和使用布尔变量?

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

variable=$false
variable=$true

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

if [ $variable ]
if [ !$variable ]
1455394 次浏览

修订答复(2014年2月12日)

the_world_is_flat=true# ...do something interesting...if [ "$the_world_is_flat" = true ] ; thenecho '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 ; thenecho 'Be careful not to fall off!'fi

来自:在Bash中使用布尔变量

原答案出现在这里的原因是因为在2014年2月12日的修改前的评论只针对原答案,当与修改后的答案联系在一起时,许多评论是错误的。例如,Dennis Williamson在2010年6月2日关于bash Builtintrue的评论只适用于原答案,不适用于修改后的答案。

很久以前,当我们只有sh时,布尔值通过依赖test程序的约定来处理,其中test在没有任何参数的情况下运行时返回错误的退出状态。

这允许人们将未设置的变量视为false,并将设置为任何值的变量视为true。今天,test是Bash的内置组件,通常以其单字符别名[(或在没有它的shell中使用的可执行文件,正如dolmen指出的那样)而闻名:

FLAG="up or <set>"
if [ "$FLAG" ] ; thenecho 'Is true'elseecho 'Is false'fi
# Unset FLAG#    also worksFLAG=
if [ "$FLAG" ] ; thenecho 'Continues true'elseecho 'Turned false'fi

由于引用约定,脚本编写者更喜欢使用模仿test的复合命令[[,但语法更好:带有空格的变量不需要引用;可以使用&&||作为具有奇怪优先级的逻辑运算符,并且对术语数量没有POSIX限制。

例如,要确定是否设置了FLAG并且COUNT是大于1的数字:

FLAG="u p"COUNT=3
if [[ $FLAG  && $COUNT -gt '1' ]] ; thenecho 'Flag up, count bigger than 1'elseecho 'Nope'fi

这东西会让人困惑当空格、零长度字符串和空变量都需要时,以及当您的脚本需要使用多个shell时。

太长别读

my_bool=true
if [ "$my_bool" = true ]

Miku的问题(原始)答案

我确实没有推荐公认的答案1。它的语法很漂亮,但它有一些缺陷。

假设我们有以下条件。

if $var; thenecho 'Muahahaha!'fi

在以下情况2中,此条件将评估为真正并执行嵌套命令。

# Variable var not defined beforehand. Case 1var=''  # Equivalent to var="".      # Case 2var=                                 # Case 3unset var                            # Case 4var='<some valid command>'           # Case 5

通常,当您的“布尔”变量(在本例中为var)显式设置为true时,您只希望您的条件评估为true。所有其他情况都是危险的误导!

最后一种情况(#5)特别顽皮,因为它将执行变量中包含的命令(这就是为什么有效命令3、4的条件评估为true)。

下面是一个无害的例子:

var='echo this text will be displayed when the condition is evaluated'if $var; thenecho 'Muahahaha!'fi
# Outputs:# this text will be displayed when the condition is evaluated# Muahahaha!

引用您的变量更安全,例如if "$var"; then。在上面的情况下,您应该会收到找不到命令的警告。但我们仍然可以做得更好(请参阅底部的我的建议)。

另见Mike Holt对Miku原始答案的解释。

问题Hbar的回答

这种方法也有意想不到的行为。

var=falseif [ $var ]; thenecho "This won't print, var is false!"fi
# Outputs:# This won't print, var is false!

您会期望上述条件的计算结果为false,因此永远不会执行嵌套语句。惊喜!

引用值("false"),引用变量("$var"),或者使用test[[而不是[,都没有区别。

推荐:

以下是我建议您检查“布尔值”的方法。它们按预期工作。

my_bool=true
if [ "$my_bool" = true ]; thenif [ "$my_bool" = "true" ]; then
if [[ "$my_bool" = true ]]; thenif [[ "$my_bool" = "true" ]]; thenif [[ "$my_bool" == true ]]; thenif [[ "$my_bool" == "true" ]]; then
if test "$my_bool" = true; thenif test "$my_bool" = "true"; then

它们几乎都是等价的。您必须比其他答案5中的方法多键入一些击键,但您的代码将更具防御性。


脚注

  1. Miku的回答已经过编辑,不再包含(已知的)缺陷。
  2. 不是一个详尽的清单。
  3. 在此上下文中,有效命令是指存在的命令。命令使用正确与否并不重要。例如。即使不存在这样的手册页,man woman仍将被视为有效命令。
  4. 对于无效的(不存在的)命令,Bash只会抱怨找不到命令。
  5. 如果你关心长度,第一个建议是最短的。

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

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

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

the_world_is_flat=yeahif [ "$the_world_is_flat" = yeah ]; thenecho '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=trueif $the_world_is_flat; thenecho 'Be careful not to fall off!'fi

两个代码片段将以相同的方式表现,但括号完全改变了引擎盖下发生的事情。

以下是Bash在每种情况下所做的事情:

无括号:

  1. 将变量$the_world_is_flat展开为字符串"true"
  2. 尝试将字符串"true"解析为命令。
  3. 查找并运行true命令(内置命令或/bin/true命令,具体取决于Bash版本)。
  4. true命令的退出代码(始终为0)与0进行比较。回想一下,在大多数shell中,退出代码为0表示成功,其他任何内容都表示失败。
  5. 由于退出代码为0(成功),执行if语句的then子句

括号:

  1. 将变量$the_world_is_flat展开为字符串"true"
  2. 解析现在完全扩展的条件表达式,其形式为string1 = string2=运算符是bash的字符串比较运算符。所以…
  3. "true""true"进行字符串比较。
  4. 是的,两个字符串是相同的,所以条件的值是true。
  5. 执行if语句的then子句。

无括号代码有效,因为true命令返回0的退出代码,这表示成功。括号中的代码有效,因为$the_world_is_flat的值与=右侧的字符串文字true相同。

只是为了把这一点带回家,考虑以下两个代码片段:

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

var=rebootif $var; thenecho 'Muahahaha! You are going down!'fi

这段代码只是打印“不错的尝试”。

var=rebootif [ $var ]; thenecho 'Nice try.'fi

更新(2014-04-14)要回答评论中关于===之间区别的问题:AFAIK,没有区别。==运算符是=的特定于Bash的同义词,据我所知,它们在所有上下文中的工作方式完全相同。

但是请注意,我专门讨论的是[ ][[ ]]测试中使用的===字符串比较运算符。我并不是说===在bash中可以互换到处都是

例如,你显然不能用==进行变量赋值,例如var=="foo"(从技术上讲,你可以可以这样做,但var的值将是"=foo",因为Bash在这里看不到==运算符,它看到了=(赋值)运算符,然后是文字值="foo",它只是变成了"=foo")。

此外,尽管===是可以互换的,但你应该记住,这些测试的工作方式确实取决于你是在[ ]还是[[ ]]中使用它,也取决于操作数是否被引用。你可以在高级Bash脚本指南:7.3其他比较运算符中阅读更多关于这方面的信息(向下滚动到===的讨论)。

与其伪造布尔值并为未来的读者留下陷阱,为什么不使用比true和false更好的值呢?

例如:

build_state=successif something-horrible; thenbuild_state=failedfi
if [[ "$build_state" == success ]]; thenecho go home; you are doneelseecho your head is on fire; run around in circlesfi

Bash真的把这个问题与[[[(($((等混淆了。

所有人都踩着彼此的代码空间。我想这主要是历史上的,Bash不得不偶尔假装是sh

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

TRUE=1; FALSE=0

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

testvar=$FALSE
if [[ -d ${does_directory_exist} ]]thentestvar=$TRUE;fi
if (( testvar == TRUE )); then# Do stuff because the directory does existfi
  1. 你必须遵守纪律。你的testvar必须始终设置为$TRUE$FALSE

  2. (())比较器中,您不需要前面的$,这使其更具可读性。

  3. 我可以使用(()),因为$TRUE=1$FALSE=0,即数值。

  4. 缺点是必须偶尔使用$

    testvar=$TRUE

    #36825;不太好

这不是一个完美的解决方案,但它涵盖了我需要这样一个测试的每一个案例。

使用算术表达式。

#!/bin/bash
false=0true=1
((false)) && echo false((true)) && echo true((!false)) && echo not false((!true)) && echo not true

输出:

true
不是假的

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

就个人而言,我只是想拥有一些看起来和工作方式都像C的东西。

此代码段在生产环境中每天工作多次:

snapshotEvents=true
if ($snapshotEvents)then# Do stuff if truefi

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

snapshotEvents=false
if !($snapshotEvents)then# Do stuff if falsefi

它也工作得很好。

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

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

这是对miku的原始答案的改进,解决了丹尼斯·威廉姆森对未设置变量的情况的担忧:

the_world_is_flat=true
if ${the_world_is_flat:-false} ; thenecho "Be careful not to fall off!"fi

然后测试变量是否为false

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

关于变量中含有讨厌内容的其他情况,这是任何外部输入馈送到程序的问题。

任何外部输入都必须在信任它之前进行验证。但该验证只需要在收到该输入时进行一次。

它不必像丹尼斯·威廉姆森建议的那样在每次使用变量时都这样做来影响程序的性能。

如何在外壳脚本中声明和使用布尔变量?

与许多其他编程语言不同,Bash不按“类型”隔离其变量。

所以答案很清楚。Bash中没有任何布尔变量

但是:

使用声明语句,我们可以将值赋值限制为变量。[2]

#!/bin/bashdeclare -ir BOOL=(0 1) # Remember BOOL can't be unset till this shell terminatesreadonly 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选项用于明确声明变量是只读。我希望目的很明确。

比尔·帕克被否决了,因为他的定义与正常的代码约定相反。通常,true定义为0,false定义为非零。1适用于false,9999和-1也是如此。函数返回值也是如此-0是成功,任何非零的都是失败。对不起,我还没有街头可信度来投票或直接回复他。

Bash建议现在习惯使用双括号而不是单括号,Mike Holt给出的链接解释了它们工作方式的差异。

首先,-eq是一个数字运算符,所以有了代码

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

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

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

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

# 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所指出的,不要用引号括起来)。然后使用单或双等号(=或==)以及单或双括号([]或 [[ ]]). 就个人而言,我喜欢双等号,因为它让我想起了其他编程语言中的逻辑比较,双引号只是因为我喜欢打字。所以这些工作:

# 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

在这里你有它。

长话短说:

巴什没有布尔人

truefalse命令

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

无论您在Bash中看到truefalse,它都是一个字符串或命令/Builtin,仅用于其退出代码。

这个语法…

if true; then ...

本质上是…

if COMMAND; then ...

其中命令为true。当命令返回退出代码0时,条件为true。truefalse是Bash内置程序,有时也是独立程序,除了返回相应的退出代码外什么都不做。


条件if..then..fi

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

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

对应于

if COMMAND; then echo yes; fi

这里的COMMAND[[,参数为1 == 1 ]]

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

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

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

信不信由你,但这些条件都产生了相同的结果

if [[ false ]]; then ...if [[ "false" ]]; then ...if [[ true ]]; then ...if [[ "true" ]]; then ...

太长别读;总是比较字符串或数字

为了让未来的读者明白这一点,我建议始终使用truefalse左右的引号:

DO

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

不要

# Always use double square brackets in bash!if [ ... ]; then ...# This is not as clear or searchable as -nif [[ "${var}" ]]; then ...# Creates impression of Booleansif [[ "${var}" != true ]]; then ...# `-eq` is for numbers and doesn't read as easy as `==`if [[ "${var}" -eq "true" ]]; then ...

也许吧

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

下面是一个对我有效的简单例子:

temp1=truetemp2=false
if [ "$temp1" = true ] || [ "$temp2" = true ]thenecho "Do something."elseecho "Do something else."fi

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

我在这里忽略了关键点,即可移植性。这就是为什么我的头文件本身具有POSIX

从本质上讲,所有投票的答案都是正确的,除了它们是Bash特定的太多。

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


  1. [ "$var" = true ]中的[]括号不是必需的,您可以省略它们并直接使用test命令:

    test "$var" = true && yourCodeIfTrue || yourCodeIfFalse

    重要提示:我不再推荐这个了,因为它正在缓慢弃用,并且更难以组合多个语句。

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

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

    但使用引号:

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

    这同样适用于:

    echo $(( "false" ))

    shell除了字符串之外无法解释它。我希望您能了解使用正确的关键字不带引号有多好。

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

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

    • 您应该习惯布尔关键字实际上被视为数字,即true=0false=1,请记住所有非零值都被视为false

    • 由于它们被视为数字,因此您也应该这样对待它们,即如果您定义变量,例如:

      var_bool=trueecho "$var_bool"
       true

      你可以创建一个相反的值:

      var_bool=$(( 1 - $var_bool ))  # same as $(( ! $var_bool ))echo "$var_bool"
      1

    正如您自己所看到的,shell确实在您第一次使用它时打印true字符串,但从那时起,它都分别通过表示true的数字0或表示false1工作。


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

  • 首先,一个好习惯是分配0而不是true1而不是false

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

    if [ "$var_bool" -eq 0 ]; thenyourCodeIfTrueelseyourCodeIfFalsefi

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

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

例1

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

例2

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

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

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

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

manbash

((表情))

表达式根据下面在ARITHMETIC EVALUation下描述的规则进行评估。如果表达式的值非零,则返回状态为0;否则返回状态为1。这完全等效于let“表达式”。

我的发现和建议与其他帖子有点不同。我发现我基本上可以像在任何“常规”语言中一样使用“布尔值”,而没有建议的“跳圈”…

不需要[]或显式字符串比较……我尝试了多个Linux发行版。我测试了Bash、Dash和BusyBox。结果总是一样的。我不确定最初投票最多的帖子在说什么。也许时代已经改变了,这就是全部?

如果你将一个变量设置为true,它随后在条件内的计算结果为“肯定”。将其设置为false,它的计算结果为“否定”。非常简单!唯一的警告是,未定义变量的计算结果也类似于真正!如果它做相反的事情会很好(就像在大多数语言中一样),但这就是诀窍-你只需要显式地将布尔值初始化为true或false

为什么它是这样工作的?答案有两个。A)shell中的true/false实际上意味着“无错误”vs“错误”(即0 vs任何其他值)。B)true/false不是值,而是shell脚本中的声明!关于第二点,在一行上执行truefalse本身会将你所在块的返回值设置为该值,即false是“遇到错误”的声明,其中true“清除”该值。将其与变量的赋值一起使用会“返回”该变量。未定义变量的计算结果类似于条件中的true,因为它同样表示0或“没有遇到错误”。

请参阅下面的示例Bash行和结果。如果您想确认…

#!/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=trueecho "when set to ${myBool}"if ${myBool}; then echo "it evaluates to true"; else echo "it evaluates to false"; fi;
myBool=falseecho "when set to ${myBool}"if ${myBool}; then echo "it evaluates to true"; else echo "it evaluates to false"; fi;

产量

when set toit evaluates to truewhen set to trueit evaluates to truewhen set to falseit evaluates to false

您可以使用shFlags

它为您提供了定义的选项:DEFINE_bool

示例:

DEFINE_bool(big_menu, true, "Include 'advanced' options in the menu listing");

在命令行中,您可以定义:

sh script.sh --bigmenush script.sh --nobigmenu # False

替代-使用函数

is_ok(){ :;}is_ok(){ return 1;}is_ok && echo "It's OK" || echo "Something's wrong"

定义函数不那么直观,但检查其返回值非常容易。

这是一个关于在Bash中测试“布尔”值的不同方法的速度测试:

#!/bin/bashrounds=100000
b=true # For true; b=false for falsetype -a truetime for i in $(seq $rounds); do command $b; donetime for i in $(seq $rounds); do $b; donetime for i in $(seq $rounds); do [ "$b" == true ]; donetime for i in $(seq $rounds); do test "$b" == true; donetime for i in $(seq $rounds); do [[ $b == true ]]; done
b=x; # Or any non-null string for true; b='' for falsetime for i in $(seq $rounds); do [ "$b" ]; donetime for i in $(seq $rounds); do [[ $b ]]; done
b=1 # Or any non-zero integer for true; b=0 for falsetime for i in $(seq $rounds); do ((b)); done

它会打印出类似

true is a shell builtintrue is /bin/true
real    0m0,815suser    0m0,767ssys     0m0,029s
real    0m0,562suser    0m0,509ssys     0m0,022s
real    0m0,829suser    0m0,782ssys     0m0,008s
real    0m0,782suser    0m0,730ssys     0m0,015s
real    0m0,402suser    0m0,391ssys     0m0,006s
real    0m0,668suser    0m0,633ssys     0m0,008s
real    0m0,344suser    0m0,311ssys     0m0,016s
real    0m0,367suser    0m0,347ssys     0m0,017s

关于语法,这是一个简单的方法论,我用它(通过示例)来一致和理智地管理布尔逻辑:

# Testsvar=var=''var=""var=0var=1var="abc"var=abc
if [[ -n "${var}" ]] ; thenecho 'true'fiif [[ -z "${var}" ]] ; thenecho 'false'fi
# Results# var=        # false# var=''      # false# var=""      # false# var=0       # true# var=1       # true# var="abc"   # true# var=abc     # true

如果变量从未声明过,答案是:# false

因此,将变量设置为true的简单方法(使用此语法方法论)将是var=1;相反,var=''

参考:

-n=如果var字符串的长度非零,则为True。

-z=如果var字符串的长度为零,则为True。

我对(我自己的)白痴的收据:

# setting ----------------commonMode=falseif [[ $something == 'COMMON' ]]; thencommonMode=truefi
# using ----------------if $commonMode; thenecho 'YES, Common Mode'elseecho 'NO, no Common Mode'fi
$commonMode && echo 'commonMode is ON  ++++++'$commonMode || echo 'commonMode is OFF xxxxxx'

使用布尔值的另一种方法是测试值的空虚。这具有缩短测试时间的优点:

first=1  # A true valuesecond=   # A false value
[ -n "$first" ]  && echo 'First var is true'[ -z "$first" ]  && echo 'First var is false'[ -n "$second" ] && echo 'Second var is true'[ -z "$second" ] && echo 'Second var is false'

输出:

First var is trueSecond var is false

这是一个使用bash的替代测试语法:[[ -n $one ]]

[[ "$x" == 'true' || "$x" -ne 0 ]] && ...

足够简单,没有依赖关系。

在大多数情况下,您需要“布尔”来进行布尔操作,例如!&&||。在某些语言中,根本不存在特殊的布尔类型(因为实际上您在技术上不需要它),在大多数解释语言中(几乎)所有类型都会在!&&||等操作中自动转换为某种布尔类型。

布尔总是与布尔运算一起工作。在Bash中,这样的操作是(在$var周围没有"",这非常重要!):

[[ $var ]] - check if var is true[[ ! $var ]] - check if var is false[[ $var1 || $var2 ]] - var1 or var2[[ $var1 && $var2 ]] - var1 and var2

只有当var=''(或unset)时,[[ $var ]]才是虚假。所以bash中变量的唯一正确的'false'值是"(空字符串)。对于true,您可以选择任何值,但我更喜欢var=1(就像在其他语言中一样,true是任何非空int,但出于可读的目的,程序员总是使用1)。

注意:对于布尔检查中的var='false' var是真正。在Bash中,字符串'false'实际上是true(与所有其他语言相同!)。Bash和Python、Perl或PHP之间唯一的区别是,在Bash0中也是true。但同样:Bash中有个布尔操作,它们的工作方式与所有其他解释语言一样,除了Bash中的0是true。

在Bash中使用字符串'true''false'作为布尔替换是绝对不合理的。这就像在Python、Perl或PHP中使用同样奇怪的概念。它的工作速度较慢(在Bash中也是如此),并且没有人在其他语言中这样做,但是在Bash中有很多程序员认为这是一个很好的解决方案。不。没有理由不直接在Bash中使用布尔运算,而不会像$var == 'true'$var == 'false'这样绝对奇怪的比较。

同样,Bash中的布尔替换是:

var=''  # falsevar=1   # true (actually any non-empty string)

在Bash中直接使用布尔检查也是进行类似布尔检查的最快方法。所有其他结构的工作速度要慢得多。

P. S.像a=true; if $a; then ...这样的“boolean”检查的“旧”风格绝对是愚蠢的,因为:

  1. 您不能直接在条件[[ ]]中使用它们
  2. 它们充当bash代码的eval,存储在变量中。好吧,如果你认为这是个好主意,请不要编写任何程序;)

P. P. S.如果$var可以取消设置,并且您使用非常有用的set -u,只需将检查中的$var替换为${var-},例如[[ ${var-} ]](还有:周围没有"",这对代码执行速度很重要!)