函数的本地`set -e`

PSk*_*cik 11 shell bash zsh

是否有这样的功能,或者可以很容易地模拟它吗?我想要相同的行为,除了它应该return在哪里set -e导致调用exit.

yae*_*shi 12

子外壳可能有用。

func() {(set -e
        echo a
        ehco b
        echo c
)}

func
func
func
Run Code Online (Sandbox Code Playgroud)

这个脚本产生:

a
script.sh: line 3: ehco: command not found
a
script.sh: line 3: ehco: command not found
a
script.sh: line 3: ehco: command not found
Run Code Online (Sandbox Code Playgroud)

或者,您可能对bash 中的 try/catch 实现感兴趣。

  • 在这种情况下不需要大括号:`func () ( ... )` 是等价的。请注意,由于该函数是在子 shell 中执行的,因此其变量分配、重定向等不会影响调用者。 (5认同)
  • 如果你运行 `func && foo`、`if func then ... fi` 或依赖于 `func` 退出状态的类似结构,这将无法提前退出。[见说明](http://unix.stackexchange.com/a/65564/85237)。 (2认同)

Gil*_*il' 8

您可以设置ERR陷阱,每当命令返回非零状态时就会执行该陷阱。

在 bash 中,它有点繁琐,因为陷阱不是函数本地的。默认情况下,子shell或子函数不继承陷阱;呼吁set -E改变这一点。这是一些演示代码。

#!/bin/bash

subroutine () {
  false
  echo "Subroutine continued after status $?"
}

trapper () {
  local i ret
  trap 'ret=$?
        echo "Command $BASH_COMMAND returned status $ret"
        for ((i=0; i<$((${#FUNCNAME[@]}-1)); i++)) do
          echo "  from ${FUNCNAME[$i]} at ${BASH_SOURCE[$((i+1))]} line ${BASH_LINENO[$((i+1))]}"
        done
        return $ret' ERR
  trap 'ret=$?; trap - ERR RETURN; return $ret' RETURN
  echo ok
  subroutine
  echo "By default, the ERR trap is not inherited"
  false
  echo "You won't see this"
}

main () {
  trapper
  echo "trapper returned status $?"
  false
  echo "still there"
}

main
Run Code Online (Sandbox Code Playgroud)

在 zsh 中,您可以定义TRAPZERR函数而不是为ERR(为了兼容性)或ZERR(在具有称为信号的系统上设置陷阱SIGERR——我不知道)。但是,如果您只想立即返回(而不是例如打印错误消息),则更简单:只需设置err_return选项即可。选项默认是全局的;设置local_options选项以使其成为调用函数的本地local_options选项(如果该选项在函数返回时设置,则从调用函数时起的选项将被恢复)。默认情况下,陷阱也是全局的。选项和陷阱在函数调用中继承。

myfunction () {
  setopt local_options err_return
  false
  echo not executed
}
Run Code Online (Sandbox Code Playgroud)


Sté*_*las 6

使用ksh93,如果您使用ksh自己的语法定义函数 ( function f {...;}),则选项和陷阱具有局部作用域。所以在那里,你可以这样做:

function f {
  trap 'return 99' ERR
  set -e
  echo foo
  false
  echo never output
}
f
echo "f exited with status $?"
Run Code Online (Sandbox Code Playgroud)

这使:

foo
f exited with status 99
Run Code Online (Sandbox Code Playgroud)