Bash函数中的返回值

我正在使用一个bash脚本,我想执行一个函数来打印一个返回值。

function fun1(){
  return 34
}
function fun2(){
  local res=$(fun1)
  echo $res
}

当我执行fun2时,它没有打印"34"。为什么会出现这种情况?

对该问题的评论 (3)
解决办法

虽然bash有一个return'语句,但你能用它指定的唯一东西是函数自己的exit'状态(一个介于0'和255'之间的值,0意味着"成功")。所以return不是你想要的。

你可能想把你的 "return "语句转换成 "echo "语句--这样你的函数输出可以用"$() "大括号捕获,这似乎正是你想要的。

下面是一个例子。

function fun1(){
  echo 34
}

function fun2(){
  local res=$(fun1)
  echo $res
}

另一种获取返回值的方法(如果你只想返回一个0-255的整数)是$?

function fun1(){
  return 34
}

function fun2(){
  fun1
  local res=$?
  echo $res
}

另外,请注意,你可以使用返回值来使用布尔逻辑,如fun1 || fun2只有在fun1返回0值时才会运行fun2。 默认的返回值是函数内最后执行的语句的退出值。

评论(12)

$(...)捕获其中包含的命令发送到stdout的文本。return不输出到stdout。$?包含最后一条命令的结果代码。

fun1 (){
  return 34
}

fun2 (){
  fun1
  local res=$?
  echo $res
}
评论(2)

Bash中的函数并不像其他语言中的函数。 它们实际上是命令. 所以函数的使用就像从你的路径中获取的二进制文件或脚本一样。 从你的程序逻辑的角度来看,其实应该没有什么区别。

Shell命令是通过管道(也就是流)来连接的,而不是像"real&quot.编程语言中的基本或用户定义的数据类型。 编程语言中那样。 没有命令的返回值这样的东西,也许主要是因为没有真正的方法来声明它。 它可能出现在man-page上,或者命令的--help输出中,但这两种情况都是只能被人读懂的,因此被写在了风中。

当一个命令想要获得输入时,它从它的输入流,或者参数列表中读取。 在这两种情况下,都要对文本字符串进行解析。

当一个命令想要返回某样东西时,它必须将其echo到它的输出流中。 另一种经常实践的方式是将返回值存储在专用的全局变量中。 写入输出流更清晰、更灵活,因为它也可以接受二进制数据。 例如,你可以很容易地返回一个BLOB。

encrypt() {
    gpg -c -o- $1 # encrypt data in filename to stdout (asks for a passphrase)
}

encrypt public.dat > private.dat # write function result to file

就像其他人在这个帖子里写的那样,调用者也可以使用命令替换$()来捕获输出。

同理,函数会"return" gpg(GnuPG)的退出代码。 把退出代码看作是其他语言所没有的奖励,或者,根据你的脾气,看作是"Schmutzeffekt&quot。 的shell函数。 按照惯例,这个状态在成功时为0,或者在1-255的范围内为整数。 为了明确这一点。 return(像exit)只能取0-255的值,0以外的值不一定是错误的,这一点经常被断言。

当你没有用return提供一个显式的值时,状态是取自Bash语句/函数/命令等中的最后一条命令。 所以总是有一个状态,而return只是提供状态的一个简单方法。

评论(2)

语句 "return "设置了函数的退出代码,与 "exit "对整个脚本的作用相同。

最后一条命令的退出代码总是可以在$?变量中找到。


function fun1(){
  return 34
}

function fun2(){
  local res=$(fun1)
  echo $? # 
评论(0)

其他答案的问题是,它们要么使用全局,当几个函数在一个调用链中时,全局可能会被覆盖,要么使用echo,这意味着你的函数不能输出诊断信息(你会忘记你的函数是这样做的,而"结果",即 返回值,将包含比你的调用者期望的更多的信息,导致奇怪的bug),或者eval,这太重了,太黑了。

正确的方法是把最上层的东西放在一个函数中,然后用bash'的动态作用域规则使用local。 例如:{{195614}。

func1() 
{
    ret_val=hi
}

func2()
{
    ret_val=bye
}

func3()
{
    local ret_val=nothing
    echo $ret_val
    func1
    echo $ret_val
    func2
    echo $ret_val
}

func3

该输出

nothing
hi
bye

动态作用域意味着ret_val根据调用者的不同而指向不同的对象!这与大多数编程语言使用的词法作用域不同。 这和词法作用域不同,大多数编程语言都是用词法作用域。 这其实是一个文档化的功能,只是容易被忽略,而且解释的不是很清楚,这里是它的文档(重点是我的)。

函数本地的变量可以用本地的

内置的。 这些变量只有函数***和函数的

它调用的命令***。

对于有C/C++/Python/Java/C#/javascript背景的人来说,这可能是最大的障碍。 bash中的函数不是函数,而是命令,而且行为也是如此。 它们可以输出到stdout/stderr, 它们可以用管道输入/输出, 它们可以返回一个退出代码. 基本上,在脚本中定义一个命令和创建一个可以在命令行中调用的可执行文件之间没有区别。

所以,不要像这样写脚本。

top-level code 
bunch of functions
more top-level code

这样写道:{{{195617}}}

# define your main, containing all top-level code
main() 
bunch of functions
# call main
main  

其中main()ret_val声明为local,所有其他函数通过ret_val返回值。

也请看下面的Unix & Linux问题。 Shell函数中局部变量的范围

另一个可能更好的解决方案是[ya.teck发布的][2],它使用local -n

1:

[2]: https://stackoverflow.com/a/52678279/869951

评论(0)

另一种方法是 [name references][1] (需要 Bash 4.3+).

function example {
  local -n VAR=$1
  VAR=foo
}

example RESULT
echo $RESULT

[1]: https://www.gnu.org/software/bash/manual/bashref.html#Shell-Parameters

评论(1)

如果在定义了函数的脚本中运行,我喜欢做如下操作。

POINTER= # used for function return values

my_function() {
    # do stuff
    POINTER="my_function_return"
}

my_other_function() {
    # do stuff
    POINTER="my_other_function_return"
}

my_function
RESULT="$POINTER"

my_other_function
RESULT="$POINTER"

我喜欢这样,因为如果我想的话,我可以在我的函数中加入echo语句。


my_function() {
    echo "-> my_function()"
    # do stuff
    POINTER="my_function_return"
    echo "
评论(0)

作为对他人&#39。 的优秀文章,这里有一篇文章总结了这些技术。

  • 设置一个全局变量
  • 设置一个全局变量,你传递给函数的名称是
  • 设置返回码(并用$?
  • 'echo' 一些数据(用MYVAR=$(myfunction)拾取)

[从Bash函数返回值][1]

[1]: https://www.linuxjournal.com/content/return-values-bash-functions

评论(0)

Git BashWindows上使用数组来实现多个的返回值。

BASH代码:


#!/bin/bash

##A 6-element array used for returning
##values from functions:
declare -a RET_ARR
RET_ARR[0]="A"
RET_ARR[1]="B"
RET_ARR[2]="C"
RET_ARR[3]="D"
RET_ARR[4]="E"
RET_ARR[5]="F"

function FN_MULTIPLE_RETURN_VALUES(){

   ##give the positional arguments/inputs
   ##$1 and $2 some sensible names:
   local out_dex_1="$1" ##output index
   local out_dex_2="$2" ##output index

   ##Echo for debugging:
   echo "running: FN_MULTIPLE_RETURN_VALUES"

   ##Here: Calculate output values:
   local op_var_1="Hello"
   local op_var_2="World"

   ##set the return values:
   RET_ARR[ $out_dex_1 ]=$op_var_1
   RET_ARR[ $out_dex_2 ]=$op_var_2
}

echo "FN_MULTIPLE_RETURN_VALUES EXAMPLES:"
echo "-------------------------------------------"
fn="FN_MULTIPLE_RETURN_VALUES"
out_dex_a=0
out_dex_b=1
eval $fn $out_dex_a $out_dex_b  ##
评论(0)