Tôi đang tạo một tập lệnh bash đơn giản và tôi muốn tạo một menu chọn trong đó, như thế này:
$./script
echo "Choose your option:"
1) Option 1
2) Option 2
3) Option 3
4) Quit
Và theo lựa chọn của người dùng, tôi muốn các hành động khác nhau được thực thi. Tôi là một boo Shell scripting noob, tôi đã tìm kiếm trên mạng một số câu trả lời, nhưng không có gì thực sự cụ thể.
#!/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
Thêm câu lệnh break
bất cứ nơi nào bạn cần vòng lặp select
để thoát. Nếu một break
không được thực hiện, các vòng lặp câu lệnh select
và menu sẽ được hiển thị lại.
Trong tùy chọn thứ ba, tôi đã bao gồm các biến được đặt bởi câu lệnh select
để chứng minh rằng bạn có quyền truy cập vào các giá trị đó. Nếu bạn chọn nó, nó sẽ xuất ra:
you chose choice 3 which is Option 3
Bạn có thể thấy rằng $REPLY
chứa chuỗi bạn đã nhập tại Nhắc. Nó được sử dụng như một chỉ mục vào mảng ${options[@]}
như thể mảng dựa trên 1. Biến $opt
chứa chuỗi từ chỉ mục đó trong mảng.
Lưu ý rằng các lựa chọn có thể là một danh sách đơn giản trực tiếp trong câu lệnh select
như thế này:
select opt in foo bar baz 'multi Word choice'
nhưng bạn không thể đặt một danh sách như vậy trong một biến vô hướng vì các khoảng trắng trong một trong các lựa chọn.
Bạn cũng có thể sử dụng tệp toàn cầu nếu bạn chọn trong số các tệp:
select file in *.tar.gz
Không phải là một câu trả lời mới per se, nhưng vì chưa có câu trả lời nào được chấp nhận, nên đây là một vài mẹo và thủ thuật mã hóa, cho cả lựa chọn và sự thoải mái:
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
Đáng nói:
Cả hai sẽ lặp cho đến khi người dùng chọn rõ ràng Thoát (hoặc Hủy vì sự thoải mái). Đây là một cách tiếp cận tốt cho các menu script tương tác: sau khi lựa chọn được chọn và thực hiện hành động, menu sẽ được trình bày lại cho lựa chọn khác. Nếu sự lựa chọn chỉ là một lần duy nhất, chỉ cần sử dụng break
sau esac
(cách tiếp cận tiện ích cũng có thể được giảm thêm)
Cả case
đều dựa trên chỉ mục, thay vì dựa trên giá trị. Tôi nghĩ rằng điều này là dễ dàng hơn để mã hóa và duy trì
Mảng cũng được sử dụng cho cách tiếp cận zenity
.
Tùy chọn "Thoát" không nằm trong số các tùy chọn ban đầu, ban đầu. Nó được "thêm" khi cần, vì vậy mảng của bạn sạch sẽ. Dù sao đi nữa, "Thoát" không cần thiết cho sự thoải mái, người dùng chỉ cần nhấp vào "Hủy" (hoặc đóng cửa sổ) để thoát. Lưu ý cách cả hai sử dụng cùng một mảng tùy chọn chưa được chạm tới.
PS3
và REPLY
vars có thể không được đổi tên. select
được mã hóa cứng để sử dụng chúng. Tất cả các biến khác trong tập lệnh (opt, tùy chọn, Nhắc, tiêu đề) có thể có bất kỳ tên nào bạn muốn, miễn là bạn thực hiện các điều chỉnh
Sử dụng dialog
NAME _ , lệnh sẽ như thế này:
hộp thoại --clear --backtitle "Backtitle here" --title "Title here" --menu "Chọn một trong các tùy chọn sau:" 15 40 4\[.__.] 1 "Tùy chọn 1"\[.__.] 2 "Tùy chọn 2"\[.__.] 3 "Tùy chọn 3" [.__.]
Đưa nó vào một kịch bản:
#!/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
Bạn có thể sử dụng tập lệnh đơn giản này để tạo tùy chọn
#!/bin/bash [.__.] echo "chọn thao tác ************" [.__.] echo "1) thao tác 1" [.__.] echo "2) hoạt động 2 "[.__.] echo" 3) hoạt động 3 "[.__.] echo" 4) hoạt động 4 "
[.__.] đọc n [.__.] trường hợp $ n trong [.__.] 1) echo "Bạn đã chọn Tùy chọn 1" ;; [.__.] 2) echo "Bạn đã chọn Tùy chọn 2" ;; 3) echo "Bạn đã chọn Tùy chọn 3" ;; [.__.] 4) echo "Bạn đã chọn Tùy chọn 4" ;; [.__.] *) Echo "tùy chọn không hợp lệ" ;; [.__.] Esac [.__.]
Vì mục tiêu này được nhắm mục tiêu tại Ubuntu, bạn nên sử dụng bất kỳ nội dung phụ trợ nào được cấu hình để sử dụng. Bạn có thể tìm hiểu phần phụ trợ gỡ lỗi với:
Sudo -s "echo get debconf/frontend | debconf-communicate"
Nếu nó nói "hộp thoại" thì có khả năng nó sử dụng whiptail
hoặc dialog
. Trên Lucid, đó là whiptail
.
Nếu thất bại, hãy sử dụng bash "select" như được giải thích bởi Dennis Williamson.
#!/bin/sh [.__.] show_menu () {[.__.] normal = `echo"\033 [m "` [.___ .__.] number = `echo"\033 [33m "` #yellow [.__.] bgred = `echo"\033 [41m "` [.__. .__.] printf "\ n $ {menu} ******/TÌM KIẾM ******* $ {normal}\n "[.__.] printf" $ {menu} ** $ {number} 1) $ {menu} Mount dropbox $ {normal}\n "[.___ ] printf "$ {menu} ** $ {number} 2) $ {menu} Gắn USB 500 Gig Drive $ {normal}\n" [.__.] printf "$ {menu} ** $ {number} 3) $ {menu} Khởi động lại Apache $ {normal}\n "[.__.] printf" $ {menu} ** $ {number} 4) $ {menu} ssh Frost Tomcat Server $ {normal}\n "[.___ .] printf "$ {menu} ** $ {number} 5) $ {menu} Một số lệnh khác $ {normal}\n" [.__.] printf "$ {menu} ********* ******/TÌM KIẾM Vui lòng nhập một tùy chọn menu và nhập hoặc $ {fgred} x để thoát. $ {Bình thường} "[.__.] Đọc opt [.__.]} [.__.] [.__.] Option_picky () { dircolor = `echo"\033 [01; 31m "` # đậm màu đỏ [.__.] normal = `echo"\033 [00; 00m "` # normal trắng [.__.] message = $ {@: - "$ {normal} Lỗi: Không có tin nhắn nào được chuyển"} [.__.] printf "$ {dircolor } $ {message} $ {normal}\n "[.__.]} [.__.] [.__.] xóa [.__.] show_menu [.__.] trong khi [$ opt! = ''] [ .__.] làm [.__.] nếu [$ opt = '']; sau đó [.__.] thoát; [.__.] khác [.__.] case $ opt in [.__.] 1) rõ ràng; [.__.] tùy chọn_picky "Tùy chọn 1 được chọn"; [.__.] printf "Sudo mount/dev/sdh1/mnt/DropBox /; #The 3 terabyte"; [.___] Show_menu; [.__.] ;; 2 Đã chọn "; [.__.] Printf" Sudo mount/dev/sdi1/mnt/usbDrive; #The 500 gig drive "; [.___ rõ ràng; [.__.] tùy chọn_picky "Tùy chọn 3 đã chọn"; [.__.] printf "Dịch vụ Sudo Apache2 khởi động lại"; [.___ [.__.] tùy chọn_picky "Tùy chọn 4 đã chọn"; [.__.] printf "ssh lmesser @ -p 2010"; [.___ [.__.] ;; [.__.]\n) thoát; [.__.] ;; [.__.] *) rõ ràng; [.__.] tùy chọn_picky "Chọn một tùy chọn từ menu "; [.__.] show_menu; [.__.] ;; [.__.] esac [.__.] fi [.__.] xong
Tôi có thêm một tùy chọn là hỗn hợp của những câu trả lời này, nhưng điều làm cho nó hay là bạn chỉ cần nhấn một phím và sau đó tập lệnh tiếp tục nhờ vào tùy chọn đọc -n
. Trong ví dụ này, chúng tôi đang nhắc tắt máy, khởi động lại hoặc đơn giản là thoát tập lệnh bằng cách sử dụng ANS
làm biến của chúng tôi và người dùng chỉ phải nhấn E, R hoặc S. Tôi cũng đặt mặc định để thoát vì vậy nếu nhấn enter thì nhấn kịch bản sẽ thoát.
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
Tôi đã sử dụng Zenity, dường như luôn có trong Ubuntu, hoạt động rất tốt và có nhiều khả năng. Đây là một bản phác thảo của một menu có thể:
#! /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
Thực đơn ưa thích của Bash
Hãy dùng thử trước, sau đó truy cập trang của tôi để biết mô tả chi tiết ... Không cần thư viện hoặc chương trình bên ngoài như hộp thoại hoặc tiện nghi ...
#/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
Đã có câu hỏi tương tự trong serverfault đã trả lời. Giải pháp ở đó sử dụng whiptail .