217

为什么会出现以下输出True

#!/bin/sh

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

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

4

6 回答 6

265

You are running the [ (aka test) command with the argument "false", not running the command false. Since "false" is a non-empty string, the test command always succeeds. To actually run the command, drop the [ command.

if false; then
   echo "True"
else
   echo "False"
fi
于 2013-10-29T22:06:19.713 回答
87

Bash 的快速布尔入门

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

test语句将运算符和操作数作为参数,并返回格式与if. test语句的别名是[,通常用于if执行更复杂的比较。

trueand语句不执行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"

所以:

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'vs.的事情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”)的内容,则将命令传递给您的ifor &&etc. 语句,不带括号。对于复杂的比较,请使用带有适当运算符的括号。

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

于 2017-12-18T20:58:40.447 回答
4

我发现我可以通过运行类似的东西来做一些基本的逻辑:

A=true
B=true
if ($A && $B); then
    C=true
else
    C=false
fi
echo $C
于 2017-01-24T06:41:39.143 回答
3

使用真/假消除了一些括号混乱...

#! /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
于 2017-11-07T13:00:24.270 回答
2

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

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

不得不处理用户可访问的配置文件,我使用这个功能:

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

可以这样使用

if isTrue "$whatever"; then..

您可以更改正则表达式中的“真值列表”,此示例中的“真值列表”与法语兼容,并将“是的,是的,on,1, Oui,y,true”之类的字符串视为“真”。

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

于 2020-09-26T11:09:06.283 回答
0

添加上下文以希望有助于在此主题上提供一些额外的清晰度。对于 BaSH 新手来说,真/假陈述的感觉相当奇怪。举以下简单的例子及其结果。

此语句将返回“true”:

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

但这将返回“假”:

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

你明白为什么吗?第一个示例有一个带引号的 "" 字符串。这导致 BaSH 按字面意思对待它。所以,从字面上看,空格不是空的。虽然在非字面意义上(上面的第二个示例),但 BaSH(作为 $foo 中的值)将空格视为“无”,因此它等同于 null(此处解释为“假”)。

这些语句都将返回一个文本字符串“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

注意区别;条件中变量名前面的 $ 符号已被省略。在括号之间插入什么词并不重要。BaSH 将始终将此语句视为正确,即使您使用的词以前从未与同一 shell 中的变量相关联。

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 条件的这些变化都有效,但返回相反的结果。

这些返回错误:

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

而且,当然这会返回一个语法错误(以及“假”的结果):

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

迷茫了吗?一开始就将其牢记在心可能非常具有挑战性,尤其是如果您习惯于其他更高级别的编程语言。

于 2020-09-06T18:49:14.867 回答