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

variable=$false

variable=$true

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

if [ $variable ]

if [ !$variable ]

当前回答

你可以使用shFlags。

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

例子:

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

在命令行中你可以定义:

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

其他回答

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

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

所以答案很明确。在Bash中没有任何布尔变量。

然而:

使用declare语句,可以将赋值限制为 变量。[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"

declare和readonly中的r选项用于显式声明变量为只读。我希望目的很明确。

博士TL;

my_bool=true

if [ "$my_bool" = true ]

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

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

假设我们有以下条件。

if $var; then
  echo 'Muahahaha!'
fi

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

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

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

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

这里有一个无害的例子:

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

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

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

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

赫巴的回答有问题

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

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

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

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

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

我的建议是:

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

my_bool=true

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

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

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

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


脚注

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

长话短说:

Bash中没有布尔值

true和false命令

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

无论你在Bash中看到真或假,它要么是一个字符串,要么是一个命令/内置,它只用于退出代码。

这语法…

if true; then ...

本质上是…

if COMMAND; then ...

其中命令为true。当命令返回退出代码0时,条件为真。true和false是Bash内置的,有时也是独立的程序,它们什么都不做,只返回相应的退出码。


条件在if..then..fi

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

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

对应于

if COMMAND; then echo yes; fi

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

如果…那么…Fi构念只是语法糖。你可以用双&号分隔命令来运行同样的效果:

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

当在这些测试结构中使用true和false时,您实际上只是将字符串“true”或“false”传递给测试命令。这里有一个例子:

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

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

TL,博士;总是与字符串或数字进行比较

为了让未来的读者更清楚地了解这一点,我建议在真假周围使用引号:

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

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

也许

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

修正答案(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 builtin true的评论只适用于原始答案,而不适用于修改后的答案。

Bash确实将问题与[,[[,((,$((等))等混淆了。

所有人都在践踏彼此的代码空间。我想这主要是历史原因,巴什不得不偶尔装成。

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

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

你必须遵守纪律。你的testvar必须在任何时候都被设置为$TRUE或$FALSE。 在(……))比较器,你不需要前面的$,这使得它更可读。 我可以用(…)),因为$TRUE=1和$FALSE=0,即数值。 缺点是不得不偶尔使用$: 真正testvar = $ 这可不太好。

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