因此,我尝试在 bash 中创建一个菜单系统作为学习经验。我确信有无数的方法,甚至“更好”的方法来做到这一点,但我所拥有的是这样的......
echo "
2nd Menu
********
1) command
2) command
M) Main menu
X) Exit program
"
read -p "Choose option >" opt
if [ "$opt" -eq 1 ]; then
commands
elif [ "$opt" -eq 2 ]; then
commands
elif [[ "$opt" = [m,M] ]]; then
main #calls the function main()
elif [[ "$opt" = [x,X] ]]; then
exit
else
echo "Invalid option"
main
fi
该脚本适用于除“X)退出程序”之外的每个选项。当我运行“X”或“x”时,我收到此错误......
./acct-mgr.sh: line 10: [: x: integer expression expected
./acct-mgr.sh: line 12: [: x: integer expression expected
Invalid option
这让我很困惑!我很确定我对每种数据类型使用了正确的比较运算符(整数使用 -eq,字符串使用 =),而且除了“x”之外,每个选项都有效。
任何帮助是极大的赞赏。谢谢。
PS - 非常感谢实现预期结果的替代方法,但即使如此,我也想知道为什么这对我的启发不起作用。再次感谢。
答案1
当您输入 M/m 或 X/x 时,您正在使用 比较非数字与数字-eq
,这会导致失败。如果有时想$opt
成为字符串,则始终将其视为字符串:
...
if [ "$opt" = "1" ]; then
commands
elif [ "$opt" = "2" ]; then
commands
...
答案2
作为补充@安迪已经说过了, 注意
[[ "$opt" = [m,M] ]]
匹配m
、,
和M
。如果你想匹配m
且M
仅匹配,那就是
[[ "$opt" = [mM] ]]
在这里,我将使用标准case
构造:
case $opt in
(1) commands;;
(2) commands;;
(m|M) main;;
(x|X) exit;;
(*) echo >&2 "Invalid option"; main
esac
另请注意, 的行为read
取决于 的当前值$IFS
。如果您想从用户那里读取一行,您可以使用:
IFS= read -r opt
读取一个字符:
IFS= read -rn1 opt
去读一单词(读一行,但忽略前导空格和制表符以及除第一个单词之外的任何内容):
IFS=$' \t' read -r opt ignored
或者允许使用在单词通过添加反斜杠前缀:
IFS=$' \t' read opt ignored