如何在 Bash 脚本中将函数的输出设置为变量值?

如何在 Bash 脚本中将函数的输出设置为变量值?

我有以下函数来计算我的 bash 脚本中的目录中的文件数量。

file_count() {
  no_of_files=$(find "$1" -maxdepth 1 -type f -printf '.' | wc -c)
}

我想在不同的目录中重复使用它,并将计数保存到每个目录的变量中。目前,为了做到这一点,我使用

file_count $somedir
files_in_somedir="$no_of_files"

我知道我每次都在函数之外设置变量,并且想将其设置为函数的本地变量,而不是在主脚本中设置中间变量。这只是为了防止出现一些错误,即变量在函数调用之间没有改变(可能是函数名称输入错误),并且使用no_of_files旧的值。no_of _files

如果我的功能是:

file_count() {
  local no_of_files=$(find "$1" -maxdepth 1 -type f -printf '.' | wc -c)
}

我如何轻松设置这些目录数变量?

答案1

Bash 函数与其他编程语言中的函数不同,它们更像命令。这意味着它们没有经典的返回值,但是

  • 退出/返回代码。这是 0-255 范围内的整数,其中 0 表示“成功”,其他所有值都表示错误。如果您尝试指定超出此范围的数字,则会将其取模 256(从您的数字中加或减 255,直到符合 0-255 的范围)。

    此代码会自动设置为函数内部执行的最后一条语句的返回代码,除非您使用以下命令手动设置它return,如下所示:

    return 1
    
  • 输出流。每个 Bash 函数都可以将任意字符串写入输出流(STDOUT 和 STDERR),就像普通脚本一样。输出可以直接来自您在函数中运行的命令,也可以使用 手动设置echo

    但是,您不必让该输出显示在控制台中,而是可以在运行函数时捕获它,例如使用 Bash 的命令替换语法,并将其存储在主脚本中的变量中:

    example_function() {
        # do something useful
        echo "return this message"
    }
    
    returned_value="$(example_function)"
    

因此你的代码必须看起来像这样:

file_count() {
    find "$1" -maxdepth 1 -type f -printf '.' | wc -c
    # the line above already prints the desired value, so we don't need an echo
}

files_in_somedir="$(file_count "$somedir")"

Bash 脚本中的返回值(在 Stack Overflow 上)了解更多信息。

答案2

我是一名C++程序员,所以我喜欢模仿“getter 和 setter“哲学,使用微小的函数来获取和设置变量的值。我知道有一些不可移植的解决方案,比如 的新版本declare,但我喜欢只编写可移植的代码。使用 getter 和 setter 的缺点是您需要为每个要管理的值创建一个函数(或两个函数)。所以......我制作了一个“工厂函数”,为您处理创建 getter/setter(见下文)。然后,您只需删除用于设置的等号,其他一切看起来都非常相似(参见usage)......除了现在,您可以将“类似指针的东西”传递到函数中。

makeGetSet() {
. /dev/fd/0 <<END_FUNC
${1}Val()  { [ "\${1}" ] && ${1}="\${1}" || echo "\${${1}}"; }
END_FUNC
}

用法:

Setup: makeGetSet myVariable
Set: myVariableVal newValue
Get: anotherVariable="`myVariableVal`"
Print: myVariableVal

它不需要任何具有特殊功能(如间接或namerefs,或declare实用程序)的特定 shell(100%POSIX)。您只需将变量名称传递给makeGetSet,您的 getter/setter 函数就会使用相同的名称,并Val在末尾添加“ ”(例如myVariableVal)。已使用bash和进行测试dash

对于您的具体问题,您可以像这样使用它:

makeGetSet files_in_somedir

file_count() {
  "${2}" $(find "$1" -maxdepth 1 -type f -printf '.' | wc -c)
}

file_count "/some/directory" files_in_somedirVal

相关内容