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

发布于 2024-09-04 13:28:28 字数 218 浏览 9 评论 0原文

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

variable=$false

variable=$true

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

if [ $variable ]

if [ !$variable ]

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

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 ]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(27

同展鸳鸯锦 2024-09-11 13:28:28

修订后的答案(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

原始答案

注意事项: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

来自:在 Bash 中使用布尔变量

将原始答案包含在这里的原因是因为 2014 年 2 月 12 日修订之前的评论仅与原始答案有关,并且许多与修订后的答案相关联时,评论是错误的。例如,Dennis Williamson 在 2010 年 6 月 2 日关于 bash 内置 true 的评论仅适用原始答案,而不是修改后的答案。

Revised Answer (Feb 12, 2014)

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

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

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.

时光无声 2024-09-11 13:28:28

TL;DR

my_bool=true

if [ "$my_bool" = true ]

Miku(原始)答案的问题

推荐接受的答案1。它的语法很漂亮,但有一些缺陷。

假设我们有以下条件。

if $var; then
  echo 'Muahahaha!'
fi

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

  1. 未事先定义变量 var
  2. var=''(相当于 var=""var=
  3. unset var
  4. var=''

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

最后一种情况 (#4) 特别顽皮,因为它将执行变量中包含的命令(这就是为什么有效命令3, 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 原始答案的解释。

Hbar的回答

这种做法也有意想不到的效果行为。

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[[< /code> 而不是 [,没有区别。

我的建议:

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

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中的方法相比,您必须输入更多的按键次数,但您的代码将更具防御性。


脚注

  1. Miku 的答案已被编辑,不再包含(已知的)缺陷。
  2. 不是详尽的清单。
  3. 在此上下文中,有效命令意味着存在的命令。该命令使用正确或错误并不重要。例如,即使不存在这样的手册页,man Woman 仍将被视为有效命令。
  4. 对于无效(不存在)的命令,Bash 只会抱怨找不到该命令。
  5. 如果您关心长度,第一个推荐是最短的。

TL;DR

my_bool=true

if [ "$my_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.

  1. Variable var not defined beforehand
  2. var='' (equivalent to var="" or var=)
  3. unset var
  4. var='<some valid command>'

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 other cases are dangerously misleading!

The last case (#4) 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).

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).

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

Issues with Hbar's answer

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.

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 answers5, but your code will be more defensive.


Footnotes

  1. Miku's answer has since been edited and no longer contains (known) flaws.
  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. E.g. man woman would still be considered a valid command, even if no such man page exists.
  4. For invalid (non-existent) commands, Bash will simply complain that the command wasn't found.
  5. If you care about length, the first recommendation is the shortest.
脸赞 2024-09-11 13:28:28

这里似乎对 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'。就是这样。没有尝试调用名为 yeah 的命令或内置函数,也没有(在 miku 的示例中)当 Bash 解析标记 true 时进行任何特殊处理。它只是一根字符串,而且是一个完全任意的字符串。

更新(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 在每种情况下所做的操作:

无括号

  1. 将变量 $the_world_is_flat 展开为字符串 "true"
  2. 尝试将字符串 "true" 解析为命令。
  3. 查找并运行 true 命令(内置命令或 /bin/true,具体取决于 Bash 版本)。
  4. true 命令的退出代码(始终为 0)与 0 进行比较。回想一下,在大多数 shell 中,退出代码 0 表示成功,其他值表示失败。
  5. 由于退出代码为 0(成功),因此执行 if 语句的 then 子句

括号:

  1. 展开变量 $the_world_is_flat 到字符串“true”
  2. 解析现在完全扩展的条件表达式,其格式为 string1 = string2= 运算符是 bash 的字符串比较运算符。所以...
  3. "true""true" 进行字符串比较。
  4. 是的,两个字符串相同,因此条件的值为 true。
  5. 执行 if 语句的 then 子句。

无括号代码有效,因为 true 命令返回退出代码 0,这表示成功。括号内的代码有效,因为 $the_world_is_flat 的值与 = 右侧的字符串文字 true 相同。

为了让大家明白这一点,请考虑以下两个代码片段:

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

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

该代码仅打印“Nice try”。未调用重新启动命令。

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

更新 (2014-04-14) 要回答评论中有关 === 之间差异的问题:据我所知,没有不同之处。 == 运算符是 Bash 特定的 = 同义词,据我所知,它们在所有上下文中的工作方式完全相同。

但请注意,我专门讨论 [ ][ 中使用的 === 字符串比较运算符[ ]] 测试。我并不是建议 === 在 bash 中任何地方都可以互换。

例如,您显然不能使用 == 进行变量赋值,例如 var=="foo" (从技术上讲,您可以这个,但是 var 的值将是 "=foo",因为 Bash 在这里没有看到 == 运算符,它看到的是=(赋值)运算符,后跟文字值 ="foo",它就变成了 "=foo")。

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

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

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.

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

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.

Update (2014-02-19): 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:

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:

No brackets:

  1. Expand the variable $the_world_is_flat to the string "true".
  2. Attempt to parse the string "true" as a command.
  3. Find and run the true command (either a builtin or /bin/true, depending on the Bash version).
  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.
  5. Since the exit code was 0 (success), execute the if statement's then clause

Brackets:

  1. Expand the variable $the_world_is_flat to the string "true".
  2. Parse the now-fully-expanded conditional expression, which is of the form string1 = string2. The = operator is bash's string comparison operator. So...
  3. Do a string comparison on "true" and "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.

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 =.

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

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

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 (2014-04-14) 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").

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 ==).

鸢与 2024-09-11 13:28:28

长话短说:

Bash 中没有布尔值

truefalse 命令

Bash 在比较和条件方面确实有布尔表达式。也就是说,您可以在 Bash 中声明和比较的是字符串和数字。就是这样。

无论您在 Bash 中何处看到 truefalse,它要么是字符串,要么是命令/内置命令,仅用于其退出代码。

此语法...

if true; then ...

本质上是...

if COMMAND; then ...

命令为 true 的情况。每当命令返回退出代码 0 时,条件就为 true。 truefalse 是 Bash 内置程序,有时也是除了返回相应的退出代码之外不执行任何操作的独立程序。


if..then..fi 中的条件

当使用方括号或 test 命令时,您依赖于该构造的退出代码。请记住,[ ][[ ]] 也只是像其他命令/内置命令一样。所以 ...

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

对应于

if COMMAND; then echo yes; fi

这里的 COMMAND[[ ,参数为 1 == 1 ]]

if.. then..fi 构造只是语法糖。您始终可以运行由双与号分隔的命令以获得相同的效果:

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

在这些测试构造中使用 truefalse 时,您实际上只传递字符串 “true”“false” 到测试命令。这是一个例子:

不管你信不信,但这些条件都会产生相同的结果

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

TL;DR;始终与字符串或数字进行比较

为了让未来的读者清楚这一点,我建议始终在 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 story short:

There are no Booleans in Bash

The true and false commands

Bash does have 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.

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.

This syntax...

if true; then ...

is essentially...

if COMMAND; then ...

where the command is 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.


Conditions in if..then..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

corresponds to

if COMMAND; then echo yes; fi

and the COMMAND here is [[ with the parameters 1 == 1 ]]

The if..then..fi construct is just syntactic sugar. 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. 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; 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 [[ "${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 ... 
半步萧音过轻尘 2024-09-11 13:28:28

使用算术表达式。

#!/bin/bash

false=0
true=1

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

输出:

真实
不假

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

塔塔猫 2024-09-11 13:28:28

很久以前,当我们只有 sh 时,布尔值是通过依赖 test 程序的约定来处理的,其中 test 返回错误的退出状态如果不带任何参数运行。

这允许人们将未设置的变量视为 false,并将设置为任何值的变量视为 true。如今,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

因为关于引用约定,脚本编写者更喜欢使用模仿 test 的复合命令 [[,但具有更好的语法:带有空格的变量不需要引用;人们可以使用 &&|| 作为具有奇怪优先级的逻辑运算符,并且对术语数量没有 POSIX 限制。

例如,要确定 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

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

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.

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):

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; one can use && and || as logical operators with weird precedence, and there are no POSIX limitations on the number of terms.

For example, to determine if FLAG is set and COUNT is a number greater than 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.

往日 2024-09-11 13:28:28

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

例如:

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

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
雨夜星沙 2024-09-11 13:28:28

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

与许多其他编程语言不同,Bash 不按“类型”分隔其变量。 [1]

所以答案非常清楚。 Bash 中没有任何布尔变量。

但是:

使用声明语句,我们可以将值分配限制为
变量。[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"

rdeclarereadonly 中的 code> 选项用于明确声明变量是只读。我希望目的很明确。

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

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

So the answer is pretty clear. There isn't any Boolean variable in Bash.

However:

Using a declare statement, we can limit the value assignment to
variables.[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. I hope the purpose is clear.

甚是思念 2024-09-11 13:28:28

我的发现和建议与其他帖子略有不同。我发现我基本上可以像在任何“常规”语言中一样使用“布尔值”,而不需要建议“跳环”...

不需要 [] 或显式字符串比较...我尝试了多个Linux发行版。我测试了 Bash、Dash 和 BusyBox。结果总是一样的。我不确定最初投票最高的帖子在谈论什么。也许时代变了,仅此而已?

如果将变量设置为 true,它随后将在条件中计算为“肯定”。将其设置为 false,其计算结果为“负”。非常简单!唯一需要注意的是,未定义变量的计算结果也类似于true!如果它执行相反的操作(就像在大多数语言中一样),那就太好了,但这就是技巧 - 您只需要显式地将布尔值初始化为 true 或 false

为什么会这样呢?这个答案有两个方面。 A) shell 中的 true/false 实际上意味着“无错误”与“错误”(即 0 与其他任何值)。 B) true/false 不是值 - 而是 shell 脚本中的语句!关于第二点,在一行上执行 truefalse 本身会将您所在块的返回值设置为该值,即 false code> 是“遇到错误”的声明,其中 true 会“清除”该错误。将其与对变量的赋值一起使用会将其“返回”到变量中。 未定义变量在条件中的计算结果类似于true,因为它同样代表 0 或“未遇到错误”。

请参阅下面的示例 Bash 行和结果。如果您想确认的话,请自行测试...

#!/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;

产量

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

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. I tested Bash, Dash, and 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. Set it to false, and it evaluates to a "negative". Very straightforward! The only caveat, is that an undefined variable also evaluates like 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.

Why does it work this way? That answer is two fold. A) true/false in a shell really means "no error" vs "error" (i.e. 0 vs anything else). B) true/false are not values - but rather statements in shell scripting! 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, i.e. false is a declaration of "error encountered", where true "clears" that. 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".

See the example Bash lines and results below. 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
如果没有你 2024-09-11 13:28:28

POSIX(可移植操作系统接口)

我在这里错过了关键点,即可移植性。这就是为什么我的标题本身有 POSIX

本质上,所有投票的答案都是正确的,除了 Bash-具体太多了。

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


  1. [] 括号(例如 [ "$var" = true ] 中的括号)不是必需的,您可以省略它们并使用直接测试命令:

    测试 "$var" = true && yourCodeIfTrue ||你的代码如果为假
    

    重要说明:我不再推荐此方法,因为它正在慢慢被弃用,并且组合多个语句变得更加困难。

  2. 想象一下 truefalse 对 shell 意味着什么,自己测试一下:

    echo $(( true ))
    

    <块引用>

    0
    

    echo $(( false ))
    

    <块引用>

    1
    

    但使用引号:

    echo $(( "true" ))
    

    <块引用>

    bash: "true": 语法错误:需要操作数(错误标记为 ""true"")
    sh(破折号):sh:1:算术表达式:期望主要:“”true“”
    

    这同样适用于:

    echo $(( "false" ))
    

    除了字符串之外,shell 无法解释它。我希望您能够了解使用正确的关键字不带引号有多好。

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

  3. 这是什么意思?嗯,有几件事。

    • 您应该习惯布尔关键字实际上被视为数字,即 true = 0false = < code>1,记住所有非零值都被视为 false

    • 由于它们被视为数字,因此您也应该这样对待它们,即如果您定义变量说:

      var_bool=true
      回显“$var_bool”
      

      <块引用>

       true
      

      您可以使用以下方法创建相反的值:

      var_bool=$(( 1 - $var_bool )) # 与 $(( ! $var_bool )) 相同
      回显“$var_bool”
      

      <块引用>

      1
      

    正如您所看到的,第一次使用 shell 时,它会打印 true 字符串,但从那时起,它就通过代表 0 的数字来工作。 code>true或1分别代表false


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

  • 首先,一个好习惯是分配 0 而不是 true1 而不是 false

  • 第二个好习惯是测试变量是否等于/不等于0:

    if [ "$var_bool" -eq 0 ];然后
         你的代码如果为真
    别的
         你的代码如果为假
    菲
    

POSIX (Portable Operating System Interface)

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

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

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:

    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:

    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 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.

    • Since they are treated as numbers, you should treat them like that too, i.e. 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 trueor 1 representing false, respectively.


Finally, what you should do with all that information

  • First, one good habit would be assigning 0 instead of true; 1 instead of 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
    
情绪操控生活 2024-09-11 13:28:28

在许多编程语言中,布尔类型是整数的子类型,或者被实现为整数的子类型,其中 true 的行为类似于 1 ,而 false 的行为类似于0

数学上,布尔代数类似于整数算术模 2。因此,如果一种语言不提供原生布尔类型,最自然、最高效的解决方案是使用整数。这几乎适用于任何语言。例如,在 Bash 中,您可以执行以下操作:

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

man bash

((表达式))

根据下面算术评估中描述的规则评估表达式。如果表达式的值非零,则返回状态为0;否则返回状态为1。这与let“表达式”完全相同。

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:

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. This works with almost any language. For example, in Bash you can do:

# 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; otherwise the return status is 1. This is exactly equivalent to let "expression".

五里雾 2024-09-11 13:28:28

关于语法,这是一种简单的方法,我使用它(通过示例)来一致且合理地管理布尔逻辑:

# 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。

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

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

So, a simple way to set a variable to true (using this syntax methodology) would be, var=1; conversely, var=''.

Reference:

-n = True if the length of var string is non-zero.

-z = True if the length of var string is zero.

野味少女 2024-09-11 13:28:28

使用布尔值的另一种方法是测试值的空性。这样做的优点是可以缩短测试时间:

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 ]]

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 ]]

柳絮泡泡 2024-09-11 13:28:28

比尔·帕克被否决,因为他的定义与正常的代码约定相反。通常,true 定义为 0,false 定义为非零。 1 将适用于 false,9999 和 -1 也适用。函数返回值也是如此 - 0 表示成功,任何非零值表示失败。抱歉,我还没有足够的信誉来投票或直接回复他。

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

一方面,-eq 是一个数字运算符,因此代码

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

将发出错误语句,需要整数表达式。这适用于任一参数,因为两者都不是整数值。然而,如果我们用双括号括起来,它不会发出错误语句,但会产生错误的值(嗯,在 50% 的可能排列中)。它将评估为 [[0 -eq true]] = 成功,但也会评估为 [[0 -eq false]] = 成功,这是错误的(嗯......那个内置值是一个数值怎么样?)。

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

条件条件的其他排列也会给出错误的输出。基本上,任何将变量设置为数值并将其与真/假内置函数进行比较,或将变量设置为真/假内置函数并将其与数值进行比较的任何内容(除了上面列出的错误条件之外)。此外,任何将变量设置为 true/false 内置变量并使用 -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

那么,现在看看什么是有效的。使用 true/false 内置函数进行比较和评估(正如 Mike Hunt 指出的,不要将它们放在引号中)。然后使用单等号或双等号(= 或 ==)以及单括号或双括号([ ] 或 [[ ]])。就我个人而言,我喜欢双等号,因为它让我想起其他编程语言中的逻辑比较,而双引号只是因为我喜欢打字。所以这些工作:

# 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

就是这样。

Bill Parker is getting voted down, because his definitions are reversed from the 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. The same with function return values - 0 is success and anything nonzero is failure. 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. 7.3. Other Comparison Operators

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

#**** 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). 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?).

#**** 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:

# 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.

趁年轻赶紧闹 2024-09-11 13:28:28

最高性能的方法是检查变量是否为空:

#false:
condition=""

#true:
condition=x

#check:
[[ -n "${condition}" ]]

The way with the highest performance is by checking if a variable is empty or not:

#false:
condition=""

#true:
condition=x

#check:
[[ -n "${condition}" ]]
﹎☆浅夏丿初晴 2024-09-11 13:28:28

在大多数情况下,您需要“boolean”来进行布尔运算,例如 ! &&||。在某些语言中,特殊的布尔类型根本不存在(因为事实上您在技术上不需要它),在大多数解释语言中(几乎)所有类型都会在诸如 ! &&||

布尔值总是与布尔运算一起使用。在 Bash 中,此类操作是($var 周围没有 "",这非常重要!):

[[ $var ]] - check if var is true
[[ ! $var ]] - check if var is false
[[ $var1 || $var2 ]] - var1 or var2
[[ $var1 && $var2 ]] - var1 and var2

[[ $var ]]仅当 var=''(或未设置)时为 false。因此,bash 中变量的唯一正确“假”值是“”(空字符串)。对于 true,您可以选择任何值,但我更喜欢 var=1(就像在其他语言中一样,其中 true 是任何非空 int,但出于可读目的,程序员总是使用 1)。

注意:对于 var='false' 布尔检查中的 var 为 true。在 Bash 中,字符串 'false' 实际上是 true(与所有其他语言相同!)。 Bash 与 Python、Perl 或 PHP 之间的唯一区别是,在 Bash 中 0 也是如此。但再说一遍:Bash 中有布尔运算,它们的工作方式与所有其他解释语言类似,只是 Bash 中的 0 为 true。

在 Bash 中使用字符串 'true''false' 作为布尔值替换是绝对不合理的。这就像在 Python、Perl 或 PHP 中使用同样奇怪的概念。它运行速度较慢(在 Bash 中也是如此),并且没有人在其他语言中这样做,但在 Bash 中,有很多程序员认为这是一个很好的解决方案。不。没有理由不在 Bash 中直接使用布尔运算,除非有像 $var == 'true'$var == 'false' 这样绝对奇怪的比较。

再说一次,Bash 中的布尔替换是:

var=''  # false
var=1   # true (actually any non-empty string)

在 Bash 中直接使用布尔检查也是进行类似布尔检查的最快方法。所有其他结构的运行速度都会慢得多。

PS“旧”风格的“布尔”检查,例如 a=true;如果 $a; then ... 绝对是愚蠢的,因为:

  1. 你不能在条件中直接使用它们 [[ ]]
  2. 它们充当 bash 代码的 eval ,存储在变量中。好吧,如果您认为这是个好主意,请不要编写任何程序;)

PPS 如果可以取消设置 $var 并且您使用非常有用的 set -u只需将检查中的 $var 替换为 ${var-},例如 [[ ${var-} ]] (另外:没有 "" 周围,这对于代码执行速度很重要!)

In most cases you need "boolean" for boolean operations, such as ! && or ||. In some languages special boolean type do not exists at all (because in fact you do not need it technically), in most of interpreted languages (almost) all types automatically converted to some kind of boolean in operations like ! && or ||.

Boolean always is something that works with boolean operations. In Bash such operations are (no "" around $var, it's very important!):

[[ $var ]] - check if var is true
[[ ! $var ]] - check if var is false
[[ $var1 || $var2 ]] - var1 or var2
[[ $var1 && $var2 ]] - var1 and var2

[[ $var ]] is false only if var='' (or unset). So the only one correct 'false' value of variable in bash is '' (empty string). For true you can select any value, but I prefer var=1 (like in other languages, where true is any not-null int, but for readable purposes programmers always use 1).

NOTE: for var='false' var in boolean checks is true. In Bash string 'false' is actually true (same as in all other languages!). The only one difference between Bash and, e.g. Python, Perl or PHP, is that in Bash 0 is also true. But again: there are boolean operations in Bash, and they works like in all other interpreted languages, except that 0 in Bash is true.

It's absolutely irrational to use strings 'true' and 'false' as boolean replacement in Bash. It's like using same strange concept in Python, or Perl, or PHP. It works slower (in Bash too), and nobody do it in other languages, but in Bash there are a lot of coders that think it's a good solution. No. There are no reasons not to use boolean operations in Bash directly, without absolutely strange comparisons like $var == 'true' or $var == 'false'.

So again, boolean replacements in Bash are:

var=''  # false
var=1   # true (actually any non-empty string)

And direct usage of boolean checks in Bash also is a fastest way to do boolean-like checks. All other constructions will works much slower.

P.S. "old" style of "boolean" checks like a=true; if $a; then ... are absolutely idiotic, because:

  1. you can't use them directly in conditions [[ ]]
  2. they act as eval of bash code, stored in variable. Well, if you think it's a good idea, just do not ever write any program, please;)

P.P.S. If $var can be unset and you use very helpful set -u just replace $var in checks to ${var-}, e.g. [[ ${var-} ]] (also: no "" around, it's important for speed of code execution!)

初见终念 2024-09-11 13:28:28

我对(我自己的)白痴的接受:

# 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'

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'
极致的悲 2024-09-11 13:28:28

这是对 miku 的原始答案的改进,解决了丹尼斯·威廉姆森对未设置变量的情况的担忧:

the_world_is_flat=true

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

以及测试变量是否为false

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

关于其他情况下包含令人讨厌的内容变量,这是输入到程序的任何外部输入的问题。

任何外部输入在信任之前都必须经过验证。但验证只需在收到输入时进行一次。

它不必通过在每次使用变量时都这样做来影响程序的性能,例如 Dennis Williamson建议。

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

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.

浅紫色的梦幻 2024-09-11 13:28:28

这是一个对我有用的简单示例:

temp1=true
temp2=false

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

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
甜味拾荒者 2024-09-11 13:28:28

这是一个缺手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
}

示例 1

my_boolean=true

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

示例 2

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

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

my_boolean=true

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

Example 2

my_boolean=false
! _if ${my_boolean} && echo "Not True is True"
酒绊 2024-09-11 13:28:28

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

就我个人而言,我只想拥有一些看起来和工作起来都像 C 的东西。

这个片段在生产中每天工作很多次:

snapshotEvents=true

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

为了让每个人都高兴,我测试了:

snapshotEvents=false

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

这也工作得很好。

$snapshotEvents 计算变量 value 的内容。所以你需要$

您实际上并不需要括号,我只是发现它们很有帮助。

  • 测试于:GNU Bash,版本 4.1.11(2)-release

  • Bash 初学者指南,Machtelt Garrels,v1.11,2008

I found the existing answers confusing.

Personally, I just want to have something which looks and works like 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 $.

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

黎歌 2024-09-11 13:28:28

这是关于在 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

它会打印类似的内容

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

This is a speed test about different ways to test "Boolean" values in 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
身边 2024-09-11 13:28:28

您可以使用 shFlags

它为您提供了定义的选项:DEFINE_bool

示例:

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

您可以从命令行定义:

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

You can use shFlags.

It gives you the option to define: 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
没企图 2024-09-11 13:28:28
[[ "$x" == 'true' || "$x" -ne 0 ]] && ...

足够简单并且没有依赖性。

[[ "$x" == 'true' || "$x" -ne 0 ]] && ...

Is enough simple and has no dependencies.

原谅过去的我 2024-09-11 13:28:28

您可以使用别名以及 truefalse 内置函数的别名。也许有点不传统,但对我来说这似乎是一个很好的干净的解决方案。

alias my_bool=false

if [[ $(($RANDOM % 2)) == 0 ]]; then
  alias my_bool=true
fi

if my_bool; then
  echo 'true!'
else
  echo 'false!'
fi

You can use aliases and alias to the true and false builtins. Maybe a little unconventional but it seems like a nice clean solution to me.

alias my_bool=false

if [[ $(($RANDOM % 2)) == 0 ]]; then
  alias my_bool=true
fi

if my_bool; then
  echo 'true!'
else
  echo 'false!'
fi
舞袖。长 2024-09-11 13:28:28

Bash 确实将问题与 [[[(($(( 等) .

我想这主要是历史性的,Bash 不得不偶尔假装是 sh

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

TRUE=1; FALSE=0

然后我可以使用 (() 。 ... )) 算术运算符要这样进行测试

testvar=$FALSE

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

if (( testvar == TRUE )); then
    # Do stuff because the directory does exist
fi
  1. 您必须遵守纪律。您的 testvar 必须设置为 $TRUE 或 $FALSE 始终。

  2. (( ... )) 比较器中,您不需要前面的 $,这使得它更具可读性。

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

  4. 缺点是偶尔必须使用 $

    testvar=$TRUE
    

    这不太漂亮。

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

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

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

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.

  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.

  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.

你对谁都笑 2024-09-11 13:28:28

替代方案 - 使用函数

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

定义函数不太直观,但检查其返回值非常容易。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文