bash“;如果[假]&引用;返回true而不是false——为什么?

bash“;如果[假]&引用;返回true而不是false——为什么?,bash,boolean,conditional-operator,Bash,Boolean,Conditional Operator,为什么以下输出为True #!/bin/sh if [ false ]; then echo "True" else echo "False" fi 这将始终输出True,即使条件似乎另有指示。如果我删除括号[],它会工作,但我不明白为什么。您正在运行参数为“false”的[(又称test)命令,而不是运行命令false。因为“false”是非空字符串,test命令始终成功。若要实际运行该命令,请删除[命令 if false; then

为什么以下输出
为True

#!/bin/sh

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

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

您正在运行参数为“false”的
[
(又称
test
)命令,而不是运行命令
false
。因为“false”是非空字符串,
test
命令始终成功。若要实际运行该命令,请删除
[
命令

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

我发现我可以通过运行以下程序来实现一些基本逻辑:

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

使用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
Bash的快速布尔入门 if语句将命令作为参数(如
&
|
等)。命令的整数结果代码被解释为布尔值(0/null=true,1/else=false)

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

true
false
语句不起任何作用,返回结果代码(分别为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"
因此:

这类似于执行类似于
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)
简而言之,如果您只想测试通过/失败(也称为“真”/“假”),则将命令传递给
if
&&
等语句,不带括号。对于复杂的比较,请使用括号和适当的运算符


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

添加上下文,希望有助于在这个主题上提供一点额外的清晰性。对于BaSH新手来说,它对真/假陈述的感觉相当奇怪。以下面的简单示例及其结果为例

此语句将返回“true”:

但这将返回“false”:

你明白为什么了吗?第一个例子有一个带引号的“”字符串。这会导致BaSH逐字处理它。因此,在字面意义上,空格不是null。而在非字面意义上(上面的第二个例子),BaSH将空格(作为$foo中的值)视为“nothing”,因此它等同于null(此处解释为“false”)

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

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

foo=" "; if [ "$foo" ]; then echo "true"; else echo "false"; fi
这些语句都将返回“true”的结果:

请注意差异;在条件中变量名前面省略了$符号。在括号之间插入什么单词无关紧要。BaSH始终会将此语句视为true,即使您使用的单词以前从未与同一shell中的变量关联

if [ sooperduper ]; then echo "true"; else echo "false"; fi
同样,将其定义为未声明的变量可确保其始终返回false:

foo=" "; if [ $foo ]; then echo "true"; else echo "false"; fi
if [ $sooperduper ]; 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
至于BaSH,这与写:

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

还有一个提示

括号与无括号的比较

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

这些返回值为false:

foo=" "; if [ $foo ]; then echo "true"; else echo "false"; fi
if [ $sooperduper ]; 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
但是,这些将返回true的结果:

foo=""; 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
if [ ! $foo ]; then echo "true"; else echo "false"; fi
当然,这会返回一个语法错误(以及“false”的结果):


还不明白吗?一开始就想清楚这一点是很有挑战性的,特别是如果你习惯了其他更高级的编程语言。

正如@tripleee所指出的,这充其量是相切的

不过,如果你到这里来寻找类似的东西(就像我做的那样),这里是我的解决方案

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

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

if isTrue "$whatever"; then..
您可以更改regexp中的“真值列表”,此示例中的列表与法语兼容,并将“Yeah,yup,on,1,Oui,y,true”等字符串视为“真”


请注意,“^^”提供了不区分大小写的功能。顺便说一句,以
#!/bin/sh
开头的脚本不是bash脚本,而是POSIX sh脚本。即使系统上的POSIX sh解释器是由bash提供的,它也会关闭一系列扩展。如果要编写bash脚本,请使用
#!/bin/bash
或其本地相应的等价物(
#!/usr/bin/env bash
使用路径中的第一个bash解释器)。这会影响
[[false]]
也是。false是一个命令,甚至是一个字符串的想法对我来说似乎很奇怪,但我猜它是有效的。谢谢。
bash
没有布尔数据类型,因此没有表示true和false的关键字。
if
语句只检查您发出的命令是否成功。
test
命令接受一个表达式,然后执行如果表达式为true,则为cceeds;与大多数其他编程语言一样,非空字符串是一个计算结果为true的表达式。
false
是一个总是失败的命令。
true
是一个总是成功的命令。
if[[false]];
也返回true。
if[[0]]如果[/usr/bin/false]];
也不跳过该块,那么怎么能将false或0计算为非零?该死的,这太令人沮丧了。如果重要的话,OS X 10.8;Bash 3。不要搞错
false