アップデートの確認、テーマの再インストールという2つの機能を持つテーマ用のツールスクリプトを作成しています。
メニューを選択するコードは次のとおりです。
PS3='Choose an option: '
options=("Check for update" "Reinstall theme")
select opt in "${options[@]}"
do
case $opt in
"Check for update")
echo "Checking update"
;;
"Reinstall theme")
echo "Reinstalling"
;;
*) echo invalid option;;
esac
done
実行すると、これが発生します
1) Check for update
2) Reinstall theme
Choose an option:
1と入力してEnterを押して、更新コマンドの確認を実行します。
問題は、スクリプトの実行が終了すると、メニューの代わりに「オプションの選択:」が再び表示されることです。したがって、メニューがなければ、ユーザーは選択するのが難しいかもしれません(特に非常に長いスクリプトの後)。
1) Check for update
2) Reinstall theme
Choose an option: 1
Checking update
Choose an option:
では、オプションの実行後にメニューを再表示するにはどうすればよいですか?
答え1
私はあなたが本当に次のようなことをしたいと思います:
check_update () {
echo "Checking update"
}
reinstall_theme () {
echo "Reinstalling theme"
}
while true; do
options=("Check for update" "Reinstall theme")
echo "Choose an option:"
select opt in "${options[@]}"; do
case $REPLY in
1) check_update; break ;;
2) reinstall_theme; break ;;
*) echo "What's that?" >&2
esac
done
echo "Doing other things..."
echo "Are we done?"
select opt in "Yes" "No"; do
case $REPLY in
1) break 2 ;;
2) break ;;
*) echo "Look, it's a simple question..." >&2
esac
done
done
最初のステートメントを小さくするために、ジョブを別の関数に分割しましたcase
。また、ステートメントの$REPLY
オプション文字列の代わりに使用しました。オプション文字列case
が短く変更することにしましたが、2つの場所で更新するのを忘れた場合でも壊れないからです。また、スクリプトの後続の呼び出しPS3
に影響を与える可能性があるため、触れないようにしました。select
別のプロンプトが必要な場合は一度設定してそのままにします(おそらくPS3="Your choice: "
)。これにより、複数の問題を含むスクリプトにさらに統一された感じを与えることができます。
ユーザーが操作を完了するまですべてを繰り返す外部ループを追加しました。最初の文の質問を再表示するには、このループが必要ですselect
。
それ以外の場合は、スクリプトを中断する以外に終了する方法はbreak
ありcase
ません。
aの目的は、select
実際にスクリプトのメインイベントループ(それ自体)になるのではなく、ユーザーから質問に対する答えを得ることです。通常、a select
- はcase
実際に変数を設定するか、関数を呼び出して続行する必要があります。
最初のバージョンに「exit」オプションを含む短いバージョンselect
:
check_update () {
echo "Checking update"
}
reinstall_theme () {
echo "Reinstalling theme"
}
while true; do
options=("Check for update" "Reinstall theme" "Quit")
echo "Choose an option: "
select opt in "${options[@]}"; do
case $REPLY in
1) check_update; break ;;
2) reinstall_theme; break ;;
3) break 2 ;;
*) echo "What's that?" >&2
esac
done
done
echo "Bye bye!"
答え2
doループは無限であり、select文はその外部にあります。スクリプトはselectステートメントを一度実行してからdoループチェックケース$ optに続けます。私の提案は、ケースの説明の後にブレークを追加することです。
esac
break
done
その後、スクリプト全体を繰り返すには、selectステートメントからdidステートメントまですべてを含む別のループを作成します。
答え3
私はこのトリックを使います:
options=("First option" "Second option" "Quit")
PS3="So what? "
select opt in "${options[@]}"
do
case $opt in
"First option")
echo "First option"
;;
"Second option")
echo "Second option"
;;
"Quit")
echo "We are done..."
break
;;
*)
PS3="" # this hides the prompt
echo asdf | select foo in "${options[@]}"; do break; done # dummy select
PS3="So what? " # this displays the common prompt
;;
esac
done
答え4
私の方法を確認することもできます。単純なループでfunction
処理します。for
for((i=0;i<${#opt[@]};i++));do echo "$((i+1))) ${opt[$i]}";done
私のサンプルコードは次のとおりです。
msg="Choose an option:"
opt=("Check_for_update" "Reinstall_theme")
refresh_the_list(){
echo -e "\n$msg"
for((i=0;i<${#opt[@]};i++))
do
echo "$((i+1))) ${opt[$i]}"
done
}
echo $msg
select i in ${opt[@]}
do
case $i in
${opt[0]})
echo "Checking update"
refresh_the_list;;
${opt[1]})
echo "Reinstalling"
refresh_the_list;;
*)
echo "invalid option"
refresh_the_list;;
esac
done