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
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 ,即数值 .
缺点是偶尔使用 $ :
testvar=$TRUE
这不是那么漂亮 .
它不是一个完美的解决方案,但它涵盖了所有情况,我需要进行这样的测试 .
40
这是一个简短的 if true 的实现 .
# 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
}
Example 1
my_boolean=true
_if ${my_boolean} && {
echo "True Is True"
} || {
echo "False Is False"
}
Example 2
my_boolean=false
! _if ${my_boolean} && echo "Not True is True"
if [[ false ]]; then ...
if [[ "false" ]]; then ...
if [[ true ]]; then ...
if [[ "true" ]]; then ...
TL; DR;总是与字符串或数字进行比较
为了向未来的读者表明这一点,我建议始终使用 true 和 false 周围的引号:
DO
if [[ "${var}" == "true" ]]; then ...
if [[ "${var}" == "false" ]]; then ...
if [[ -n "${var:-}" ]]; then echo "var is not empty" ...
不要
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 `==`
也许吧
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".
2
Revised Answer (Feb 12, 2014)
the_world_is_flat=true
# ...do something interesting...
if [ "$the_world_is_flat" = true ] ; then
echo 'Be careful not to fall off!'
fi
#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
#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
# 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
通常,只有当您的"boolean"变量(在此示例中为 var )显式设置为true时,您才希望将条件计算为true . 所有其他案件都具有危险的误导性!
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 . 在上述情况下,您应该收到一条警告,指出找不到该命令 . 但我们仍然可以做得更好(请参阅我在底部的建议) .
另请参阅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!
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
很久以前,当我们所有的都是 sh 时,通过依赖 test 程序的约定来处理布尔值,其中 test 如果没有参数运行则返回错误的退出状态 . 这允许人们将未设置的变量视为false,将变量设置为任何值为true . 今天,测试内置于 bash ,并且通常以其一个字符别名 [ (或者在缺少它的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
由于引用约定,脚本编写者更喜欢使用模仿 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
16 回答
为什么不使用比true和false更好的值,而不是伪造布尔值并为未来的读者留下陷阱?
例如:
在许多编程语言中,布尔类型是整数的子类型,或者实现为整数的子类型,其中
true
的行为类似于1
,而false
的行为类似于0
:Boolean in C
Boolean in Python
Boolean in Java
Mathematically,布尔代数类似于整数算术模2.因此,如果一种语言不提供本机布尔类型,最自然有效的解决方案是使用整数 . 这几乎适用于任何语言 . 例如,在Bash中你可以这样做:
man bash:
Bash真的把这个问题与
[
,_[[
,((
,$((
等问题混为一谈 .所有处理彼此的代码空间 . 我想这主要是历史性的,Bash不得不偶尔假装是
sh
.大多数时候,我可以选择一种方法并坚持下去 . 在这种情况下,我倾向于声明(最好在一个公共库文件中,我可以在我的实际脚本中包含
.
) .然后,我可以使用
((
...))
算术运算符进行测试 .你必须受到纪律处分 . 您的
testvar
必须始终设置为$TRUE
或$FALSE
.在
((
...))
比较器中,您不需要前面的$
,这使它更具可读性 .我可以使用
((
...))
因为$TRUE=1
和$FALSE=0
,即数值 .缺点是偶尔使用
$
:这不是那么漂亮 .
它不是一个完美的解决方案,但它涵盖了所有情况,我需要进行这样的测试 .
这是一个简短的
if true
的实现 .Example 1
Example 2
使用算术表达式 .
输出:
长话短说:
bash中没有布尔值
bash所拥有的是比较和条件方面的布尔表达式 . 也就是说,你可以在bash中声明和比较的是字符串和数字 . 而已 .
无论你在bash中看到
true
或false
,它都是一个字符串或一个命令/ builtin,它只用于退出代码 .这个语法......
基本上......
只要命令返回退出代码0,条件就为真 .
你也可以这样做:
使用方括号或
test
命令时,您依赖于该构造的退出代码 . 请记住[ ]
和[[ ]]
也像其他任何命令/内置命令一样 . 所以......只是...的语法糖
因此,当在上述任何构造中使用
true
和false
时,实际上只是将字符串"true"
或"false"
传递给测试命令 . 这是一个例子:信不信由你,但这些条件都产生了 same result :
TL; DR;总是与字符串或数字进行比较
为了向未来的读者表明这一点,我建议始终使用
true
和false
周围的引号:DO
不要
也许吧
Revised Answer (Feb 12, 2014)
Original Answer
注意事项:https://stackoverflow.com/a/21210966/89391
来自:Using boolean variables in Bash
这里包含原始答案的原因是因为2014年2月12日修订前的评论仅涉及原始答案,并且许多评论与修订后的答案相关时是错误的 . 例如,Dennis Williamson关于2010年6月2日bash builtin
true
的评论仅适用于原始答案,而非修订版 .Bill Parker is getting voted down,因为他的定义与正常的代码约定相反 . 通常,true定义为0,false定义为非零 . 1将用于false,9999和-1也是如此 . 与函数返回值相同 - 0表示成功,任何非零表示失败 . 对不起,我还没有街头信誉可以投票或直接回复他 .
Bash建议现在使用双括号作为习惯而不是单个括号,Mike Holt给出的链接解释了它们的工作方式的差异 . 7.3. Other Comparison Operators
首先,
-eq
是一个数值运算符,所以有代码将发出一个错误语句,期望一个整数表达式 . 这适用于任何一个参数,因为都不是整数值 . 然而,如果我们在它周围放置双括号,它将不会发出错误声明,但它会产生错误的值(好吧,在50%的可能排列中) . 它会评估为[[0 -eq true]] =成功,但也会[[0 -eq false]] =成功,这是错误的(嗯......那个内置数字值是什么?) .
条件的其他排列也会产生错误的输出 . 基本上,将变量设置为数值并将其与true / false内置值进行比较,或将变量设置为true / false内置并将其与数值进行比较的任何事物(上面列出的错误条件除外) . 此外,任何将变量设置为true / false内置并使用
-eq
进行比较的内容 . 因此,避免使用-eq
进行布尔比较,并避免使用数值进行布尔比较 . 以下是将产生无效结果的排列摘要:所以,现在到底有效 . 使用true / false内置函数进行比较和评估(正如Mike Hunt指出的那样,不要将它们括在引号中) . 然后使用单或双等号(=或==)和单括号或双括号([]或[[]]) . 就个人而言,我喜欢双等号,因为它让我想起其他编程语言中的逻辑比较,而双引号只是因为我喜欢打字 . 所以这些工作:
你有它 .
POSIX(便携式操作系统接口)
我想念这里的关键点,即便携性 . 这就是为什么我的 Headers 本身就是POSIX .
基本上,所有投票的答案都是正确的,除了它们是特定的_s7615_特定的太多 .
基本上,我只希望添加有关可移植性的更多信息 .
169
[
和]
中的]
括号不是必需的,您可以省略它们并直接使用test
命令:true
和false
对shell的意思是什么,自己测试一下:但是使用引号:
同样适用于:
shell不能解释它而不是字符串 . 我希望你能够了解使用正确的关键字 without 引用有多好 .
但在之前的答案中没有人说过 .
这意味着什么?好吧,好几件事 .
你应该习惯布尔关键字实际上被视为数字,即
true
=0
和false
=1
,记住所有非零值都被视为false
.因为它们被视为数字,你应该像对待它们一样,即如果你定义变量说:
你可以创建一个相反的值:
正如您自己可以看到的,shell在您第一次使用它时会打印
true
字符串,但从那时起,它们分别通过数字0
或1
工作 .最后,您应该对所有这些信息做些什么
第一个好习惯是分配
0
而不是true
;1
而不是false
.第二个好习惯是测试变量是否等于零:
TL; DR
Miku(原创)答案的问题
我做 not 推荐接受的答案1 . 它的语法很漂亮,但它有一些缺陷 .
假设我们有以下条件 .
在以下情况2中,此条件将计算为 true 并执行嵌套命令 .
通常,只有当您的"boolean"变量(在此示例中为
var
)显式设置为true时,您才希望将条件计算为true . 所有其他案件都具有危险的误导性!最后一种情况(#5)特别顽皮,因为它将执行变量中包含的命令(这就是为什么条件对有效命令3,4评估为真) .
这是一个无害的例子:
引用变量更安全,例如
if "$var"; then
. 在上述情况下,您应该收到一条警告,指出找不到该命令 . 但我们仍然可以做得更好(请参阅我在底部的建议) .另请参阅Mike Holt对Miku原始答案的解释 .
Hbar答案的问题
这种方法也有意想不到的行为 .
您可能希望将上述条件计算为false,从而从不执行嵌套语句 . 惊喜!
引用值(
"false"
),引用变量("$var"
),或使用test
或[[
而不是[
,没有什么区别 .我建议的内容:
以下是我建议您检查“布尔”的方法 . 他们按预期工作 .
他们需要键入比其他答案中的方法更多的键击5,但是你的代码将更具防御性 .
脚注
Miku's答案已被编辑,不再包含(已知)缺陷 .
不是详尽的清单 .
此上下文中的有效命令表示存在的命令 . 如果正确或错误地使用命令并不重要 . 例如 . 即使没有这样的手册页,
man woman
仍将被视为有效命令 .对于无效(不存在)命令,Bash只会抱怨找不到该命令 .
如果你关心长度,第一个建议是最短的 .
与许多其他编程语言不同,Bash不会通过"type." [1]隔离其变量
所以答案很清楚 . bash中没有
boolean variable
. 但是:使用declare语句,我们可以将值赋值限制为变量 . [2]
declare
和readonly
中的r
选项用于明确声明变量为 readonly . 希望目的很明确 .这里似乎存在一些关于Bash内置
true
的误解,更具体地说,关于Bash如何扩展和解释括号内的表达式 .miku's answer中的代码与Bash内置
true
完全无关,也与/bin/true
完全无关,也与true
命令的任何其他风格无关 . 在这种情况下,true
只不过是一个简单的字符串,并且不会通过变量赋值或条件表达式的求值来调用true
command / builtin .以下代码在功能上与miku的答案中的代码相同:
这里的 only 差异在于被比较的四个字符是'y','e','a'和'h'而不是't',_ 'r','u'和'e' . 's it. There'没有尝试调用名为
yeah
的命令或内置,也没有(在miku的例子中)当Bash解析令牌true
时进行任何类型的特殊处理 . 它只是一个字符串,而且是一个完全随意的字符串 .Update (2014-02-19): 跟随miku 's answer, now I see where some of the confusion is coming from. Miku'中的链接后,答案使用单括号,但他链接到的代码段不使用括号 . 只是:
两个代码片段的行为方式都相同,但括号完全改变了引擎盖下的内容 .
这是Bash在每种情况下所做的事情:
No brackets:
将变量
$the_world_is_flat
展开为字符串"true"
.尝试将字符串
"true"
解析为命令 .查找并运行
true
命令(内置或/bin/true
,具体取决于Bash版本) .将
true
命令的退出代码(始终为0)与0进行比较 . 回想一下,在大多数shell中,退出代码0表示成功,其他任何表示失败 .由于退出代码为0(成功),执行
if
语句的then
子句Brackets:
将变量
$the_world_is_flat
展开为字符串"true"
.解析现在完全展开的条件表达式,其形式为
string1 = string2
.=
运算符是bash的字符串比较运算符 . 所以...在
"true"
和"true"
上进行字符串比较 .是的,两个字符串是相同的,因此条件的值为true .
执行
if
语句的then
子句 .无括号代码有效,因为
true
命令返回退出代码0,表示成功 . 括号中的代码有效,因为$the_world_is_flat
的值与=
右侧的字符串文字true
相同 .只是为了推动这一点,请考虑以下两段代码:
此代码(如果以root权限运行)将重新启动您的计算机:
这段代码只打印“Nice try” . 不调用reboot命令 .
Update (2014-04-14) 要回答有关
=
和==
:AFAIK之间差异的评论中的问题,没有区别 .==
运算符是=
的特定于Bash的同义词,据我所见,它们在所有上下文中的工作方式完全相同 .但请注意,我特别谈到
[ ]
或[[ ]]
测试中使用的=
和==
字符串比较运算符 . 我并不是说_b7544_和==
在bash中可以互换 .例如,你显然无法使用
==
进行变量赋值,例如var=="foo"
(技术上你可以做到这一点,但var
的值将是"=foo"
,因为Bash在这里没有看到==
运算符,它看到=
(赋值运算符,后跟文字值="foo"
,它只是"=foo"
) .此外,尽管
=
和==
是可以互换的,但您应该记住,这些测试的工作方式取决于您是在[ ]
或[[ ]]
中使用它,还是在是否引用了操作数 . 您可以在中阅读更多相关信息Advanced Bash Scripting Guide: 7.3 Other Comparison Operators(向下滚动到=
和==
的讨论) .很久以前,当我们所有的都是
sh
时,通过依赖test
程序的约定来处理布尔值,其中test
如果没有参数运行则返回错误的退出状态 . 这允许人们将未设置的变量视为false,将变量设置为任何值为true . 今天,测试内置于bash
,并且通常以其一个字符别名[
(或者在缺少它的shell中使用的可执行文件,如dolmen注释)而闻名:由于引用约定,脚本编写者更喜欢使用模仿
test
但具有更好语法的复合命令[[
:不需要引用带空格的变量,可以使用&&
和||
作为具有奇怪优先级的逻辑运算符,并且没有POSIX术语数量的限制 .例如,要确定是否设置了FLAG并且COUNT是大于1的数字:
This stuff can get confusing当需要空格,零长度字符串和空变量时,以及脚本需要使用多个shell时 .
我发现现有的答案令人困惑 .
就个人而言,我只想拥有像C一样的外观和作品 .
这个片段每天在制作中多次使用:
为了让每个人都开心,我测试过:
哪个也很好 .
$snapshotEvents
评估变量值的内容 . 所以你需要$
.你真的不需要括号,我发现它们很有帮助 .
测试:GNU Bash,版本4.1.11(2) - 发布
Bash Guide for Beginners,Machtelt Garrels,v1.11,2008
这是一个适合我的简单示例:
这是对miku的original answer的改进,它解决了Dennis Williamson对案例的担忧,其中未设置变量:
并测试变量是否
false
:关于变量中含有令人讨厌的内容的其他情况,这是任何输入程序的外部输入的问题 .
在信任之前,必须验证任何外部输入 . 但是,当接收到该输入时,该验证必须只进行一次 .
它不必像每个使用变量那样影响程序的性能,如Dennis Williamson建议的那样 .