Shell如何根据变量值选择执行脚本段 实现类goto分支逻辑
Shell 没有原生的类 C 语言 goto 语句,但你要实现的「根据用户输入选择执行对应代码段」的需求,根本不需要 goto,用 Shell 原生的流程控制就可以清晰实现。
先指出你原有代码的几个明显问题:
- 第一个选择X/W的循环没有设置合法输入后的跳出逻辑,会无限循环要求用户输入,永远走不到后面的确认流程
server=$x、server=$w中引用的$x、$w是未定义变量,你实际需要的是给server变量赋值为"x"或"w"的字符串标识(server=$x)这类用小括号包裹的命令是在子Shell中执行,子Shell内部的变量修改不会同步到当前主Shell,属于无效赋值- 你把两段Y/N确认逻辑和选择循环写成平级结构,不管用户输入什么,脚本跑完选择循环后都会默认先执行X的确认分支,永远走不到W的分支,这也是你想要找goto跳转功能的直接原因。
推荐实现方案
方案1:函数封装(可维护性最高,优先选择)
你写的两段Y/N确认逻辑几乎完全一致,只有提示文案中的X/W标识不同,完全可以封装成通用函数传参复用,根据用户选择直接调用对应逻辑即可,实现你要的分支跳转效果。
修正后的完整代码:
#!/bin/bash # 封装通用确认逻辑,入参为用户选择的服务类型 confirm_action() { local selected_type=$1 while true; do read -p "What $selected_type do you want to enter? (Y/N) " yn case $yn in [Yy]* ) echo -e "Starting...\n" exec test ;; [Nn]* ) echo -e "Aborting...\n" exit ;; * ) echo -e "Incorrect input detected, repeating prompt..." ;; esac done } # 第一步选择服务类型 while true; do read -p "Do you want to run X or W? (X/W) " xw case $xw in [Xx]* ) echo -e "Starting X prompt..." server="x" break # 拿到合法输入跳出选择循环 ;; [Ww]* ) echo -e "Starting W prompt..." server="w" break ;; * ) echo -e "Incorrect input detected, repeating prompt..." ;; esac done # 根据选择直接执行对应逻辑,替代goto的跳转效果 confirm_action $server
如果两段Y/N确认逻辑后续会演化出完全不同的流程,你也可以拆成confirm_x、confirm_w两个独立函数,在选择分支里匹配到对应输入直接调用对应函数即可。
方案2:case分支直接嵌套(适合逻辑简单的短脚本)
如果不想单独封装函数,可以直接把对应后续逻辑写在case的匹配分支里,不需要把选择逻辑和执行逻辑拆成平级块:
#!/bin/bash while true; do read -p "Do you want to run X or W? (X/W) " xw case $xw in [Xx]* ) echo -e "Starting X prompt..." # X分支对应的确认逻辑直接写在这里 while true; do read -p "What X do you want to enter? (Y/N) " yn case $yn in [Yy]* ) echo -e "Starting...\n" && exec test;; [Nn]* ) echo -e "Aborting...\n" && exit;; * ) echo -e "Incorrect input detected, repeating prompt...";; esac done ;; [Ww]* ) echo -e "Starting W prompt..." # W分支对应的确认逻辑直接写在这里 while true; do read -p "What W do you want to enter? (Y/N) " yn case $yn in [Yy]* ) echo -e "Starting...\n" && exec test;; [Nn]* ) echo -e "Aborting...\n" && exit;; * ) echo -e "Incorrect input detected, repeating prompt...";; esac done ;; * ) echo -e "Incorrect input detected, repeating prompt...";; esac done
关于Shell goto的补充说明
- 主流的bash、dash等符合POSIX标准的Shell 没有内置原生goto语法
- 网上流传的利用
exec、sed解析脚本标签实现的goto属于奇技淫巧,可读性和可维护性极差,正式生产环境脚本不建议使用 - Shell本身的流程控制设计(函数、分支、循环)完全可以覆盖goto的合理使用场景,不需要硬套其他语言的语法特性。
内容的提问来源于stack exchange,提问作者Mephres
相关产品推荐
相关产品推荐

