W poprzednich rozdziałach omówiliśmy sposoby korzystania z podstawowych poleceń shella. Jednak aby w pełni z niego korzystać, potrzebne są polecenie, które umożliwiają sprawowanie nadzoru nad tym co i kiedy zostanie wykonane. Nalezą do nich polecenia, za pomocą których, użytkownik może:
→ wybrać jedną z dwóch czynności (if-then-else-fi)
→ wybrać jedna z wielu czynności (case)
→ powtarzać czynności wiele razy ( while, for, until )
Struktury tych poleceń składają się z dwóch głównych składników: testu i poleceń. Jeżeli wynik testu jest pozytywny, komendy zostają uruchomione. W programach powłoki shella używa się dwóch typów struktur kontrolnych: pętli i instrukcji warunkowych. Pętle służą do powtarzania komend, zaś instrukcje warunkowe – wykonują polecenia gdy spełnione sa określone warunki.
Bash Shell posiada trzy struktury pętli while , for, for in, oraz dwie instrukcje warunkowe if i case. Struktury while i if są dość ogólne. Są używane przede wszystkim do zdefiniowania warunków w jakich następują wykonywania powtórzeń i dokonywania decyzji przy użyciu rozmaitych testów. Natomiast instrukcje case i for i ich użycie jest używane w dość szczególnych sytuacjach; case jest rozwiniętą formą warunku if i jest często używana do budowy i obsługi menu. Struktura for jest zawężonym typem pętli. Przetwarza ona listę wartości przyporządkowując z każdym powtórzeniem pętli, nowa wartość określonej pętli. Możliwość korzystania z pętli i instrukcji warunkowych w połączeniu z poznanymi już poleceniami czyni z basha shella pełnowartościowy język programowania, który można wykorzystać do złożonych zadań przetwarzania informacji. Użytkownik bash shella będzie po zapoznaniu się i zrozumieniu tego rozdziału, zdolny do budowy skomplikowanych programów.
Używanie konstrukcji if-then-fi
W jaki sposób - przy pomocy jakich logicznych konstrukcji – człowiek podejmuje określone decyzje? Najprostszą logikę, leżącą u fundamentów każdej decyzji, można streścić w następujący sposób: jeśli (if) zachodzi jakiś warunek, to (then) wykonuje działanie. Można to odnieść do każdej sytuacji, w tym do naszego codziennego życia. Na przykład, jeśli zadzwoni telefon to podniosę słuchawkę, jeśli zadzwoni dzwonek u drzwi to je otworze, jeśli będzie zimno to założę płaszcz itd. Przykłady można mnożyć w nieskończoność. Składnia tego typu logiki w krypcie pisanym bash-shell, wygląda tak:
if [ zachodzi określony warunek ]
then [ wykonaj jakieś działanie ]
fi
Struktura if umieszcza warunek w poleceniu, jeśli polecenie zostanie pozytywnie zweryfikowane to wszystkie inne czynności w strukturze if zostaną wykonane. Mówimy w takim przypadku, że status polecenia-warunku jest równy 0, jeśli natomiast warunek zostanie zweryfikowany negatywnie – to znaczy, że nie jest prawdziwy, w takim wypadku status przybiera wartość fałszywą równą 1 i czynności zawarte w strukturze if nie zostaną wykonane.
Struktura if rozpoczyna się od słowa kluczowego if , po którym następuje polecenie Linuxa, którego status tzw. „status wyjściowy” ma zostać poddany weryfikacji. Polecenie-warunek jest zawsze uruchamiane. Po nim umieszczone jest słowo kluczowe then , po którym następuje dowolny zbiór poleceń Linuxa. Słowo fi kończy całą strukturę. Często – pisząc skrypt – użytkownik musi wybrać pomiędzy dwoma alternatywami. Słowo kluczowe else pozwala strukturze if na wybór pomiędzy dwiema alternatywami. Jeżeli weryfikacja polecenia-warunku jest prawdziwa, uruchomiony zostaje fragment programu umieszczony po słowie then , w przeciwnym wypadku ten umieszczony po słowie else. Struktura polecenia if-then-else-fi pokazana jest poniżej :
if [ zachodzi okreslony warunek ]
then
wykonaj polecenie x
else
wykonaj polecenie y
fi
Wykonajmy prosty skrypt który zilustruje nam działanie struktury if-then-else-fi. Skrypt proces1 w poniższym przykładzie uruchamia polecenie ps z dwiema różnymi opcjami w celu wyświetlenia aktualnych procesów użytkownika egzekwującego ten skrypt albo procesy wszystkich użytkowników zalogowanych do systemu:
$ vi proces1
#!/bin/bash
echo ”wcisnij u w celu wyswietlenia procesow uzytkownika”
echo ”w przeciwnym wypadku zostana wyswietlone procesy wszystkich użytkowników’’
echo -n „”Proszę wybrac opcje : ”
read wybor
if [ „”$wybor=u ]
....then
..........ps -ul
....else
..........ps -al
fi
Uruchomienie skryptu ma postać:
wcisnij u w celu wyswietlenia procesow uzytkownika
w przeciwnym wypadku zostana wyswietlone procesy wszystkich uzytkownikow
Proszę wybrac opcje : u
piotr 11736 11731 0 13:45 pts/0 00:00:00 /bin/bash
piotr 11737 11732 0 13:45 pts/1 00:00:00 /bin/bash
piotr 11738 11733 0 13:45 pts/0 00:00:00 /bin/bash
Przejdźmy teraz do zaprezentowania ostatniej formy struktury if zwanej przez logików : „w przeciwnym razie jeśli”. Struktura elif pozwala na zagnieżdżenie operacji if-then-else-if. Jej nazwa jest skrótem od „else if”. W strukturze elif pierwsza operacja jest określona strukturą if, za którą następują kolejne. Jeśli weryfikacja warunku-polecenia ze struktury if jest nieprawdziwa, to kontrola zostaje przekazana strukturze elif i jej warunek jest testowany. Jeżeli warunek-polecenie elif jest nieprawdziwy to wtedy, kontrola zostaje przekazana do następnej struktury elif, jeżeli i ta jest nieprawdziwa wykonujemy polecenia zawarte w strukturze else. Składnia struktury elif znajduje się poniżej.
if [ warunek polecenie ]
....then
...komendy Linuxa
.....elif
...komendy Linuxa
....else
...komendy Linuxa
fi
W skrypcie proces2 zaprezentowane zostały dwie metody wyświetlenia procesów użytkownika lub użytkowników.
echo ” wyswietl procesy uzytkownika”
echo ”wyswietl procesy wszystkich uzytkownikow”
echo -n „”Proszę wybrac opcej : ”
read wybor
if [ ”$wybor”=u ]
then
ps -ul
elif [ “$wybor”=l ]
then
ps -al
else
echo “niewlasciwa opcja”
fi
echo ”Do widzenia”
Polecenie test
Niezbędnym uzupełnieniem struktury kontrolnej if-then-fi jest polecenie test. Z jego pomocą można na przykład stwierdzić, czy dana nazwa jest nazwą pliku czy katalogu, czy jest to plik z prawami do czytania, pisania i wykonywania, czy dwa napisy lub dwie liczby są sobie równe lub nie czy jedna z nich jest większa albo mniejsza od drugiej. Polecenie to składa się z słowa test wraz z wartościami, które maja być porównane, oddzielonymi operatorem określającym typ porównania. Porównywać można ciąg lub ciągi znaków, w tym wypadku występują następujące opcje dla tzw. porównania tekstowego
-z sprawdza czy ciąg jest pusty
-n sprawdza wartość ciągu
= równy
!= nierówny
Str sprawdza czy ciąg jest zerowy
Polecenie test może także porównywać dwie liczby, w tym wypadku występują następujące opcje dla tzw. porównania liczbowego:
Porównanie liczbowe: funkcje:
-gt większy od
-lt mniejszy od
-ge większy lub równy
-le mniejszy lub równy
-eq równy
-ne nierówny
Jak widać używanie polecenia test jest bardzo skomplikowane, dlatego pierwsza uwaga: aby sprawdzić czy dwa ciągi znaków są równe używa się znaku równości = , aby porównać dwie liczby używa się opcji -eq. Zauważmy, że te porównania są sprzeczne z naszym kulturowym doświadczeniem, ponieważ przez całe życie dwie liczby porównywaliśmy przy pomocy znaku równości = .
Poszczególne opcje czy wyrażenia możemy łączyć przy pomocy operatorów logicznych AND (logiczna suma), OR (logiczna alternatywa) i NOT (logiczna negacja). Opcje operacji logicznych są następujące:
-a logiczna suma ( i )
-o logiczna alternatywa (lub)
! logiczna negacja ( nie )
Polecenie test służy także do przeprowadzenia testów na plikach:
Opcja: funkcja:
-f plik istnieje i jest zwykłym plikiem
-s plik nie jest pusty
-r plik jest możliwy do odczytu
-w plik może być modyfikowany
-x plik jest skryptem uruchamialnym
-d plik jest katalogiem
-h plik jest łączem symbolicznym
-c plik jest urządzeniem
-b plik jest plikiem blokowym
Polecenie test , podobnie do innych poleceń shella, zwraca wartość 0 jeżeli jest prawdą i 1 jeżeli jest fałszem w zmiennej $? . Podamy teraz kilka przykładów w których użyjemy polecenia test. Chcemy się upewnić czy dwa napisy: „ala” i „kola” są równe .Przypominamy ,że zmienna specjalna $? przechowuje status wyjściowy ostatnio użytej komendy Linuxa:
$ test „ala” = „kola”
$ echo $?
1
$ num=1
$ test $num -eq 3
$ echo $?
1
Polecenie test można zastąpić stosując kwadratowe nawiasy [ ]. Dlatego powyższe ćwiczenia można zapisać.
$ [ „ala” = „kola” ] .. równoważne $ test „ala” = „kola”
$ [ $num -eq 3 ] ......równoważne $ test $num –eq 3
Po pierwszym [ musimy wystukać spacje, tak samo przed ] musimy zrobić to samo.
[ $num -eq 3 ]
..↑ ↑
spacja spacja
Jeżeli pomiędzy [ i $num nie będzie spacji komenda nie będzie działać: omijanie tej zasady jest źródłem licznych błędów. Jak widzimy polecenie test może przybierać różne formy.
1. test
2. [ ]
Innymi słowy polecenie [ ] jest aliasem polecenia test, stąd trzeba po nim wpisywać spacje. Przypominamy, że po każdym poleceniu w linii poleceń lub w skrypcie musimy wpisać spacje, jeżeli zamiast np.
$ grep plik1
napisalibyśmy grepplik1, to polecenie nie zostałoby wykonane, tak samo jeżeli zamiast:
[ plik1 ] wpisalibyśmy [plik1] to polecenie nie zostałoby wykonane.
Kładziemy na to nacisk ponieważ nawiasy kwadratowe i ich użycie często nie są uważane przez użytkowników jako polecenie!
Wykonajmy kilka przykładów z poleceniem [ ] i jego równoważnikiem poleceniem test. Aby sprawdzić czy zalogowany właśnie użytkownik jest rootem (administratorem systemu), należy wydąć polecenie:
$ [ ’’$LOGNAME’’ = root ]
$ echo $?
0
Oznacza to że root jest zalogowany i że to właśnie wykonuje polecenie. Gdyby tak nie było, zwrócona zostałaby wartość 1 lub większa od zera, co możemy zobaczyć w poniższym przykładzie:
$ [ ’’$LOGNAME’’ = ‘’piotr” ]
$ echo $?
1
$
Polecenia logiczne : && i ||
Polecenia logiczne wykonują operacje logiczne na dwóch poleceniach logicznych. W przypadku logicznej koniunkcji wyrażonej tutaj symbolem && jeśli oba polecenia umieszczone po obu stronach operatora są prawdziwe, to całość jest prawdziwa.
W przypadku logicznej alternatywy wyrażonej tutaj symbolem || , jeśli jedno z poleceń umieszczonych po obu stronach operatora jest prawdziwe, to całość jest prawdziwa.
polecenie && polecenie
polecenie || polecenie
Programowanie Rozdział 9.7 Darmowy kurs Linux