답변:
#!/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
명령문이 반복되고 메뉴가 다시 표시됩니다.
세 번째 옵션에는 select
해당 값에 액세스 할 수 있음을 나타 내기 위해 명령문에서 설정 한 변수를 포함 시켰습니다 . 선택하면 다음과 같이 출력됩니다.
you chose choice 3 which is Option 3
$REPLY
프롬프트에서 입력 한 문자열 이 포함되어 있음을 알 수 있습니다 . ${options[@]}
배열이 1 기반 인 것처럼 배열에 대한 인덱스로 사용됩니다 . 변수 $opt
는 배열에서 해당 인덱스의 문자열을 포함합니다.
선택 사항은 다음 select
과 같이 명령문 에서 직접 간단한 목록이 될 수 있습니다 .
select opt in foo bar baz 'multi word choice'
그러나 선택 중 하나의 공백으로 인해 이러한 목록을 스칼라 변수에 넣을 수 없습니다.
파일 중에서 선택하는 경우 파일 globbing을 사용할 수도 있습니다.
select file in *.tar.gz
break
를 벗어나는를 실행합니다 select
. break
필요한 곳에 추가 할 수 있습니다 . 배쉬 수동 상태는 "명령은 휴식 명령이있는 선택 명령이 완료 지점, 실행될 때까지 각 선택 후 실행됩니다."
./test.sh: line 9: syntax error near unexpected token
"Option 1" './test.sh : line 9 :` "Option 1")'`
$options
에 case
대신 값의 문). 값을 사용하면 case
진술 섹션의 기능이 더 잘 문서화된다고 생각 합니다.
새로운 답변 자체 는 아니지만 아직 받아 들여진 답변이 없으므로 선택과 정력에 대한 몇 가지 코딩 팁과 요령이 있습니다.
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
언급 할 가치가있는 것 :
사용자가 명시 적으로 Quit (또는 zenity로 Cancel)을 선택할 때까지 둘 다 반복됩니다. 이는 대화식 스크립트 메뉴에 적합한 접근 방식입니다. 선택을 선택하고 동작을 수행 한 후 다른 선택을 위해 메뉴가 다시 표시됩니다. 선택은 한 시간이 의미하는 경우에만, 다만 사용 break
후 esac
합니다 (zenity의 접근 방식은 더도 감소 될 수있다)
둘 다 case
가치 기반이 아니라 인덱스 기반입니다. 코딩하고 유지하기가 더 쉽다고 생각합니다.
배열은 zenity
접근 에도 사용됩니다 .
"종료"옵션은 최초의 원래 옵션 중 하나가 아닙니다. 필요할 때 "추가"되므로 어레이가 깨끗하게 유지됩니다. 어쨌든 "종료"는 zenity에 필요하지 않습니다. 사용자는 "취소"를 클릭하거나 창을 닫으면 종료됩니다. 둘 다 동일한 수정되지 않은 옵션 배열을 사용하는 방법에 주목하십시오.
PS3
그리고 REPLY
바르가 할 수 없는 이름을 바꿀 수. select
그것들을 사용하도록 하드 코딩되어 있습니다. 스크립트의 다른 모든 변수 (옵션, 옵션, 프롬프트, 제목)는 원하는대로 조정할 수 있습니다.
case
에 대한 구조를 select
당신이를 위해 사용하고있는 버전 zenity
: 버전 case "$opt" in . . . "${options[0]}" ) . . .
(대신 $REPLY
과 인덱스 1
, 2
및 3
).
$REPLY
, 색인 및 값 사이의 관계를 보여주고 싶었습니다 .
를 사용 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
매개 변수는 무엇입니까?
이 답변이 혼합 된 옵션이 하나 더 있지만 좋은 점은 하나의 키만 누르면 스크립트가 계속 -n
읽기 옵션 덕분에 계속된다는 것입니다. 이 예제에서는 ANS
변수를 사용하여 스크립트를 종료, 재부팅 또는 간단히 종료하라는 메시지가 표시 되며 사용자는 E, R 또는 S 만 누르면됩니다. Enter 키를 누르면 스크립트가 종료되도록 기본값도 설정합니다. 종료됩니다.
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
. Lucid에서는 whiptail
입니다.
실패하면 Dennis Williamson의 설명에 따라 bash "select"를 사용하십시오.
#! / bin / sh show_menu () { normal =`에코 "\ 033 [m"` menu =`echo "\ 033 [36m"`# 블루 숫자 =`에코 "\ 033 [33m"`#yellow bgred =`에코 "\ 033 [41m"` fgred =`에코 "\ 033 [31m"` printf "\ n $ {menu} ********************************************* *** $ {normal} \ n " printf "$ {menu} ** $ {number} 1) $ {menu} 드롭 박스 마운트 $ {normal} \ n" printf "$ {menu} ** $ {number} 2) $ {menu} USB 500 Gig 드라이브 마운트 $ {normal} \ n" printf "$ {menu} ** $ {number} 3) $ {menu} Apache $ {normal} \ n"을 다시 시작하십시오. printf "$ {menu} ** $ {number} 4) $ {menu} ssh Frost TomCat 서버 $ {normal} \ n" printf "$ {menu} ** $ {number} 5) $ {menu} 다른 명령들 {{normal} \ n" printf "$ {menu} *********************************************** * $ {normal} \ n " printf "메뉴 옵션을 입력하고 종료하려면 $ {fgred} x를 입력하십시오. $ {normal}" opt 읽기 } option_picked () { msgcolor =`echo "\ 033 [01; 31m"`# 굵은 빨간색 normal =`echo "\ 033 [00; 00m"`# 보통 흰색 message = $ {@ :- "$ {normal} 오류 : 메시지가 전달되지 않았습니다"} printf "$ {msgcolor} $ {message} $ {normal} \ n" } 명확한 show_menu [$ opt! = ''] 동안 하다 [$ opt = ''] 인 경우; 그때 출구; 그밖에 사례 $ opt in 1) 클리어; option_picked "옵션 1 선택"; printf "sudo mount / dev / sdh1 / mnt / DropBox /; # 3 테라 바이트"; show_menu; ;; 2) 클리어; option_picked "옵션 2 선택"; printf "sudo mount / dev / sdi1 / mnt / usbDrive; # 500 기가 드라이브"; show_menu; ;; 3) 클리어; option_picked "옵션 3 선택"; printf "sudo service apache2 restart"; show_menu; ;; 4) 클리어; option_picked "옵션 4 선택"; printf "ssh lmesser @ -p 2010"; show_menu; ;; x) 출구; ;; \ n) 종료; ;; *)명확한; option_picked "메뉴에서 옵션을 선택하십시오"; show_menu; ;; esac fi 끝난
$
의 $opt
변수에서 가 누락되었습니다 while
. if
문은 중복입니다. 일관되지 않은 들여 쓰기 menu
'show_menu .
show_menu '가 필요한 곳에서 사용하면 각각 반복되는 대신 루프의 맨 위에 놓을 수 있습니다 case
. 일관되지 않은 들여 쓰기 단일 대괄호와 이중 대괄호 사용 혼합. 대신 하드 코딩 된 ANSI 시퀀스를 사용 tput
합니다. 모든 대문자 var 이름을 사용하지 않는 것이 좋습니다. FGRED
호출되어야합니다 bgred
. 대신 백틱을 사용하십시오 $()
. 함수 정의는 일관성이 있어야하고 사용하지 않아야합니다.
\n
는 절대 실행되지 않습니다. 아마도 더.
나는 우분투에 항상있는 것처럼 보이는 Zenity를 사용했으며 매우 잘 작동하며 많은 기능을 가지고 있습니다. 가능한 메뉴의 스케치입니다.
#! /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