linux shell 编程:select生成交互式菜单 作者:马育民 • 2026-10-14 20:43 • 阅读:10000 # 介绍 `select` 是 bash 内置命令,**用来快速生成交互式菜单**,属于 shell 循环的一种,常和 `case` 搭配使用。 > 只在 bash / ksh 支持,sh(posix shell)没有 select。 # 语法 ```bash select 变量名 [in 选项列表] do 循环体 done ``` ### 工作机制 1. `select` 自动把 `in` 后面的每一项编号输出成菜单 2. 打印提示符 `PS3`(默认 `#? `)等待用户输入数字 3. 用户输入数字回车: - 对应选项赋值给【变量名】 - 内置变量 `REPLY` 保存用户输入的内容 4. 输入不在菜单的数字 → 变量为空,REPLY 保留输入值 5. 直接回车 → 重复打印菜单 6. 输入 `Ctrl+C` 退出循环 > ⚠️ select**默认是无限循环**,需要手动用 `break` 退出。 ### 示例 ```bash #!/bin/bash PS3="请选择一个选项: " # 修改菜单提示符 select fruit in apple banana orange quit do case $fruit in apple) echo "你选了苹果" ;; banana) echo "你选了香蕉" ;; orange) echo "你选了橙子" ;; quit) echo "退出菜单" break ;; *) echo "无效选项,请重新选择" ;; esac done ``` 运行效果: ``` 1) apple 2) banana 3) orange 4) quit 请选择一个选项: ``` ### 关键内置变量 1. **`PS3`**:select 专用提示符,一定要在 select 之前定义 2. **`REPLY`**:保存用户键盘输入的原始字符串(数字) 3. 循环变量:保存选中的选项文本;选错时为空字符串 示例看 REPLY: ```bash #!/bin/bash PS3="输入编号 > " select name in Alice Bob do echo "REPLY=$REPLY" echo "name=$name" break done ``` 输入`1`: ``` REPLY=1 name=Alice ``` 输入`9`: ``` REPLY=9 name= ``` # 省略 in 列表 的写法 `select var` 不带 in,则 **使用位置参数 $@** ```bash #!/bin/bash PS3="请选择:" select arg do echo "选中:$arg" break done ``` 执行:`./test.sh a b c`,菜单自动生成 a b c。 # 常见技巧 ### 1. 菜单选项来自数组(推荐,动态菜单) ```bash #!/bin/bash opts=("重启服务" "停止服务" "查看状态" "退出") PS3="请输入编号:" select opt in "${opts[@]}"; do case $opt in "重启服务") echo "restart" ;; "停止服务") echo "stop" ;; "查看状态") echo "status" ;; "退出") break ;; *) echo "错误输入" ;; esac done ``` ### 2. 只允许数字,限制输入 ```bash #!/bin/bash PS3="请选择:" select o in one two three exit do if ! [[ $REPLY =~ ^[0-9]+$ ]];then echo "请输入数字编号" continue fi case $o in exit) break;; *) echo "选中 $o";; esac done ``` ### 3. 一次性菜单,选择后自动退出(不循环) 把 `break` 放到每个分支,或者根据业务逻辑跳出。 # select 退出方式 1. `break`:退出 select 循环(最常用) 2. `exit`:直接退出整个脚本 3. `Ctrl + C`:SIGINT 终止脚本 # 注意坑点 1. **select 不会自动退出**,忘记写 break 就无限循环 2. 用户输入的是**数字编号**,不是选项文字!不要拿 `REPLY` 和选项字符串比较 3. 菜单每次循环都会重新打印;如果不想重复打印菜单,可以清空 `PS3`,或者把菜单放到循环外面自己打印 4. 数组展开务必写 `"${arr[@]}"`,防止带空格的选项被拆分 5. POSIX sh 不支持 select,脚本开头必须 `#!/bin/bash` 原文出处:/show_1GW4EAFGSlIG.html