it-swarm-ko.tech

쉘 스크립트에서 선택 메뉴를 작성하는 방법

간단한 bash 스크립트를 만들고 다음과 같이 선택 메뉴를 만들고 싶습니다.

$./script

echo "Choose your option:"

1) Option 1  
2) Option 2  
3) Option 3  
4) Quit  

그리고 사용자의 선택에 따라 다른 작업을 실행하고 싶습니다. 나는 bash Shell 스크립팅 멍청한 놈입니다. 웹에서 몇 가지 답변을 검색했지만 실제로는 아무것도 얻지 못했습니다.

129
Daniel Rodrigues
#!/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 문을 추가하십시오. break을 수행하지 않으면 select 문이 반복되고 메뉴가 다시 표시됩니다.

세 번째 옵션에서는 select 문에서 설정 한 변수를 포함하여 해당 값에 액세스 할 수 있음을 보여줍니다. 선택하면 다음과 같이 출력됩니다.

you chose choice 3 which is Option 3

$REPLY에 프롬프트에서 입력 한 문자열이 포함되어 있음을 알 수 있습니다. 배열이 1 기반 인 것처럼 배열 ${options[@]}에 대한 인덱스로 사용됩니다. 변수 $opt에는 해당 인덱스의 문자열이 배열에 포함되어 있습니다.

선택은 다음과 같이 select 문에 직접 간단한 목록이 될 수 있습니다.

select opt in foo bar baz 'multi Word choice'

그러나 선택 중 하나의 공백으로 인해 이러한 목록을 스칼라 변수에 넣을 수 없습니다.

파일 중에서 선택하는 경우 파일 globbing을 사용할 수도 있습니다.

select file in *.tar.gz
147

새로운 대답은 아니지만 se 자체, 그러나 아직 대답이 없기 때문에 선택과 정력에 대한 몇 가지 코딩 팁과 요령이 있습니다.

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을 사용하십시오 (정도 접근 방식을 더 줄일 수도 있음)

  • case은 모두 값 기반이 아니라 인덱스 기반입니다. 코딩하고 유지하기가 더 쉽다고 생각합니다.

  • zenity 접근법에도 배열이 사용됩니다.

  • "종료"옵션은 최초의 원래 옵션 중 하나가 아닙니다. 필요할 때 "추가"되므로 어레이가 깨끗하게 유지됩니다. 어쨌든 "종료"는 zenity에 필요하지 않습니다. 사용자는 "취소"를 클릭하거나 창을 닫으면 종료됩니다. 두 가지 모두 동일한 수정되지 않은 옵션 배열을 사용하는 방법에 유의하십시오.

  • PS3REPLY vars는 not 이름을 바꿀 수 있습니다. select에서 사용하도록 하드 코딩되었습니다. 스크립트의 다른 모든 변수 (옵션, 옵션, 프롬프트, 제목)는 원하는대로 조정할 수 있습니다.

56
MestreLion

dialog 을 사용하면 명령은 다음과 같습니다.

대화 상자 --clear --backtitle "Backtitle here"--title "Title here"--menu "다음 옵션 중 하나를 선택하십시오."15 40 4\
 1 "Option 1"\ 
 2 "옵션 2"\ 
 3 "옵션 3"

enter image description here

스크립트에 넣는 방법 :

#!/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
54
Alaa Ali

이 간단한 스크립트를 사용하여 옵션을 만들 수 있습니다

#!/bin/bash 
 echo "작업 ***********"
 echo "1) operation 1"
 echo "2) 작업 2 "
 echo"3) 작업 3 "
 echo"4) 작업 4 " 
에서 n case $ n을 읽습니다. 1) echo "옵션 1을 선택했습니다. ;; 2) echo"옵션 2를 선택했습니다. ;; 3) echo "옵션 3을 선택했습니다. ;; 4) echo"옵션 4를 선택했습니다. ;; *) echo "잘못된 옵션";; esac
14
jibin

이 답변이 혼합 된 옵션이 하나 더 있지만 니스를 만드는 이유는 하나의 키만 누르면 스크립트의 -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
8
HarlemSquirrel

이것은 Ubuntu를 대상으로하기 때문에 사용하도록 구성된 백엔드 debconf를 사용해야합니다. 다음과 같이 debconf 백엔드를 찾을 수 있습니다.

Sudo -s "echo get debconf/frontend | debconf-communicate"

"dialog"라고 표시되면 whiptail 또는 dialog을 사용하는 것입니다. Lucid에서는 whiptail입니다.

실패하면 Dennis Williamson의 설명에 따라 bash "select"를 사용하십시오.

7
Li Lo
#!/bin/sh 
 show_menu () {
 normal =`echo "\ 033 [m"`
 menu =`echo "\ 033 [36m"`#Blue 
 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 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"`# normal white 
 message = $ {@ :- "$ {normal} 오류 : 메시지가 전달되지 않았습니다"} 
 printf "$ {msgcolor } $ {message} $ {normal}\n "
} 
 
 clear 
 show_menu 
 동안 [$ opt! = ''] 
 do 
 if [$ opt = '']; 그런 다음 
 종료; 
 else 
 case $ opt in 
 1) clear; 
 option_picked "Option 1 Picked"; 
 printf "Sudo mount/dev/sdh1/mnt/DropBox /; #The 3 terabyte"; 
 show_menu; 
 ;; 
 2) clear; 
 option_picked "옵션 2 선택 "; 
 printf"Sudo mount/dev/sdi1/mnt/usbDrive; # 500 기가 드라이브 "; 
 show_menu; 
 ;; 
 3) clear; 
 option_picked "Option 3 Picked"; 
 printf "Sudo service Apache2 restart"; 
 show_menu; 
 ;; 
 4) clear; 
 option_picked "옵션 4 선택"; 
 printf "ssh lmesser @ -p 2010"; 
 show_menu; 
 ;; 
 x) 종료; 
 ;; 
\n) 종료; 
 ;; 
 *) clear; 
 option_picked "옵션을 선택하십시오 메뉴 "; 
 show_menu; 
 ;; 
 esac 
 fi 
 완료
7
Alex Lucard

나는 우분투에 항상있는 것처럼 보이는 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
6
LazyEchidna

배쉬 팬시 메뉴

먼저 시도한 다음 자세한 설명을 보려면 내 페이지를 방문하십시오 ... 대화 상자 또는 정력과 같은 외부 라이브러리 또는 프로그램이 필요하지 않습니다 ...

#/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
5
user360154

serverfault 에서 이미 같은 질문이 있습니다. 이 솔루션은 whiptail 을 사용합니다.

2
txwikinger