Bash if [false];返回true

时间:2013-10-29 22:04:08

标签: bash conditional-operator

本周一直在学习bash并陷入困境。

#!/bin/sh

if [ false ]; then
    echo "True"
else
    echo "False"
fi

这将始终输出True,即使条件似乎另有说明。如果我删除括号[]然后它可以工作,但我不明白为什么。

6 个答案:

答案 0 :(得分:143)

您正在使用参数“false”运行[(aka test)命令,而不是运行命令false。由于“false”是非空字符串,因此test命令始终成功。要实际运行该命令,请删除[命令。

if false; then
   echo "True"
else
   echo "False"
fi

答案 1 :(得分:27)

Bash的快速布尔入门

if语句将命令作为参数(与&&||等一样)。该命令的整数结果代码被解释为布尔值(0 / null = true,1 / else = false)。

test语句将运算符和操作数作为参数,并以与if相同的格式返回结果代码。 test语句的别名为[,通常与if一起用于执行更复杂的比较。

truefalse语句不执行任何操作并返回结果代码(分别为0和1)。所以它们可以在Bash中用作布尔文字。但是如果你把语句放在一个被解释为字符串的地方,你就会遇到问题。在你的情况下:

if [ foo ]; then ... # "if the string 'foo' is non-empty, return true"
if foo; then ...     # "if the command foo succeeds, return true"

所以:

if [ true  ] ; then echo "This text will always appear." ; fi;
if [ false ] ; then echo "This text will always appear." ; fi;
if true      ; then echo "This text will always appear." ; fi;
if false     ; then echo "This text will never appear."  ; fi;

这类似于执行echo '$foo'echo "$foo"之类的内容。

使用test语句时,结果取决于使用的运算符。

if [ "$foo" = "$bar" ]   # true if the string values of $foo and $bar are equal
if [ "$foo" -eq "$bar" ] # true if the integer values of $foo and $bar are equal
if [ -f "$foo" ]         # true if $foo is a file that exists (by path)
if [ "$foo" ]            # true if $foo evaluates to a non-empty string
if foo                   # true if foo, as a command/subroutine,
                         # evaluates to true/success (returns 0 or null)

简而言之,如果您只想测试通过/失败(又名“true”/“false”),请将命令传递给if或{{1等等声明,没有括号。对于复杂的比较,请使用括号和适当的运算符。

是的,我知道在Bash中没有本地布尔类型,&&if[在技术上是“命令“而不是”语句“;这只是一个非常基本的功能性解释。

答案 2 :(得分:3)

我发现我可以通过运行以下内容来执行一些基本逻辑:

A=true
B=true
if ($A && $B); then
    C=true
else
    C=false
fi
echo $C

答案 3 :(得分:0)

使用true / false可以删除某些支架杂乱......

#! /bin/bash    
#  true_or_false.bash

[ "$(basename $0)" == "bash" ] && sourced=true || sourced=false

$sourced && echo "SOURCED"
$sourced || echo "CALLED"

# Just an alternate way:
! $sourced  &&  echo "CALLED " ||  echo "SOURCED"

$sourced && return || exit

答案 4 :(得分:0)

添加上下文希望对本主题有所帮助。对于BaSH新手来说,对/错陈述的感觉相当奇怪。拿下面的简单例子及其结果。

此语句将返回“ true”:

foo=" "; if [ "$foo" ]; then echo "true"; else echo "false"; fi

但这将返回“ false”:

foo=" "; if [ $foo ]; then echo "true"; else echo "false"; fi

您知道为什么吗?第一个示例具有带引号的“”字符串。这使BaSH从字面上对待它。因此,从字面上看,空格不是null。从非字面意义上(上面的第二个示例),BaSH将空格($ foo中的值)视为“无”,因此它等于null(在此解释为“ false”)。

这些语句都将返回文本字符串“ false”:

foo=; if [ $foo ]; then echo "true"; else echo "false"; fi
foo=; if [ "$foo" ]; then echo "true"; else echo "false"; fi
foo=""; if [ $foo ]; then echo "true"; else echo "false"; fi
foo=""; if [ "$foo" ]; then echo "true"; else echo "false"; fi

有趣的是,这种条件类型将始终返回true:

这些语句都将返回结果为“ true”:

foo=""; if [ foo ]; then echo "true"; else echo "false"; fi

注意区别;条件符号中变量名之前的$符号已被省略。在括号之间插入什么单词都没有关系。即使您使用的单词以前从未与同一shell中的变量关联,BaSH始终会将此语句视为真实。

if [ sooperduper ]; then echo "true"; else echo "false"; fi

同样,将其定义为未声明的变量可确保其始终返回false:

if [ $sooperduper ]; then echo "true"; else echo "false"; fi

关于BaSH与写作相同:

sooperduper="";if [ $sooperduper ]; then echo "true"; else echo "false"; fi

另一个提示。...

方括号与无方括号

更令人困惑的是,IF / THEN条件上的这些变体都起作用,但返回相反的结果。

这些返回false:

if [ $foo ]; then echo "true"; else echo "false"; fi
if [ ! foo ]; then echo "true"; else echo "false"; fi

但是,这些将返回true的结果:

if $foo; then echo "true"; else echo "false"; fi
if [ foo ]; then echo "true"; else echo "false"; fi
if [ ! $foo ]; then echo "true"; else echo "false"; fi

并且,当然,这将返回语法错误(以及结果为“ false”):

if foo; then echo "true"; else echo "false"; fi

困惑了吗?一开始要直截了当可能会非常具有挑战性,特别是如果您习惯于其他高级编程语言。

答案 5 :(得分:0)

如@tripleee所述,这充其量是切线的。

不过,如果您到达这里是在搜索类似的内容(就像我一样),这是我的解决方法

必须处理用户可访问的配置文件,我使用此功能:

function isTrue() {
    if [[ "${@^^}" =~ ^(TRUE|OUI|Y|O$|ON$|[1-9]) ]]; then return 0;fi
    return 1
    }

wich可以这样使用

if isTrue "$whatever"; then..

您可以在regexp中更改“真值列表”,此示例中的那个是法语兼容的,并认为诸如“是,是,on,1,Oui,y,true之类的字符串为” True”。

请注意,'^^'区分大小写