假设我有一个像这样的 bash 函数:
gmx(){
echo "foo";
}
该函数是否会隐式返回命令的退出值echo
,或者是否需要使用 return ?
gmx(){
echo "foo";
return $?
}
我假设 bash 的工作方式是,bash 函数的最终命令的退出状态是“返回”的状态,但不是 100% 确定。
答案1
return
做一个明确的从 shell 函数或“点脚本”(源脚本)返回。如果return
不执行,则在 shell 函数或点脚本末尾隐式返回。
如果return
不带参数执行,则相当于返回最近执行的命令的退出状态。
这就是return
所有 POSIX shell 中的工作原理。
例如,
gmx () {
echo 'foo'
return "$?"
}
因此相当于
gmx () {
echo 'foo'
return
}
这与以下相同
gmx () {
echo 'foo'
}
一般来说,您很少需要使用$?
它。实际上,仅当您需要保存它以供将来使用时才需要它,例如,如果您需要多次调查其值(在这种情况下,您会将其值分配给变量并对该变量执行一系列测试)。
答案2
从bash(1)
手册页:
执行时,函数的退出状态是函数体中执行的最后一个命令的退出状态。
答案3
我将在已经提供的答案中添加一些注意事项:
尽管
return
对 shell 具有非常特殊的含义,但从语法的角度来看,它是 shell 内置命令,并且 return 语句的解析方式与任何其他简单命令一样。因此,这意味着就像任何其他命令的参数一样,$?
当不加引号时,将受到 split+glob 的影响所以你需要引用它
$?
来避免它:return "$?"
return
通常不接受任何选项(ksh93
's 接受通常的--help
,--man
,--author
... 但)。它期望的唯一参数(可选)是返回码。接受的返回码的范围因 shell 而异,并且是否正确反映 0..255 之外的任何值$?
也因 shell 而异。看进程终止时的默认退出代码?详细信息。大多数 shell 接受负数(毕竟,传递给
_exit()
/exitgroup()
系统调用的参数是 anint
,因此值至少包含 -2 31到 2 31 -1,因此 shell 接受相同范围的函数才有意义) 。大多数 shell 使用
waitpid()
and co。用于检索退出状态的 API,但是在这种情况下,它会被截断为 0 到 255 之间的数字已存储在$?
。尽管调用函数不涉及生成进程并用于waitpid()
检索其退出状态,因为所有操作都是在同一个进程中完成的,但许多 shellwaitpid()
在调用函数时也会模仿该行为。这意味着即使您return
使用负值调用,$?
也会包含正数。现在,在那些接受负数的 shell 中
return
(ksh88、ksh93、bash、zsh、pdksh 以及除 mksh、yash 之外的衍生物),有一些(pdksh 和 yash)需要将其写return -- -123
为-123
3-1
,-2
,-3
无效选项。由于 pdksh 及其衍生产品(如 OpenBSD
sh
或posh
)保留 中的负数$?
,这意味着当包含负数时执行操作return "$?"
将会失败(当最后运行的命令是返回负数的函数时会发生这种情况)。$?
所以
return -- "$?"
在那些贝壳里会更好。但请注意,虽然大多数 shell 支持该语法,但该语法不是 POSIX,并且实际上不受mksh
ash 衍生物支持。因此,总而言之,使用基于 pdksh 的 shell,您可以在函数参数中使用负数,但如果这样做,
return "$@"
将无法工作。在其他 shell 中,return "$@"
会起作用,您应该避免使用负数(或 0..255 之外的数字)作为 的参数return
。在我知道的所有 shell 中,
return
从函数内运行的子 shell 内部调用将导致子 shell 退出(如果有的话,则使用提供的退出状态或最后运行的命令的退出状态),但不会以其他方式导致从函数返回(对我来说,不清楚 POSIX 是否给你这样的保证,有些人认为exit
应该使用它来退出函数内的子 shell)。例如f() { (return 3) echo "still inside f. Exit status: $?" } f echo "f exit status: $?"
将输出:
still inside f. Exit status: 3 f exit status: 0