如何在shell脚本中声明和使用布尔变量?

时间:2021-05-28 23:50:23

I tried to declare a boolean variable in a shell script using the following syntax:

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

variable=$false

variable=$true

Is this correct? Also, if I wanted to update that variable would I use the same syntax? Finally, is the following syntax for using boolean variables as expressions correct:

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

if [ $variable ]

if [ !$variable ]

15 个解决方案

#1


760  

Revised Answer (Feb 12, 2014)

修订答案(2014年2月12日)

the_world_is_flat=true
# ...do something interesting...
if [ "$the_world_is_flat" = true ] ; then
    echo 'Be careful not to fall off!'
fi

Original Answer

原来的答案

Caveats: https://*.com/a/21210966/89391

警告:https://*.com/a/21210966/89391

the_world_is_flat=true
# ...do something interesting...
if $the_world_is_flat ; then
    echo 'Be careful not to fall off!'
fi

From: Using boolean variables in Bash

From:在Bash中使用布尔变量。

The reason the original answer is included here is because the comments before the revision on Feb 12, 2014 pertain only to the original answer, and many of the comments are wrong when associated with the revised answer. For example, Dennis Williamson's comment about bash builtin true on Jun 2, 2010 only applies to the original answer, not the revised.

之所以将原始答案包含在这里,是因为在2014年2月12日修订之前的评论仅适用于最初的答案,而许多评论在与修改后的答案相关时是错误的。例如,Dennis Williamson在2010年6月2日对bash builtin的评论只适用于最初的答案,而不是修改过的。

#2


565  

TL;DR

bool=true

if [ "$bool" = true ]

Issues with Miku's (original) answer

I do not recommend the accepted answer1. Its syntax is pretty but it has some flaws.

我不推荐接受的答案。它的语法很漂亮,但也有一些缺点。

Say we have the following condition.

假设我们有以下条件。

if $var; then
  echo 'Muahahaha!'
fi

In the following cases2, this condition will evaluate to true and execute the nested command.

在下面的cases2中,该条件将评估为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

Typically you only want your condition to evaluate to true when your "boolean" variable, var in this example, is explicitly set to true. All the others cases are dangerously misleading!

通常,您只希望在“布尔”变量(这个例子中的var)被显式地设置为true时,您的条件才会被计算为true。所有其他的案例都是危险的误导!

The last case (#5) is especially naughty because it will execute the command contained in the variable (which is why the condition evaluates to true for valid commands3, 4).

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

Here is a harmless example:

这里有一个无害的例子:

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!

Quoting your variables is safer, e.g. if "$var"; then. In the above cases, you should get a warning that the command is not found. But we can still do better (see my recommendations at the bottom).

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

Also see Mike Holt's explanation of Miku's original answer.

还可以看到迈克·霍尔特对Miku最初答案的解释。

Issues with Hbar's answer

This approach also has unexpected behaviour.

这种方法也有出乎意料的行为。

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

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

You would expect the above condition to evaluate to false, thus never executing the nested statement. Surprise!

您将期望上述条件对false进行评估,因此不会执行嵌套语句。惊喜!

Quoting the value ("false"), quoting the variable ("$var"), or using test or [[ instead of [, do not make a difference.

引用这个值(“false”),引用变量(“$var”),或者使用test或[而不是[,不改变]。

What I DO recommend:

Here are ways I recommend you check your "booleans". They work as expected.

下面是我推荐你检查你的“布尔人”的方法。他们像预期的那样工作。

bool=true

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

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

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

They're all pretty much equivalent. You'll have to type a few more keystrokes than the approaches in the other answers5 but your code will be more defensive.

它们都是等价的。您将不得不键入一些比其他答案中的方法更多的击键,但是您的代码将更具防御性。


Footnotes

  1. Miku's answer has since been edited and no longer contains (known) flaws.
  2. 自那以后,Miku的答案被编辑,不再包含(已知)缺陷。
  3. Not an exhaustive list.
  4. 不是一个详尽的清单。
  5. A valid command in this context means a command that exists. It doesn't matter if the command is used correctly or incorrectly. E.g. man woman would still be considered a valid command, even if no such man page exists.
  6. 这个上下文中的有效命令意味着存在一个命令。命令是否正确使用并不重要。男人女人仍然被认为是一个有效的命令,即使没有这样的男人页面存在。
  7. For invalid (non-existent) commands, Bash will simply complain that the command wasn't found.
  8. 对于无效的(不存在的)命令,Bash只会抱怨没有找到命令。
  9. If you care about length, the first recommendation is the shortest.
  10. 如果你关心长度,第一个建议是最短的。

#3


90  

There seems to be some misunderstanding here about the bash builtin true, and more specifically, about how bash expands and interprets expressions inside brackets.

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

The code in miku's answer has absolutely nothing to do with the bash builtin true, nor /bin/true, nor any other flavor of the true command. In this case, true is nothing more than a simple character string, and no call to the true command/builtin is ever made, neither by the variable assignment, nor by the evaluation of the conditional expression.

在miku的答案中,代码与bash构建的true、或/bin/true、以及真正命令的任何其他味道完全无关。在这种情况下,true只不过是一个简单的字符串,并且没有调用真正的命令/构建,既不是由变量赋值,也不是由条件表达式的评估。

The following code is functionally identical to the code in the miku's answer:

以下代码在功能上与miku的答案中的代码相同:

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

The only difference here is that the four characters being compared are 'y', 'e', 'a', and 'h' instead of 't', 'r', 'u', and 'e'. That's it. There's no attempt made to call a command or builtin named yeah, nor is there (in miku's example) any sort of special handling going on when bash parses the token true. It's just a string, and a completely arbitrary one at that.

唯一的区别是,被比较的四个字符是y, e, a, h,而不是t, r, u, e。就是这样。没有尝试调用一个命令或内置的命令,也没有(在miku的例子中)在bash解析标记为真时进行任何类型的特殊处理。它只是一个弦,一个完全任意的弦。

Update (2/19/2014): After following the link in miku's answer, now I see where some of the confusion is coming from. Miku's answer uses single brackets, but the code snippet he links to does not use brackets. It's just:

更新(2/19/2014):继miku的答案后,现在我看到了一些困惑的来源。Miku的答案使用单个方括号,但是他链接的代码段不使用括号。它只是:

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

Both code snippets will behave the same way, but the brackets completely change what's going on under the hood.

这两个代码片段的行为都是相同的,但是括号完全改变了引擎盖下发生的事情。

Here's what bash is doing in each case:

下面是bash在每个案例中所做的:

No brackets:

没有括号:

  1. Expand the variable $the_world_is_flat to the string "true".
  2. 将变量$the_world_is_flat扩展为字符串“true”。
  3. Attempt to parse the string "true" as a command.
  4. 尝试将字符串“true”解析为命令。
  5. Find and run the true command (either a builtin or /bin/true, depending on bash version).
  6. 查找并运行真正的命令(根据bash版本,可以使用builtin或/bin/true)。
  7. Compare the exit code of the true command (which is always 0) with 0. Recall that in most shells, an exit code of 0 indicates success and anything else indicates failure.
  8. 比较真正的命令(始终为0)和0的退出代码。回想一下,在大多数shell中,一个0的退出代码表示成功,其他任何表示失败。
  9. Since the exit code was 0 (success), execute the if statement's then clause
  10. 因为退出代码是0(成功),所以执行if语句的then子句。

Brackets:

括号:

  1. Expand the variable $the_world_is_flat to the string "true".
  2. 将变量$the_world_is_flat扩展为字符串“true”。
  3. Parse the now-fully-expanded conditional expression, which is of the form string1 = string2. The = operator is bash's string comparison operator. So...
  4. 解析已扩展的条件表达式,它是string1 = string2的形式。操作符是bash的字符串比较运算符。所以…
  5. Do a string comparison on "true" and "true".
  6. 对“真”和“真”做一个字符串比较。
  7. Yep, the two strings were the same, so the value of the conditional is true.
  8. 是的,这两个字符串是一样的,所以条件的值是正确的。
  9. Execute the if statement's then clause.
  10. 执行if语句的then子句。

The no-brackets code works because the true command returns an exit code of 0, which indicates success. The bracketed code works because the value of $the_world_is_flat is identical to the string literal true on the right side of the =.

无括号代码起作用,因为真正的命令返回0的退出代码,这表示成功。括号中的代码是有效的,因为$the_world_is_flat的值与=的右边的字符串字面上相同。

Just to drive the point home, consider the following two snippets of code:

为了让这个观点更有意义,请考虑以下两段代码:

This code (if run with root privs) will reboot your computer:

此代码(如果使用root privs运行)将重新启动计算机:

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

This code just prints "Nice try." The reboot command is not called.

这段代码只是打印了“不错的尝试”。不调用重新启动命令。

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

Update (4/14/2014) To answer the question in the comments regarding the difference between = and ==: AFAIK, there is no difference. The == operator is a bash-specific synonym for =, and as far as I've seen, they work exactly the same in all contexts. Note, however, that I'm specifically talking about the = and == string comparison operators used in either [ ] or [[ ]] tests. I'm not suggesting that = and == are interchangeable everywhere in bash. For example, you obviously can't do variable assignment with ==, such as var=="foo" (well technically you can do this, but the value of var will be "=foo", because bash isn't seeing an == operator here, it's seeing an = (assignment) operator, followed by the literal value ="foo", which just becomes "=foo").

更新(4/14/2014)在评论中回答关于=和==:AFAIK的区别,没有区别。==操作符是=的bash特定的同义词,就我所见,它们在所有上下文中都是完全相同的。但是,请注意,我特别讨论了在[]或[[]]测试中使用的=和==字符串比较运算符。我不是说在bash中,=和==是可互换的。例如,您显然不能与= =变量赋值,如var = =“foo”(技术上可以做到这一点,但价值var = foo”,因为bash不是看到一个= =操作符,它看到一个=(作业)算子,紧随其后的是文字值=“foo”,这就变成了“= foo”)。

Also, although = and == are interchangeable, you should keep in mind that how those tests work does depend on whether you're using it inside [ ] or [[ ]], and also on whether or not the operands are quoted. You can read more about that here: Advanced Bash Scripting Guide: 7.3 Other Comparison Operators (scroll down to the discussion of = and ==).

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

#4


39  

Use arithmetic expressions.

使用算术表达式。

#!/bin/bash

false=0
true=1

((false)) && echo false
((true)) && echo true
((!false)) && echo not false
((!true)) && echo not true

Output:

输出:

true
not false

真的不是假的

#5


14  

Long ago, when all we had was sh, booleans where handled by relying on a convention of the test program where test returns a false exit status if run with no arguments. This allows one to think of a variable that is unset as false and variable set to any value as true. Today, test is builtin to bash and is commonly known by its one character alias [ (or an executable to use in shells lacking it, as dolmen notes):

很久以前,当我们只有sh的时候,布尔值通过一个测试程序的约定来处理,测试程序在没有参数的情况下返回一个错误的退出状态。这使人能够想到一个不设为false的变量,并将变量设置为true。今天,测试是在bash中构建的,通常以其一个字符别名[(或一个可执行程序在缺少它的shell中使用,就像dolmen所指出的那样):

FLAG="up or <set>"

if [ "$FLAG" ] ; then 
    echo 'Is true'
else 
    echo 'Is false'
fi

# unset FLAG
#    also works
FLAG=

if [ "$FLAG" ] ; then
    echo 'Continues true'
else
    echo 'Turned false'
fi

Because of quoting conventions, script writers prefer to use the compound command [[ that mimics test but has nicer syntax: variables with spaces do not need to be quoted, one can use && and || as logical operators with weird precedence, and there are no POSIX limitations on the number of terms.

因为引用公约,脚本作家喜欢用复合命令[[模拟测试,但有更好的语法:不需要引用变量与空间,一个可以使用& &和| |与奇怪的逻辑运算符的优先级,并且没有POSIX限制条款的数量。

For example, to determine if FLAG is set and COUNT is a number greater than 1:

例如,要确定是否设置了标志并计数是大于1的数字:

FLAG="u p"
COUNT=3

if [[ $FLAG  && $COUNT -gt '1' ]] ; then 
    echo 'Flag up, count bigger than 1'
else 
    echo 'Nope'
fi

This stuff can get confusing when spaces, zero length strings, and null variables are all needed and also when your script needs to work with several shells.

当空格、零长度字符串和空变量都是必需的,以及脚本需要使用多个shell时,这些内容可能会变得混乱。

#6


10  

How to declare and use boolean variables in shell script?

如何在shell脚本中声明和使用布尔变量?

Unlike many other programming languages, Bash does not segregate its variables by "type." [1]

与许多其他编程语言不同,Bash不会通过“类型”来隔离变量。[1]

So the answer is pretty clear. There is no boolean variable in bash. However :

答案很清楚。bash中没有布尔变量。然而:

Using a declare statement, we can limit the value assignment to variables.[2]

使用声明语句,我们可以将值赋值限制为变量。[2]

#!/bin/bash
declare -ir BOOL=(0 1) #remember BOOL can't be unset till this shell terminate
readonly false=${BOOL[0]}
readonly true=${BOOL[1]}
#same as declare -ir false=0 true=1
((true)) && echo "True"
((false)) && echo "False"
((!true)) && echo "Not True"
((!false)) && echo "Not false"

The r option in declare and readonly is used to state explicitly that the variables are readonly. Hope the purpose is clear.

声明和readonly中的r选项用于显式地声明变量是只读的。希望目标明确。

#7


5  

Instead of faking a boolean and leaving a trap for future readers, why not just use a better value than true and false?

与其伪造一个布尔值,给未来的读者留下一个陷阱,为什么不使用一个比true和false更好的值呢?

For example:

例如:

build_state=success
if something-horrible; then
  build_state=failed
fi

if [[ "$build_state" == success ]]; then
  echo go home, you are done
else
  echo your head is on fire, run around in circles
fi

#8


5  

Long story short:

长话短说:

Thee are no booleans in bash

What bash does have, is boolean expressions in terms of comparison and conditions. That said, what you can declare and compare in bash are strings and numbers. That's it.

bash所拥有的,是在比较和条件下的布尔表达式。这就是说,在bash中可以声明和比较的是字符串和数字。就是这样。

Wherever you see true or false in bash, it's either a string or a command/builtin which is only used for its exit code.

无论您在bash中看到true或false,它都是仅用于其退出代码的string或command/builtin。

This syntax...

这语法…

if true; then ...

is essentially...

本质上是…

if COMMAND; then ...

The condition is true whenever the command returns exit code 0.

当命令返回退出码0时,条件为真。

You could just as well do this:

你也可以这样做:

if which foo; then echo "program foo found"; fi

When using square brackets or the test command, you rely on the exit code of that construct. Keep in mind that [ ] and [[ ]] are also just commands/builtins like any other. So ...

当使用方括号或测试命令时,您依赖于该构造的退出代码。请记住,[]和[[]]也仅仅是命令/构建。所以…

if [[ 1 == 1 ]]; then echo yes; fi

is just syntactic sugar for ...

只是……

[[ 1 == 1 ]] && echo yes

So when using true and false in any of the aforementioned constructs you are actually only passing the string "true" or "false" to the testing command. Here an example:

因此,当在上述结构中使用true和false时,实际上只是将字符串“true”或“false”传递给测试命令。下面一个例子:

Believe it or not but those conditions are all yielding the same result:

信不信由你,但这些条件都产生了同样的结果:

if [[ false ]]; then ...
if [[ "false" ]]; then ...
if [[ true ]]; then ...
if [[ "true" ]]; then ...

TL;DR; always compare against strings or numbers

To make this clear to future readers, I would recommend always using quotes around true and false:

为了让未来的读者明白这一点,我建议总是用引号来描述真和假:

DO

if [[ "${var}" == "true" ]]; then ...
if [[ "${var}" == "false" ]]; then ...
if [[ -n "${var:-}" ]]; then echo "var is not empty" ...

DON'T

if [ ... ]; then ...  # always use double square brackets in bash!
if [[ "${var}" ]]; then ...  # this is not as clear or searchable as -n
if [[ "${var}" != true ]]; then ...  # creates impression of booleans
if [[ "${var}" -eq "true" ]]; then ...  # `-eq` is for numbers and doesn't read as easy as `==`

Maybe

if [[ "${var}" != "true" ]]; then ...  # creates impression of booleans. Can be used for strict checking of dangerous operations. This condition is false for anything but the literal string "true". 

#9


2  

POSIX (Portable Operating System Interface)

I miss here the key point, which is portability. That's why my header has POSIX in itself.

我很怀念这里的关键点,那就是可移植性。这就是为什么我的头本身有POSIX。

Essentially, all of the voted answers are correct, with the exception they are BASH-specific too much.

从本质上讲,所有投票的答案都是正确的,但例外的是,它们的具体内容太多了。

So basically, I only wish to add more information about portability.

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


  1. [ and ] brackets like in [ "$var" = true ] are not necessary, and you can omit them and use the test command directly:

    [和]像["$var" = true]这样的括号是不必要的,您可以省略它们并直接使用测试命令:

    test "$var" = true && CodeIfTrue || CodeIfFalse
    
  2. Imagine what those words true and false mean to the shell, test it yourself:

    想象一下这些单词对shell的真实和错误的含义,你自己测试一下:

    echo $((true))
    
    0
    
    echo $((false))
    
    1
    

    But using quotes:

    但使用引号:

    echo $(("true"))
    
    bash: "true": syntax error: operand expected (error token is ""true"")
    sh (dash): sh: 1: arithmetic expression: expecting primary: ""true""
    

    The same goes for:

    这同样适用于:

    echo $(("false"))
    

    The shell can't interpret it other than a string. I hope you are getting the idea of how good is using proper keyword without quotes.

    除了一个字符串外,shell不能解释它。我希望你能明白使用恰当的关键字没有引号。

    But no one said it in previous answers.

    但是没有人在之前的回答中说过。

  3. What this means? Well, several things.

    这意味着什么吗?嗯,几件事情。

    • You should get used to the Boolean keywords are actually treated like numbers, that is true = 0 and false = 1, remember all non-zero values are treated like false.

      你应该习惯布尔的关键字被当作数字处理,这是真的= 0和false = 1,记住所有的非零值都是假的。

    • Since they are treated like numbers, you should treat them like that too, i.e. if you define variable say:

      因为他们被当作数字对待,你也应该这样对待他们,也就是说,如果你定义了变量:

      var_a=true
      echo "$var_a"
      
       true
      

      you can create an opposite value of it with:

      你可以用以下方法创造一个相反的值:

      var_a=$((1 - $var_a))
      echo "$var_a"
      
      1
      

      As you can see for yourself, shell does print true string for the first time you use it, but since then, it all works via number 0 or 1, respectively.

      正如您自己所看到的,shell在您第一次使用它时确实会打印出真正的字符串,但是从那以后,它将分别通过数字0或1进行工作。


Finally, what you should do with all that information

  • First good habit would be assigning 0 instead of true; 1 instead of false.

    第一个好习惯是分配0而不是true;1而不是假的。

  • Second good habit would be to test if the variable is / isn't equal to zero:

    第二个好习惯是测试变量是否等于零:

    test "$var" -eq 0 && CodeIfTrue || CodeIfFalse
    

#10


1  

Bill Parker is getting voted down because his definitions are reversed from normal code convention. Normally, true is defined as 0 and false is defined as nonzero. 1 will work for false, as will 9999 and -1. Same with function return values - 0 is success and anything nonzero is failure. Sorry I don't have the street creds yet to vote or to reply to him directly.

比尔·帕克被投票否决了,因为他的定义与正常的代码惯例相反。通常,true被定义为0,而false被定义为非零。1将为false工作,如9999和-1。与函数返回值相同——0是成功,任何非零都是失败。很抱歉,我还没有投票或者直接回复他。

Bash recommends using double brackets now as a habit instead of single brackets, and the link Mike Holt gave explains the differences in how they work. 7.3. Other Comparison Operators

Bash建议现在使用双括号作为习惯,而不是单一的括号,而Mike Holt给出的链接解释了他们工作方式的不同。7.3。其他比较运算符

For one thing -eq is a numerical operator, so having the code

首先,eq是一个数字运算符,所以有了代码。

#**** NOTE *** This gives error message *****
The_world_is_flat=0;
if [ "${The_world_is_flat}" -eq true ]; then

will issue an error statement, expecting an integer expression. This applies to either parameter, as neither is an integer value. Yet, if we put double brackets around it, it will not issue an error statement, but will yield a wrong value (well, in 50% of the possible permutations). It will evaluate to [[0 -eq true]] = success but also to [[0 -eq false]] = success, which is wrong (hmmm.... what about that builtin being a numerical value?).

将发出一个错误语句,期望一个整数表达式。这对任何一个参数都适用,因为它们都不是整数值。但是,如果我们在它周围加上一个双括号,它就不会发出错误语句,但是会产生一个错误的值(好吧,在可能的排列的50%中)。它将评估[[0情商真的]]=成功,但也[[0 eq假]]=成功,这是错误的(嗯....那建物是一个数值呢?

#**** NOTE *** This gives wrong output *****
The_world_is_flat=true;
if [[ "${The_world_is_flat}" -eq true ]]; then

There are other permutations of the conditional which will give wrong output as well. Basically, anything (other than the error condition listed above) that sets a variable to a numerical value and compares it to a true/false builtin, or sets a variable to a true/false builtin and compares it to a numerical value. Also, anything that sets a variable to a true/false builtin and does a comparison using -eq. So avoid -eq for boolean comparisons and avoid using numerical values for boolean comparisons. Here's a summary of the permutations that will give invalid results:

有条件的其他排列也会产生错误的输出。基本上,任何东西(除了上面列出的错误条件)都将变量设置为数值,并将其与true/false builtin进行比较,或者将一个变量设置为true/false builtin,并将其与数值进行比较。此外,任何将变量设置为true/false builtin并使用-eq进行比较的任何操作。因此,避免使用-eq进行布尔比较,避免使用数字值进行布尔比较。下面是对可能导致无效结果的排列的总结:

#With variable set as an integer and evaluating to true/false
#*** This will issue error warning and not run: *****
The_world_is_flat=0;
if [ "${The_world_is_flat}" -eq true ]; then

#With variable set as an integer and evaluating to true/false
#*** These statements will not evaluate properly: *****
The_world_is_flat=0;
if [ "${The_world_is_flat}" -eq true ]; then
#
if [[ "${The_world_is_flat}" -eq true ]]; then
#
if [ "${The_world_is_flat}" = true ]; then
#
if [[ "${The_world_is_flat}" = true ]]; then
#
if [ "${The_world_is_flat}" == true ]; then
#
if [[ "${The_world_is_flat}" == true ]]; then


#With variable set as an true/false builtin and evaluating to true/false
#*** These statements will not evaluate properly: *****
The_world_is_flat=true;
if [[ "${The_world_is_flat}" -eq true ]]; then
#
if [ "${The_world_is_flat}" = 0 ]; then
#
if [[ "${The_world_is_flat}" = 0 ]]; then
#
if [ "${The_world_is_flat}" == 0 ]; then
#
if [[ "${The_world_is_flat}" == 0 ]]; then

So, now to what works. Use true/false builtins for both your comparison and your evaluations (as Mike Hunt noted, don't enclose them in quotes). Then use either or single or double equal sign (= or ==) and either single or double brackets ([ ] or [[ ]]). Personally, I like the double equals sign because it reminds me of logical comparisons in other programming languages, and double quotes just because I like typing. So these work:

那么,现在来看看什么管用。对你的比较和评价使用真/假的建筑(正如迈克·亨特指出的,不要用引号括起来)。然后使用任一或单或双等号(=或=),或单或双方括号([]或[[]])。就个人而言,我喜欢双等号,因为它让我想起了其他编程语言的逻辑比较,而双引号只是因为我喜欢打字。所以这些工作:

#With variable set as an integer and evaluating to true/false
#*** These statements will work properly: *****
#
The_world_is_flat=true/false;
if [ "${The_world_is_flat}" = true ]; then
#
if [[ "${The_world_is_flat}" = true ]]; then
#
if [ "${The_world_is_flat}" = true ]; then
#
if [[ "${The_world_is_flat}" == true ]]; then

There you have it.

你拥有它。

#11


1  

I found the existing answers confusing.

我发现现有的答案令人困惑。

Personally, I just want to have something which looks and works like C.

就我个人而言,我只是想要一些看起来像C的东西。

This snippet works many times a day in production:

这段代码在生产中每天工作很多次:

snapshotEvents=true

if ($snapshotEvents)
then
    # do stuff if true
fi

and to keep everyone happy, I tested:

为了让大家开心,我测试了一下:

snapshotEvents=false

if !($snapshotEvents)
then
    # do stuff if false
fi

Which also worked fine.

也工作得很好。

The $snapshotEvents evaluates the contents of value of the variable. So you need the $.

$snapshotEvents评估变量的值。所以你需要美元。

You don't really need the parentheses, I just find them helpful.

你不需要括号,我只是觉得它们很有用。

  • Tested on: GNU Bash, version 4.1.11(2)-release

    测试:GNU Bash,版本4.1.11(2)-发布。

  • Bash Guide for Beginners, Machtelt Garrels, v1.11, 2008

    《初学者的Bash指南》,Machtelt Garrels, v1.11, 2008。

#12


1  

Here is an implementation of a short handed if true.

如果是真的,这是一个短传的实现。

# Function to test if a variable is set to "true"
_if () {
    [ "${1}" == "true" ] && return 0
    [ "${1}" == "True" ] && return 0
    [ "${1}" == "Yes" ] && return 0
    return 1
}

Example 1

示例1

my_boolean=true

_if ${my_boolean} && {
    echo "True Is True"
} || {
    echo "False Is False"
}

Example 2

示例2

my_boolean=false
! _if ${my_boolean} && echo "Not True is True"

#13


0  

Here is a simple example which works for me:

下面是一个简单的例子:

temp1=true
temp2=false

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

#14


-1  

Here is an improvement on miku's original answer, that addresses Dennis Williamson's concerns about the case, where the variable is not set:

这是对miku的原始答案的改进,这是丹尼斯·威廉姆森对这个案例的担忧,在这个案例中,变量没有设置:

the_world_is_flat=true

if ${the_world_is_flat:-false} ; then
    echo "Be careful not to fall off!"
fi

And to test if the variable is false:

测试变量是否为假:

if ! ${the_world_is_flat:-false} ; then
    echo "Be careful not to fall off!"
fi

About other cases with a nasty content in the variable, this is a problem with any external input fed to a program.

对于变量中含有恶意内容的其他情况,这是任何输入到程序的外部输入的问题。

Any external input must be validated before trusting it. But that validation has to be done just once, when that input is received.

任何外部输入必须在信任它之前进行验证。但是在接收到输入时,必须只执行一次验证。

It doesn't have to impact the performance of the program by doing it on every use of the variable like Dennis Williamson suggests.

它不需要像丹尼斯·威廉姆森(Dennis Williamson)所建议的那样,在每次使用变量时都对程序的性能产生影响。

#15


-2  

BASH really confuses the issue with the likes of [, [[, ((, $((, etc.

BASH确实将这个问题与诸如[,[],(,$(,等等)之类的问题混淆了。

All treating on each others' code spaces. I guess this is mostly historical, where bash had to pretend to be sh occasionally.

对彼此的代码空间进行处理。我想这主要是历史上的,在这里,bash有时不得不假装是sh。

Most of the time, I can just pick a method and stick with it. In this instance, I tend to declare (preferably in a common library file I can include with . in my actual script(s)).

大多数时候,我可以选择一种方法并坚持下去。在此实例中,我倾向于声明(最好是在我可以包含的公共库文件中)。在我实际的脚本(s))。

TRUE=1; FALSE=0

I can then use the (( ... )) arithmetic operator to test thusly.

然后我可以使用(…)算术运算符来测试。

testvar=$FALSE

if [[ -d ${does_directory_exist} ]]
then
    testvar=$TRUE;
fi

if (( testvar == TRUE )); then
    # do stuff because the directory does exist
fi
  1. You do have to be disciplined, your testvar must either be set to $TRUE or $FALSE at all times.

    你必须要有纪律,你的testvar必须在任何时候被设置为$TRUE或$FALSE。

  2. In (( ... )) comparators, you don't need the preceding $, which makes it more readable.

    在(…)比较器中,您不需要前面的$,这使它更容易读。

  3. I can use (( ... )) because $TRUE=1 and $FALSE=0, i.e. numeric values.

    我可以使用((…))因为$TRUE=1和$FALSE=0,即数值。

  4. The downside is having to use a $ occasionally:

    缺点是不得不偶尔使用一美元:

    testvar=$TRUE
    

    which is not so pretty.

    这不是很漂亮。

It's not a perfect solution, but it covers every case, I need of such a test.

这不是一个完美的解决方案,但它涵盖了所有的情况,我需要这样的测试。

#1


760  

Revised Answer (Feb 12, 2014)

修订答案(2014年2月12日)

the_world_is_flat=true
# ...do something interesting...
if [ "$the_world_is_flat" = true ] ; then
    echo 'Be careful not to fall off!'
fi

Original Answer

原来的答案

Caveats: https://*.com/a/21210966/89391

警告:https://*.com/a/21210966/89391

the_world_is_flat=true
# ...do something interesting...
if $the_world_is_flat ; then
    echo 'Be careful not to fall off!'
fi

From: Using boolean variables in Bash

From:在Bash中使用布尔变量。

The reason the original answer is included here is because the comments before the revision on Feb 12, 2014 pertain only to the original answer, and many of the comments are wrong when associated with the revised answer. For example, Dennis Williamson's comment about bash builtin true on Jun 2, 2010 only applies to the original answer, not the revised.

之所以将原始答案包含在这里,是因为在2014年2月12日修订之前的评论仅适用于最初的答案,而许多评论在与修改后的答案相关时是错误的。例如,Dennis Williamson在2010年6月2日对bash builtin的评论只适用于最初的答案,而不是修改过的。

#2


565  

TL;DR

bool=true

if [ "$bool" = true ]

Issues with Miku's (original) answer

I do not recommend the accepted answer1. Its syntax is pretty but it has some flaws.

我不推荐接受的答案。它的语法很漂亮,但也有一些缺点。

Say we have the following condition.

假设我们有以下条件。

if $var; then
  echo 'Muahahaha!'
fi

In the following cases2, this condition will evaluate to true and execute the nested command.

在下面的cases2中,该条件将评估为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

Typically you only want your condition to evaluate to true when your "boolean" variable, var in this example, is explicitly set to true. All the others cases are dangerously misleading!

通常,您只希望在“布尔”变量(这个例子中的var)被显式地设置为true时,您的条件才会被计算为true。所有其他的案例都是危险的误导!

The last case (#5) is especially naughty because it will execute the command contained in the variable (which is why the condition evaluates to true for valid commands3, 4).

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

Here is a harmless example:

这里有一个无害的例子:

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!

Quoting your variables is safer, e.g. if "$var"; then. In the above cases, you should get a warning that the command is not found. But we can still do better (see my recommendations at the bottom).

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

Also see Mike Holt's explanation of Miku's original answer.

还可以看到迈克·霍尔特对Miku最初答案的解释。

Issues with Hbar's answer

This approach also has unexpected behaviour.

这种方法也有出乎意料的行为。

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

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

You would expect the above condition to evaluate to false, thus never executing the nested statement. Surprise!

您将期望上述条件对false进行评估,因此不会执行嵌套语句。惊喜!

Quoting the value ("false"), quoting the variable ("$var"), or using test or [[ instead of [, do not make a difference.

引用这个值(“false”),引用变量(“$var”),或者使用test或[而不是[,不改变]。

What I DO recommend:

Here are ways I recommend you check your "booleans". They work as expected.

下面是我推荐你检查你的“布尔人”的方法。他们像预期的那样工作。

bool=true

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

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

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

They're all pretty much equivalent. You'll have to type a few more keystrokes than the approaches in the other answers5 but your code will be more defensive.

它们都是等价的。您将不得不键入一些比其他答案中的方法更多的击键,但是您的代码将更具防御性。


Footnotes

  1. Miku's answer has since been edited and no longer contains (known) flaws.
  2. 自那以后,Miku的答案被编辑,不再包含(已知)缺陷。
  3. Not an exhaustive list.
  4. 不是一个详尽的清单。
  5. A valid command in this context means a command that exists. It doesn't matter if the command is used correctly or incorrectly. E.g. man woman would still be considered a valid command, even if no such man page exists.
  6. 这个上下文中的有效命令意味着存在一个命令。命令是否正确使用并不重要。男人女人仍然被认为是一个有效的命令,即使没有这样的男人页面存在。
  7. For invalid (non-existent) commands, Bash will simply complain that the command wasn't found.
  8. 对于无效的(不存在的)命令,Bash只会抱怨没有找到命令。
  9. If you care about length, the first recommendation is the shortest.
  10. 如果你关心长度,第一个建议是最短的。

#3


90  

There seems to be some misunderstanding here about the bash builtin true, and more specifically, about how bash expands and interprets expressions inside brackets.

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

The code in miku's answer has absolutely nothing to do with the bash builtin true, nor /bin/true, nor any other flavor of the true command. In this case, true is nothing more than a simple character string, and no call to the true command/builtin is ever made, neither by the variable assignment, nor by the evaluation of the conditional expression.

在miku的答案中,代码与bash构建的true、或/bin/true、以及真正命令的任何其他味道完全无关。在这种情况下,true只不过是一个简单的字符串,并且没有调用真正的命令/构建,既不是由变量赋值,也不是由条件表达式的评估。

The following code is functionally identical to the code in the miku's answer:

以下代码在功能上与miku的答案中的代码相同:

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

The only difference here is that the four characters being compared are 'y', 'e', 'a', and 'h' instead of 't', 'r', 'u', and 'e'. That's it. There's no attempt made to call a command or builtin named yeah, nor is there (in miku's example) any sort of special handling going on when bash parses the token true. It's just a string, and a completely arbitrary one at that.

唯一的区别是,被比较的四个字符是y, e, a, h,而不是t, r, u, e。就是这样。没有尝试调用一个命令或内置的命令,也没有(在miku的例子中)在bash解析标记为真时进行任何类型的特殊处理。它只是一个弦,一个完全任意的弦。

Update (2/19/2014): After following the link in miku's answer, now I see where some of the confusion is coming from. Miku's answer uses single brackets, but the code snippet he links to does not use brackets. It's just:

更新(2/19/2014):继miku的答案后,现在我看到了一些困惑的来源。Miku的答案使用单个方括号,但是他链接的代码段不使用括号。它只是:

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

Both code snippets will behave the same way, but the brackets completely change what's going on under the hood.

这两个代码片段的行为都是相同的,但是括号完全改变了引擎盖下发生的事情。

Here's what bash is doing in each case:

下面是bash在每个案例中所做的:

No brackets:

没有括号:

  1. Expand the variable $the_world_is_flat to the string "true".
  2. 将变量$the_world_is_flat扩展为字符串“true”。
  3. Attempt to parse the string "true" as a command.
  4. 尝试将字符串“true”解析为命令。
  5. Find and run the true command (either a builtin or /bin/true, depending on bash version).
  6. 查找并运行真正的命令(根据bash版本,可以使用builtin或/bin/true)。
  7. Compare the exit code of the true command (which is always 0) with 0. Recall that in most shells, an exit code of 0 indicates success and anything else indicates failure.
  8. 比较真正的命令(始终为0)和0的退出代码。回想一下,在大多数shell中,一个0的退出代码表示成功,其他任何表示失败。
  9. Since the exit code was 0 (success), execute the if statement's then clause
  10. 因为退出代码是0(成功),所以执行if语句的then子句。

Brackets:

括号:

  1. Expand the variable $the_world_is_flat to the string "true".
  2. 将变量$the_world_is_flat扩展为字符串“true”。
  3. Parse the now-fully-expanded conditional expression, which is of the form string1 = string2. The = operator is bash's string comparison operator. So...
  4. 解析已扩展的条件表达式,它是string1 = string2的形式。操作符是bash的字符串比较运算符。所以…
  5. Do a string comparison on "true" and "true".
  6. 对“真”和“真”做一个字符串比较。
  7. Yep, the two strings were the same, so the value of the conditional is true.
  8. 是的,这两个字符串是一样的,所以条件的值是正确的。
  9. Execute the if statement's then clause.
  10. 执行if语句的then子句。

The no-brackets code works because the true command returns an exit code of 0, which indicates success. The bracketed code works because the value of $the_world_is_flat is identical to the string literal true on the right side of the =.

无括号代码起作用,因为真正的命令返回0的退出代码,这表示成功。括号中的代码是有效的,因为$the_world_is_flat的值与=的右边的字符串字面上相同。

Just to drive the point home, consider the following two snippets of code:

为了让这个观点更有意义,请考虑以下两段代码:

This code (if run with root privs) will reboot your computer:

此代码(如果使用root privs运行)将重新启动计算机:

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

This code just prints "Nice try." The reboot command is not called.

这段代码只是打印了“不错的尝试”。不调用重新启动命令。

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

Update (4/14/2014) To answer the question in the comments regarding the difference between = and ==: AFAIK, there is no difference. The == operator is a bash-specific synonym for =, and as far as I've seen, they work exactly the same in all contexts. Note, however, that I'm specifically talking about the = and == string comparison operators used in either [ ] or [[ ]] tests. I'm not suggesting that = and == are interchangeable everywhere in bash. For example, you obviously can't do variable assignment with ==, such as var=="foo" (well technically you can do this, but the value of var will be "=foo", because bash isn't seeing an == operator here, it's seeing an = (assignment) operator, followed by the literal value ="foo", which just becomes "=foo").

更新(4/14/2014)在评论中回答关于=和==:AFAIK的区别,没有区别。==操作符是=的bash特定的同义词,就我所见,它们在所有上下文中都是完全相同的。但是,请注意,我特别讨论了在[]或[[]]测试中使用的=和==字符串比较运算符。我不是说在bash中,=和==是可互换的。例如,您显然不能与= =变量赋值,如var = =“foo”(技术上可以做到这一点,但价值var = foo”,因为bash不是看到一个= =操作符,它看到一个=(作业)算子,紧随其后的是文字值=“foo”,这就变成了“= foo”)。

Also, although = and == are interchangeable, you should keep in mind that how those tests work does depend on whether you're using it inside [ ] or [[ ]], and also on whether or not the operands are quoted. You can read more about that here: Advanced Bash Scripting Guide: 7.3 Other Comparison Operators (scroll down to the discussion of = and ==).

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

#4


39  

Use arithmetic expressions.

使用算术表达式。

#!/bin/bash

false=0
true=1

((false)) && echo false
((true)) && echo true
((!false)) && echo not false
((!true)) && echo not true

Output:

输出:

true
not false

真的不是假的

#5


14  

Long ago, when all we had was sh, booleans where handled by relying on a convention of the test program where test returns a false exit status if run with no arguments. This allows one to think of a variable that is unset as false and variable set to any value as true. Today, test is builtin to bash and is commonly known by its one character alias [ (or an executable to use in shells lacking it, as dolmen notes):

很久以前,当我们只有sh的时候,布尔值通过一个测试程序的约定来处理,测试程序在没有参数的情况下返回一个错误的退出状态。这使人能够想到一个不设为false的变量,并将变量设置为true。今天,测试是在bash中构建的,通常以其一个字符别名[(或一个可执行程序在缺少它的shell中使用,就像dolmen所指出的那样):

FLAG="up or <set>"

if [ "$FLAG" ] ; then 
    echo 'Is true'
else 
    echo 'Is false'
fi

# unset FLAG
#    also works
FLAG=

if [ "$FLAG" ] ; then
    echo 'Continues true'
else
    echo 'Turned false'
fi

Because of quoting conventions, script writers prefer to use the compound command [[ that mimics test but has nicer syntax: variables with spaces do not need to be quoted, one can use && and || as logical operators with weird precedence, and there are no POSIX limitations on the number of terms.

因为引用公约,脚本作家喜欢用复合命令[[模拟测试,但有更好的语法:不需要引用变量与空间,一个可以使用& &和| |与奇怪的逻辑运算符的优先级,并且没有POSIX限制条款的数量。

For example, to determine if FLAG is set and COUNT is a number greater than 1:

例如,要确定是否设置了标志并计数是大于1的数字:

FLAG="u p"
COUNT=3

if [[ $FLAG  && $COUNT -gt '1' ]] ; then 
    echo 'Flag up, count bigger than 1'
else 
    echo 'Nope'
fi

This stuff can get confusing when spaces, zero length strings, and null variables are all needed and also when your script needs to work with several shells.

当空格、零长度字符串和空变量都是必需的,以及脚本需要使用多个shell时,这些内容可能会变得混乱。

#6


10  

How to declare and use boolean variables in shell script?

如何在shell脚本中声明和使用布尔变量?

Unlike many other programming languages, Bash does not segregate its variables by "type." [1]

与许多其他编程语言不同,Bash不会通过“类型”来隔离变量。[1]

So the answer is pretty clear. There is no boolean variable in bash. However :

答案很清楚。bash中没有布尔变量。然而:

Using a declare statement, we can limit the value assignment to variables.[2]

使用声明语句,我们可以将值赋值限制为变量。[2]

#!/bin/bash
declare -ir BOOL=(0 1) #remember BOOL can't be unset till this shell terminate
readonly false=${BOOL[0]}
readonly true=${BOOL[1]}
#same as declare -ir false=0 true=1
((true)) && echo "True"
((false)) && echo "False"
((!true)) && echo "Not True"
((!false)) && echo "Not false"

The r option in declare and readonly is used to state explicitly that the variables are readonly. Hope the purpose is clear.

声明和readonly中的r选项用于显式地声明变量是只读的。希望目标明确。

#7


5  

Instead of faking a boolean and leaving a trap for future readers, why not just use a better value than true and false?

与其伪造一个布尔值,给未来的读者留下一个陷阱,为什么不使用一个比true和false更好的值呢?

For example:

例如:

build_state=success
if something-horrible; then
  build_state=failed
fi

if [[ "$build_state" == success ]]; then
  echo go home, you are done
else
  echo your head is on fire, run around in circles
fi

#8


5  

Long story short:

长话短说:

Thee are no booleans in bash

What bash does have, is boolean expressions in terms of comparison and conditions. That said, what you can declare and compare in bash are strings and numbers. That's it.

bash所拥有的,是在比较和条件下的布尔表达式。这就是说,在bash中可以声明和比较的是字符串和数字。就是这样。

Wherever you see true or false in bash, it's either a string or a command/builtin which is only used for its exit code.

无论您在bash中看到true或false,它都是仅用于其退出代码的string或command/builtin。

This syntax...

这语法…

if true; then ...

is essentially...

本质上是…

if COMMAND; then ...

The condition is true whenever the command returns exit code 0.

当命令返回退出码0时,条件为真。

You could just as well do this:

你也可以这样做:

if which foo; then echo "program foo found"; fi

When using square brackets or the test command, you rely on the exit code of that construct. Keep in mind that [ ] and [[ ]] are also just commands/builtins like any other. So ...

当使用方括号或测试命令时,您依赖于该构造的退出代码。请记住,[]和[[]]也仅仅是命令/构建。所以…

if [[ 1 == 1 ]]; then echo yes; fi

is just syntactic sugar for ...

只是……

[[ 1 == 1 ]] && echo yes

So when using true and false in any of the aforementioned constructs you are actually only passing the string "true" or "false" to the testing command. Here an example:

因此,当在上述结构中使用true和false时,实际上只是将字符串“true”或“false”传递给测试命令。下面一个例子:

Believe it or not but those conditions are all yielding the same result:

信不信由你,但这些条件都产生了同样的结果:

if [[ false ]]; then ...
if [[ "false" ]]; then ...
if [[ true ]]; then ...
if [[ "true" ]]; then ...

TL;DR; always compare against strings or numbers

To make this clear to future readers, I would recommend always using quotes around true and false:

为了让未来的读者明白这一点,我建议总是用引号来描述真和假:

DO

if [[ "${var}" == "true" ]]; then ...
if [[ "${var}" == "false" ]]; then ...
if [[ -n "${var:-}" ]]; then echo "var is not empty" ...

DON'T

if [ ... ]; then ...  # always use double square brackets in bash!
if [[ "${var}" ]]; then ...  # this is not as clear or searchable as -n
if [[ "${var}" != true ]]; then ...  # creates impression of booleans
if [[ "${var}" -eq "true" ]]; then ...  # `-eq` is for numbers and doesn't read as easy as `==`

Maybe

if [[ "${var}" != "true" ]]; then ...  # creates impression of booleans. Can be used for strict checking of dangerous operations. This condition is false for anything but the literal string "true". 

#9


2  

POSIX (Portable Operating System Interface)

I miss here the key point, which is portability. That's why my header has POSIX in itself.

我很怀念这里的关键点,那就是可移植性。这就是为什么我的头本身有POSIX。

Essentially, all of the voted answers are correct, with the exception they are BASH-specific too much.

从本质上讲,所有投票的答案都是正确的,但例外的是,它们的具体内容太多了。

So basically, I only wish to add more information about portability.

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


  1. [ and ] brackets like in [ "$var" = true ] are not necessary, and you can omit them and use the test command directly:

    [和]像["$var" = true]这样的括号是不必要的,您可以省略它们并直接使用测试命令:

    test "$var" = true && CodeIfTrue || CodeIfFalse
    
  2. Imagine what those words true and false mean to the shell, test it yourself:

    想象一下这些单词对shell的真实和错误的含义,你自己测试一下:

    echo $((true))
    
    0
    
    echo $((false))
    
    1
    

    But using quotes:

    但使用引号:

    echo $(("true"))
    
    bash: "true": syntax error: operand expected (error token is ""true"")
    sh (dash): sh: 1: arithmetic expression: expecting primary: ""true""
    

    The same goes for:

    这同样适用于:

    echo $(("false"))
    

    The shell can't interpret it other than a string. I hope you are getting the idea of how good is using proper keyword without quotes.

    除了一个字符串外,shell不能解释它。我希望你能明白使用恰当的关键字没有引号。

    But no one said it in previous answers.

    但是没有人在之前的回答中说过。

  3. What this means? Well, several things.

    这意味着什么吗?嗯,几件事情。

    • You should get used to the Boolean keywords are actually treated like numbers, that is true = 0 and false = 1, remember all non-zero values are treated like false.

      你应该习惯布尔的关键字被当作数字处理,这是真的= 0和false = 1,记住所有的非零值都是假的。

    • Since they are treated like numbers, you should treat them like that too, i.e. if you define variable say:

      因为他们被当作数字对待,你也应该这样对待他们,也就是说,如果你定义了变量:

      var_a=true
      echo "$var_a"
      
       true
      

      you can create an opposite value of it with:

      你可以用以下方法创造一个相反的值:

      var_a=$((1 - $var_a))
      echo "$var_a"
      
      1
      

      As you can see for yourself, shell does print true string for the first time you use it, but since then, it all works via number 0 or 1, respectively.

      正如您自己所看到的,shell在您第一次使用它时确实会打印出真正的字符串,但是从那以后,它将分别通过数字0或1进行工作。


Finally, what you should do with all that information

  • First good habit would be assigning 0 instead of true; 1 instead of false.

    第一个好习惯是分配0而不是true;1而不是假的。

  • Second good habit would be to test if the variable is / isn't equal to zero:

    第二个好习惯是测试变量是否等于零:

    test "$var" -eq 0 && CodeIfTrue || CodeIfFalse
    

#10


1  

Bill Parker is getting voted down because his definitions are reversed from normal code convention. Normally, true is defined as 0 and false is defined as nonzero. 1 will work for false, as will 9999 and -1. Same with function return values - 0 is success and anything nonzero is failure. Sorry I don't have the street creds yet to vote or to reply to him directly.

比尔·帕克被投票否决了,因为他的定义与正常的代码惯例相反。通常,true被定义为0,而false被定义为非零。1将为false工作,如9999和-1。与函数返回值相同——0是成功,任何非零都是失败。很抱歉,我还没有投票或者直接回复他。

Bash recommends using double brackets now as a habit instead of single brackets, and the link Mike Holt gave explains the differences in how they work. 7.3. Other Comparison Operators

Bash建议现在使用双括号作为习惯,而不是单一的括号,而Mike Holt给出的链接解释了他们工作方式的不同。7.3。其他比较运算符

For one thing -eq is a numerical operator, so having the code

首先,eq是一个数字运算符,所以有了代码。

#**** NOTE *** This gives error message *****
The_world_is_flat=0;
if [ "${The_world_is_flat}" -eq true ]; then

will issue an error statement, expecting an integer expression. This applies to either parameter, as neither is an integer value. Yet, if we put double brackets around it, it will not issue an error statement, but will yield a wrong value (well, in 50% of the possible permutations). It will evaluate to [[0 -eq true]] = success but also to [[0 -eq false]] = success, which is wrong (hmmm.... what about that builtin being a numerical value?).

将发出一个错误语句,期望一个整数表达式。这对任何一个参数都适用,因为它们都不是整数值。但是,如果我们在它周围加上一个双括号,它就不会发出错误语句,但是会产生一个错误的值(好吧,在可能的排列的50%中)。它将评估[[0情商真的]]=成功,但也[[0 eq假]]=成功,这是错误的(嗯....那建物是一个数值呢?

#**** NOTE *** This gives wrong output *****
The_world_is_flat=true;
if [[ "${The_world_is_flat}" -eq true ]]; then

There are other permutations of the conditional which will give wrong output as well. Basically, anything (other than the error condition listed above) that sets a variable to a numerical value and compares it to a true/false builtin, or sets a variable to a true/false builtin and compares it to a numerical value. Also, anything that sets a variable to a true/false builtin and does a comparison using -eq. So avoid -eq for boolean comparisons and avoid using numerical values for boolean comparisons. Here's a summary of the permutations that will give invalid results:

有条件的其他排列也会产生错误的输出。基本上,任何东西(除了上面列出的错误条件)都将变量设置为数值,并将其与true/false builtin进行比较,或者将一个变量设置为true/false builtin,并将其与数值进行比较。此外,任何将变量设置为true/false builtin并使用-eq进行比较的任何操作。因此,避免使用-eq进行布尔比较,避免使用数字值进行布尔比较。下面是对可能导致无效结果的排列的总结:

#With variable set as an integer and evaluating to true/false
#*** This will issue error warning and not run: *****
The_world_is_flat=0;
if [ "${The_world_is_flat}" -eq true ]; then

#With variable set as an integer and evaluating to true/false
#*** These statements will not evaluate properly: *****
The_world_is_flat=0;
if [ "${The_world_is_flat}" -eq true ]; then
#
if [[ "${The_world_is_flat}" -eq true ]]; then
#
if [ "${The_world_is_flat}" = true ]; then
#
if [[ "${The_world_is_flat}" = true ]]; then
#
if [ "${The_world_is_flat}" == true ]; then
#
if [[ "${The_world_is_flat}" == true ]]; then


#With variable set as an true/false builtin and evaluating to true/false
#*** These statements will not evaluate properly: *****
The_world_is_flat=true;
if [[ "${The_world_is_flat}" -eq true ]]; then
#
if [ "${The_world_is_flat}" = 0 ]; then
#
if [[ "${The_world_is_flat}" = 0 ]]; then
#
if [ "${The_world_is_flat}" == 0 ]; then
#
if [[ "${The_world_is_flat}" == 0 ]]; then

So, now to what works. Use true/false builtins for both your comparison and your evaluations (as Mike Hunt noted, don't enclose them in quotes). Then use either or single or double equal sign (= or ==) and either single or double brackets ([ ] or [[ ]]). Personally, I like the double equals sign because it reminds me of logical comparisons in other programming languages, and double quotes just because I like typing. So these work:

那么,现在来看看什么管用。对你的比较和评价使用真/假的建筑(正如迈克·亨特指出的,不要用引号括起来)。然后使用任一或单或双等号(=或=),或单或双方括号([]或[[]])。就个人而言,我喜欢双等号,因为它让我想起了其他编程语言的逻辑比较,而双引号只是因为我喜欢打字。所以这些工作:

#With variable set as an integer and evaluating to true/false
#*** These statements will work properly: *****
#
The_world_is_flat=true/false;
if [ "${The_world_is_flat}" = true ]; then
#
if [[ "${The_world_is_flat}" = true ]]; then
#
if [ "${The_world_is_flat}" = true ]; then
#
if [[ "${The_world_is_flat}" == true ]]; then

There you have it.

你拥有它。

#11


1  

I found the existing answers confusing.

我发现现有的答案令人困惑。

Personally, I just want to have something which looks and works like C.

就我个人而言,我只是想要一些看起来像C的东西。

This snippet works many times a day in production:

这段代码在生产中每天工作很多次:

snapshotEvents=true

if ($snapshotEvents)
then
    # do stuff if true
fi

and to keep everyone happy, I tested:

为了让大家开心,我测试了一下:

snapshotEvents=false

if !($snapshotEvents)
then
    # do stuff if false
fi

Which also worked fine.

也工作得很好。

The $snapshotEvents evaluates the contents of value of the variable. So you need the $.

$snapshotEvents评估变量的值。所以你需要美元。

You don't really need the parentheses, I just find them helpful.

你不需要括号,我只是觉得它们很有用。

  • Tested on: GNU Bash, version 4.1.11(2)-release

    测试:GNU Bash,版本4.1.11(2)-发布。

  • Bash Guide for Beginners, Machtelt Garrels, v1.11, 2008

    《初学者的Bash指南》,Machtelt Garrels, v1.11, 2008。

#12


1  

Here is an implementation of a short handed if true.

如果是真的,这是一个短传的实现。

# Function to test if a variable is set to "true"
_if () {
    [ "${1}" == "true" ] && return 0
    [ "${1}" == "True" ] && return 0
    [ "${1}" == "Yes" ] && return 0
    return 1
}

Example 1

示例1

my_boolean=true

_if ${my_boolean} && {
    echo "True Is True"
} || {
    echo "False Is False"
}

Example 2

示例2

my_boolean=false
! _if ${my_boolean} && echo "Not True is True"

#13


0  

Here is a simple example which works for me:

下面是一个简单的例子:

temp1=true
temp2=false

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

#14


-1  

Here is an improvement on miku's original answer, that addresses Dennis Williamson's concerns about the case, where the variable is not set:

这是对miku的原始答案的改进,这是丹尼斯·威廉姆森对这个案例的担忧,在这个案例中,变量没有设置:

the_world_is_flat=true

if ${the_world_is_flat:-false} ; then
    echo "Be careful not to fall off!"
fi

And to test if the variable is false:

测试变量是否为假:

if ! ${the_world_is_flat:-false} ; then
    echo "Be careful not to fall off!"
fi

About other cases with a nasty content in the variable, this is a problem with any external input fed to a program.

对于变量中含有恶意内容的其他情况,这是任何输入到程序的外部输入的问题。

Any external input must be validated before trusting it. But that validation has to be done just once, when that input is received.

任何外部输入必须在信任它之前进行验证。但是在接收到输入时,必须只执行一次验证。

It doesn't have to impact the performance of the program by doing it on every use of the variable like Dennis Williamson suggests.

它不需要像丹尼斯·威廉姆森(Dennis Williamson)所建议的那样,在每次使用变量时都对程序的性能产生影响。

#15


-2  

BASH really confuses the issue with the likes of [, [[, ((, $((, etc.

BASH确实将这个问题与诸如[,[],(,$(,等等)之类的问题混淆了。

All treating on each others' code spaces. I guess this is mostly historical, where bash had to pretend to be sh occasionally.

对彼此的代码空间进行处理。我想这主要是历史上的,在这里,bash有时不得不假装是sh。

Most of the time, I can just pick a method and stick with it. In this instance, I tend to declare (preferably in a common library file I can include with . in my actual script(s)).

大多数时候,我可以选择一种方法并坚持下去。在此实例中,我倾向于声明(最好是在我可以包含的公共库文件中)。在我实际的脚本(s))。

TRUE=1; FALSE=0

I can then use the (( ... )) arithmetic operator to test thusly.

然后我可以使用(…)算术运算符来测试。

testvar=$FALSE

if [[ -d ${does_directory_exist} ]]
then
    testvar=$TRUE;
fi

if (( testvar == TRUE )); then
    # do stuff because the directory does exist
fi
  1. You do have to be disciplined, your testvar must either be set to $TRUE or $FALSE at all times.

    你必须要有纪律,你的testvar必须在任何时候被设置为$TRUE或$FALSE。

  2. In (( ... )) comparators, you don't need the preceding $, which makes it more readable.

    在(…)比较器中,您不需要前面的$,这使它更容易读。

  3. I can use (( ... )) because $TRUE=1 and $FALSE=0, i.e. numeric values.

    我可以使用((…))因为$TRUE=1和$FALSE=0,即数值。

  4. The downside is having to use a $ occasionally:

    缺点是不得不偶尔使用一美元:

    testvar=$TRUE
    

    which is not so pretty.

    这不是很漂亮。

It's not a perfect solution, but it covers every case, I need of such a test.

这不是一个完美的解决方案,但它涵盖了所有的情况,我需要这样的测试。