为什么我会得到预期的整数表达式?

dlo*_*290 4 bash shell-script test

所以,我试图在 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
Run Code Online (Sandbox Code Playgroud)

该脚本适用于除“X) 退出程序”之外的每个选项。当我运行“X”或“x”时,我收到此错误...

./acct-mgr.sh: line 10: [: x: integer expression expected
./acct-mgr.sh: line 12: [: x: integer expression expected
Invalid option
Run Code Online (Sandbox Code Playgroud)

这让我很困惑!我很确定我为每种数据类型使用了正确的比较运算符(-eq 表示整数,= 表示字符串),再加上每个选项都可以工作,除了“x”。

任何帮助是极大的赞赏。谢谢。

PS - 非常感谢实现预期结果的替代方法,但即便如此,我还是想知道为什么这对我的启发不起作用。再次感谢。

And*_*ton 10

当您输入 M/m 或 X/x 时,您将使用 将非数字与数字进行比较-eq,这会导致失败。如果你$opt有时想成为一个字符串,就一直把它当作一个字符串:

...
if [ "$opt" = "1" ]; then
    commands
elif [ "$opt" = "2" ]; then
    commands
...
Run Code Online (Sandbox Code Playgroud)


Sté*_*las 6

作为对@Andy 已经说过的内容的补充,请注意

[[ "$opt" = [m,M] ]]
Run Code Online (Sandbox Code Playgroud)

匹配m,,M。如果你想匹配mM只,这将是

[[ "$opt" = [mM] ]]
Run Code Online (Sandbox Code Playgroud)

在这里,我会使用一个标准的case构造:

case $opt in
  (1)   commands;;
  (2)   commands;;
  (m|M) main;;
  (x|X) exit;;
  (*)   echo >&2 "Invalid option"; main
esac
Run Code Online (Sandbox Code Playgroud)

另请注意, 的行为read取决于 的当前值$IFS。如果您想从用户那里读取一行,您可以使用:

IFS= read -r opt
Run Code Online (Sandbox Code Playgroud)

读取一个字符:

IFS= read -rn1 opt
Run Code Online (Sandbox Code Playgroud)

阅读一个单词(阅读一行,但忽略前导空格和制表符以及除第一个单词以外的任何内容):

IFS=$' \t' read -r opt ignored
Run Code Online (Sandbox Code Playgroud)

或者通过添加反斜杠前缀来允许使用在单词中包含空格或制表符:

IFS=$' \t' read opt ignored
Run Code Online (Sandbox Code Playgroud)