在 shell 中跳出嵌套函数

在 shell 中跳出嵌套函数

如果我有一系列嵌套函数,如何从最内层的函数中脱离出所有函数?

编辑:忙于研究内置的“陷阱”......

答案1

实现此目的的一种相当丑陋但简单的方法是定义 STOP 变量并在每次函数调用后检查它:

a ()
{
    echo a
    b; [[ "$STOP" == 1 ]] && return
    a; [[ "$STOP" == 1 ]] && return
}

b ()
{
    echo b
    c; [[ "$STOP" == 1 ]] && return
    b; [[ "$STOP" == 1 ]] && return
}

c ()
{
    echo c
    STOP=1; return
}

a
echo d

虽然不太漂亮,但它在 bash 和 zsh 中可以运行。

答案2

这是一个不一定可移植的 hack,它跳过所有必需的级别,绕过所有RETURN陷阱,有效地防止返回除 0 之外的任何内容,并且至少在某些方面可能是一个错误。此特定实现仅适用于 Bash,但可以适用于其他 shell。

function f {
    printf 'Current level: %d\n' ${n:+"$1"}
    if [[ $FUNCNAME != "${FUNCNAME[1]}" ]]; then
        [[ $1 == +([[:digit:]]) ]] || return 1
        typeset n=$1
        while ! f 1; do :; done
        unset -v n
    elif (( n - $1 )); then
        f $(($1 + 1))
    else
        trap 'printf "Returning from level: %d\n" ${n+"$1"}' RETURN
        # return # toggle
        break
    fi
}

f "${1:-5}"

输出

Current level: 0
Current level: 1
Current level: 2
Current level: 3
Current level: 4
Current level: 5
Returning from level: 0

答案3

当然,它可以以“经典”(类似 C 的错误处理)方式完成,即:

  1. 从带有状态代码的函数返回。
  2. 每次函数调用后检查状态代码并执行相应操作。

如果我们只需要非零状态代码(又名错误),
我们可以使用|| command
而不是if [ $? != 0 ]; then command; fi
使其简短而干净:

    f1(){
        f2(){
            if [ "${things_went_wrong}" == y ]; then echo "Sorry!"; return 1; fi
        }
        f2 some arguments || return 1
    }
f1 some arguments || return 1

希望有所帮助。

答案4

我选择将所有逻辑存储在单独的 shell 脚本中,而不是使用函数。Exit 将完全脱离脚本并允许包装器脚本继续执行。

相关内容