if-else és case – alapvető script megoldás egyszerűen

Ha, akkor, azaz if-then-fi blokkokról volt szó. Ez a megoldás nagyon jó, hiszen a feltétel ellenőrzése után lefut, vagy nem az adott teendő. Így már nagyot léptünk előre a valódi scriptek felé, hiszen nem csak felsoroltunk egy csomó parancsot, és futtattuk egymás után. Aki itt megáll, és ezt az egyszerű szerkezetet használja, már sokkal jobban tud dolgozni, mint aki a scripteket az ördögtől való, kockák játékszerének véli. De itt is van még hova fejlődni! Logikus felvetés, ha azt elvárjuk egy „programozói nyelvtől” jelen esetben a shell scriptektől, hogy ha igaz valami, akkor az egyik, ha nem igaz, akkor egy másik parancsot futtasson. Ez már egy valódi választási lehetőség.

If-else kapcsolat: váltóállítás

Vázlatosan így lehet felvázolni ezt a „váltó állítási” lehetőséget?

if [ a tesztelendő állítás ]
       then
            parancs, amit akkor futtat, amikor igaz
       else
            a másik parancs, amit akkor futtat, amikor hamis
fi

Így már máris képbe kerültünk, csak ki kell tölteni a sablont. Az előző részben megírtunk egy egyszerű kis scriptet:

#!/bin/bash 

# Nagy, vagy kicsi? Adj meg paraméternek egy számot! 
if [ $1 -gt 100 ] 
then 
    echo "Ez egy nagy szám!" 
    pwd 
fi 
date

Most ezt visszük tovább, bár a hasznossága pont olyan, mint az előzőnek.

#!/bin/bash 

# Nagy, vagy kicsi? Adj meg paraméternek egy számot! 
If [ $1 -gt 100 ] 
then 
    echo "Ez egy nagy szám!" 
else
    echo "Ez meg egy kicsike szám!"
    
fi 
date

Szuper! Pár teszt után láthatjuk, hogy a szerkezet egy virtuális váltóként üzemel: vagy az egyik, vagy a másik vágányra tereli a scriptet.

Itt is alkalmazhatunk egymásba ágyazást, mit az előző „sima” if-then-fi szerkezetben:

if [ $1 -gt 100 ] 
then 	echo ”Hát ez nagy!”; 
	if (( $1 % 2 == 0 )) 
	then  	
        echo ”Ráadásul páros is!”
	fi 
else	echo "Ez meg egy kicsike szám!"
	if (( $1 % 2 == 0 )) 
	then  	
        echo ”Ráadásul páros is!”
	fi
fi

Remélem mindenkinek érthető, hogy mit is tettünk. Most lépjünk még egyet:

f [ $1 -gt 100 ] 
	then echo ”Hát ez nagy!”; 
		if (( $1 % 2 == 0 )) 
			then  	echo ”Ráadásul páros is!”
			else 	echo ”Ez meg páratlan!!”
		fi 
	else echo "Ez meg egy kicsike szám!";
		if (( $1 % 2 == 0 )) 
			then  	echo ”Ráadásul páros is!”
			else 	echo ”Ez meg páratlan!!”
		fi
fi

Konklúzió: a megismert alapvető, faék egyszerűségű szerkezetekkel, nagyon jól egymásba tudunk ágyazni választási lehetőségeket. Bár itt is igaz, hogy elméletileg bármennyi mélységű blokkot létrehozhatunk, de ha három szintnél nagyobb, akkor már átláthatatlan lesz számunkra. Ennél nagyobb bonyolultságot ne használjunk, inkább szervezzük meg másképp.

Én praktikusság okán a fenti behúzásokat használom, bár elméletileg nem mindig kellene. De jobban olvasható a kód. Plusz ha kódszerkesztőt használsz, pld. sublimetext, akkor a bal oldalon a sorok előtt megjelennek kis nyilacskák és azt össze is tudod csukni. Így egy-egy részfeladatnál hamar kiderül, hogy nincs kezdő if és záró fi.

Két, eltérő feltétel szerinti választás:

Itt két feltételt is vizsgálunk, a szerkezete már ismerős lehet, csak kiegészítjük

if  [ egyik tesztelendő ]
then
     ha igaz, akkor ez fut le
elif [ másik tesztelendő ]
then
     ha igaz, akkor ez fut le
else
    ha egyik sem igaz, ez fut le
fi

A színekre figyelj, itt egy-egy egybetartozó részt jeleznek. Mindig így, blokkokban gondolkodj és nem marad ki semmi.

Egy példa már jobban megvilágítja. Akkor mehetsz el a buliba, ha 18 évesnél idősebb vagy, illetve, ha szüleid megengedik, hogy elmenj. Ha egyik feltétel sem áll fenn, akkor… maradsz otthon, és tanulsz!

A futtatáshoz kép paramétert meg kell adni: teszt.sh életkor igen/nem:pld.: teszt.sh 12 nem

#!/bin/bash

# buli lesz? két paraméter kell életkor és igen/nem
if [ $1 -ge 18 ]
    then
    echo "Nagykorú vagy, indulhatsz!"
elif [ $2 == 'igen' ]
    then
    echo "Anyuci elengedett, de ne igyál alkoholt!"
else
    echo "Gyerek vagy még ehhez!"
fi

Teszteld le, és vedd észre azt, hogy ha az első igaz (18 vagy több), akkor a második (elif) ág már lényegtelen, azaz az már nem kerül értékelésre, ha az első igaz. Ha egyik sem igaz, csak akkor kapja meg az else a szerepét. A sorrendiséget mindig vizsgáld meg előre, mert:

if  [ $2 == 'igen' ]
    then
    echo "Anyuci elengedett, de ne igyál alkoholt!"
elif [ $1 -ge 18 ]
    then
    echo "Nagykorú vagy, indulhatsz!"
else
    echo "Gyerek vagy még ehhez!"
fi

Azaz a két vizsgálandó kérdés sorrendjét felcserélve, előbb az engedélyt vizsgálja, és hiába vagy 18+, akkor is azt írja ki, ha van engedélyed, hogy „Anyuci elengedett, de ne igyál alkoholt!”. Ami technikailag helyes, de logikátlan.

Értelemszerűen a paraméterezés ($1, $2 azaz első és második paraméter megadás a script neve után) helyett bekérhetnénk az adatokat a terminálban az usertől, de arról még nem volt szó! Lesz, és nem túl bonyolult, de itt csak zavaró lenne.

Bármennyi elif feltételt vizsgálhatsz, nincs korlát, ilyen lehet, hogy „Ki tudsz szökni az ablakon?” kérdésre adott $3 (azaz a harmadik paraméter) igen, akkor egy harmadik szöveget írathatsz ki.

Az else megadása nem kötelező, ha nincs megadva és egyik feltétel sem lesz igaz, akkor simán kilép. De sok esetben jó, ha egyik feltétel sem felelt meg, akkor is kap valami visszajelzést a felhasználó. Egy echo sor már sokat segíthet neki: valóban lefutott, de nem volt teendője.

Boolean, azaz a logikai kapcsolatok

Az előzőekben a felsorolt (if, elif) utáni vizsgálandóak sima ha igaz, akkor kapcsolatok voltak, melyeknél az első teljesülése után a többit nem vizsgálta. És ha egyik sem igaz, akkor az else ág kapott szerepet. De mi van ha két feltétel együttes teljesülése esetén akarunk futtatni valamit? Csak akkor, ha mindkettő (vagy több) igaz. Azaz legyél nagykorú, ÉS a kész a munkád, akkor mehetsz el bulizni.

if  [ $2 == 'igen' ] && [ $1 -ge 18 ]
    then
    echo "Nagykorú vagy, indulhatsz!"
else
    echo "Ebből nem lesz buli!!!"
fi

A már ismert && kapcsolatot használtuk itt is. Már volt hasonló megoldásunk: akkor indítja el a következő parancsrészt, ha az első hibátlanul fut le. Itt is hasonló az elv, akkor vizsgálja a második, illetve a következő állítást, ha az első igaz. Ha nem, akkor már nem is lép tovább, az else ág kapja meg a lehetőséget, hogy megtegye a feladatát. De pld. nagyon hasznos ha egy fájl, vagy könyvtár meglétét vizsgálod, és azután annak valami tulajdonságát.

#!/bin/bash
# Nagyobb mint nulla a méret?

if [ -r $1 ] && [ -s $1 ]
then
    echo „A fájl nem üres!”
fi

Az -r, a -s a test parancs kapcsolója, így ha nem érted, hogy mit tesznek, akkor az egyuk régebbi részben ismételd át!

A && társa a || (két pipe, azaz Alt gr +w ). Ez a vagy kapcsolatot jelképezi, azaz az egyik vagy a másik igaz, akkor hajtja végre a parancsot, ha egyik sem, akkor az else kapja meg a folytatást.

A következő példa egyszerű, ha laci, vagy bence indítja el, akkor a bőbeszédű, minden fájladatot kilistázza, ha nem e két felhasználó, akkor csak a szűkebb adatokhoz fér hozzá.

#!/bin/bash

if [ $USER == 'laci' ] || [ $USER == 'bence' ]
then
	ls -alh
else
	ls
fi

Az egyik legyen a te felhasználói neved, egyébként csak a sima ls-t kapod meg. A $USER egy belső változó, volt róla szó.

Sok if, elif helyett case megoldásunk

Ha sok variáció van, azaz egy változó párnál több értéket vehet fel, akkor a case szerkezetben soroljuk fel a lehetséges lépéseket. Itt is egy egyszerű felsorolást teszünk ha a változó értéke minta 1, akkor a parancs 1-et, ha változó értéke minta 2, akkor a parancs 2-t stb. stb hajtjuk végre.

case Változó neve in
minta 1)
parancs 1
;;

minta 2)
parancs 2
;;
esac

A legszemléletesebb megoldás, ha van egy script, aminek van egy, pontosan egy paramétere ($1).

Készítsünk el egy nagyon egyszerű scriptet, azzal a céllal, hogy a kedvenc Linuxunkat frissíteni tudjuk, és pár rendrakó műveletet is elvégezzünk. A teszt.sh paraméterezése:

r
# yay rendszerfissítés
yay -Syu –noconfirm

f
# Flatpak frissítés
flatpak update

t
# Átmeneti tárhely rendberakása
paccache -rk 2

a
# Árva csomagok
pacman -Rns $(pacman -Qtdq)

fa
# Flatpak árvák
flatpak uninstall –unused

c
# .cache takarítása
rm -r /home/laci/.cache

h
Helpet adjon a paraméterekről

Ahogy látni, ezt az Arch Linuxra írom, mert azt használom, és simán csak a takarításos cikkből másoltam ki.

#!/bin/bash
case $1 in
    r)
    yay -Syu --noconfirm
    ;;
    f)
    flatpak update
    ;;
    t)
    paccache -rk 2
    ;;
    a)
    pacman -Rns $(pacman -Qtdq)
    ;;
    fa)
    flatpak uninstall --unused
    ;;
    c)
    rm -r /home/laci/.cache
    ;;
    h)
    echo r yay rendszerfissítés 
    echo f flatpak update
    echo t Átmeneti tárhely rendberakása
    echo a Árva csomagok
    echo fa Flatpak árvák
    echo c .cache takarítása
    ;;
    *)
    echo teszt.sh h adja a helpet!
    ;;
esac

Valóban gyorsan be lehet dobálni egy ilyen szerkezetbe a lehetséges értékeket, és a hozzátartozó teendőket. Gyakorlatilag bármilyen változó értékeihez tartozó teendőket meg tudjuk adni ezzel. A paraméter és a kapcsolókezelésnek ennél sokkal kifinomultabb lehetőségei vannak, de első nekifutásra ez megfelel.

Az utolsó rész a

*)
echo teszt.sh h adja a helpet!
;;

lehet még érdekes, mert a * jelzi, hogy bármi olyan érték esetén, amit nem soroltunk fel, azaz a case nem ismert, ezt a teendőt végezze el. Nem kötelező, de ha legalább egy paramétert elvár a script, vagy kedveskedni akarsz a felhasználónak ha rossz, ismeretlen paraméter adna meg, akkor használd.

Szuper? Igen. Egyszerű? Az. De van egy nagy hibája! Nagyon monoton tud lenni, ha sok variáció van, figyelni kell. Kiemelten figyelj a ;; rész lezárásra, mert ha elmarad igen fura dolgokra képes a shell. Hiányolhatja a zárójelet, vagy „sor: 15: szintaktikai hiba „)” váratlan token közelében”, stb.

Az esac már értelemszerű: a case fordítottja, ami lezárja a blokkot.

OK, mára ennyit gondoltam. Érdemes az interneten körbenézni példákért, mert ezek valóban csak bemutatásra jól. Minden szerkezetet teszteld le, írj pár hasonlóan egyszerű, tesztelésre megfelelő scriptet.

Kettő, az adott témán túlmutató következtetést érdemes levonni, és NAGYON figyelni rá:

  1. Használj kódszerkesztőt, ami a behúzásokat segíti, kiemeli a szintaktikát. Minden esetben érdemes kialakítani azt a behúzási módszert (mikor mit, mennyire húzol be) ami neked megfelel. Sokat segít a kórok olvasásában, ha egyes összetartozó részeket, alárendeltséget behúzással jelzel.
  2. Egyre összetettebb logikájú scripteket készítünk, így már most érdemes megszokni, hogy előre átgondoljuk, hogy mit akarunk, és azt is, hogy milyen sorrendben kell azt elvégezni. Bár valószínű, hogy ha ezt olvasod, akkor nemprogramozónak készülsz, de a TE saját érdeked, hogy előbb tervezz, azután állj neki írogatni.

Kiegészítésül érdemes ezt a kis, pár perces videót megnézni, egy automata frissítési scriptben használja kollega a if-then-else blokkot. Példának nagyon jó,  hogy faék egyszerű megoldásokkal mennyire meg lehet könnyíteni a dolgokat:

A következő részt július 18-ra időzítettem!

Related Posts