简体   繁体   English

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

[英]How can I declare and use Boolean variables in a shell script?

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 ]

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://stackoverflow.com/a/21210966/89391注意事项: https ://stackoverflow.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来自: 在 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.之所以将原始答案包含在此处,是因为 2014 年 2 月 12 日修订之前的评论仅与原始答案有关,并且与修订后的答案相关联的许多评论是错误的。 For example, Dennis Williamson's comment about bash builtin true on Jun 2, 2010 only applies to the original answer, not the revised.例如,Dennis Williamson 在 2010 年 6 月 2 日关于 bash builtin true的评论仅适用于原始答案,而不适用于修订后的答案。

TL;DR TL;博士

my_bool=true

if [ "$my_bool" = true ]

Issues with Miku's ( original ) answer Miku(原始)答案的问题

I do not recommend the accepted answer 1 .推荐接受的答案1 Its syntax is pretty, but it has some flaws.它的语法很漂亮,但有一些缺陷。

Say we have the following condition.假设我们有以下条件。

if $var; then
  echo 'Muahahaha!'
fi

In the following cases 2 , this condition will evaluate to true and execute the nested command.在以下情况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

Typically you only want your condition to evaluate to true when your "Boolean" variable, var in this example, is explicitly set to true.通常,当您的“布尔”变量(在本例中为var )显式设置为 true 时,您只希望您的条件评估为 true。 All the other cases are dangerously misleading!所有其他情况都具有危险的误导性!

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 commands 3, 4 ).最后一种情况(#5)特别顽皮,因为它将执行包含在变量中的命令(这就是为什么对于有效命令3, 4的条件评估为 true 的原因)。

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, eg if "$var"; then引用变量更安全,例如if "$var"; then if "$var"; then . 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).但我们仍然可以做得更好(见底部我的建议)。

Also see Mike Holt's explanation of Miku's original answer.另请参阅 Mike Holt 对 Miku 原始答案的解释。

Issues with Hbar's answer Hbar回答的问题

This approach also has unexpected behavior.这种方法也有意想不到的行为。

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!惊喜!

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.他们按预期工作。

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

They're all pretty much equivalent.它们都差不多。 You'll have to type a few more keystrokes than the approaches in the other answers 5 , but your code will be more defensive.与其他答案5中的方法相比,您必须键入更多的击键,但您的代码将更具防御性。


Footnotes脚注

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

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 内置的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. miku 的答案中的代码与 Bash 内置true/bin/true或任何其他类型的true命令完全无关。 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.在这种情况下, 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'.这里唯一的区别是被比较的四个字符是'y'、'e'、'a'和'h'而不是't'、'r'、'u'和'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 .当 Bash 解析令牌true时,没有尝试调用名为yeah的命令或内置命令,也没有(在 miku 的示例中)进行任何类型的特殊处理。 It's just a string, and a completely arbitrary one at that.它只是一个字符串,而且是一个完全任意的字符串。

Update (2014-02-19): After following the link in miku's answer, now I see where some of the confusion is coming from.更新(2014-02-19):按照 miku 的答案中的链接后,现在我看到了一些混乱的来源。 Miku's answer uses single brackets, but the code snippet he links to does not use brackets. Miku 的答案使用单括号,但他链接到的代码片段不使用括号。 It's just:只是:

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" .将变量$the_world_is_flat展开为字符串"true"
  2. Attempt to parse the string "true" as a command.尝试将字符串"true"解析为命令。
  3. Find and run the true command (either a builtin or /bin/true , depending on the Bash version).查找并运行true命令(内置命令或/bin/true ,具体取决于 Bash 版本)。
  4. 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.比较true命令的退出代码(始终为 0)和 0。回想一下,在大多数 shell 中,退出代码 0 表示成功,其他任何值都表示失败。
  5. Since the exit code was 0 (success), execute the if statement's then clause由于退出代码为 0(成功),执行if语句的then子句

Brackets:括号:

  1. Expand the variable $the_world_is_flat to the string "true" .将变量$the_world_is_flat展开为字符串"true"
  2. Parse the now-fully-expanded conditional expression, which is of the form string1 = string2 .解析现在完全扩展的条件表达式,其形式为string1 = string2 The = operator is bash's string comparison operator. =运算符是 bash 的字符串比较运算符 So...所以...
  3. Do a string comparison on "true" and "true" ."true""true"进行字符串比较。
  4. Yep, the two strings were the same, so the value of the conditional is true.是的,这两个字符串是相同的,所以条件的值为真。
  5. Execute the if statement's then clause.执行if语句的then子句。

The no-brackets code works, because the true command returns an exit code of 0, which indicates success.无括号代码有效,因为true命令返回退出代码 0,表示成功。 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 = .括号中的代码有效,因为$the_world_is_flat的值与=右侧的字符串文字true相同。

Just to drive the point home, consider the following two snippets of code:只是为了说明这一点,请考虑以下两个代码片段:

This code (if run with root privileges) will reboot your computer:此代码(如果以 root 权限运行)将重新启动您的计算机:

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

This code just prints "Nice try."这段代码只打印“Nice try”。 The reboot command is not called.不调用reboot 命令。

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

Update (2014-04-14) To answer the question in the comments regarding the difference between = and == : AFAIK, there is no difference.更新 (2014-04-14)要回答评论中关于===之间区别的问题:AFAIK,没有区别。 The == operator is a Bash-specific synonym for = , and as far as I've seen, they work exactly the same in all contexts. ==运算符是=的 Bash 特定同义词,据我所知,它们在所有上下文中的工作方式完全相同。

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.我并不是说===在 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" ).例如,您显然不能使用==进行变量赋值,例如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 in Advanced Bash Scripting Guide: 7.3 Other Comparison Operators (scroll down to the discussion of = and == ).您可以在Advanced Bash 脚本指南:7.3 其他比较运算符中阅读更多相关信息(向下滚动到===的讨论)。

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不假

Long story short:长话短说:

There are no Booleans in Bash Bash 中没有布尔值

The true and false commands true false

Bash does have Boolean expressions in terms of comparison and conditions. Bash 在比较和条件方面确实有布尔表达式。 That said, what you can declare and compare in Bash are strings and numbers.也就是说,您可以在 Bash 中声明和比较的是字符串和数字。 That's it.而已。

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 ,它要么是一个字符串,要么是一个仅用于其退出代码的命令/内置命令。

This syntax...这种语法...

if true; then ...

is essentially...本质上是...

if COMMAND; then ...

where the command is true .命令为true地方。 The condition is true whenever the command returns exit code 0. true and false are Bash builtins and sometimes also standalone programs that do nothing but returning the corresponding exit code.只要命令返回退出代码 0,条件就为真。 truefalse是 Bash 内置程序,有时也是独立程序,它们只返回相应的退出代码。


Conditions in if..then..fi if..then..fi中的条件

When using square brackets or the test command, you rely on the exit code of that construct.当使用方括号或test命令时,您依赖于该构造的退出代码。 Keep in mind that [ ] and [[ ]] are also just commands/builtins like any other.请记住, [ ][[ ]]也只是命令/内置命令,就像任何其他命令一样。 So ...所以 ...

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

corresponds to对应于

if COMMAND; then echo yes; fi

and the COMMAND here is [[ with the parameters 1 == 1 ]]这里的COMMAND[[参数为1 == 1 ]]

The if..then..fi construct is just syntactic sugar. if..then..fi结构只是语法糖。 You can always just run the commands separated by a double ampersand for the same effect:您始终可以只运行以双 & 号分隔的命令以获得相同的效果:

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

When using true and false in these testing constructs you are actually only passing the string "true" or "false" to the testing command.在这些测试结构中使用truefalse时,您实际上只是将字符串"true""false"传递给测试命令。 Here is an example:这是一个例子:

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; TL;博士; always compare against strings or numbers始终与字符串或数字进行比较

To make this clear to future readers, I would recommend always using quotes around true and false :为了让未来的读者清楚这一点,我建议始终在truefalse周围使用引号:

DO

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

DON'T

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

Maybe也许

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

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 without any arguments.很久以前,当我们只有sh时,布尔值通过依赖test程序的约定来处理,如果在没有任何参数的情况下运行, test返回错误的退出状态。

This allows one to think of a variable that is unset as false and variable set to any value as true.这允许人们将未设置为假的变量和设置为任何值的变量视为真。 Today, test is a builtin to Bash and is commonly known by its one-character alias [ (or an executable to use in shells lacking it, as dolmen notes):今天, test是 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 a nicer syntax: variables with spaces do not need to be quoted;由于引用约定,脚本编写者更喜欢使用复合命令[[模仿test ,但语法更好:带空格的变量不需要引用; 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:例如,要确定是否设置了 FLAG 并且 COUNT 是大于 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 一起工作时, 这些东西可能会让人感到困惑

How can I declare and use Boolean variables in a shell script?如何在 shell 脚本中声明和使用布尔变量?

Unlike many other programming languages, Bash does not segregate its variables by "type."与许多其他编程语言不同,Bash 不按“类型”来隔离其变量。 [1] [1]

So the answer is pretty clear.所以答案很明确。 There isn't any Boolean variable in Bash. Bash 中没有任何布尔变量

However:然而:

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 terminates
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 . declarereadonly中的r选项用于明确声明变量是只读的。 I hope the purpose is clear.我希望目的很明确。

Instead of faking a Boolean and leaving a trap for future readers, why not just use a better value than true and 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

My findings and suggestion differ a bit from the other posts.我的发现和建议与其他帖子略有不同。 I found that I could use "booleans" basically as one would in any "regular" language, without the "hoop jumping" suggested...我发现我基本上可以像使用任何“常规”语言一样使用“布尔值”,而没有建议的“箍跳”......

There isn't any need for [] or explicit string comparisons... I tried multiple Linux distributions.不需要[]或显式字符串比较...我尝试了多个 Linux 发行版。 I tested Bash, Dash, and BusyBox .我测试了 Bash、Dash 和BusyBox The results were always the same.结果总是一样的。 I'm not sure what the original top voted posts are talking about.我不确定最初投票最多的帖子在说什么。 Maybe times have changed and that's all there is to it?也许时代变了,仅此而已?

If you set a variable to true , it subsequently evaluates as an "affirmative" within a conditional.如果将变量设置为true ,它随后会在条件中评估为“肯定”。 Set it to false , and it evaluates to a "negative".将其设置为false ,它的评估结果为“否定”。 Very straightforward!很直接! The only caveat, is that an undefined variable also evaluates like true !唯一需要注意的是,未定义的变量也会像true一样评估! It would be nice if it did the opposite (as it would in most languages), but that's the trick - you just need to explicitly initialize your booleans to true or false .如果它做相反的事情会很好(就像在大多数语言中那样),但这就是诀窍 -你只需要明确地将你的布尔值初始化为 true 或 false

Why does it work this way?为什么它会这样工作? That answer is two fold.这个答案是双重的。 A) true/false in a shell really means "no error" vs "error" (ie 0 vs anything else). A)shell中的真/假实际上意味着“无错误”与“错误”(即0与其他任何东西)。 B) true/false are not values - but rather statements in shell scripting! B)真/假不是值-而是shell脚本中的语句 Regarding the second point, executing true or false on a line by itself sets the return value for the block you're in to that value, ie false is a declaration of "error encountered", where true "clears" that.关于第二点,单独在一行上执行truefalse会将您所在块的返回值设置为该值,即false是“遇到错误”的声明,其中 true 会“清除”该值。 Using it with an assignment to a variable "returns" that into the variable.将其与对变量的赋值一起使用会将其“返回”到变量中。 An undefined variable evaluates like true in a conditional because that equally represents 0 or "no error encountered".未定义的变量在条件中的计算结果类似于true ,因为它同样表示 0 或“未遇到错误”。

See the example Bash lines and results below.请参阅下面的示例 Bash 行和结果。 Test it yourself if you want to confirm...如果您想确认,请自行测试...

#!/bin/sh

# Not yet defined...
echo "when set to ${myBool}"
if ${myBool}; then echo "it evaluates to true"; else echo "it evaluates to false"; fi;

myBool=true
echo "when set to ${myBool}"
if ${myBool}; then echo "it evaluates to true"; else echo "it evaluates to false"; fi;

myBool=false
echo "when set to ${myBool}"
if ${myBool}; then echo "it evaluates to true"; else echo "it evaluates to false"; fi;

Yields产量

when set to
it evaluates to true
when set to true
it evaluates to true
when set to false
it evaluates to false

POSIX (Portable Operating System Interface) POSIX (便携式操作系统接口)

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.本质上,所有投票的答案都是正确的,除了它们是Bash特定的太多。

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命令:

     test "$var" = true && yourCodeIfTrue || yourCodeIfFalse

    Important note: I no longer recommend this as it's being slowly deprecated and more difficult to combine multiple statements.重要提示:我不再推荐这个,因为它正在慢慢被弃用,并且更难以组合多个语句。

  2. Imagine what those words true and false mean to the shell, test it yourself:想象一下truefalse这些词对 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.除了字符串之外,shell 无法解释它。 I hope you are getting the idea of how good it is using proper keyword without quotes .我希望您了解使用不带引号的正确关键字有多好。

    But no one said it in previous answers.但是在之前的答案中没有人这么说。

  3. What does this mean?这是什么意思? 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 .您应该习惯布尔关键字实际上被视为数字,即true = 0false = 1 ,记住所有非零值都被视为false

    • Since they are treated as numbers, you should treat them like that too, ie if you define variable say:由于它们被视为数字,因此您也应该这样对待它们,即如果您定义变量说:

       var_bool=true echo "$var_bool"
       true

      you can create an opposite value of it with:您可以使用以下方法创建相反的值:

       var_bool=$(( 1 - $var_bool )) # same as $(( ! $var_bool )) echo "$var_bool"
       1

    As you can see for yourself, the shell does print true string for the first time you use it, but since then, it all works via number 0 representing true or 1 representing false , respectively.正如您自己所看到的,shell 在您第一次使用它时会打印true字符串,但从那时起,它都通过数字0表示true1表示false分别工作。


Finally, what you should do with all that information最后,您应该如何处理所有这些信息

  • First, one good habit would be assigning 0 instead of true ;首先,一个好习惯是分配0而不是true 1 instead of false . 1而不是false

  • Second good habit would be to test if the variable is / isn't equal to zero:第二个好习惯是测试变量是否 / 不等于零:

     if [ "$var_bool" -eq 0 ]; then yourCodeIfTrue else yourCodeIfFalse fi

In many programming languages, the Boolean type is, or is implemented as, a subtype of integer, where true behaves like 1 and false behaves like 0 :在许多编程语言中,布尔类型是或实现为整数的子类型,其中true行为类似于1false的行为类似于0

Mathematically , Boolean algebra resembles integer arithmetic modulo 2. Therefore, if a language doesn't provide native Boolean type, the most natural and efficient solution is to use integers.数学上,布尔代数类似于整数算术模 2。因此,如果一种语言不提供原生布尔类型,最自然和最有效的解决方案是使用整数。 This works with almost any language.这几乎适用于任何语言。 For example, in Bash you can do:例如,在 Bash 中,您可以执行以下操作:

# val=1; ((val)) && echo "true" || echo "false"
true
# val=0; ((val)) && echo "true" || echo "false"
false

man bash :男子重击

((expression)) ((表达))

The expression is evaluated according to the rules described below under ARITHMETIC EVALUATION.表达式根据下面算术评估中描述的规则进行评估。 If the value of the expression is non-zero, the return status is 0;如果表达式的值为非零,则返回状态为0; otherwise the return status is 1. This is exactly equivalent to let "expression".否则返回状态为 1。这完全等同于 let "表达式"。

Regarding syntax, this is a simple methodology that I use (by example) to consistently and sanely manage Boolean logic:关于语法,这是我使用(通过示例)一致和理智地管理布尔逻辑的一种简单方法:

# 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

If the variable is never declared the answer is: # false如果从未声明变量,则答案是: # false

So, a simple way to set a variable to true (using this syntax methodology) would be, var=1 ;因此,将变量设置为 true(使用此语法方法)的简单方法是var=1 conversely, var='' .相反, var=''

Reference:参考:

-n = True if the length of var string is non-zero. -n = True 如果 var 字符串的长度不为零。

-z = True if the length of var string is zero. -z = 如果 var 字符串的长度为零,则为真。

Bill Parker is getting voted down , because his definitions are reversed from the normal code convention. 比尔·帕克(Bill Parker)被否决了,因为他的定义与正常的代码约定相反。 Normally, true is defined as 0 and false is defined as nonzero.通常,true 定义为 0,false 定义为非零。 1 will work for false, as will 9999 and -1. 1 适用于 false,9999 和 -1 也适用。 The same with function return values - 0 is success and anything nonzero is failure.与函数返回值相同 - 0 表示成功,任何非零值表示失败。 Sorry, I don't have the street credibility yet to vote or to reply to him directly.对不起,我还没有街头信誉可以投票或直接回复他。

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. Bash 建议现在使用双括号而不是单括号作为习惯,Mike Holt 给出的链接解释了它们工作方式的差异。 7.3. 7.3. Other Comparison Operators其他比较运算符

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 it will yield a wrong value (well, in 50% of the possible permutations).然而,如果我们在它周围加上双括号,它不会发出错误声明,但会产生错误的值(嗯,在 50% 的可能排列中)。 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?).它将评估为 [[0 -eq true]] = 成功,但也将评估为 [[0 -eq false]] = 成功,这是错误的(嗯......那个内置是一个数值呢?)。

#**** 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 .此外,任何将变量设置为真/假内置并使用-eq进行比较的东西。 So avoid -eq for Boolean comparisons and avoid using numerical values for Boolean comparisons.因此,避免使用-eq进行布尔比较,并避免使用数值进行布尔比较。 Here's a summary of the permutations that will give invalid results:以下是会给出无效结果的排列的摘要:

# 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).使用 true/false 内置函数进行比较和评估(正如 Mike Hunt 指出的那样,不要将它们括在引号中)。 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.你有它。

My receipe to (my own) idiocy:我对(我自己的)白痴的收据:

# setting ----------------
commonMode=false
if [[ $something == 'COMMON' ]]; then
    commonMode=true
fi

# using ----------------
if $commonMode; then
    echo 'YES, Common Mode'
else
    echo 'NO, no Common Mode'
fi

$commonMode && echo 'commonMode is ON  ++++++'
$commonMode || echo 'commonMode is OFF xxxxxx'

Another way of using booleans is to test the emptyness of values.使用布尔值的另一种方法是测试值的空性 This has the advantage of making shorter tests:这样做的好处是可以进行更短的测试:

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'

Output:输出:

First var is true
Second var is false

Here is an alternative test syntax with bash: [[ -n $one ]]这是使用 bash 的另一种测试语法: [[ -n $one ]]

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. $snapshotEvents评估变量值的内容。 So you need the $ .所以你需要$

You don't really need the parentheses, I just find them helpful.你真的不需要括号,我只是觉得它们很有帮助。

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原始答案的改进,解决了Dennis Williamson对未设置变量的情况的担忧:

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 :并测试变量是否为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.它不必像丹尼斯威廉姆森建议的那样,通过在每次使用变量时都这样做来影响程序的性能。

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

Here is an implementation of a short handed if true .这是一个短手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"

You can use shFlags .您可以使用shFlags

It gives you the option to define: DEFINE_bool它使您可以选择定义: DEFINE_bool

Example:例子:

DEFINE_bool(big_menu, true, "Include 'advanced' options in the menu listing");

From the command line you can define:从命令行您可以定义:

sh script.sh --bigmenu
sh script.sh --nobigmenu # False

This is a speed test about different ways to test "Boolean" values in Bash:这是关于在 Bash 中测试“布尔”值的不同方法的速度测试:

#!/bin/bash
rounds=100000

b=true # For true; b=false for false
type -a true
time for i in $(seq $rounds); do command $b; done
time for i in $(seq $rounds); do $b; done
time for i in $(seq $rounds); do [ "$b" == true ]; done
time for i in $(seq $rounds); do test "$b" == true; done
time for i in $(seq $rounds); do [[ $b == true ]]; done

b=x; # Or any non-null string for true; b='' for false
time for i in $(seq $rounds); do [ "$b" ]; done
time for i in $(seq $rounds); do [[ $b ]]; done

b=1 # Or any non-zero integer for true; b=0 for false
time for i in $(seq $rounds); do ((b)); done

It would print something like它会打印类似的东西

true is a shell builtin
true is /bin/true

real    0m0,815s
user    0m0,767s
sys     0m0,029s

real    0m0,562s
user    0m0,509s
sys     0m0,022s

real    0m0,829s
user    0m0,782s
sys     0m0,008s

real    0m0,782s
user    0m0,730s
sys     0m0,015s

real    0m0,402s
user    0m0,391s
sys     0m0,006s

real    0m0,668s
user    0m0,633s
sys     0m0,008s

real    0m0,344s
user    0m0,311s
sys     0m0,016s

real    0m0,367s
user    0m0,347s
sys     0m0,017s
[[ "$x" == 'true' || "$x" -ne 0 ]] && ...

足够简单并且没有依赖关系。

Bash really confuses the issue with the likes of [ , [[ , (( , $(( , etc. Bash 确实将问题与[[[(($((等) 之类的问题混淆了。

All treading 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)).在这种情况下,我倾向于声明(最好在一个公共库文件中,我可以在我的实际脚本中包含. )。

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 , ie 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.这不是一个完美的解决方案,但它涵盖了我需要进行此类测试的所有情况。

Alternative - use a function替代方案 - 使用函数

is_ok(){ :;}
is_ok(){ return 1;}
is_ok && echo "It's OK" || echo "Something's wrong"

Defining the function is less intuitive, but checking its return value is very easy.定义函数不太直观,但检查它的返回值非常容易。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM