bash 函数中的隐式返回?

bash 函数中的隐式返回?

假设我有一个像这样的 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()系统调用的参数是 an int,因此值至少包含 -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-1233 -1-2,-3无效选项。

    由于 pdksh 及其衍生产品(如 OpenBSDshposh)保留 中的负数$?,这意味着当包含负数时执行操作return "$?"将会失败(当最后运行的命令是返回负数的函数时会发生这种情况)。$?

    所以return -- "$?"在那些贝壳里会更好。但请注意,虽然大多数 shell 支持该语法,但该语法不是 POSIX,并且实际上不受mkshash 衍生物支持。

    因此,总而言之,使用基于 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
    

相关内容