我尝试在shell脚本中使用以下语法声明一个布尔变量:
variable=$false
variable=$true
这对吗?另外,如果我想更新这个变量,我会使用相同的语法吗?最后,下面使用布尔变量作为表达式的语法正确吗?
if [ $variable ]
if [ !$variable ]
我尝试在shell脚本中使用以下语法声明一个布尔变量:
variable=$false
variable=$true
这对吗?另外,如果我想更新这个变量,我会使用相同的语法吗?最后,下面使用布尔变量作为表达式的语法正确吗?
if [ $variable ]
if [ !$variable ]
当前回答
在大多数情况下,您需要“布尔”来执行布尔操作,例如!&&或||。在一些语言中,特殊的布尔类型根本不存在(因为实际上你在技术上不需要它),在大多数解释型语言中(几乎)所有类型在操作中自动转换为某种布尔类型,比如!&&或||。
布尔运算总是适用于布尔运算。在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]]仅当var= "(或未设置)时为false。所以唯一一个正确的“假”值的变量在bash是“(空字符串)。对于true,你可以选择任何值,但我更喜欢var=1(就像在其他语言中,true是任何非null int,但出于可读性的目的,程序员总是使用1)。
注意:对于var='false', var在布尔检查中为真。在Bash中字符串'false'实际上是true(与所有其他语言相同!)。Bash和Python、Perl或PHP之间唯一的区别是,在Bash 0中也是如此。但是,Bash中也有布尔运算,它们的工作原理和所有其他解释语言一样,除了Bash中的0为真。
在Bash中使用字符串'true'和'false'作为布尔替换是绝对不合理的。这就像在Python、Perl或PHP中使用相同的奇怪概念一样。它的工作速度较慢(在Bash中也是如此),没有人在其他语言中这样做,但在Bash中有很多程序员认为这是一个很好的解决方案。不。在Bash中没有理由不直接使用布尔运算,没有像$var == 'true'或$var == 'false'这样绝对奇怪的比较。
再次强调,Bash中的布尔替换是:
var='' # false
var=1 # true (actually any non-empty string)
在Bash中直接使用布尔检查也是执行类布尔检查的最快方法。所有其他结构都要慢得多。
注:“旧”风格的“布尔”检查像a=true;如果美元;然后……绝对是白痴,因为:
不能在[[]]条件下直接使用 它们充当bash代码的eval,存储在变量中。好吧,如果你认为这是个好主意,请不要写任何程序;)
P.P.S.如果$var可以取消设置,并且你使用了非常有用的set -u,只需在检查中将$var替换为${var-},例如[[${var-}]](还有:没有“”,这对代码执行速度很重要!)
其他回答
我发现现有的答案令人困惑。
就我个人而言,我只是想要一些看起来和工作起来像C的东西。
这段代码在生产中每天工作多次:
snapshotEvents=true
if ($snapshotEvents)
then
# Do stuff if true
fi
为了让大家开心,我测试了:
snapshotEvents=false
if !($snapshotEvents)
then
# Do stuff if false
fi
这也很有效。
$snapshotEvents计算变量value的内容。所以你需要$。
你们其实不需要括号,我只是觉得它们很有用。
在GNU Bash, version 4.1.11(2)-release上测试 Bash初学者指南,Machtelt Garrels, v1.11, 2008
这里似乎有一些关于Bash内置true的误解,更具体地说,关于Bash如何展开和解释括号内的表达式的误解。
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'。就是这样。在Bash解析令牌true时,没有尝试调用名为yeah的命令或内置命令,(在miku的例子中)也没有任何特殊处理。它只是一个字符串,一个完全任意的字符串。
更新(2014-02-19):在看了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 (success),所以执行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”。没有调用reboot命令。
var=reboot
if [ $var ]; then
echo 'Nice try.'
fi
更新(2014-04-14)回答评论中关于=和==的区别的问题:AFAIK,没有区别。==操作符是特定于bash的=的同义词,据我所知,它们在所有上下文中的工作方式完全相同。
但是请注意,我特别讨论的是[]或[[]]测试中使用的=和==字符串比较运算符。我并不是说=和==在bash中到处都可以互换。
例如,你显然不能用==来做变量赋值,比如var=="foo"(技术上你可以这样做,但var的值将是"=foo",因为Bash在这里没有看到==运算符,它看到的是=(赋值)运算符,后面跟着字面值="foo",这就变成了"=foo")。
此外,虽然=和==是可互换的,但您应该记住,这些测试的工作方式取决于您是否在[]或[[]]中使用它,以及操作数是否被引用。您可以在高级Bash脚本指南:7.3其他比较操作符(向下滚动到=和==的讨论)中阅读更多相关内容。
我的发现和建议与其他帖子有所不同。我发现我可以像使用任何“常规”语言一样使用“布尔值”,而不需要“跳篮”……
不需要使用[]或显式的字符串比较…我尝试了多个Linux发行版。我测试了Bash、Dash和BusyBox。结果总是一样的。我不确定最初投票最多的帖子在谈论什么。也许时代变了,就是这样?
如果将一个变量设置为true,它随后会在条件中作为“肯定”进行计算。将其设置为false,它的计算结果为“负”。很简单的!唯一需要注意的是,未定义的变量的计算结果也类似于true!如果它做了相反的事情(就像在大多数语言中那样),那就好了,但这就是诀窍——你只需要显式地将你的布尔值初始化为true或false。
为什么会这样?答案是双重的。A) true/false在shell中实际上意味着“无错误”vs“错误”(即0 vs任何其他)。B) true/false不是值——而是shell脚本中的语句!关于第二点,在一行中执行true或false本身就设置了你所在块的返回值,即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;
收益率
when set to
it evaluates to true
when set to true
it evaluates to true
when set to false
it evaluates to false
替代-使用函数
is_ok(){ :;}
is_ok(){ return 1;}
is_ok && echo "It's OK" || echo "Something's wrong"
定义函数不那么直观,但是检查它的返回值非常容易。
下面是一个适合我的简单例子:
temp1=true
temp2=false
if [ "$temp1" = true ] || [ "$temp2" = true ]
then
echo "Do something."
else
echo "Do something else."
fi