如何使用布尔参数调用bash函数?

4

我有一个名为install_cont的函数,它从我的bash脚本中被调用两次。然而,在该函数内部,如果布尔参数为真,我只想执行代码块。在Python中我会这样做:


```python def install_cont(param): if param: # execute this code block only if param is true ```

如何在Bash中实现这个功能呢?

def install_cont(expres=False):
    if expres:
         # Do some code...

install_cont(True)
install_cont() # Can call with default False

我该如何在bash中实现这个功能?从网上阅读资料,我了解到所有的变量都是字符串。但是,如何实现类似布尔类型的参数呢?


“bash” 本来就没有布尔值。它只有字符串。选择任何你喜欢的字符串,并在函数内适当处理它。 - chepner
将其中一个设为默认情况,对于另一个,则传递一个可选参数并在脚本中检查该参数的存在。 - karakfa
5个回答

8

Shell脚本没有布尔值,但是有一种表示成功的约定,即用一个整数表示。对于从其他语言转换过来的程序员来说,这可能会令人困惑,因为在shell scripting中,0代表成功,而任何其他的整数代表失败。

这是if条件控制结构的基础,它运行一个命令并检查其结果是否成功。你不能直接用if测试一个变量,但是你可以使用test内置命令,如果某个特定的测试通过,它就会"成功"。

test还可以写成[,所以你经常会看到带有if [ ... ]的代码 - 这些括号不是if语法的一部分,它们只是一个名称奇怪的命令。(Bash还有一个带有一些额外功能的[[内置命令,但是[更加标准,所以值得学习。)

test命令可以执行各种测试 - 检查数字、检查文件系统等。对于命令行选项,你可以使用=二元运算符与字符串truefalse进行比较。

所以你最终会得到如下代码:

install_cont() {
    # Name the parameter for convenience
    local expres="$1";

    if [ "$expres" = "true" ];
    then
         # Do some code...
    fi;
}

install_cont true
install_cont # default will not pass the test

如果您想要更高级的参数,可以使用稍微有些奇怪的${foo:-default}${foo:=default}参数展开语法来设置实际默认值。例如:
install_cont() {
    # Default the mode to "boring"
    local mode="${1:-boring}";

    if [ "$mode" = "exciting" ];
    then
         # Do some code...
    elif [ "$mode" = "boring" ];
    then
         # Do some code...
    else
         echo "Unrecognised mode";
    fi;
}

因为对我尝试解释这个内容所做的更详细的扩展表示赞同。 - Yokai
为什么要撤销多余分号的删除?没有人应该编写这样的脚本。 - Jens
@Jens Meh,也许撤销是不必要的,但我通常更喜欢在不需要分号的地方使用它们,而不是学习关于何时可能或不可能使用它们的规则(对JavaScript挥舞拳头)。如果您因任何原因在一行上编写此代码,则请考虑将其放置在分号应该放置的位置,因为如果您习惯其他语言,则这并不明显-我经常因缺少;或将其放在thendo的错误一侧而得到语法错误。 - IMSoP

0

关于bash和其他Bourne衍生的shell的一个棘手问题是,在ifwhile语句中使用的条件不是表达式。它是一个命令,根据命令成功或失败来处理条件为真或假。命令通过返回退出状态0表示成功,通过返回其他任何内容表示失败。

内置命令truefalse除了返回表示成功或失败的退出状态之外,什么也不做。

[ ... ][[ ... ]]结构可以用于模拟使用表达式作为条件。 [实际上是一个命令,几乎等同于test命令。

如果我需要在bash脚本中使用布尔变量的等效值,我会使用一个变量,其值为字符串true或字符串false。如果我将该变量用作条件,则它会扩展为命令名称truefalse。我只需要小心确保这样的变量永远不会取其他值而不是truefalse

需要记住的是不要使用[ ... ]语法。例如,只有一个参数时

if [ false ] ; then # This is incorrect!

该命令成功是因为false是一个非空字符串。请记住,[]不是if语句的语法部分(尽管它们被设计成看起来像是)。

一个例子:

#!/bin/bash

func() {
    if $1 ; then
        echo In func, the condition is true
    else
        echo In func, the condition is false
    fi
}

func false
func true

输出:

In func, the condition is false
In func, the condition is true

这种技术确实有一些缺点。如果您将变量赋值为除了truefalse之外的其他值,甚至拼写变量名称时出错,它就会失效。与具有内置布尔类型和falsetrue字面值的语言不同,在shell中很可能无法诊断此类错误,导致脚本默默地运行不正常。


只要记住,如果你要将未经信任的来源的输入视为布尔值并执行它们,请不要从这些来源获取任意输入。 - ilkkachu
@ilkkachu 当然可以 - 但是也很容易*意外地将变量的值设置为除了truefalse之外的其他值,或者拼写变量名称时出错。与具有内置布尔类型和falsetrue字面值的语言不同,shell不太可能诊断您的错误。这是这种技术的一个重大缺点。 - Keith Thompson

0

Unix提供了两个命令:

  • true:返回真值(即退出值为0)
  • false:返回假值(即退出值为非0)

您可以在ifwhileuntil结构中使用它们。

例如:

install_cont()
{
    local expres="${1:-false}"    # Default value is false

    if "$expres"; then
        # Do some code...
    else
        # Do something else...
    fi
}

install_cont true
install_cont          # false implied

您正在使用Bash。如果您想要布尔值也在算术运算中有效,那么您可以使用算术布尔值:

declare -i false=0 true=1

cond1="$true"
cond2="$false"
if ((cond1 || cond2)); then
    # Do some code...
fi

个人而言,我不使用算术布尔值,因为我完全满意于truefalse命令。


2
只要记住,如果你要将未经信任的来源的输入视为布尔值并执行它们,请不要从这些来源获取任意输入。 - ilkkachu
@ilkkachu非常正确,但是Bash中有很多安全陷阱,因此在所有情况下都必须对输入进行消毒处理。 - xhienne
1
你错过了一个很好的机会来包含我最喜欢的手册摘要:true - 成功地不做任何事情false - 不成功地不做任何事情 - IMSoP
@IMSoP 有时候,就像此刻一样,我努力什么都不做,但并不总是成功 :-) 顺便说一句,这可能是我第一次打开 GNU manpages 中 true 和 false 的页面,我发现它们甚至为它们的命令提供了通常的 --help--version选项。那些文本可能比剩下的源代码还长... - xhienne
@xhienne 是的,GNU 版本的 true.c 有时被用作不必要膨胀的示例,达到了长达 80 行;公平地说,它还通过 2 行存根文件 false.c 实现了 false - IMSoP

0

可能像这样。

your_func () {
    if [[ $1 ]]; then
        # do things if parameter was present
    fi
    # do unconditional things
}

那么我假设这个检查参数是否存在。这意味着我可以传递任何东西吗?我可以像 your_func 1 这样调用它吗,还是需要引号? - Gilbert Williams
它检查参数是否为非空字符串。对于单个标记,您不需要引用它,但始终引用字符串是一个好习惯;也许还可以参考何时在shell变量周围包装引号? - tripleee

0
Bash本身没有内置的布尔处理功能。它处理字符串和整数。但是,您可以为明确的退出状态代码定义字符串和数字,并通过设计进行伪布尔逻辑。在bash中看到truefalse的任何地方,都是看到具有特定退出代码的结构。由于默认命令退出代码为0或1,除非您分配相反的代码,否则您基本上具有内置方法(即使不是固有目的)来执行布尔逻辑。
使用test命令及其后续的[][[]]将输出0表示true或1表示false。但这些只是退出状态代码。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接