[KURS] Programowanie w powłoce #3 – instrukcje warunkowe

[KURS] Programowanie w powłoce #3 - instrukcje warunkowe

Kolejny artykuł z serii „Programowanie w powłoce” poświęcony jest wyrażeniu logicznemu test, instrukcji warunkowej if oraz instrukcji wyboru case. Znajdziesz również informacje dotyczące operatorów pozwalających na formułowanie złożonych wyrażeń logicznych, które można zastosować w warunkach instrukcji if (dotyczące zarówno zmiennych jak i plików).

Schemat działania wszystkich przedstawionych instrukcji jest taki sam – w zależności od warunku zostanie wykonany ciąg poleceń. Skoro wszystkie instrukcje działają tak samo, to po co ich aż tyle? Po przeczytaniu artykułu na pewno poznasz odpowiedź na to pytanie.

Od razu uprzedzam – stosowane w zapisie spacje (w zapisie instrukcji) nie są moim wymysłem a odgórnym wymogiem języka. Jeśli ich zabraknie, skrypt nie uruchomi się!
Warto zwrócić uwagę, że instrukcja warunkowa/wyboru kończy się w momencie wpisania jej odwrotnej nazwy (dla if będzie to fi, dla caseesac). Bez tego również skrypt się nie uruchomi.

Wyrażenie warunkowe test

Wyrażenie logiczne zbliżone jest do instrukcji warunkowej if jednak nie można go rozbudować. Rozpatruje jedynie dwa warunki – wyrażenie jest prawdziwe lub fałszywe

Schemat:

warunek && co jeśli prawda || co jeśli fałsz

Przykład

#!/bin/bash
echo -n "Podaj pierwsza zmienna: "
read a
echo -n "Podaj druga zmienna: "
read b

[ "$a" -eq "$b" ] && echo "a jest równe b" || echo "Zmienne się różnią"

exit 0

Jeśli obie zmienne są równe pojawi się zdanie „a jest równe b”, w przeciwnym wypadku „Zmienne się różnią”.

Instrukcja warunkowa IF

Sprawdza czy warunek jest prawdziwy, jeśli tak to wykonane zostaną polecenia znajdujące się po słowie kluczowym then – w przeciwnym wypadku polecenia znajdujące się po słowie kluczowym else. Instrukcja kończy się słowem fi.

Schemat:

if warunek
then
  polecenia
else
  polecenia
fi

Co może być warunkiem?
Praktycznie wszystko – zaczynając od zmiennej, przez wyrażenia logiczne, kończąc na poleceniach.
Przykład:

#!/bin/bash

echo -n "Podaj swoj wiek: "
read twoj_wiek
moj_wiek=20

if [ "$twoj_wiek" -lt "$moj_wiek" ]
then 
echo -e "Jestes ode mnie młodszy!"
else
echo -e "Jestes ode mnie starszy!"
fi

exit 0

Powyższy przykład rozpatruje dwa przypadki – gdy wpisany z klawiatury wiek jest mniejszy lub większy niż zadeklarowany w programie. Nie bierze pod uwagę przypadku, gdy wiek jest równy. Jak to zmienić? Poprzez rozbudowę instrukcji warunkowej do postaci:

if warunek
then
  polecenia
elif then
  polecenia
else
  polecenia
fi

Przykład:

#!/bin/bash

echo -n "Podaj swoj wiek: "
read twoj_wiek
moj_wiek=20

if [ "$twoj_wiek" -lt "$moj_wiek" ]
then 
echo "Jestem ode mnie młodszy!"
elif [ "$twoj_wiek" = "$moj_wiek" ]
then
echo "Jestesmy rowiesnikami!"
else
echo "Jestes ode mnie starszy!"
fi

exit 0

W przykładach zastosowałem dwa operatory -lt oraz =, poniżej umieszczam listę wszystkich dostępnych operacji wraz z komentarzem:

Zmienne i wyrażenia:

  • argument1 -eq argument2 – prawda, jeśli argument1 jest równy argumentowi2
  • argument1 -ne argument2 – prawda, jeśli argument1 jest różny od argumentu2
  • argument1 -gt argument2 – prawda, jeśli argument1 jest większy od argumentu2
  • argument1 -ge argument2 – prawda, jeśli argument1 jest większy lub równy argumentu2
  • argument1 -lt argument2 – prawda, jeśli argument1 jest mniejszy od argumentu2
  • argument1 -le argument2 – prawda, jeśli argument1 jest mniejszy lub równy argumentowi2
  • wyrażenie -a wyrażenie -prawda, jeśli oba wyrażenia są prawdziwe
  • wyrażenie -o wyrażenie – prawda, jeżeli przynajmniej jedno z wyrażeń jest prawdziwe
  • -z ciąg – prawda, jeśli długość ciągu równa jest zero
  • -n ciąg – prawda, jeśli długość ciągu jest większa od zera
  • ciąg1 = ciąg2 – prawda, jeżeli ciągi są jednakowe
  • ciąg1 != ciąg2 – prawda, jeżeli ciągi są różne
  • ! wyrażenie – prawda, jeżeli wyrażenie jest fałszywe

Pliki i katalogi:

  • -e plik – prawda, jeśli plik istnieje
  • -d plik – prawda, jeśli plik istnieje i jest katalogiem
  • -f plik – prawda, jeśli plik istnieje i jest zwykłym plikiem
  • -L plik – prawda, jeśli plik istnieje i jest dowiązaniem symbolicznym
  • -r plik – prawda, jeśli plik istnieje i można go czytać
  • -w plik – prawda, jeśli plik istnieje i można do niego pisać
  • -x plik – prawda, jeśli plik istnieje i można go wykonywać
  • -s plik – prawda, jeśli plik istnieje i ma rozmiar większy od zera
  • -g plik – prawda, jeśli plik istnieje i ma ustawiony bit set-group-id
  • -u plik – prawda, jeśli plik istnieje i ma ustawiony bit set-user-id
  • -b plik – prawda, jeśli plik istnieje i jest urządzeniem blokowym
  • -c plik – prawda, jeśli plik istnieje i jest urządzeniem znakowym
  • plik1 -nt plik2 – prawda, jeśli plik1 jest nowszy (zgodnie z datą modyfikacji) niż plik2
  • plik1 -ot plik2 – prawda, jeśli plik1 jest starszy niż plik2
  • plik1 -ef plik2 – prawda, jeśli plik1 i plik2 mają te same numery urządzenia i i-węzła

Instrukcja case

Instrukcja case jest inaczej nazywana instrukcją wyboru. Jej struktura jest nieco trudniejsza do zapamiętania niż rozbudowanej instrukcji if, ale jest bardziej czytelna. Na początku sprawdzana jest wartość danej zmiennej (warunki odpadają!), a następnie, w zależności od tej wartości, wykonywany ciąg dalszych instrukcji

Schemat:

case zmienna in
  "wzorzec1") polecenie1 ;; "wzorzec2") polecenie2 ;; "wzorzec3") polecenie3 ;; *) polecenie_domyślne
esac

Oczywiście nie istnieje ograniczenie co do ilości wzorców. Jeśli zmienna nie będzie spełniać żadnego z wzorców, zostaną wykonanie instrukcje zawarte po *).
Przykład:

#!/bin/bash

echo -n "Podaj liczbe od 0 do 3: "
read a

case "$a" in
"0") echo "Podales zero";;
"1") echo "Podales jeden";;
"2") echo "Podales dwa";;
"3") echo "Podales trzy";;
*) echo "Twoja liczba nie jest rowna 0,1,2 lub 3"
esac

exit 0

Przykład jest bardzo trywialny, ale idealnie pokazuje możliwości instrukcji case. W zależności od wpisanej wartości zostanie wypisany odpowiedni komunikat.
Ćwiczenie dla Ciebie
W powyższym skrypcie spróbuj zamienić instrukcję case na if i ocenić czytelność oraz długość kodu :)

To tyle na dzisiaj. Następny artykuł zostanie poświęcony pętlom.


Jeżeli powyższy artykuł nie rozwiązał lub rozwiązał częściowo Twój problem, dodaj swój komentarz opisujący, w którym miejscu napotkałeś trudności.
Mile widziane komentarze z uwagami lub informacjami o rozwiązaniu problemu.
  • adam

    super tutek! dzieki i pozdrawiam!

  • http://ospulse.pl lukas

    „Wyrażenie logiczne zbliżone jest do instrukcji warunkowej if jednak nie można go rozbudować.”

    Można można ;)

    #!/bin/bash

    LISTA_NAZWISK=’Kowalski Nowak Wiśniewski’

    Kowalski=30
    Nowak=25
    Wisniewski=18

    echo „$LISTA_NAZWISK” | grep -q ‚Kowalski’ && ( (( $Kowalski > $Nowak )) && echo ‚Kowalski ma głos decydujący’ || echo ‚Decydujący głos ma Nowak’ ) || echo ‚Błąd – coś poszło źle’

    1. po grep do zamiast Kowalski wpiszcie Kowalskii (2xi) i sprawdźcie co się dzieje.
    2. dodajcie Nowakowi lat tak, żeby był starszy od Kowalskiego i sprawdźcie ponownie co się dzieje.