我尝试在shell脚本中使用以下语法声明一个布尔变量:
variable=$false
variable=$true
这对吗?另外,如果我想更新这个变量,我会使用相同的语法吗?最后,下面使用布尔变量作为表达式的语法正确吗?
if [ $variable ]
if [ !$variable ]
我尝试在shell脚本中使用以下语法声明一个布尔变量:
variable=$false
variable=$true
这对吗?另外,如果我想更新这个变量,我会使用相同的语法吗?最后,下面使用布尔变量作为表达式的语法正确吗?
if [ $variable ]
if [ !$variable ]
当前回答
博士TL;
my_bool=true
if [ "$my_bool" = true ]
未来音乐(最初)的回答有问题
我不推荐公认的答案。它的语法很漂亮,但也有一些缺陷。
假设我们有以下条件。
if $var; then
echo 'Muahahaha!'
fi
在以下情况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
通常,当你的“布尔”变量var显式设置为true时,你只希望你的条件值为true。其他所有的案例都是危险的误导!
最后一种情况(#5)特别淘气,因为它将执行变量中包含的命令(这就是为什么对于有效的command3,4,条件的计算结果为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";然后。在上述情况下,您应该得到一个警告,表示没有找到该命令。但我们仍然可以做得更好(见下面我的建议)。
也可以看看Mike Holt对Miku最初答案的解释。
赫巴的回答有问题
这种方法也有意想不到的行为。
var=false
if [ $var ]; then
echo "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 ]; then
if [ "$my_bool" = "true" ]; then
if [[ "$my_bool" = true ]]; then
if [[ "$my_bool" = "true" ]]; then
if [[ "$my_bool" == true ]]; then
if [[ "$my_bool" == "true" ]]; then
if test "$my_bool" = true; then
if test "$my_bool" = "true"; then
它们几乎都是一样的。与其他答案5中的方法相比,您将不得不输入更多的按键,但您的代码将更具防御性。
脚注
未来音乐的回答已被编辑,不再包含(已知的)缺陷。 这不是一个详尽的清单。 在此上下文中,有效命令是指存在的命令。命令使用正确或不正确并不重要。例如,man woman仍然被认为是一个有效的命令,即使没有这样的手册页存在。 对于无效的(不存在的)命令,Bash只会报错说没有找到该命令。 如果你关心长度,第一个建议是最短的。
其他回答
这是一个关于在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
使用布尔值的另一种方法是测试值是否为空。这样做的好处是可以进行更短的测试:
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'
输出:
First var is true
Second var is false
下面是bash的另一个测试语法:[[-n $one]]
以下是对miku原始答案的改进,解决了Dennis Williamson对未设置变量的情况的担忧:
the_world_is_flat=true
if ${the_world_is_flat:-false} ; then
echo "Be careful not to fall off!"
fi
测试变量是否为false:
if ! ${the_world_is_flat:-false} ; then
echo "Be careful not to fall off!"
fi
关于变量中有讨厌内容的其他情况,这是任何外部输入馈送到程序的问题。
任何外部输入都必须在信任它之前进行验证。但是,当接收到输入时,这种验证只需要执行一次。
它不必像Dennis Williamson建议的那样,每次使用变量都这样做,从而影响程序的性能。
[[ "$x" == 'true' || "$x" -ne 0 ]] && ...
足够简单并且没有依赖项。
我发现现有的答案令人困惑。
就我个人而言,我只是想要一些看起来和工作起来像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