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

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

当我执行fun2时,它不会打印“34”。为什么会这样呢?


当前回答

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

最后一个命令的退出码总是在$?变量。

function fun1(){
  return 34
}

function fun2(){
  local res=$(fun1)
  echo $? # <-- Always echos 0 since the 'local' command passes.

  res=$(fun1)
  echo $?  #<-- Outputs 34
}

其他回答

尽管Bash有一个返回语句,但你唯一可以用它指定的是函数自己的退出状态(0到255之间的值,0表示“成功”)。所以返回不是你想要的。

您可能希望将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。默认返回值是函数中执行的最后一条语句的退出值。

$(…)捕获其中包含的命令发送到标准输出的文本。返回不输出到标准输出。$ ?包含最后一个命令的结果代码。

fun1 (){
  return 34
}

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

作为对其他人优秀文章的补充,这里有一篇文章总结了这些技巧:

设置一个全局变量 设置一个全局变量,将其名称传递给函数 设置返回代码(并使用$?) 'echo'一些数据(并使用MYVAR=$(myfunction)获取它)

从Bash函数返回值

Git Bash在Windows上使用数组表示多个返回值

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  ## <-- Call function
a=${RET_ARR[0]} && echo "RET_ARR[0]: $a "
b=${RET_ARR[1]} && echo "RET_ARR[1]: $b "
echo
## ---------------------------------------------- ##
c="2"
d="3"
FN_MULTIPLE_RETURN_VALUES $c $d ## <--Call function
c_res=${RET_ARR[2]} && echo "RET_ARR[2]: $c_res "
d_res=${RET_ARR[3]} && echo "RET_ARR[3]: $d_res "
echo
## ---------------------------------------------- ##
FN_MULTIPLE_RETURN_VALUES 4 5  ## <--- Call function
e=${RET_ARR[4]} && echo "RET_ARR[4]: $e "
f=${RET_ARR[5]} && echo "RET_ARR[5]: $f "
echo
##----------------------------------------------##


read -p "Press Enter To Exit:"

预期的输出:

FN_MULTIPLE_RETURN_VALUES EXAMPLES:
-------------------------------------------
Running: FN_MULTIPLE_RETURN_VALUES
RET_ARR[0]: Hello
RET_ARR[1]: World

Running: FN_MULTIPLE_RETURN_VALUES
RET_ARR[2]: Hello
RET_ARR[3]: World

Running: FN_MULTIPLE_RETURN_VALUES
RET_ARR[4]: Hello
RET_ARR[5]: World

Press Enter To Exit:

Bash中的函数不同于其他语言中的函数;它们实际上是命令。因此,函数就像从路径中获取的二进制文件或脚本一样使用。从程序逻辑的角度来看,实际上不应该有任何区别。

Shell命令是通过管道(又名流)连接的,而不是像“真正的”编程语言中那样,由基本或用户定义的数据类型连接。没有命令的返回值这样的东西,可能主要是因为没有真正的方法来声明它。它可能出现在命令的手册页或——help输出中,但两者都是人类可读的,因此被写入到风中。

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

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

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

encrypt public.dat > private.dat # Write the function result to a file

正如其他人在这个线程中所写的那样,调用者还可以使用命令替换$()来捕获输出。

同时,该函数将“返回”gpg (GnuPG)的退出代码。可以将退出码视为其他语言没有的额外功能,或者根据您的喜好,将其视为shell函数的“Schmutzeffekt”。按照惯例,这个状态在成功时为0,在其他情况下为1-255范围内的整数。要明确一点:return(像exit)只能接受0-255之间的值,而不是0的值不一定是错误,这是经常断言的。

当您没有使用return提供显式值时,状态将从Bash语句/函数/命令中的最后一条命令中获取。所以总是有一个状态,返回只是提供它的一个简单方法。