猛击。返回两个函数级别(两个嵌套调用)

Osc*_*vis 3 bash nested function-call

我需要知道 Bash 是否有针对我的情况的解决方案。我需要在某些条件后进行“双重回报”。我的意思是,执行函数的返回并返回父函数以跳过该父函数的其余代码。

我知道我可以使用函数返回值进行条件操作来实现此目的。但我想知道 Bash 中是否存在类似“break 2”的函数。如果可能的话,我不想修改父函数的代码,因为正如你可以想象的,在我的真实脚本中有几十个函数,我不想修改所有函数。

例子:

#!/bin/bash

function sublevelone() {
    echo "sublevelone"
    # Return 2, or break 2 or something :D
}

function main() {
    sublevelone
    echo "This is the part of the code to being avoid executed"
}

main
Run Code Online (Sandbox Code Playgroud)

jhn*_*hnc 5

我不知道 bash 专家会怎么想,但这至少适用于简单的情况:

\n
multireturn(){\n    [ -n "$1" ] && poplevel="$1"\n    if [ "$poplevel" -ge 0 ]; then\n        trap multireturn DEBUG\n        shopt -s extdebug\n        (( poplevel-- ))\n        return 2\n    else\n        shopt -u extdebug\n        trap - DEBUG\n        return 0\n    fi\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这利用了 DEBUG 陷阱和extdebug标志:

\n
\ntrap [-lp] [[arg] sigspec ...]\n [...] 如果 sigspec 是 DEBUG,则命令 arg 是 exe\xe2\x80\x90\n 在每个简单命令之前切割,对于命令, case 命令、\n 选择命令、命令的每个算术以及在 shell 函数中执行\n 第一个命令之前 [...]\n
\n
\nshopt [-pqsu] [-o] [optname ...]\n [...]\n extdebug\n 如果在 shell 调用时或在 shell 启动文件中设置,\n 安排在之前执行调试器配置文件shell\n 启动,与 --debugger 选项相同。如果在调用后设置 af\xe2\x80\x90\n,则将启用供调试器\n 使用的行为:\n [...]\n 2. 如果 DEBUG 陷阱运行的命令返回\n 非值为零,则跳过下一个命令,\n 不执行。\n 3. 如果 DEBUG 陷阱运行的命令返回值\n 2,并且 shell 正在 sub\xe2\x80\x90\n 中执行例程(由 . 或 source 内置函数剪切的 shell 函数或 shell 脚本 exe\xe2\x80\x90\n),shell\n 模拟调用 return。\n [...]\n 5. 函数跟踪已启用: 命令替换\xe2\x80\x90\n 和 shell 函数以及使用\n ( command ) 调用的子 shell 继承 DEBUG 和 RETURN 陷阱。\n
\n

用法示例:

\n
#!/bin/bash\n\nmultireturn(){\n    [ -n "$1" ] && poplevel="$1"\n    if [ "$poplevel" -ge 0 ]; then\n        trap multireturn DEBUG\n        shopt -s extdebug\n        (( poplevel-- ))\n        return 2\n    else\n        shopt -u extdebug\n        trap - DEBUG\n        return 0\n    fi\n}\n\n# define 8 levels of function calls\n# (level N prints output, calls level N+1, then prints more output)\nfor i in $(seq 1 8); do\n    eval \\\n\'level\'$i\'(){\n    echo -n " \'$i\'"\n    level\'$((i+1))\'\n    echo -n "(\'$i\')"\n}\'\ndone\n\n# final level calls multireturn\nlevel9(){\n    echo -n " 9"\n    multireturn $n\n    echo -n "(9)"\n}\n\n# test various skip amounts\nfor i in $(seq 0 10); do\n    echo -n "$i:"\n    n=$i\n    level1\n    echo .\ndone\n\necho\necho done\n
Run Code Online (Sandbox Code Playgroud)\n

结果:

\n
0: 1 2 3 4 5 6 7 8 9(9)(8)(7)(6)(5)(4)(3)(2)(1).\n1: 1 2 3 4 5 6 7 8 9(8)(7)(6)(5)(4)(3)(2)(1).\n2: 1 2 3 4 5 6 7 8 9(7)(6)(5)(4)(3)(2)(1).\n3: 1 2 3 4 5 6 7 8 9(6)(5)(4)(3)(2)(1).\n4: 1 2 3 4 5 6 7 8 9(5)(4)(3)(2)(1).\n5: 1 2 3 4 5 6 7 8 9(4)(3)(2)(1).\n6: 1 2 3 4 5 6 7 8 9(3)(2)(1).\n7: 1 2 3 4 5 6 7 8 9(2)(1).\n8: 1 2 3 4 5 6 7 8 9(1).\n9: 1 2 3 4 5 6 7 8 9.\n10: 1 2 3 4 5 6 7 8 9\ndone\n
Run Code Online (Sandbox Code Playgroud)\n
\n

请注意,每个将被短路的函数在调用multireturn(或调用它的函数)之后都应至少包含一个附加命令。如果没有,DEBUG 陷阱将在错误的上下文中被调用,并且将跳过额外的级别。例如,比较一下删除echo -n "(\'$i\')"echo -n "(9)"行后会发生什么情况。

\n

另请注意,这multireturn不可重入的

\n