Bash脚本select命令异常:sh运行报错bash运行选项无效
问题分析:Bash脚本的两个运行异常问题
编写了如下Bash脚本:
#!/bin/bash PS3="Select an install package: " items=("Essentials - VLC" "Graphics Suite - Inkscape, GIMP, Blender" "Streaming Suite - OBS, Openshot, Blender") select opt in "${items[@]}" "Cancel - Install Manually" do case $opt in 1) echo "== Installing Essentials ==";; sudo apt install vlc -y; wait; break;; 2) echo "== Installing Graphics Suite ==";; sudo apt install vlc inkscape gimp blender -y; wait; break;; 3) echo "== Installing Streaming Suite ==";; sudo apt install vlc obs openshot blender -y; wait; break;; $((${#items[@]}+1))) echo "Remember, you can manually install with";; echo " 'sudo apt install [app name]'";; echo " 'sudo flatpak install [app name]'";; echo "or through the 'Software Manager'";; sleep 8; break;; *) echo "Invalid option - please select a number from 1 to $((${#items[@]}+1))";; esac done clear遇到的问题:
- 将脚本设为可执行文件直接运行时一切正常;但用
sh命令运行脚本时,数组定义行出现"("意外的语法错误。- 改用
bash命令运行后无报错,但无论选择哪个选项都会触发无效选项的分支。
1. sh运行报语法错误的原因
sh是遵循POSIX标准的Shell解释器,而Bash的数组定义语法(items=(...))属于Bash专属的扩展特性,POSIX Shell并不支持这种写法。用sh执行脚本时,解释器无法识别数组语法,因此抛出"("意外的语法错误。- 解决方式:始终用
bash命令执行该脚本,不要依赖sh兼容Bash扩展特性。
2. bash运行触发无效选项分支的原因
select命令中,opt变量存储的是选中的选项文本内容,而非选项对应的数字序号。但你的case语句里用数字(1、2、3)作为匹配模式,自然无法匹配到文本内容,每次都会走到*)分支。- 另外,
$((${#items[@]}+1))的模式写法存在双重问题:一是它会被展开为数字字符串,依然和opt存储的文本不匹配;二是语法不完整,模式定义后没有用;;或闭合的)衔接后续代码,属于语法隐患。
修正方案
方案1:匹配REPLY变量(推荐)
select会自动将用户输入的数字存在REPLY变量里,直接匹配这个变量即可:
case $REPLY in 1) echo "== Installing Essentials ==" sudo apt install vlc -y; wait; break;; 2) echo "== Installing Graphics Suite ==" sudo apt install vlc inkscape gimp blender -y; wait; break;; 3) echo "== Installing Streaming Suite ==" sudo apt install vlc obs openshot blender -y; wait; break;; $((${#items[@]}+1))) echo "Remember, you can manually install with" echo " 'sudo apt install [app name]'" echo " 'sudo flatpak install [app name]'" echo "or through the 'Software Manager'" sleep 8; break;; *) echo "Invalid option - please select a number from 1 to $((${#items[@]}+1))";; esac
方案2:匹配选项文本
直接用数组元素或取消选项的文本作为匹配模式:
case $opt in "${items[0]}") echo "== Installing Essentials ==" sudo apt install vlc -y; wait; break;; "${items[1]}") echo "== Installing Graphics Suite ==" sudo apt install vlc inkscape gimp blender -y; wait; break;; "${items[2]}") echo "== Installing Streaming Suite ==" sudo apt install vlc obs openshot blender -y; wait; break;; "Cancel - Install Manually") echo "Remember, you can manually install with" echo " 'sudo apt install [app name]'" echo " 'sudo flatpak install [app name]'" echo "or through the 'Software Manager'" sleep 8; break;; *) echo "Invalid option - please select a number from 1 to $((${#items[@]}+1))";; esac
内容的提问来源于stack exchange,提问作者AJSarley223
相关产品推荐
相关产品推荐

