为什么会出现以下输出True
?
#!/bin/sh
if [ false ]; then
echo "True"
else
echo "False"
fi
True
即使条件似乎另有说明,这也将始终输出。如果我删除括号[]
,那么它可以工作,但我不明白为什么。
为什么会出现以下输出True
?
#!/bin/sh
if [ false ]; then
echo "True"
else
echo "False"
fi
True
即使条件似乎另有说明,这也将始终输出。如果我删除括号[]
,那么它可以工作,但我不明白为什么。
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
该if
语句将命令作为参数(如&&
,||
等)。命令的整数结果代码被解释为布尔值 (0/null=true, 1/else=false)。
该test
语句将运算符和操作数作为参数,并返回格式与if
. test
语句的别名是[
,通常用于if
执行更复杂的比较。
true
and语句不执行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”)的内容,则将命令传递给您的if
or &&
etc. 语句,不带括号。对于复杂的比较,请使用带有适当运算符的括号。
是的,我知道在 Bash 中没有原生布尔类型这样的东西,而且从技术上讲,if
and [
andtrue
是“命令”而不是“语句”;这只是一个非常基本的功能性解释。
我发现我可以通过运行类似的东西来做一些基本的逻辑:
A=true
B=true
if ($A && $B); then
C=true
else
C=false
fi
echo $C
使用真/假消除了一些括号混乱...
#! /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
正如@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”之类的字符串视为“真”。
请注意,'^^' 不区分大小写
添加上下文以希望有助于在此主题上提供一些额外的清晰度。对于 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
迷茫了吗?一开始就将其牢记在心可能非常具有挑战性,尤其是如果您习惯于其他更高级别的编程语言。