我尝试在shell脚本中使用以下语法声明一个布尔变量:

variable=$false

variable=$true

这对吗?另外,如果我想更新这个变量,我会使用相同的语法吗?最后,下面使用布尔变量作为表达式的语法正确吗?

if [ $variable ]

if [ !$variable ]

当前回答

POSIX(便携式操作系统接口)

我忽略了关键的一点,那就是便携性。这就是为什么我的头文件本身有POSIX。

基本上,所有投票的答案都是正确的,除了它们太特定于bash之外。

基本上,我只想添加更多关于可移植性的信息。


像["$var" = true]中的[和]括号是不必要的,你可以省略它们,直接使用test命令: test "$var" = true && yourCodeIfTrue || yourCodeIfFalse 重要提示:我不再推荐这种方法,因为它正在慢慢被弃用,而且组合多个语句更加困难。 想象一下这些单词true和false对shell意味着什么,自己测试一下: Echo $((true)) 0 Echo $((false)) 1 但是使用引号: Echo $(("true")) Bash: "true":语法错误:操作数预期(错误令牌是"true") Sh(破折号):Sh: 1:算术表达式:期望主:""true"" 这同样适用于: Echo $(("false")) shell只能解释一个字符串。我希望你的想法是多么好的使用适当的关键字没有引号。 但在之前的回答中没有人这么说。 这是什么意思?嗯,有几件事。 你应该习惯布尔关键字实际上被视为数字,即true = 0和false = 1,记住所有非零值都被视为false。 因为它们被视为数字,你也应该这样对待它们,即如果你定义变量说: var_bool = true 回声“var_bool美元” 真正的 你可以用以下方法创建它的相反值: Var_bool =$((1 - $ Var_bool)) #与$((!美元var_bool)) 回声“var_bool美元” 1 正如您自己所看到的,shell在您第一次使用它时确实打印了true字符串,但从那以后,它都分别通过数字0表示true或1表示false来工作。


最后,你应该如何处理所有这些信息

首先,一个好习惯是赋值0而不是true;1而不是false。 第二个好习惯是测试变量是否等于0: If ["$var_bool" -eq 0];然后 yourCodeIfTrue 其他的 yourCodeIfFalse fi

其他回答

这里似乎有一些关于Bash内置true的误解,更具体地说,关于Bash如何展开和解释括号内的表达式的误解。

miku回答中的代码与Bash内置的true,或/bin/true,或任何其他类型的true命令完全无关。在这种情况下,true只不过是一个简单的字符串,并且没有调用true命令/内置,无论是通过变量赋值,还是通过条件表达式求值。

下面的代码在功能上与miku回答中的代码相同:

the_world_is_flat=yeah
if [ "$the_world_is_flat" = yeah ]; then
    echo 'Be careful not to fall off!'
fi

唯一不同的是,这里比较的四个字符是'y'、'e'、'a'和'h',而不是't'、'r'、'u'和'e'。就是这样。在Bash解析令牌true时,没有尝试调用名为yeah的命令或内置命令,(在miku的例子中)也没有任何特殊处理。它只是一个字符串,一个完全任意的字符串。

更新(2014-02-19):在看了miku回答中的链接后,现在我知道困惑来自哪里了。Miku的回答使用了单括号,但他链接的代码片段没有使用括号。它只是:

the_world_is_flat=true
if $the_world_is_flat; then
  echo 'Be careful not to fall off!'
fi

这两个代码段将以相同的方式运行,但括号完全改变了底层的内容。

以下是Bash在每种情况下所做的事情:

没有括号:

将变量$the_world_is_flat展开为字符串“true”。 尝试将字符串“true”解析为命令。 找到并运行true命令(内置或/bin/true,取决于Bash版本)。 比较true命令的退出码(总是0)和0。回想一下,在大多数shell中,退出码为0表示成功,其他任何退出码都表示失败。 因为退出代码是0 (success),所以执行if语句的then子句

括号:

将变量$the_world_is_flat展开为字符串“true”。 解析现在完全展开的条件表达式,其形式为string1 = string2。=操作符是bash的字符串比较操作符。所以… 对"true"和"true"进行字符串比较。 是的,这两个字符串是一样的,所以条件的值为真。 执行if语句的then子句。

不带括号的代码可以工作,因为true命令返回一个退出代码0,表示成功。括号内的代码可以工作,因为$the_world_is_flat的值与=右边的字符串字面量true相同。

为了说明这一点,请考虑以下两段代码:

这段代码(如果以root权限运行)将重启您的计算机:

var=reboot
if $var; then
  echo 'Muahahaha! You are going down!'
fi

这段代码只是打印出“Nice try”。没有调用reboot命令。

var=reboot
if [ $var ]; then
  echo 'Nice try.'
fi

更新(2014-04-14)回答评论中关于=和==的区别的问题:AFAIK,没有区别。==操作符是特定于bash的=的同义词,据我所知,它们在所有上下文中的工作方式完全相同。

但是请注意,我特别讨论的是[]或[[]]测试中使用的=和==字符串比较运算符。我并不是说=和==在bash中到处都可以互换。

例如,你显然不能用==来做变量赋值,比如var=="foo"(技术上你可以这样做,但var的值将是"=foo",因为Bash在这里没有看到==运算符,它看到的是=(赋值)运算符,后面跟着字面值="foo",这就变成了"=foo")。

此外,虽然=和==是可互换的,但您应该记住,这些测试的工作方式取决于您是否在[]或[[]]中使用它,以及操作数是否被引用。您可以在高级Bash脚本指南:7.3其他比较操作符(向下滚动到=和==的讨论)中阅读更多相关内容。

下面是一个适合我的简单例子:

temp1=true
temp2=false

if [ "$temp1" = true ] || [ "$temp2" = true ]
then
    echo "Do something." 
else
    echo "Do something else."
fi

使用布尔值的另一种方法是测试值是否为空。这样做的好处是可以进行更短的测试:

first=1  # A true value
second=   # A false value

[ -n "$first" ]  && echo 'First var is true'
[ -z "$first" ]  && echo 'First var is false'
[ -n "$second" ] && echo 'Second var is true'
[ -z "$second" ] && echo 'Second var is false'

输出:

First var is true
Second var is false

下面是bash的另一个测试语法:[[-n $one]]

关于语法,这是一个简单的方法,我使用(通过例子)来一致和理智地管理布尔逻辑:

# Tests
var=
var=''
var=""
var=0
var=1
var="abc"
var=abc

if [[ -n "${var}" ]] ; then
    echo 'true'
fi
if [[ -z "${var}" ]] ; then
    echo 'false'
fi

# Results
# var=        # false
# var=''      # false
# var=""      # false
# var=0       # true
# var=1       # true
# var="abc"   # true
# var=abc     # true

如果变量从未被声明,答案是:# false

因此,将变量设置为true(使用这种语法方法)的简单方法是,var=1;相反,var = "。

参考:

如果var字符串的长度非零,则-n = True。

如果var字符串的长度为零,则-z = True。

博士TL;

my_bool=true

if [ "$my_bool" = true ]

未来音乐(最初)的回答有问题

我不推荐公认的答案。它的语法很漂亮,但也有一些缺陷。

假设我们有以下条件。

if $var; then
  echo 'Muahahaha!'
fi

在以下情况2中,此条件将计算为true并执行嵌套命令。

# Variable var not defined beforehand. Case 1
var=''  # Equivalent to var="".      # Case 2
var=                                 # Case 3
unset var                            # Case 4
var='<some valid command>'           # Case 5

通常,当你的“布尔”变量var显式设置为true时,你只希望你的条件值为true。其他所有的案例都是危险的误导!

最后一种情况(#5)特别淘气,因为它将执行变量中包含的命令(这就是为什么对于有效的command3,4,条件的计算结果为true)。

这里有一个无害的例子:

var='echo this text will be displayed when the condition is evaluated'
if $var; then
  echo 'Muahahaha!'
fi

# Outputs:
# this text will be displayed when the condition is evaluated
# Muahahaha!

引用你的变量是更安全的,例如,if "$var";然后。在上述情况下,您应该得到一个警告,表示没有找到该命令。但我们仍然可以做得更好(见下面我的建议)。

也可以看看Mike Holt对Miku最初答案的解释。

赫巴的回答有问题

这种方法也有意想不到的行为。

var=false
if [ $var ]; then
  echo "This won't print, var is false!"
fi

# Outputs:
# This won't print, var is false!

您可能期望上述条件的值为false,因此永远不会执行嵌套语句。惊喜!

引用值("false"),引用变量("$var"),或者使用test或[[而不是[,都没有区别。

我的建议是:

以下是我建议你检查“布尔值”的方法。他们按照预期工作。

my_bool=true

if [ "$my_bool" = true ]; then
if [ "$my_bool" = "true" ]; then

if [[ "$my_bool" = true ]]; then
if [[ "$my_bool" = "true" ]]; then
if [[ "$my_bool" == true ]]; then
if [[ "$my_bool" == "true" ]]; then

if test "$my_bool" = true; then
if test "$my_bool" = "true"; then

它们几乎都是一样的。与其他答案5中的方法相比,您将不得不输入更多的按键,但您的代码将更具防御性。


脚注

未来音乐的回答已被编辑,不再包含(已知的)缺陷。 这不是一个详尽的清单。 在此上下文中,有效命令是指存在的命令。命令使用正确或不正确并不重要。例如,man woman仍然被认为是一个有效的命令,即使没有这样的手册页存在。 对于无效的(不存在的)命令,Bash只会报错说没有找到该命令。 如果你关心长度,第一个建议是最短的。