我尝试在shell脚本中使用以下语法声明一个布尔变量:
variable=$false
variable=$true
这对吗?另外,如果我想更新这个变量,我会使用相同的语法吗?最后,下面使用布尔变量作为表达式的语法正确吗?
if [ $variable ]
if [ !$variable ]
我尝试在shell脚本中使用以下语法声明一个布尔变量:
variable=$false
variable=$true
这对吗?另外,如果我想更新这个变量,我会使用相同的语法吗?最后,下面使用布尔变量作为表达式的语法正确吗?
if [ $variable ]
if [ !$variable ]
当前回答
这是一个关于在Bash中测试“布尔”值的不同方法的速度测试:
#!/bin/bash
rounds=100000
b=true # For true; b=false for false
type -a true
time for i in $(seq $rounds); do command $b; done
time for i in $(seq $rounds); do $b; done
time for i in $(seq $rounds); do [ "$b" == true ]; done
time for i in $(seq $rounds); do test "$b" == true; done
time for i in $(seq $rounds); do [[ $b == true ]]; done
b=x; # Or any non-null string for true; b='' for false
time for i in $(seq $rounds); do [ "$b" ]; done
time for i in $(seq $rounds); do [[ $b ]]; done
b=1 # Or any non-zero integer for true; b=0 for false
time for i in $(seq $rounds); do ((b)); done
它会打印出
true is a shell builtin
true is /bin/true
real 0m0,815s
user 0m0,767s
sys 0m0,029s
real 0m0,562s
user 0m0,509s
sys 0m0,022s
real 0m0,829s
user 0m0,782s
sys 0m0,008s
real 0m0,782s
user 0m0,730s
sys 0m0,015s
real 0m0,402s
user 0m0,391s
sys 0m0,006s
real 0m0,668s
user 0m0,633s
sys 0m0,008s
real 0m0,344s
user 0m0,311s
sys 0m0,016s
real 0m0,367s
user 0m0,347s
sys 0m0,017s
其他回答
很久以前,当我们只有sh时,布尔值依赖于测试程序的约定来处理,在测试程序中,如果运行时不带任何参数,则返回错误的退出状态。
这允许人们认为一个未设置为false的变量和设置为任何值的变量为true。今天,test是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
当空格、零长度字符串和空变量都需要时,或者当脚本需要使用多个shell时,这些东西可能会令人困惑。
修正答案(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
原来的答案
警告: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
来自:在Bash中使用布尔变量
此处包含原答案的原因是,2014年2月12日修改前的评论仅涉及原答案,许多评论与修改后的答案相关联时是错误的。例如,Dennis Williamson在2010年6月2日关于bash builtin true的评论只适用于原始答案,而不适用于修改后的答案。
我发现现有的答案令人困惑。
就我个人而言,我只是想要一些看起来和工作起来像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中,这样的操作是(在$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-}]](还有:没有“”,这对代码执行速度很重要!)
Bash确实将问题与[,[[,((,$((等))等混淆了。
所有人都在践踏彼此的代码空间。我想这主要是历史原因,巴什不得不偶尔装成。
大多数时候,我可以选择一种方法并坚持下去。在这种情况下,我倾向于声明(最好是在我可以包含的公共库文件中)。在我的实际脚本(s))。
TRUE=1; FALSE=0
然后我可以使用((…))算术运算符来测试。
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 = $ 这可不太好。
这不是一个完美的解决方案,但它涵盖了我需要这种测试的所有情况。