Bash 函数中的返回值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17336915/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Return value in a Bash function
提问by mindia
I am working with a bash script and I want to execute a function to print a return value:
我正在使用 bash 脚本,我想执行一个函数来打印返回值:
function fun1(){
return 34
}
function fun2(){
local res=$(fun1)
echo $res
}
When I execute fun2
, it does not print "34". Why is this the case?
当我执行时fun2
,它不会打印“34”。为什么会这样?
回答by tamasgal
Although bash has a return
statement, the only thing you can specify with it is the function's own exit
status (a value between 0
and 255
, 0 meaning "success"). So return
is not what you want.
尽管 bash 有一条return
语句,但您唯一可以用它指定的是函数自身的exit
状态(介于0
和之间的值255
,0 表示“成功”)。所以return
不是你想要的。
You might want to convert your return
statement to an echo
statement - that way your function output could be captured using $()
braces, which seems to be exactly what you want.
您可能希望将return
语句转换为echo
语句 - 这样就可以使用$()
大括号捕获函数输出,这似乎正是您想要的。
Here is an example:
下面是一个例子:
function fun1(){
echo 34
}
function fun2(){
local res=$(fun1)
echo $res
}
Another way to get the return value (if you just want to return an integer 0-255) is $?
.
获取返回值的另一种方法(如果您只想返回一个 0-255 的整数)是$?
.
function fun1(){
return 34
}
function fun2(){
fun1
local res=$?
echo $res
}
Also, note that you can use the return value to use boolean logic like fun1 || fun2
will only run fun2
if fun1
returns a 0
value. The default return value is the exit value of the last statement executed within the function.
另外,请注意,您可以使用返回值来使用布尔逻辑,例如fun1 || fun2
仅fun2
在fun1
返回0
值时才运行。默认返回值是函数内执行的最后一条语句的退出值。
回答by Ignacio Vazquez-Abrams
$(...)
captures the text sent to stdout by the command contained within. return
does not output to stdout. $?
contains the result code of the last command.
$(...)
捕获由其中包含的命令发送到 stdout 的文本。return
不输出到标准输出。$?
包含最后一条命令的结果代码。
fun1 (){
return 34
}
fun2 (){
fun1
local res=$?
echo $res
}
回答by Andreas Spindler
Functions in Bash are not functions like in other language; they're actually commands. So functions are used as if they were binaries or scripts fetched from your path. From the perspective of your program logic there should be really no difference.
Bash 中的函数不同于其他语言中的函数;它们实际上是命令。因此,函数的使用就好像它们是从您的路径中获取的二进制文件或脚本一样。从你的程序逻辑的角度来看,应该没有什么区别。
Shell commands are connected by pipes (aka streams), and not fundamental or user-defined data types, as in "real" programming languages. There is no such thing like a return value for a command, maybe mostly because there's no real way to declare it. It could occur on the man-page, or the --help
output of the command, but both are only human-readable and hence are written to the wind.
Shell 命令通过管道(又名流)连接,而不是像在“真正的”编程语言中那样的基本或用户定义的数据类型。没有像命令的返回值这样的东西,可能主要是因为没有真正的方法来声明它。它可能出现在手册页或--help
命令的输出中,但两者都只是人类可读的,因此被写入风中。
When a command wants to get input it reads it from its input stream, or the argument list. In both cases text strings have to be parsed.
当一个命令想要获取输入时,它会从它的输入流或参数列表中读取它。在这两种情况下,都必须解析文本字符串。
When a command wants to return something it has to echo
it to its output stream. Another oftenly practiced way is to store the return value in dedicated, global variables. Writing to the output stream is clearer and more flexible, because it can take also binary data. For example, you can return a BLOB easily:
当一个命令想要返回一些它必须返回echo
到它的输出流时。另一种常用的方法是将返回值存储在专用的全局变量中。写入输出流更清晰、更灵活,因为它也可以采用二进制数据。例如,您可以轻松返回 BLOB:
encrypt() {
gpg -c -o- # encrypt data in filename to stdout (asks for a passphrase)
}
encrypt public.dat > private.dat # write function result to file
As others have written in this thread, the caller can also use command substitution $()
to capture the output.
正如其他人在此线程中所写的那样,调用者还可以使用命令替换$()
来捕获输出。
Parallely, the function would "return" the exit code of gpg
(GnuPG). Think of the exit code as a bonus that other languages don't have, or, depending on your temperament, as a "Schmutzeffekt" of shell functions. This status is, by convention, 0 on success or an integer in the range 1-255 for something else. To make this clear: return
(like exit
) can only take a value from 0-255, and values other than 0 are not necessarily errors, as is often asserted.
同时,该函数将“返回” gpg
(GnuPG)的退出代码。将退出代码视为其他语言没有的奖励,或者,根据您的气质,将其视为 shell 函数的“Schmutzeffekt”。按照惯例,此状态是 0 表示成功,或者是 1-255 范围内的整数(表示其他情况)。明确这一点:(return
如exit
)只能取 0-255 之间的值,并且 0 以外的值不一定是错误,正如经常断言的那样。
When you don't provide an explicit value with return
the status is taken from the last command in a Bash statement/function/command and so forth. So there is always a status, and return
is just an easy way to provide it.
当您不提供显式值时return
,状态取自 Bash 语句/函数/命令等中的最后一个命令。所以总是有一个状态,并且return
只是一种提供它的简单方法。
回答by Austin Phillips
The return
statement sets the exit code of the function, much the same as exit
will do for the entire script.
该return
语句设置函数的退出代码,与exit
对整个脚本所做的非常相似。
The exit code for the last command is always available in the $?
variable.
最后一个命令的退出代码始终在$?
变量中可用。
function fun1(){
return 34
}
function fun2(){
local res=$(fun1)
echo $? # <-- Always echos 0 since the 'local' command passes.
res=$(fun1)
echo $? #<-- Outputs 34
}
回答by Oliver
The problem with other answers is they either use a global, which can be overwritten when several functions are in a call chain, or echo
which means your function cannot output diagnostic info (you will forget your function does this and the "result", i.e. return value, will contain more info than your caller expects, leading to weird bug), or eval
which is way too heavy and hacky.
其他答案的问题是它们要么使用全局变量,当多个函数在调用链中时,它可以被覆盖,或者echo
这意味着你的函数不能输出诊断信息(你会忘记你的函数这样做和“结果”,即返回值,将包含比您的调用者预期的更多的信息,导致奇怪的错误),或者eval
太重和太笨拙。
The proper way to do this is to put the top level stuff in a function and use a local
with bash's dynamic scoping rule. Example:
这样做的正确方法是将顶级内容放在函数中,并使用local
bash 的动态范围规则。例子:
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
This outputs
这输出
nothing
hi
bye
Dynamic scoping means that ret_val
points to a different object depending on the caller! This is different from lexical scoping, which is what most programming languages use. This is actually a documented feature, just easy to miss, and not very well explained, here is the documentation for it (emphasis is mine):
动态范围意味着ret_val
根据调用者指向不同的对象!这与大多数编程语言使用的词法范围不同。这实际上是一个记录在案的功能,只是很容易错过,而且没有很好地解释,这是它的文档(重点是我的):
Variables local to the function may be declared with the local builtin. These variables are visible only to the function and the commands it invokes.
函数的局部变量可以用 local 内置函数声明。这些变量仅对函数及其调用的命令可见。
For someone with a C/C++/Python/Java/C#/javascript background, this is probably the biggest hurdle: functions in bash are not functions, they are commands, and behave as such: they can output to stdout
/stderr
, they can pipe in/out, they can return an exit code. Basically there is no difference between defining a command in a script and creating an executable that can be called from the command line.
对于有 C/C++/Python/Java/C#/javascript 背景的人来说,这可能是最大的障碍:bash 中的函数不是函数,它们是命令,并且行为如下:它们可以输出到stdout
/ stderr
,它们可以输入/out,他们可以返回退出代码。在脚本中定义命令和创建可以从命令行调用的可执行文件之间基本上没有区别。
So instead of writing your script like this:
因此,不要像这样编写脚本:
top-level code
bunch of functions
more top-level code
write it like this:
像这样写:
# define your main, containing all top-level code
main()
bunch of functions
# call main
main
where main()
declares ret_val
as local
and all other functions return values via ret_val
.
wheremain()
声明ret_val
为local
,所有其他函数通过ret_val
.
See also the following Unix & Linux question: Scope of Local Variables in Shell Functions.
另请参阅以下 Unix 和 Linux 问题:Shell 函数中的局部变量范围。
Another, perhaps even better solution depending on situation, is the one posted by ya.teckwhich uses local -n
.
根据情况,另一种可能更好的解决方案是ya.teck 发布的使用local -n
.
回答by ya.teck
Another way to achive this is name references(requires Bash 4.3+).
实现此目的的另一种方法是名称引用(需要 Bash 4.3+)。
function example {
local -n VAR=
VAR=foo
}
example RESULT
echo $RESULT
回答by doc
I like to do the following if running in a script where the function is defined:
如果在定义函数的脚本中运行,我喜欢执行以下操作:
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"
I like this, becase I can then include echo statements in my functions if I want
我喜欢这个,因为如果我愿意,我可以在我的函数中包含 echo 语句
my_function() {
echo "-> my_function()"
# do stuff
POINTER="my_function_return"
echo "<- my_function. $POINTER"
}
回答by Tom Hundt
As an add-on to others' excellent posts, here's an article summarizing these techniques:
作为其他人优秀帖子的补充,这里有一篇总结这些技术的文章:
- set a global variable
- set a global variable, whose name you passed to the function
- set the return code (and pick it up with $?)
- 'echo' some data (and pick it up with MYVAR=$(myfunction) )
- 设置全局变量
- 设置一个全局变量,你传递给函数的名字
- 设置返回代码(并用 $ 选择它?)
- “回显”一些数据(并使用 MYVAR=$(myfunction) 获取)
回答by J.M.I. MADISON
Git Bashon Windowsusing arrays for multiplereturn values
Windows上的Git Bash使用数组获取多个返回值
BASH CODE:
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
## and some sensible names:
local out_dex_1="" ##output index
local out_dex_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:"
EXPECTED OUTPUT:
预期产出:
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: