it-swarm-tr.com

Shell betiğinde nasıl seçim menüsü oluşturabilirim?

Basit bir bash betiği oluşturuyorum ve bunun gibi bir seçim menüsü oluşturmak istiyorum:

$./script

echo "Choose your option:"

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

Ve kullanıcının seçimine göre, farklı eylemlerin gerçekleştirilmesini istiyorum. Ben bir bash Shell scripting noob, bazı cevaplar için web aradım ama gerçekten somut bir şeyim yok.

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

Çıkmak için break döngüsüne ihtiyaç duyduğunuz her yere select deyimi ekleyin. Bir break gerçekleştirilmezse, select deyimi döngüler ve menü yeniden görüntülenir.

Üçüncü seçenekte, bu değerlere erişiminiz olduğunu göstermek için select ifadesi tarafından ayarlanan değişkenleri dahil ettim. Seçerseniz, çıktı olacaktır:

you chose choice 3 which is Option 3

$REPLY öğesinin İstemde girdiğiniz dizeyi içerdiğini görebilirsiniz. Dizinin 1 tabanlı olduğu gibi ${options[@]} dizisine bir dizin olarak kullanılır. $opt değişkeni, dizideki o dizinden gelen dizeyi içerir.

Seçimlerin, şöyle doğrudan select ifadesinde basit bir liste olabileceğini unutmayın:

select opt in foo bar baz 'multi Word choice'

ancak, seçimlerden birindeki boşluklar nedeniyle böyle bir listeyi skaler değişkene koyamazsınız.

Dosyalar arasında seçim yapıyorsanız globbing dosyasını da kullanabilirsiniz:

select file in *.tar.gz
147

Yeni bir cevap değil per se, fakat henüz kabul edilmiş bir cevap olmadığı için, hem seçme hem de seçkinlik için birkaç kodlama ipucu ve püf noktası:

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

Bahsetmeye değer:

  • Her ikisi de kullanıcı açıkça Quit (veya zenity için Cancel) seçimini yapana kadar döngülenecektir. Bu, etkileşimli script menüleri için iyi bir yaklaşımdır: bir seçim seçilip işlem yapıldıktan sonra, menü başka bir seçim için tekrar sunulur. Eğer seçim sadece bir kereye mahsustursa, sadece break'den sonra esac kullanın (zenity yaklaşımı daha da azaltılabilir)

  • Her ikisi de case, değere dayalı değil, dizin temellidir. Bunun kodlanması ve bakımı daha kolay olduğunu düşünüyorum

  • Dizi ayrıca zenity yaklaşımı için kullanılır.

  • "Çık" seçeneği, başlangıçtaki orijinal seçenekler arasında değildir. Gerektiğinde "eklenir", böylece diziniz temiz kalır. Bundan sonra, yine de zenit için "Çık" gerekli değildir, kullanıcı çıkmak için sadece "İptal" tıklayabilir (veya pencereyi kapatabilir). Her ikisinin de aynı, el değmemiş seçenek dizisini nasıl kullandığına dikkat edin.

  • PS3 ve REPLY vars can değil yeniden adlandırılabilir. select bunları kullanmak için kodlanmış. Komut dosyasındaki diğer tüm değişkenler (opt, options, Prompt, title), ayarları yapmanız şartıyla, istediğiniz adlara sahip olabilir.

56
MestreLion

dialog kullanarak komut şu şekilde görünür:

dialog --clear --backtitle "Backtitle here" --title "Title here" --menu "Aşağıdaki seçeneklerden birini seçin:" 15 40 4\
 1 "Seçenek 1"\
 2 "Seçenek 2"\
 3 "Seçenek 3" 

enter image description here

Bir komut dosyasına koyarak:

#!/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

Seçenekler oluşturmak için bu basit betiği kullanabilirsiniz

#!/bin/bash 
 echo "operasyonu seç ************" 
 echo "1) operasyon 1" 
 echo "2) işlem 2 "
 echo" 3) işlem 3 "
 echo" 4) işlem 4 " 
n durumu $ n 1) yankı "Seçenek 1'i seçtin" ;; 2] seçenek 2'yi seçtiniz ";; ____.] 3) eko "Seçenek 3'ü seçtiniz" ;;; 4) eko "Seçenek 4'ü seçtiniz" ;; *) Eko "geçersiz seçenek" ;; Esac
14
jibin

Bu cevapların bir karışımı olan bir seçeneğim daha var, ancak bunu güzel yapan şey sadece bir tuşa basmanız gerektiği ve ardından senaryo okumadaki -n seçeneği sayesinde devam ediyor. Bu örnekte, değişkenimiz olarak ANS kullanarak komut dosyasını kapatmanız, yeniden başlatmanız veya basitçe çıkmanız isteniyor ve kullanıcının yalnızca E, R veya S tuşlarına basması gerekiyor. düğmesine basıldıktan sonra komut dosyası çıkacaktır.

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

Bu Ubuntu'da hedeflendiğinden, arka planda debconf kullanmak için yapılandırılmış olanı kullanmalısınız. Debconf arka ucunu şurada bulabilirsiniz:

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

Eğer "diyalog" yazıyorsa, muhtemelen whiptail veya dialog kullanır. Lucid'de whiptail.

Bu başarısız olursa, Dennis Williamson tarafından açıklandığı gibi bash "select" kullanın.

7
Li Lo
#!/bin/sh 
 show_menu () {
 normal = `eko"\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} ** $ {sayı} 1) $ {menu} Dağı dropbox $ {normal}\n "
 printf "$ {menu} ** $ {sayı} 2) $ {menu} USB 500 Gig Sürücüsünü takın $ {normal}\n" 
 printf "$ {menu} ** $ {sayı} 3) $ {menu} Apache'yi Yeniden Başlat $ {normal}\n "
 printf" $ {menu} ** $ {sayı} 4) $ {menu} ssh Frost Tomcat Sunucu $ {normal}\n "
 printf "$ {menu} ** $ {sayı} 5) $ {menu} Diğer bazı komutlar $ {normal}\n" 
 printf "$ {menu} ********* *************************************** $ {normal}\n "
 printf" Lütfen bir menü seçeneği girin ve çıkmak için $ veya {fgred} x yazın. $ {Normal} "
 Op 
} 
 
 Seçenek_picked () {
 msgcolor = `echo"\033 [01; 31m "` # koyu kırmızı 
 normal = `echo"\033 [00; 00m "` # normal beyaz 
 mesaj = $ {@: - "$ {normal} Hata: Mesaj geçilmedi"} 
 printf "$ {msgcolor } $ {message} $ {normal}\n "
} 
 
 temizle 
 show_menu 
 iken [$ opt! = ''] 
 
 yapın, eğer [$ opt = '']; sonra 
 çıkın; 
 else 
 case $ tercih 
 1) temizle; 
 option_picked "Option 1 Picked"; 
 printf "Sudo mount/dev/sdh1/mnt/DropBox /; # 3 terabayt"; 
 Show_menu; 
 ;; 
 2) temizle; 2 "; 
 Printf" Sudo mount/dev/sdi1/mnt/usbDrive; # The 500 gig sürücü "; 
 Show_menu; 
 ;; 
 3) aldı clear; 
 option_picked "Option 3 Picked"; 
 printf "Sudo service Apache2 restart"; 
 show_menu; 
 ;; 
 4) temizle; 
 option_picked "Seçenek 4 Seçildi"; 
 printf "ssh lmesser @ -p 2010"; 
 show_menu; 
 ;; 
 x) exit; 
 ;; 
\n) exit; 
 ;; 
 *) clear; 
 option_picked "Bir seçenek seç menüsü "; 
 show_menu; 
 ;; 
 esac 
 fi 
 yapıldı
7
Alex Lucard

Ubuntu'da her zaman orada görünen Zenity'yi kullandım, çok iyi çalışıyor ve birçok özelliğe sahip. Bu, olası bir menünün taslağıdır:

#! /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

Bash fantezi menüsü

Önce deneyin, sonra ayrıntılı açıklama için sayfamı ziyaret edin ... Dış kütüphanelere veya diyalog veya zenci gibi programlara gerek yok ...

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

Aynı soru zaten serverfault olarak cevaplandı. Buradaki çözüm whiptail kullanır.

2
txwikinger