Poznaliśmy już jedną konstrukcje logiczną, której zadaniem jest wybór decyzji jaką powinien podjąć czy to człowiek czy program. Aby jednak można było w pełni korzystać z shella potrzebne są także inne konstrukcje które pozwolą nadzorować co i kiedy zostanie wykonane. Oprócz konstrukcji if-then-fi i jej wielorakich odmian, należą do nich polecenia za pomocą których użytkownik może:
1. wybrać jedna z wielu czynności (case)
2. powtarzać czynności wiele razy – tzw. pętle (for, reapet, while, until)
Pętla while
Pętla while służy do wielokrotnego powtarzania poleceń. Zaczyna się ona od słowa kluczowego while, po którym następuje polecenie Linuxa. Słowo do znajduje się w następnej linii pod linią gdzie figuruje while. Składnia polecenia – lub raczej logicznej konstrukcji - while przedstawia się następująco:
while [ polecenie – test ]
...do
..polecenie(a)
...done
Polecenie Linuxa użyte w strukturze while (tuż po tym słowie) często jest testem umieszczonym w kwadratowych nawiasach. W skrypcie skrypt4 poniżej użytkownik (czytelnik) proszony jest o podanie swojego imienia. Pętla kontrolowana jest przez testowanie wartości zmiennej przy pomocy nawiasowej formy testowanego polecenia.
Jeżeli uruchomimy skrypt4 (przedtem musimy nadać mu odpowiednie prawa).
$ ./skrypt4
Czyli dopóki zmienna pytanie zachowuje wartość : „tak” dopóty pętla jest wykonywana. Czasami potrzebna jest pętla nieskończona – chociaż odradzane jest jej używanie szczególnie przez informatyków z małym doświadczeniem. Poniżej podano przykład właśnie pętli niekończonej. Wykorzystane w pętli jest polecenie test , które rozpoznaje każdą stałą jako wartość prawdziwą.
while [ 1 ]
....do
wykonuj polecenia
...done
Aby zapobiec wykonywanie pętli bez końca, lub nie zmuszać użytkownika do przerwania pętli za pomocą kombinacji klawiszy CTRL * z, należy użyć polecenia break, które powoduje wyjście z pętli:
while [ 1 ]
...do
if [ warunek zakończenia ]
.....break
else
.....wykonuj polecenia
fi
done
Pętla until
Struktura pętli until działa w sposób podobny do struktury pętli while. Różnica polega na tym, że until weryfikuje czy wynik polecenia-warunku Linuxa jest negatywny a nie pozytywny. Dopóki warunek ten (negatywny) jest spełniony polencie to kontynuuje wykonywanie pętli. W gruncie rzeczy pętla until sprawdza fałszywość testowanego warunku polecenia. Dlatego tez znacznie się ona różni od struktur kontrolnych, które są często używane w językach programowania . Jest ona bardziej podobna do operatorów sprawdzających fałszywość wyrażenia. Poniżej przedstawiamy składnie struktury until :
until {warunek-polecenie}
...do
polecenia
...done
Poniżej przedstawiamy jedna z możliwości użycia pętli until. Skrypt koniec1 wykonuje pętle dopóty nie wpiszemy słowa koniec.
# wykonujemy pętle dopóty dopóki nie wpiszemy słowa: koniec
echo wpisz slowo :
read slowo
until [ ”$slowo” = ”koniec” ]
...do
echo ”to nie dobre slowo ! ”
echo ”wpisz slowo : ”
read slowo
..done
echo ”slowo prawidlowe”
Pętla for-in
Trzeci typ pętli - najczęściej używany w systemach Linux, UNIX czy języku C – jest tylko pozornie podobny do pętli while i until ; w tych pętlach najważniejsze jest spełnienie albo niespełnienie jakiegoś – zdefiniowanego najczęściej przez użytkownika – warunku, natomiast pętla for wykonuje operacje na zbiorze zmiennych. Składnia pętli for wygląda następująco:
for {zmienna} in {zbiór}
....do
{ polecenia}
.done
Struktura pętli for została zaprojektowana w taki sposób, że odnosi się ona do zbioru wartości jaką może przyjąć zmienna. Każda wartość ze zbioru przyporządkowana jest kolejno do zmiennej w strukturze for-in. Za każdym powtórzeniem pętli for-in, zmiennej jest przyporządkowana jej kolejna wartość ze zbioru. Innymi słowy podczas wykonywania polecenia for zmienna przyjmuje każdą z wartości umieszczonych w zbiorze (wartość1 wartość2). Podajmy kilka przykładów.
zmienna „auto” zbiór (lista) wartości jaką ona przyjmuje
....... ↑ ↑
for ...auto ..... in ..........skoda warszawa fiat star
.....do
echo „ samochód : $auto”
.done
Jak możemy opisać funkcjonowanie tej pętli ? Zmienna „auto” może przybrać cztery wartości : „skoda” , „warszawa”, „fiat” , „star”, po wyświetleniu zmiennej star czyli ostatniej wartość zmiennej „auto”, pętla kończy egzekucje. Na ekranie wyświetli się następujący rezultat pętli for-in :
samochód : skoda
samochód : warszawa
samochód : fiat
samochód : star
Przećwiczmy teraz inna formę pętli for-in
echo "lista katalogow w pwd"
for i in *
do
...if [ -d $i ]
then
echo $i " : katalog"
..fi
do
Spróbujmy to ćwiczenie wykonać tworząc skrypt o nazwie petla_for, wyegzekwować i następnie objaśnić krok po kroku działanie pętli i instrukcji w niej zawartych.
Pętle for – podobnie jak inne konstrukcje sterujące shella - można zagnieżdżać. Na przykład aby wykonać operacje na plikach zawartych w katalogach bin, home i src skonstruujemy następująca formę pętli for:
for dir in bin home src
...do
cd $dir
for file in *
do
...if [ -f $plik ]
........then
process $plik
...fi
.done
cd…
...done
Polecenia true, false i break ; continue
Polecenie true jest prostą funkcją której status wyjściowy jest zawsze równy zero. Jej przeciwieństwo, polecenie false posiada status równy zawsze 1. Pierwszej z nich można używać jako polecenia testującego strukturę while jako pętli nieskończonej. Druga może mieć podobne zastosowanie w pętli until. Kiedy użytkownik decyduje się użyć niekończonej pętli – co zdecydowanie odradzamy – musi mieć możliwość jej zatrzymania. Do tego służy polecenie break, które po zastosowaniu wewnątrz pętli przekazuje kontrolę nad programem poza pętla, efektywnie zatrzymując jej wykonanie.
Polecenie continue używana jest w pętlach do pomijania pozostałych poleceń wewnątrz pętli i przechodzenia do kolejnego powtórzenia. Graficznie można w sposób następujący przedstawić polecenia continue i break.
Struktura wielokrotnego wyboru : case
Struktura case pozwala programowi na wybór pomiędzy kilkoma możliwymi alternatywami. Wybór jest dokonywany za pomocą porównywania wartości z kilkoma możliwymi wzorami. Poniżej pokazano prosty schemat polecenia case, w którym wartości zmiennej są porównywane z wzorcami wartość1, wartość2, wartość3, wartość4. Jeżeli wartość zmiennej jest równa któremuś ze wzorców, wtedy wykonywana jest odpowiednia czynność.
case $zmienna in
wzór wartość1)
..wykonujemy czynność 1
;;
wzór wartość2)
..wykonujemy czynność 2
;;
wzór wartość3)
..wykonujemy czynność 3
;;
wzór wartość4)
..wykonujemy czynność 4
;;
..*)
...czynność domyślna
...;;
esac
Wzór może zawierać dowolne znaki specjalne powłoki. Są to *, [,] , ? , | .
Ostatni test *) dotyczy czynności domyślnej czyli czynności wykonywanej wtedy kiedy wartość zmiennej nie odpowiada żadnemu ze wzorców. Jest to przydatne na przykład wtedy, kiedy zmienna nie zostanie do żadnego ze wzorców i chcemy wysłać komunikat o błędzie oraz wyjść ze skryptu. Konstrukcja case jest szczególnie przydatna do przetwarzania parametrów przekazanych do procedury.
Zmienna $# zawiera – jak pamiętamy – liczbę parametrów przekazanych do skryptu. Większość skryptów przed rozpoczęciem przetwarzania wymaga podania pewnych parametrów (co najmniej nazwy pliku, na którym wykona się operacje zawarte w skrypcie). W tym przypadku $# będzie większy od 0 . Aby sprawdzić liczbę parametrów, można użyć konstrukcji case i zmiennej $#.
case $# in
0)
.echo „
Struktura case jest często używana do obsługi menu. W programie proces1 użytkownik proszony jest o wpisanie wybranego sposobu wyświetlania informacji o procesach:
# program proces1 pozwala użytkownikowi na wybranie różnych metod wyświetlania #informacji o procesach swoich i innych użytkowników
case $wybór in
u)
..ps -u
;;
a)
..ps -au
;;
l)
..ps –aul
;;
...*)
......echo “ niewlasciwa opcja”
esac
Użycie we wzorach meta znaków (znaków specjalnych) związanych z tworzeniem plików daje użytkownikowi nowe elastyczniejsze sposoby formułowania warunków. Na przykład