Petla Select

Słuzy do generowania prostych menu. Z listy argumjentów jest tworzone proste ponumerowane menu, każdej pozycji odpowiada kolejna liczba od 1 wzwyż. Poniżej menu znajduje się znak zachęty (odpowiada za niego zmienna systemowa $PS3) gdzie wpisujemy cyfrę odpowiadająca wybranej przez nas pozycji w menu. Jeśli nic nie wpiszemy i wciśniemy ENTER, menu będzie wyświetlone ponownie. To co wpisaliśmy zachowywane jest w zmiennej REPLY. Gdy odczytane zostaje EOF (ang. End Of File) czyli znak końca pliku (CTRL+D) to select kończy pracę. Pętla działa dotąd dopóki nie wykonane zostaje polecenie break lub return.

Uwaga:

Przed dalszym czytaniem polecam zajrzeć też do składni isntrukcji case

Składnia:

select <zmienna> in <lista> ; do
  polecenie
done

Przykład:

#!/bin/bash
echo "Co wybierasz?"
select y in X Y Z Quit
do
  case $y in
    "X") echo "Wybrałeś X" ;;
    "Y") echo "Wybrałeś Y" ;;
    "Z") echo "Wybrałeś Z" ;;
    "Quit") exit ;;
    *) echo "Nic nie wybrałeś"
  esac
break
done

Najpierw zobaczymy proste ponumerowane menu, składające się z czterech elementów: X, Y, Z i Quit, teraz wystarczy tylko wpisać numer inetersującej nas opcji, a resztę zrobi instrukcja case. Polecenie break, które znajduje się w przedostatniej linii skryptu, kończy pracę pętli.

Pętle taką można zostąpić pętla while z warunkiem zawsze prawdziwym

while [ 1 -eq 1 ] ; do 
            echo "What next?"
            echo "1. X"
            echo "2. Y"
            echo "3. Z"
            read anwser
            case "$(echo "$anwser" | tr '[:upper:]' '[:lower:]')" in
                   "X")      echo "Wybrałeś X" ;;
                   "Y")      echo "Wybrałeś Y" ;;
                   "Z")     "Z") echo "Wybrałeś Z" ;;
                   "Quit")  break ;;
                   *)      echo "Nic nie wybrałeś" ;;
            esac
done

A teraz bardziej praktyczny przykład, poniższy skrypt (Uwaga!) przeznaczony dla dystrybucji Slackware wygeneruje menu składające się z listy Window Mangerów, po wybraniu konkretnej pozycji uruchomiony zostanie dany WM. Oczywiście należy skrypt zmodyfikować pod kątem własnego systemu. Jeśli komuś odpowiada takie rozwiązanie, wystarczy utworzyć alias: alias startx="~/.ten_skrypt" i po ponownym zalogowaniu mamy po wpisaniu polecenia startx menu wyboru Window Managerów.

#!/bin/bash
echo ""
echo "[ JAKI WINDOW MANAGER URUCHOMIĆ? WYBIERZ CYFRĘ Z LISTY: ]"
echo ""
select l in BLACKBOX ENLIGHTENMENT GNOME ICEWM KDE MWM OPENWIN TWM WMAKER WYJŚCIE
do
  case "$l" in
    "BLACKBOX") cat /etc/X11/xinit/xinitrc.blackbox > ~/.xinitrc; startx $@ ;;
    "ENLIGHTENMENT") cat /etc/X11/xinit/xinitrc.e > ~/.xinitrc; startx $@ ;;
    "GNOME") cat /etc/X11/xinit/xinitrc.gnome > ~/.xinitrc; startx $@ ;;
    "ICEWM") cat /etc/X11/xinit/xinitrc.icewm > ~/.xinitrc; startx $@ ;;
    "KDE") cat /etc/X11/xinit/xinitrc.kde > ~/.xinitrc; startx $@ ;;
    "MWM") cat /etc/X11/xinit/xinitrc.mwm > ~/.xinitrc; startx $@ ;;
    "OPENWIN") cat /etc/X11/xinit/xinitrc.openwin > ~/.xinitrc; startx $@ ;;
    "TWM") cat /etc/X11/xinit/xinitrc.twm > ~/.xinitrc; startx $@ ;;
    "WMAKER") cat /etc/X11/xinit/xinitrc.wmaker > ~/.xinitrc; startx $@ ;;
    "WYJŚCIE") exit ;;
    *) startx $@
  esac
break
done

Elementy składowe listy w pętli select, noszą takie same nazwy jak wzorce w instrukcji case co umożliwia bardzo proste dopasowanie odpowiedzi i wykonanie odpowiednich poleceń. Jak to wygląda w praktyce? Na przykład chcemy uruchomić KDE, wybieramy więc z menu opcje o wyżej wymienionej nazwie, następnie polecenie cat nadpisuje nasz domowy plik .xinitrc, kopiując do niego zawartość pliku xinitrc zoptymalizowanego dla KDE, znajdującego się w katalogu: /etc/X11/xinit/xinitrc.kde, po czym wykonywane jest polecenie startx.
Komentarz odnośnie polecenia startx $@

Zmienna $@ to zmienna specjalna umożliwiająca przekazywanie do skryptu parametrów (startx to też skrypt powłoki), dzięki czemu możemy spokojnie stosować wszelkie parametry np. dwukrotne odpalenie X-ów: startx — :0 na pierwszej konsoli i startx — :1 na drugiej. Gdy nie wpiszemy żadnych parametrów $@ jest pusta.

A co się stanie w przypadku gdy podczas wyboru Window Managera podamy większą cyfrę niż tą jaką ma ostatni element menu lub jakiś inny znak?

Uruchomiony zostanie ten WM, który ostatnio odpalaliśmy, odpowiada za to linia *) startx $@

Przykład poniżej powinien wyjaśnić sposób użycia jednej i drugiej instrukcji. Przykład został zmodyfikowany przez tłumacza na lepiej odpowiadający porzebom tekstu:

#!/bin/bash

echo "***********************"
echo "Jakie zwierzęta lubisz najbardziej?"
select opcja in psy koty szczury żadne
       do
       case $opcja in
               psy) 
                    echo "psy.... no fakt, są fajne"
               ;;
               koty)
                    echo "e, koty są fałszywe..."
               ;;
               szczury) 
                    echo "tak, szczurki są cudowne..."
               ;;
               *)                      
                    echo "skoro nie lubisz żadnych zwierząt"
                    echo "to ja już sobie pójdę"
                    break;
               ;;
       esac
       echo "***********************"
done

Powyższy skrypt będzie dzięki instrukcji select będzie pozwalał na wybór jednej z opcji, a następnie wyswietli tekst komunikatu odpowadający wybranej opcji.
Dla 4 przypadku została użyta instrukcja break, która przerywa działanie select. Tak więc możliwy jest wielokrotny wybór zwierząt pętla zakończy się w momencie wyboru zwierzęcia, którego nie ma na liście (zadziała instrukcja break).

Powyzszy kod pochodzi z jakieś strony - niestety nie pamiętam jakiej … jeśli ktoś ma namiary to proszę kliknąć ;)

O ile nie zaznaczono inaczej, treść tej strony objęta jest licencją Creative Commons Attribution-ShareAlike 3.0 License