本周一直在学习bash并陷入困境。
#!/bin/sh
if [ false ]; then
echo "True"
else
echo "False"
fi
这将始终输出True,即使条件似乎另有说明。如果我删除括号[]
然后它可以工作,但我不明白为什么。
答案 0 :(得分:143)
您正在使用参数“false”运行[
(aka test
)命令,而不是运行命令false
。由于“false”是非空字符串,因此test
命令始终成功。要实际运行该命令,请删除[
命令。
if false; then
echo "True"
else
echo "False"
fi
答案 1 :(得分:27)
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"
所以:
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”。
请注意,'^^'区分大小写