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

has*_*anm 884 bash shell scripting boolean sh

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

variable=$false

variable=$true
Run Code Online (Sandbox Code Playgroud)

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

if [ $variable ]

if [ !$variable ]
Run Code Online (Sandbox Code Playgroud)

mik*_*iku 1101

修订回答(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
Run Code Online (Sandbox Code Playgroud)

原始答案

警告: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
Run Code Online (Sandbox Code Playgroud)

From:在Bash中使用布尔变量

这里包含原始答案的原因是因为2014年2月12日修订前的评论仅适用于原始答案,并且许多评论在与修订后的答案相关时是错误的.例如,Dennis Williamson关于true2010年6月2日内置bash的评论仅适用于原始答案,而非修订版.

  • 要解释发生了什么:`if`语句正在执行变量的内容,即Bash内置的`true`.可以将任何命令设置为变量的值,并评估其退出值. (37认同)
  • 哦,没关系; 我知道了.是的:如果!$变量; 然后...... fi (27认同)
  • -1,[请参阅我的回答](http://stackoverflow.com/a/21210966/72321)获取解释. (12认同)
  • @pms运算符"-o"和"-a"仅用于"test"命令(又名"[]").相反,这是"if + command",没有"test".(比如"if grep foo file; then ...".)所以,使用普通的`&&`和`||`运算符:`#t1 = true; T2 =真; f1 = false;`#`if $ t1 || $ F1; 然后echo is_true; else echo is_false; fi;`_(返回"true",因为t1 = true)_#`if $ t1 && $ f1 || $ T2; 然后echo is_true; else echo is_false; fi` _(返回"true",因为t2 = true)_.同样,这只能起作用,因为"true"/"false"是bash-builtins(返回true/false).除非var是cmd(即true或false),否则不能使用"if $ var ..." (7认同)
  • 这里有很多不正确的信息./ bin/true未被有效使用.见丹尼斯的回答. (3认同)
  • 关于较新的答案:这是简单的字符串比较。在 bash 中,您应该使用双方括号并引用所有内容,以便人们知道它是字符串,没有什么特别的。 (2认同)

Den*_*nis 733

TL; DR

bool=true

if [ "$bool" = true ]
Run Code Online (Sandbox Code Playgroud)

Miku(原创)答案的问题

推荐接受的答案1.它的语法很漂亮,但它有一些缺陷.

假设我们有以下条件.

if $var; then
  echo 'Muahahaha!'
fi
Run Code Online (Sandbox Code Playgroud)

在以下情况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
Run Code Online (Sandbox Code Playgroud)

通常,只有当"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!
Run Code Online (Sandbox Code Playgroud)

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

另请参阅Mike Holt对Miku原始答案的解释.

Hbar答案的问题

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

var=false
if [ $var ]; then
  echo "This won't print, var is false!"
fi

# Outputs:
# This won't print, var is false!
Run Code Online (Sandbox Code Playgroud)

您可能希望上述条件计算为false,因此从不执行嵌套语句.惊喜!

引用value("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
Run Code Online (Sandbox Code Playgroud)

它们几乎都是等价的.你需要输入比其他答案中的方法更多的键击5但你的代码将更具防御性.


脚注

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

  • 使用`==`和`[`或`test`是不可移植的.考虑可移植性是唯一的优势``````test`超过`[[`,坚持`=`. (8认同)
  • 对我来说,从概念上讲,如果我使用bool ="true"则更容易理解.然后很明显它只是一个字符串而不是一些特殊值或内置. (5认同)
  • @Scott我使用[fish](http://fishshell.com/)作为我的主shell,在我看来,与bash相比,它有一个理智的脚本语言. (2认同)
  • 是的,我只是在评论中找不到对这个隐藏笑话的任何赞赏,所以不得不指出 =) (2认同)

Mik*_*olt 163

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

miku的答案中的代码与Bash内置完全无关true,也/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
Run Code Online (Sandbox Code Playgroud)

这里唯一的区别是被比较的四个字符是'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
Run Code Online (Sandbox Code Playgroud)

两个代码片段的行为方式都相同,但括号完全改变了引擎盖下的内容.

这是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. 是的,这两个字符串是相同的,所以条件的值是真的.
  5. 执行if语句的then子句.

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

只是为了推动这一点,请考虑以下两段代码:

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

var=reboot
if $var; then
  echo 'Muahahaha! You are going down!'
fi
Run Code Online (Sandbox Code Playgroud)

这段代码只打印"Nice try".不会调用reboot命令.

var=reboot
if [ $var ]; then
  echo 'Nice try.'
fi
Run Code Online (Sandbox Code Playgroud)

更新(2014-04-14)要回答有关===:AFAIK 之间差异的评论中的问题,没有区别.该==运营商特定的Bash-代名词=,而据我所看到的,他们的工作完全一样在所有上下文中.

但是请注意,是我专门谈论===在任一使用的字符串比较操作[ ][[ ]]测试.我并不是暗示===互换无处不在bash.

例如,你显然无法进行变量赋值==,例如var=="foo"(从技术上讲你可以做到这一点,但是值var将是"=foo",因为Bash没有在==这里看到一个运算符,它看到一个=(赋值)运算符,然后是字面值="foo",刚刚成为"=foo").

此外,虽然===可以互换,你应该记住,如何将这些测试工作取决于您是否使用它里面[ ][[ ]],还取决于是否操作数被引用.你可以阅读更多关于高级Bash脚本编程指南:7.3其他比较操作符(向下滚动到的讨论===).

  • 真正.虽然,我并不主张(或反对)任何一种方法.我只是想澄清一些在这里被投票的错误信息,以便后来偶然发现这个话题的人不会对这一切如何运作产生一些误解. (8认同)
  • 为了解决SeldomNeedy的评论,是的,您可以使用真实的“ true”,但通常不能将其与变量进行比较,因为真实的“ true”本身没有任何价值。它所做的只是将退出状态设置为“ 0”,表示成功。值得注意的是,它实际上等效于所谓的“空命令”或`:`。至于使用“ 0”和“ 1”,这就是我这些天需要布尔值的所有脚本中所做的事情。并且我使用`(())`运算符而不是`[[]]`进行评估。因此,例如,如果我有`flag = 0',则可以执行`if((flag));。然后... (2认同)

Quo*_*ons 49

使用算术表达式.

#!/bin/bash

false=0
true=1

((false)) && echo false
((true)) && echo true
((!false)) && echo not false
((!true)) && echo not true
Run Code Online (Sandbox Code Playgroud)

输出:

真的
不是假的

  • `(())`递归地扩展变量,这是我没想到的.`富=巴; 条=巴兹; ((foo))&& echo echo`什么都不打印,但是`baz = 1`就是这样.所以你可以通过`true = 1`来支持`foo = true`和`foo = false`以及0或1. (4认同)
  • 优点:(1.)行为类似于C处理bool的方式,(2.)语法非常简洁/最小(不需要右手变量和运算符,如'='或'=='),(3) .)<主观>对我来说,我理解没有冗长的解释会发生什么......与Miku和Dennis的答案相比,这些答案似乎都需要冗长的解释</ subjective> (3认同)
  • @TrevorBoydSmith你为什么不说,"专业:一切,缺点:没有".从长远来看,可以节省键盘和显示器的折旧成本. (3认同)
  • 对于交互式使用,如单行,请确保在`!`之后留一个空格,否则它将进行历史扩展.`((!foo))`有效,`!((富))`.我喜欢这个解决方案,BTW.最后一个简洁的方法来做布尔变量.`((foo || bar))`按预期工作. (3认同)
  • @wjandrea 这与问题相反,因为现在您有了一种机制来识别代码中的错误。 (3认同)
  • @quolonel 感谢您提供非常有用的资源。当然,我的理解是有限的——无论领域如何,在所有理解上都受到限制是人类的天性。但是,你介意告诉我我的哪些陈述会让你假设我对这个特定问题的理解是不完整的? (2认同)
  • 如果您指的是特殊错误不容忍模式中的某些链接命令的异常,我认为依靠下一个编辑器来了解这些含义风险太大,不值得使用看似更好的语法。我猜算术表达式在它们自己的行上见过太多次了 (2认同)

Hub*_*iak 29

长话短说:

bash中没有布尔值

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

无论你在哪里看到truefalse在bash中,它都是一个字符串或一个命令/ builtin,它只用于退出代码.

这个语法......

if true; then ...
Run Code Online (Sandbox Code Playgroud)

基本上......

if COMMAND; then ...
Run Code Online (Sandbox Code Playgroud)

只要命令返回退出代码0 true,条件就为真.它false是Bash内置的,有时也是独立的程序,除了返回相应的退出代码之外什么都不做.

上述条件相当于:

COMMAND && ...
Run Code Online (Sandbox Code Playgroud)

使用方括号或test命令时,您依赖于该构造的退出代码.请记住,[ ]并且[[ ]]也只有命令/建宏像任何其他.所以......

if [[ 1 == 1 ]]; then echo yes; fi
Run Code Online (Sandbox Code Playgroud)

对应于

if COMMAND; then echo yes; fi
Run Code Online (Sandbox Code Playgroud)

COMMAND这里是[[ 1 == 1 ]]

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

[[ 1 == 1 ]] && echo yes
Run Code Online (Sandbox Code Playgroud)

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

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

if [[ false ]]; then ...
if [[ "false" ]]; then ...
if [[ true ]]; then ...
if [[ "true" ]]; then ...
Run Code Online (Sandbox Code Playgroud)

TL; DR; 总是与字符串或数字进行比较

为了使未来的读者清楚,我建议总是使用引号truefalse:

if [[ "${var}" == "true" ]]; then ...
if [[ "${var}" == "false" ]]; then ...
if [[ -n "${var:-}" ]]; then echo "var is not empty" ...
Run Code Online (Sandbox Code Playgroud)

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 `==`
Run Code Online (Sandbox Code Playgroud)

也许

if [[ "${var}" != "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".
Run Code Online (Sandbox Code Playgroud)

  • 我不同意“在 bash 中始终使用双括号”。事实上,在我编写的几乎所有脚本中,我都使用单括号,除非我需要进行模式匹配。我认为人们应该理解`[`(即`test`)和`[[`之间的区别,并使用适合他需要的那个。 (2认同)
  • @WeijunZhou 你的例子是反对单方括号的有力论据。它使代码更难理解,并且为错误敞开了大门。双括号更加严格并鼓励更简洁的代码。 (2认同)
  • 这个答案首先帮助我理解了一些核心概念。“[”是一个内置函数,它根据其表达式的求值返回退出代码,这一想法很重要;对我来说,“啊哈”时刻是内置的 true 和 false 是相同的。因此,如果直接将 true 或 false 分配给变量并使用它们*不带括号*:`if $my_bool ; ,则可以进行简单的布尔检查。然后`或`$my_bool &amp;&amp; echo "打印这个"`。退出代码 0 和退出代码 1,这就是您从此处的 true/false 得到的全部内容。为我点击。谢谢! (2认同)

小智 16

很久以前,当我们所拥有的一切都是sh,通过依赖test程序约定处理的布尔值,test如果没有参数运行则返回错误的退出状态.这允许人们将未设置的变量视为false,将变量设置为任何值为true.今天,测试内置于test并且通常以其一个字符别名[(或者在缺少它的shell中使用的可执行文件,如dolmen注释)而众所周知:

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
Run Code Online (Sandbox Code Playgroud)

由于报价的约定,脚本编写者喜欢使用复合命令[[,模仿test,但有更好的语法:用空格变量不需要被引用,可以使用&&||怪异优先逻辑运算符,并有对数量没有POSIX限制条款.

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

FLAG="u p"
COUNT=3

if [[ $FLAG  && $COUNT -gt '1' ]] ; then
    echo 'Flag up, count bigger than 1'
else
    echo 'Nope'
fi
Run Code Online (Sandbox Code Playgroud)

当需要空格,零长度字符串和空变量以及脚本需要使用多个shell时,这些东西会让人感到困惑.

  • ```不仅仅是`bash`中的别名.此别名也作为二进制文件(或指向的链接)存在,并且可以与裸`sh`一起使用.检查`ls -l/usr/bin /\[`.使用`bash` /`zsh`你应该使用`[[`这是一个真正纯粹的内部并且更强大. (3认同)
  • @dolmen `[` 和 `test` 也是 Bash SHELL BUILTIN COMMAND 根据 Bash 手册页,因此性能上不应该有问题。与例如 Dash 相同。(/bin/sh 可能只是 /bin/dash 的符号链接)。要使用可执行文件,您必须使用完整路径,即“/usr/bin/\[”。 (2认同)

sjs*_*sam 11

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

与许多其他编程语言不同,Bash不会通过"类型"来隔离其变量.[1]

所以答案很清楚.Boolean variablebash中没有.但是:

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

#!/bin/bash
declare -ir BOOL=(0 1) # Remember BOOL can't be unset till this shell terminates
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"
Run Code Online (Sandbox Code Playgroud)

r选件declarereadonly使用,明确规定了变量是只读的.希望目的很明确.


Pyr*_*cal 10

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

例如:

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
Run Code Online (Sandbox Code Playgroud)

  • @Blauhirn因为整数的使用取决于语言.在某些语言中,`0`强制为'false`,'1`强制为'true`.关于程序退出代码(bash历史上使用),它为"0"表示正结果或"true",其他一切都是负数/错误或"假". (3认同)

Buv*_*inJ 10

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

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

如果将变量设置为true,则它随后在条件中评估为“肯定”。将其设置为false,它的计算结果为“负数”。很直接!唯一需要注意的是,未定义的变量的计算结果也像true!如果它做相反的事情会很好(就像在大多数语言中一样),但这就是诀窍 -你只需要明确地将你的布尔值初始化为 true 或 false

为什么它以这种方式工作?这个答案是双重的。A)shell 中的真/假真的意味着“没有错误”与“错误”(即 0 与其他任何东西)。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=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;
Run Code Online (Sandbox Code Playgroud)

产量

when set to
it evaluates to true
when set to true
it evaluates to true
when set to false
it evaluates to false
Run Code Online (Sandbox Code Playgroud)


Cyk*_*ker 7

在许多编程语言,布尔类型是或作为实现,整数,其中的亚型true表现得像1false行为就像0

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

# val=1; ((val)) && echo "true" || echo "false"
true
# val=0; ((val)) && echo "true" || echo "false"
false
Run Code Online (Sandbox Code Playgroud)

男人 bash

((表达))

表达式根据以下算术求值中描述的规则进行求值。如果表达式的值非零,则返回状态为 0;否则返回状态为 1。这完全等同于 let "expression"。


Lin*_*eak 6

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

我在这里想念关键点,那就是可移植性。这就是为什么我的标头本身具有POSIX的原因。

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

基本上,我只希望添加有关可移植性的更多信息。


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

    test "${var}" = true && CodeIfTrue || CodeIfFalse
    
    Run Code Online (Sandbox Code Playgroud)

请注意,由于它已逐渐被弃用,因此我不再建议这样做。

  1. 想象一下那些话true,并false指到外壳,测试自己:

    echo $(( true ))
    
    Run Code Online (Sandbox Code Playgroud)
    0
    
    Run Code Online (Sandbox Code Playgroud)
    echo $(( false ))
    
    Run Code Online (Sandbox Code Playgroud)
    1
    
    Run Code Online (Sandbox Code Playgroud)

    但是使用引号:

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

同样适用于:

    echo $(( "false" ))
Run Code Online (Sandbox Code Playgroud)

除了字符串,shell无法解释它。希望您能想到使用不带引号的适当关键字的效果如何。

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

  1. 这是什么意思?好吧,几件事。

    如您所见,shell true第一次使用时会打印字符串,但是从那时起,它都分别通过数字0表示true1表示来false工作。


最后,您应该如何处理所有这些信息

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

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

    if [ "${var_bool}" -eq 0 ]; then YourCodeIfTrue; else YourCodeIfFalse; fi
    
    Run Code Online (Sandbox Code Playgroud)


Eri*_*c P 6

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

# Tests
var=
var=''
var=""
var=0
var=1
var="abc"
var=abc

if [[ -n "${var}" ]] ; then
    echo 'true'
fi
if [[ -z "${var}" ]] ; then
    echo 'false'
fi

# Results
# var=        # false
# var=''      # false
# var=""      # false
# var=0       # true
# var=1       # true
# var="abc"   # true
# var=abc     # true
Run Code Online (Sandbox Code Playgroud)

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

所以,一个简单的方法给一个变量设置为true(使用此语法的方法)将是var=1; 反之,var=''

参考:

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

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


小智 5

Bill Parker被否决了,因为他的定义与常规代码约定相反。通常,将true定义为0,将false定义为非零。1代表false,9999和-1代表false。与函数返回值相同-0表示成功,非零表示失败。抱歉,我还没有投票或直接回复他的信誉。

Bash建议现在使用双括号代替单括号,这是一种习惯,麦克·霍尔特(Mike Holt)给出的链接说明了它们在工作方式上的差异。7.3。其他比较运算符

一方面,-eq是一个数值运算符,所以有了代码

#**** NOTE *** This gives error message *****
The_world_is_flat=0;
if [ "${The_world_is_flat}" -eq true ]; then
Run Code Online (Sandbox Code Playgroud)

将发出错误语句,期望使用整数表达式。这适用于任何一个参数,因为两者都不是整数值。但是,如果在它周围加上双括号,它将不会发出错误声明,但是会产生错误的值(可能是50%的可能排列)。它将评估为[[0 -eq真]] =成功,但也评估为[[0 -eq真]] =成功,这是错误的(hmmm ....该内建值是什么?)。

#**** NOTE *** This gives wrong output *****
The_world_is_flat=true;
if [[ "${The_world_is_flat}" -eq true ]]; then
Run Code Online (Sandbox Code Playgroud)

条件的其他排列也会产生错误的输出。基本上,任何将变量设置为数值并将其与true / false内置值进行比较,或将变量设置为true / false内置值并将其与数值进行比较的东西(上述错误条件除外)。同样,将变量设置为true / false内置变量并使用进行比较的任何操作-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
Run Code Online (Sandbox Code Playgroud)

所以,现在要做什么。对比较和评估都使用true / false内建函数(如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
Run Code Online (Sandbox Code Playgroud)

你有它。

  • 这里没有使用 `true`/`false` 内置函数(忽略一些编辑器的语法高亮可能意味着什么),特别是在 `[...]` 的情况下,你可以把它想象成一个简单的字符串(一个它作为`[`命令的参数给出)。 (2认同)

yol*_*yer 5

使用布尔值的另一种方法是测试值的空性。这样做的优点是可以缩短测试时间:

first=1  # A true value
second=   # 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'
Run Code Online (Sandbox Code Playgroud)

输出:

first=1  # A true value
second=   # 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'
Run Code Online (Sandbox Code Playgroud)

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