web-dev-qa-db-ja.com

整数式が期待されるのはなぜですか?

だから、私は学習体験として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、文字列の場合は=)を使用していることと、EVERYオプションがその "x"を除いて機能するという事実を組み合わせて使用​​していると確信しています。

どんな助けでも大歓迎です。ありがとう。

追伸-望ましい結果を達成するための別の方法は非常に高く評価されていますが、それでも、これが私の教育に役立たない理由を知りたいのです。再度、感謝します。

4
dlowrie290

M/mまたはX/xと入力すると、-eqを使用して非数値を数値と比較しているため、エラーが発生しています。 $optを文字列にしたい場合は、常に文字列として扱います。

...
if [ "$opt" = "1" ]; then
    commands
Elif [ "$opt" = "2" ]; then
    commands
...
10
Andy Dalton

@ Andyはすでに言っています の補足として、

[[ "$opt" = [m,M] ]]

m,Mに一致します。 mMのみを照合したい場合は、

[[ "$opt" = [mM] ]]

ここでは、標準のcase構文を使用します。

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

readの動作は$IFSの現在の値に依存することにも注意してください。ユーザーから1行を読みたい場合は、次のようにします。

IFS= read -r opt

1文字を読み取るには:

IFS= read -rn1 opt

1つを読み取るにはWord(1行を読み取りますが、先頭のスペースとタブ、および最初のWord以外は無視してください):

IFS=$' \t' read -r opt ignored

または、バックスラッシュを前に付けることで、スペースまたはタブをWordに含めることができるようにします。

IFS=$' \t' read opt ignored
6