私は単純なbashスクリプトを作成していますが、次のような選択メニューを作成します。
$./script
echo "Choose your option:"
1) Option 1
2) Option 2
3) Option 3
4) Quit
そして、ユーザーの選択に応じて、さまざまなアクションを実行する必要があります。私はbashシェルスクリプトの初心者です。いくつかの答えをWebで検索しましたが、実際には具体的なことは何もありませんでした。
私は単純なbashスクリプトを作成していますが、次のような選択メニューを作成します。
$./script
echo "Choose your option:"
1) Option 1
2) Option 2
3) Option 3
4) Quit
そして、ユーザーの選択に応じて、さまざまなアクションを実行する必要があります。私はbashシェルスクリプトの初心者です。いくつかの答えをWebで検索しましたが、実際には具体的なことは何もありませんでした。
回答:
#!/bin/bash
# Bash Menu Script Example
PS3='Please enter your choice: '
options=("Option 1" "Option 2" "Option 3" "Quit")
select opt in "${options[@]}"
do
case $opt in
"Option 1")
echo "you chose choice 1"
;;
"Option 2")
echo "you chose choice 2"
;;
"Option 3")
echo "you chose choice $REPLY which is $opt"
;;
"Quit")
break
;;
*) echo "invalid option $REPLY";;
esac
done
ループを終了break
する必要がある場所にステートメントを追加select
します。a break
が実行されない場合、select
ステートメントはループし、メニューが再表示されます。
3番目のオプションでは、select
これらの値にアクセスできることを示すために、ステートメントによって設定される変数を含めました。それを選択すると、出力されます:
you chose choice 3 which is Option 3
$REPLY
プロンプトで入力した文字列が含まれていることがわかります。${options[@]}
配列が1ベースであるかのように、配列へのインデックスとして使用されます。変数$opt
には、配列内のそのインデックスの文字列が含まれます。
選択肢は、次のselect
ようなステートメント内の直接の単純なリストである可能性があることに注意してください。
select opt in foo bar baz 'multi word choice'
ただし、選択肢の1つにスペースがあるため、このようなリストをスカラー変数に入れることはできません。
ファイルの中から選択する場合は、ファイルグロビングを使用することもできます。
select file in *.tar.gz
break
、select
ループから抜け出すa を実行します。break
必要な場所に追加できます。バッシュマニュアル「を選択し、コマンドが完了した時点で、breakコマンドが実行されるまでのコマンドが各選択後に実行されている、。」状態
./test.sh: line 9: syntax error near unexpected token
"オプション1" './test.sh:行9: ` "オプション1")' '
$options
case
case
それ自体は新しい答えではありませんが、まだ受け入れられている答えがないため、selectとzenityの両方のコーディングのヒントとコツをいくつか示します。
title="Select example"
prompt="Pick an option:"
options=("A" "B" "C")
echo "$title"
PS3="$prompt "
select opt in "${options[@]}" "Quit"; do
case "$REPLY" in
1 ) echo "You picked $opt which is option $REPLY";;
2 ) echo "You picked $opt which is option $REPLY";;
3 ) echo "You picked $opt which is option $REPLY";;
$(( ${#options[@]}+1 )) ) echo "Goodbye!"; break;;
*) echo "Invalid option. Try another one.";continue;;
esac
done
while opt=$(zenity --title="$title" --text="$prompt" --list \
--column="Options" "${options[@]}"); do
case "$opt" in
"${options[0]}" ) zenity --info --text="You picked $opt, option 1";;
"${options[1]}" ) zenity --info --text="You picked $opt, option 2";;
"${options[2]}" ) zenity --info --text="You picked $opt, option 3";;
*) zenity --error --text="Invalid option. Try another one.";;
esac
done
言及する価値があります:
どちらも、ユーザーが明示的に終了(または完全にキャンセル)を選択するまでループします。これは、対話型スクリプトメニューに適したアプローチです。選択項目を選択してアクションを実行した後、別の選択項目に対してメニューが再び表示されます。選択肢が1回限りである場合は、あとで使用break
しますesac
(Zenityアプローチもさらに削減できます)
どちらcase
も値ベースではなくインデックスベースです。これはコーディングと保守が簡単だと思います
配列もzenity
アプローチに使用されます。
「終了」オプションは、初期の元のオプションではありません。必要なときに「追加」されるため、アレイはクリーンなままです。とにかく、「Quit」は禅に必要ありません。ユーザーは「Cancel」をクリックして(またはウィンドウを閉じて)終了できます。両方が同じ、手つかずのオプションの配列をどのように使用するかに注目してください。
PS3
そしてREPLY
VARSはできません名前を変更します。select
これらを使用するためにハードコードされています。スクリプト内の他のすべての変数(opt、options、prompt、title)は、調整を行う限り、任意の名前にすることができます
case
ための構造をselect
あなたが使用しているバージョンzenity
:バージョンcase "$opt" in . . . "${options[0]}" ) . . .
(の代わり$REPLY
とインデックス1
、2
と3
)。
$REPLY
インデックスと値の関係を意図的に示したかったのです。
を使用するdialog
と、コマンドは次のようになります。
dialog --clear --backtitle "Backtitle here" --title "Title here" --menu "次のオプションのいずれかを選択してください:" 15 40 4 \ 1「オプション1」\ 2 "オプション2" \ 3「オプション3」
スクリプトに入れる:
#!/bin/bash
HEIGHT=15
WIDTH=40
CHOICE_HEIGHT=4
BACKTITLE="Backtitle here"
TITLE="Title here"
MENU="Choose one of the following options:"
OPTIONS=(1 "Option 1"
2 "Option 2"
3 "Option 3")
CHOICE=$(dialog --clear \
--backtitle "$BACKTITLE" \
--title "$TITLE" \
--menu "$MENU" \
$HEIGHT $WIDTH $CHOICE_HEIGHT \
"${OPTIONS[@]}" \
2>&1 >/dev/tty)
clear
case $CHOICE in
1)
echo "You chose Option 1"
;;
2)
echo "You chose Option 2"
;;
3)
echo "You chose Option 3"
;;
esac
TERMINAL=$(tty)
スクリプトを別の端末コンテキストで実行した場合のリダイレクトの問題を回避するために、スクリプトの先頭に行を追加し、CHOICE
変数定義に変更2>&1 >/dev/tty
した2>&1 >$TERMINAL
ことに注意してください。
--backtitle
パラメーターは何をしますか?
このシンプルなスクリプトを使用してオプションを作成できます
#!/ bin / bash echo "操作を選択してください************" echo "1)operation 1" echo "2)operation 2" echo "3)operation 3" echo "4)operation 4"
nを読む ケース$ n 1)echo "オプション1を選択しました" ;; 2)echo "オプション2を選択しました" ;; 3)echo "オプション3を選択しました" ;; 4)echo "オプション4を選択しました" ;; *)echo "無効なオプション" ;; エサック
これらの回答を組み合わせたオプションがもう1つありますが、良いのは、キーを1つ押すだけ-n
で、読み取りオプションのおかげでスクリプトが続行されることです。この例ではANS
、変数としてを使用して、シャットダウン、再起動、または単にスクリプトを終了するようプロンプトが表示され、ユーザーはE、R、またはSを押すだけです。終了します。
read -n 1 -p "Would you like to exit, reboot, or shutdown? (E/r/s) " ans;
case $ans in
r|R)
sudo reboot;;
s|S)
sudo poweroff;;
*)
exit;;
esac
これはUbuntuを対象としているため、使用するように設定されたバックエンドdebconfを使用する必要があります。debconfバックエンドは次の方法で確認できます。
sudo -s "echo get debconf/frontend | debconf-communicate"
「ダイアログ」と表示されている場合は、whiptail
またはを使用している可能性がありますdialog
。明晰で、それですwhiptail
。
それが失敗する場合は、デニス・ウィリアムソンが説明したように、bash「select」を使用します。
#!/ bin / sh show_menu(){ normal = `echo" \ 033 [m "` menu = `echo" \ 033 [36m "`#青 number = `echo" \ 033 [33m "` #yellow bgred = `echo" \ 033 [41m "` fgred = `echo" \ 033 [31m "` printf "\ n $ {menu} ********************************************* *** $ {normal} \ n " printf "$ {menu} ** $ {number} 1)$ {menu}ドロップボックスをマウント$ {normal} \ n" printf "$ {menu} ** $ {number} 2)$ {menu} USB 500ギグドライブをマウント$ {normal} \ n" printf "$ {menu} ** $ {number} 3)$ {menu} Apache $ {normal}を再起動します\ n" printf "$ {menu} ** $ {number} 4)$ {menu} ssh Frost TomCat Server $ {normal} \ n" printf "$ {menu} ** $ {number} 5)$ {menu}他のいくつかのコマンド$ {normal} \ n" printf "$ {menu} *********************************************** * $ {normal} \ n " printf "メニューオプションを入力し、終了するには$ {fgred} xを入力してください。$ {normal}" オプトを読む } option_picked(){ msgcolor = `echo" \ 033 [01; 31m "`#太字の赤 normal = `echo" \ 033 [00; 00m "`#通常の白 message = $ {@:-"$ {normal}エラー:メッセージが渡されませんでした"} printf "$ {msgcolor} $ {message} $ {normal} \ n" } クリア show_menu while [$ opt!= ''] 行う if [$ opt = '']; それから 出口; 他に ケース$ opt in 1)クリア; option_picked "Option 1 Picked"; printf "sudo mount / dev / sdh1 / mnt / DropBox /; #The 3テラバイト"; show_menu; ;; 2)クリア; option_picked "Option 2 Picked"; printf "sudo mount / dev / sdi1 / mnt / usbDrive;#500ギガドライブ"; show_menu; ;; 3)クリア; option_picked "Option 3 Picked"; printf "sudo service apache2 restart"; show_menu; ;; 4)クリア; option_picked "Option 4 Picked"; printf "ssh lmesser @ -p 2010"; show_menu; ;; x)exit; ;; \ n)exit; ;; *)クリア; option_picked "メニューからオプションを選択"; show_menu; ;; エサック fi やった
$
がありません。文は冗長です。一貫性のないインデント。'show_menu show_menu`のある場所で使用することは、それぞれで繰り返されるのではなく、ループの先頭に置くことができます。一貫性のないインデント。単一の角括弧と二重の角括弧の使用の混合。の代わりにハードコーディングされたANSIシーケンスを使用します。すべて大文字の変数名の使用は推奨されません。呼び出す必要があります。の代わりにバックティックを使用します。関数定義が一貫していなければならないと使用できません...$opt
while
if
menu
.
case
tput
FGRED
bgred
$()
\n
実行されません。おそらくもっと。
Zenityを使用しました。これはUbuntuに常に存在しているようで、非常にうまく機能し、多くの機能を備えています。これは可能なメニューのスケッチです:
#! /bin/bash
selection=$(zenity --list "Option 1" "Option 2" "Option 3" --column="" --text="Text above column(s)" --title="My menu")
case "$selection" in
"Option 1")zenity --info --text="Do something here for No1";;
"Option 2")zenity --info --text="Do something here for No2";;
"Option 3")zenity --info --text="Do something here for No3";;
esac
バッシュファンシーメニュー
最初に試してから、詳細な説明については私のページにアクセスしてください...外部ライブラリまたはダイアログや禅のようなプログラムは必要ありません...
#/bin/bash
# by oToGamez
# www.pro-toolz.net
E='echo -e';e='echo -en';trap "R;exit" 2
ESC=$( $e "\e")
TPUT(){ $e "\e[${1};${2}H";}
CLEAR(){ $e "\ec";}
CIVIS(){ $e "\e[?25l";}
DRAW(){ $e "\e%@\e(0";}
WRITE(){ $e "\e(B";}
MARK(){ $e "\e[7m";}
UNMARK(){ $e "\e[27m";}
R(){ CLEAR ;stty sane;$e "\ec\e[37;44m\e[J";};
HEAD(){ DRAW
for each in $(seq 1 13);do
$E " x x"
done
WRITE;MARK;TPUT 1 5
$E "BASH SELECTION MENU ";UNMARK;}
i=0; CLEAR; CIVIS;NULL=/dev/null
FOOT(){ MARK;TPUT 13 5
printf "ENTER - SELECT,NEXT ";UNMARK;}
ARROW(){ read -s -n3 key 2>/dev/null >&2
if [[ $key = $ESC[A ]];then echo up;fi
if [[ $key = $ESC[B ]];then echo dn;fi;}
M0(){ TPUT 4 20; $e "Login info";}
M1(){ TPUT 5 20; $e "Network";}
M2(){ TPUT 6 20; $e "Disk";}
M3(){ TPUT 7 20; $e "Routing";}
M4(){ TPUT 8 20; $e "Time";}
M5(){ TPUT 9 20; $e "ABOUT ";}
M6(){ TPUT 10 20; $e "EXIT ";}
LM=6
MENU(){ for each in $(seq 0 $LM);do M${each};done;}
POS(){ if [[ $cur == up ]];then ((i--));fi
if [[ $cur == dn ]];then ((i++));fi
if [[ $i -lt 0 ]];then i=$LM;fi
if [[ $i -gt $LM ]];then i=0;fi;}
REFRESH(){ after=$((i+1)); before=$((i-1))
if [[ $before -lt 0 ]];then before=$LM;fi
if [[ $after -gt $LM ]];then after=0;fi
if [[ $j -lt $i ]];then UNMARK;M$before;else UNMARK;M$after;fi
if [[ $after -eq 0 ]] || [ $before -eq $LM ];then
UNMARK; M$before; M$after;fi;j=$i;UNMARK;M$before;M$after;}
INIT(){ R;HEAD;FOOT;MENU;}
SC(){ REFRESH;MARK;$S;$b;cur=`ARROW`;}
ES(){ MARK;$e "ENTER = main menu ";$b;read;INIT;};INIT
while [[ "$O" != " " ]]; do case $i in
0) S=M0;SC;if [[ $cur == "" ]];then R;$e "\n$(w )\n";ES;fi;;
1) S=M1;SC;if [[ $cur == "" ]];then R;$e "\n$(ifconfig )\n";ES;fi;;
2) S=M2;SC;if [[ $cur == "" ]];then R;$e "\n$(df -h )\n";ES;fi;;
3) S=M3;SC;if [[ $cur == "" ]];then R;$e "\n$(route -n )\n";ES;fi;;
4) S=M4;SC;if [[ $cur == "" ]];then R;$e "\n$(date )\n";ES;fi;;
5) S=M5;SC;if [[ $cur == "" ]];then R;$e "\n$($e by oTo)\n";ES;fi;;
6) S=M6;SC;if [[ $cur == "" ]];then R;exit 0;fi;;
esac;POS;done
serverfaultの回答にはすでに同じ質問があります。そこでの解決策はwhiptailを使用しています。
シンプルなシェルスクリプトメニュー(派手なUIはありません)を使用する場合、http://www.tldp.org/LDP/abs/html/testbranch.htmlのメニュー例を確認してください。
seq 10 | fzf
。欠点は、fzfがデフォルトでインストールされないことです。ここでfzfを見つけることができます:github.com/junegunn/fzf