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
。如果我删除方括号[]
,它就可以工作,但我不明白为什么。
您正在运行带有参数“false”的[
(也称为test
)命令,而不是运行false
命令。由于"false"是一个非空字符串,因此test
命令始终成功。要实际运行命令,请删除[
命令。
if false; then
echo "True"
else
echo "False"
fi
bash
没有布尔数据类型,因此没有代表 true 和 false 的关键字。if
语句仅检查您提供的命令是否成功或失败。test
命令接受一个表达式,并在表达式为 true 时成功;非空字符串是一个评估为真的表达式,就像大多数其他编程语言一样。false
是一个始终失败的命令。(类比地,true
是一个始终成功的命令。) - chepnerif [[ false ]];
返回值也是true。if [[ 0 ]];
同样也是true。而 if [[ /usr/bin/false ]];
也不会跳过代码块。为什么false或0会被解释成非零的值呢?这真是让人沮丧。如果有关系的话,我的操作系统是OS X 10.8,Bash版本是3。 - jwwfalse
错误地视为布尔常量,也不要将 0
视为整数字面值;它们都只是普通的字符串。对于任何不以连字符开头的字符串 x
,[[ x ]]
等同于 [[ -n x ]]
。在任何情况下,bash
都没有任何布尔常量。看起来像整数的字符串会在 (( ... ))
中或在 [[ ... ]]
中使用 -eq
或 -lt
运算符时被视为整数处理。 - chepnerfalse
是一个命令,无条件地产生退出状态1。 - chepnerif
语句将命令作为参数(&&
, ||
等也是如此)。命令的整数结果代码被解释为布尔值(0/空=true,1/其他=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)
简而言之,如果你只想对某个东西进行测试,看它是否通过或失败(即“真”或“假”),那么在if
或&&
等语句中传递一个命令,不需要使用括号。对于复杂的比较,使用带有适当运算符的括号。
是的,我知道在Bash中没有本地布尔类型,而if
和[
和true
在技术上是“命令”,而不是“语句”;这只是一个非常基本的、功能性的解释。
if (( $x )); then echo "Hello"; fi
会在 x=1
的情况下输出消息,但是在 x=0
或 x=
(未定义)的情况下不会输出。 - Jonathan HA=true
B=true
if ($A && $B); then
C=true
else
C=false
fi
echo $C
( $A && $B )
是一个效率令人惊讶的操作--您将通过调用 fork()
来产生子进程,然后将 $A
的内容字符串分割为元素列表(在这种情况下大小为一),并评估每个元素作为通配符表达式(在这种情况下是一个表达自身的通配符表达式),然后运行结果作为命令(在这种情况下是一个内置命令)。 - Charles DuffyA=1; B=1
和 if (( A && B ))
进行数字处理,或者使用 [[ $A && $B ]]
,将空字符串视为假,非空字符串视为真,都比较安全。请注意,这里强调了“much, much safer”,即相对于其他方式更加安全。 - Charles Duffy使用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
[[ "$0" =~ "bash" ]]
使脚本对我起作用。 - WiringHarness正如@tripleee所指出的,这充其量只是相关的。
不过,万一你像我一样搜索到了这种内容,这里是我的解决方案。
为了处理用户可访问的配置文件,我使用这个函数:
function isTrue() {
if [[ "${@^^}" =~ ^(TRUE|OUI|Y|O$|ON$|[1-9]) ]]; then return 0;fi
return 1
}
这可以像这样使用
if isTrue "$whatever"; then..
"${@^^}"
和参数 "$whatever"
。 - tripleee为了提供更多的清晰度,下面是一些相关的背景信息。对于一个新手来说,BaSH中的真/假语句可能会感到有些奇怪。看以下简单例子及其结果。
这个语句将返回"true":
foo=" "; if [ "$foo" ]; then echo "true"; else echo "false"; fi
foo=" "; if [ $foo ]; then echo "true"; else echo "false"; fi
你看明白了吗?第一个例子有一个带引号的 "" 字符串,这会导致 BaSH 字面上处理它。因此,从字面意义上讲,空格不是 null。而在非字面意义上(如上述第二个例子),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
if [ sooperduper ]; then echo "true"; else echo "false"; fi
if [ $sooperduper ]; then echo "true"; else echo "false"; fi
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
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
你感到困惑了吗?对于初学者来说,将其弄清楚可能会相当具有挑战性,特别是如果你已经习惯了其他更高级的编程语言。
#!/bin/sh
开头的脚本不是 Bash 脚本,而是 POSIX sh 脚本。即使你的系统上提供的 POSIX sh 解释器是由 Bash 提供的,它也会关闭一些扩展功能。如果你想编写 Bash 脚本,请使用#!/bin/bash
或其适用于本地环境的等效命令(例如使用#!/usr/bin/env bash
选择 PATH 中的第一个 Bash 解释器)。 - Charles Duffy[[ false ]]
。 - CMCDragonkai