3 回答
TA贡献1821条经验 获得超6个赞
bool=true
if [ "$bool" = true ]
有三苦的(问题原)答案
我不推荐接受的答案1。它的语法很漂亮,但是有一些缺陷。
说我们有以下情况。
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)特别顽皮,因为它将执行变量中包含的命令(这就是为什么条件对于有效命令3、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"; 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!
您可能希望上述条件的计算结果为false,从而从不执行嵌套语句。惊喜!
引用值("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
它们几乎相等。您将需要比其他答案5中的方法键入更多的击键,但是您的代码将更具防御性。
脚注
此后,Miku的答案已被编辑,不再包含(已知)缺陷。
并非详尽的清单。
在此上下文中,有效命令表示存在的命令。命令的使用正确与否无关紧要。例如man woman,即使不存在这样的手册页,它也仍然被视为有效命令。
对于无效(不存在)的命令,Bash只会抱怨找不到该命令。
如果您在意长度,则第一个建议是最短的。
TA贡献1790条经验 获得超9个赞
关于Bash内置函数true,尤其是Bash如何扩展和解释方括号内的表达式,这里似乎存在一些误解。
miku的答案中的代码与内置的Bash true,nor /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”,并且代替“T”“H”,“R”,“U”,和“e”的。而已。yeah在Bash解析令牌时,没有尝试调用名为named的命令或内置命令,也没有进行任何形式的特殊处理(在miku的示例中)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
这两个代码段的行为方式相同,但是括号完全改变了引擎盖下发生的事情。
这是Bash在每种情况下所做的事情:
没有括号:
将变量$the_world_is_flat扩展为字符串"true"。
尝试将字符串解析"true"为命令。
查找并运行true命令(内置命令或/bin/true,具体取决于Bash版本)。
将true命令的退出代码(始终为0)与0进行比较。回想一下,在大多数shell中,退出代码0表示成功,而其他任何代码则表示失败。
由于退出代码为0(成功),因此执行if语句的then子句
括号:
将变量$the_world_is_flat扩展为字符串"true"。
解析现在已经扩展的条件表达式,其形式为string1 = string2。该=运算符是bash的字符串比较运算符。所以...
在"true"和上进行字符串比较"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”。重新启动命令不被调用。
var=reboot
if [ $var ]; then
echo 'Nice try.'
fi
更新(2014年4月14日)要回答在评论有关之间的差异问题=和==:据我所知,没有任何区别。该==运营商特定的Bash-代名词=,而据我所看到的,他们的工作完全一样在所有上下文中。
但是请注意,我是专门讨论在或测试中使用的=和==字符串比较运算符。我不建议这样做,并且在bash中到处都是可以互换的。[ ][[ ]]===
例如,您显然不能使用进行变量赋值==,例如var=="foo"(从技术上讲,您可以这样做,但是varwill 的值是"=foo",因为Bash ==在这里没有看到运算符,而是看到了=(赋值)运算符,然后是文字值="foo",变成"=foo")。
另外,尽管=和==可以互换,但是您应该记住,这些测试的工作方式确实取决于您是在[ ]还是内部使用它[[ ]],还取决于是否引用了操作数。你可以阅读更多关于高级Bash脚本编程指南:7.3其他比较操作符(向下滚动到的讨论=和==)。
- 3 回答
- 0 关注
- 2759 浏览
添加回答
举报