A bash-ben a szekvencia fogalma kétféle módon értendő: az egyik lehetőség, hogy azonos soron belül az utasításokat ";"-vel elválasztva írjuk egymás
után - ezesetben a ";" nem utasítás lezáró, hanem utasítás elválasztó karakternek minősül.
A másik lehetőség, hogy az utasítások egymás utáni sokrokba írjuk, így a shell értelmezője ezeket külön utasításként kezeli.
Tehát vagy
vagy
Korábbi leckében láttuk már, egy parancs kiadásakor a lefutás után lekérdezhető, hogy a kiadott parancsunknak mi lesz a visszatérési értéke. Egész pontosan a $? változó fogja tartalmazni a visszatérési értéket. Az elágazás utasítások, ciklus utasítások a korábban lefutott parancsok visszatérési értékét, mint logikai értéket vizsgálja és az értéknek megfelelő tevékenységet hajtja végre. Ha az érték 0, akkor az logikai igaz, ha 1 vagy nem nulla, akkor azt logikai hamis értékként használja a megfelelő utasítás. Az alábbi példák tesztelik a $? értékét. Megszerkesztünk egy hamis névre hallgató szkript programot, látható a lényegi utasítása az exit 1, ami azt jelenti, hogy az 1 visszatérési értéket adva lépjen ki a program. Ezen kívül az is látható, hogy egy egyszerű parancs, mint például az echo parancs is ad visszatérési értéket! (Minden parancsnak van visszatérési értéke!) Természetesen az echo parancs elvégzi a kiírási feladatot, majd a sikeres munka eredményeként logikai igaz értéket ad vissza (0). Általában elmondható, hogy egy parancs ha rendben elvégzi a feladatát, szűr valamit, összead két elemet, rendez stb, akkor logikai igaz értéket ad vissza (0), míg ha a parancs nem szűr ki egy sort sem (grep), üres sort olvas be, nem tudja rendesen elvégezni a feladatát, akkor hamis értéket (1) ad vissza. Látható, hogy nincs katalin-t tartalmazó sor, a grep sikertelen, a visszaadott érték hamis (1), míg viki-t tartalmazó sor van, így ennek szűrése sikeres, a visszaadott érték 0.
Leszűrhetjük a fenti példákból, hogy logikai értéket (0-igaz, 1-hamis) valójában majd minden program szolgáltat futása eredményeként, de szkript programok elágazásához, ciklus készítéséhez szükséges logikai kifejezéseket ezek mégsem helyettesítik.
Tudjuk, a shell mindent szöveges formában kezel, valójában csak a szövegek egymás után írása az egyetlen művelet ebben a világban, így a logikai kifejezések klasszikus használatára sincs mód. Az i<5, j==6 formájú összehasonlítások, melyek majd minden programozási környezetben hasonló módon írhatók, ebben a világban nem használhatók. Ezeknek a lehetőségnek viszont minden környezetben helyük van, így ha nincs a klasszikus forma, akkor van helyette a shell nyújtotta test parancs. Bármely szkriptben a logikai ellenőrzéshez a test parancsot tudjuk használni. Segítségével rengeteg dolgot tudunk ellenőrizni, legyen szó értékekről, szövegről, fájlokról. Amikor Nem-interaktív a program, az alkalmazás képes lesz a szituációnak megfelelően döntéseket hozni, képesek leszünk döntésre kényszeríteni. Amikor pedig interaktív a program, használhatjuk akár navigációra, vagy ugyanúgy félig-meddig automatizált működésre. A test beépített parancs 0 (igaz) vagy 1 (hamis) értéket ad vissza a paraméterek értékétől/értékeitől függően. A parancs használatakor lehetőségünk van a [ ] jeleket is igénybe venni. Ezek a jelek a test szócska kiírását helyettesítik, segítségével majdnem úgy néz ki egy parancs mint egy klasszikus logikai kifejezés. A visszaadott értéket a '$?' kiíratásával is tudjuk ellenőrizni.
Lássunk a részletes paraméterek ismerete nélkül néhány egyszerű példát
Látható a fenti néhány példában a test utasítás használata. Szöveges összehasonlító műveleti jelek az egyenlőség jel(=) az azonosság vizsgálatot jelenti, míg a != jel a nem azonos jelentéssel bír. A $gyumolcs = barack vizsgálatnál így azt kérdeztük, hogy a csapat változó tartalma (alma) a barack-e? Persze, hogy nem az, ezért az összehasonlítás eredménye hamis, ami $? változóban az 1-t jelenti. Az utolsó példában a test utasítás a [] jelekkel helyettesítettük. Ehhez csak annyi megjegyzést kell hozzátenni, hogy amint példából is látszik a [ és ] jel közé kell írni a paramétereket. A test utasításnál az így megadott adatok, összehasonlító jel, mind parancs paraméterek, így azokat helyköz választja el egymástól.
Parancsok logikai eredményétől, sikerességétől függően; lehetőségünk van két vagy több parancsot összekapcsolni, parancsokat az előző parancs eredményétől függően végrehajtani. Erre a &&, illetve a || parancsjelek használata ad lehetőséget.
Ha egy parancs sikeresen lefut, akkor a && jellel utána írt parancs is le fog futni. Ha egy parancs sikertelen, akkor a || jellel utána írt parancs fog végrehajtódni. Ez a parancs összekapcsolási mód, valójában egy elágazás utasítás helyettesít.
Lássunk a használatára egy egyszerű példát.
Az első test utasításban ([ $gyumolcs = alma ] ) igaz értéket kapok, így az echo parancs a && jelek után végrehajtódik. A második test utasításban nem igaz, hogy a gyumolcs nem az alma, így hamis értéket ad a test, azaz a || jelek utáni parancs lefut. Természetesen, ezeket a lehetőségeket össze is kapcsolhatjuk, ahogy a következő példa is mutatja.
Fájlok, könyvtárak létezésének vizsgálatát is elvégezhetjük a test parancs segítségével. Az alábbi példában, a [ ] jeleket használva megnézzük, hogy egy fájl létezik-e?
Az utolsó példában pedig a prognyelvek mappa létét nézetjük meg, hogy az létezik-e.
A test utasításról a korábban taglalt műveleti jelek használhatók a megfelelő összehasonlítások elvégzéséhez:
Műveleti jel | Angol jelentés | Magyar jelentés |
-eq | equal | egyenlő |
-ne | not equal | nem egyenlő |
-lt | less than | kevesebb mint |
-le | less than or equal | kevesebb mint vagy egyenlő |
-gt | greater than | nagyobb mint |
-ge | greater than or equal | nagyobb mint vagy egyenlő |
= | equal string | két szöveg megegyezik |
!= | not equal string | két szöveg nem egyezik |
! | not | a kifejezés eredményének negáltja |
A test parancsról is az aktuális rendszerben a man test parancs kiadásával olvasható a teljes dokumentáció.
Elágazásokat leginkább kétféle csoportba sorolhatjuk. Az egyik csoport a kétirányú elágazások, a másik csoport a többirányú elágazások, melynél egy változó több különböző értékétől függően több lehetőség közül az egyiket választja.
Ezt akkor használjuk, ha egy kódrészletet csak akkor akarunk futtatni, ha az if feltétel igaz. A szintaxisa:
Az if utáni feltételt gyakran írjuk a következő sorba, ezáltal a forma változhat:
Ennek az írásmódnak egy előnye biztosan van a korábbi formához képest, biztosan sugallja azt, hogy a feltétel nem feltétlenül egy utasítást jelent. Több utasítás is írható feltételként, és az utolsó eredményét fogja vizsgálni a shell, ha az igaz értéket ad, akkor a then ág utasításait is végre fogja hajtani!
Még egy másik írásmód az, ha két sor helyett egyben írjuk az if és then utasításokat. Ekkor közéjük pontosvesszőt (;) kell tenni, hiszen ez az utasításokat elválasztó jel.
Ha viszont tényleg kétirányba akarunk ágazni, és a ha-akkor-különben lehetőséget szeretnék megvalósítani, akkor így fog kinézni:
Természetesen az else ágban megint elágazhatunk két irányba, és mivel gyakran előfordul ilyen, ezért egyszerűbb, ha rövidebben, az elif parancsot használjuk.
FONTOS! A feltétel valójában bármilyen kifejezés, parancs lehet, csak a visszatérési értékét vizsgálja a parancsértelmező, ahol a 0 jelenti az igazat, az 1 pedig a hamisat.
Többirányú elágazásra a case szerkezetet szoktuk használni, amelyet akkor célszerű választani, ha különböző lehetőségek bekövetkezésekor különböző kódokat szeretnénk futtatni. Bizonyos feladatok megvalósítása egyszerűbb ezzel, mint az if-fel, pl. egy menürendszer kódolása. A feltételnél megadunk egy változót, és ezen változó értékének függvényében fog elágazni a case.
A parancs szintaxisa:
A case elágazás sorban megvizsgálja, hogy a $valtozo-ban megvan-e patternx érték; ha igen akkor az utána lévő parancsot hajtja végre, ha nincs, megy tovább. A *) (mint bármi) az utolsó helyen az egyéb esetet hivatott megvalósítani. Minden pattern kezdetű blokkot ;;-vel választunk el, a case utasítás záró elemeként pedig az esac utasítást használjuk.
Lehetőségünk van több értéket is vizsgálni egy blokkban a függőleges vonal (|) karakter segítségével:
Az elágazás minta konstans értékei nem reguláris kifejezések, inkább a fájlnév mintaillesztéshez hasonlítanak, a [] a választható karakterek jelölésére szolgál, a * jelentése minden, a ? egy tetszőleges karakter.
A ciklusokra is van megfelelő vezérlési szerkezet a shell szkriptes környezetben. Háromféle ciklust különböztetünk meg: a számlálós ciklust, amit akkor használunk, amikor előre tudjuk, hogy valaminek hányszor kell lefutnia; az elöltesztelő ciklust, amikor egy feltételtől függően indul el a ciklusmag, és lehet, hogy egyszer sem fut le, illetve a hátultesztelő ciklust, amiben a ciklusmag egyszer biztosan lefut, és a végén egy kilépési feltétel dönti el, hogy kiléphet-e a ciklusból a program.
A számlálós ciklusnál tehát előre ismert, hogy hányszor kell lefutnia. Ebből is van kétféle lehetőség. Ha egy ciklusváltozónk van, és annak az értékét állítjuk, akkor a következő szintaxist kell használni:
Megjegyzés! A for ciklusnak ehhez a változatához végül egy megjegyzést kell tenni. Ez a C stílusú for ciklus a bash shell környezetben használható, a normál Bourne shell, sh nem ismeri. Emiatt a szkript programokban gyakran kerülik is a használatát!
A for ciklus klasszikus alakja olyan, hogy első ránézésre nem is tűnik nagyon szerencsésnek. Egy felsorolásban az in kulcsszó után, kell megadni a ciklusváltozó értékeit. Ezeket az értékeket vagy közvetlenül a ciklusba írjuk, vagy egy változóba rakjuk. Előbbi esetben a ciklus formája a következő:
Ekkor az elem ciklusváltozó rendre felveszi az auto, a motor, majd a traktor értékeket, és így fog legfutni a do és done közötti ciklusmag. Ennek eredményeként a kimenet 3 sor lesz, amely az auto, motor, és traktor sorokból fog állni.
Ha egy változóba rakjuk az elemeket, ezt gyakran egy tömb feldolgozásának is mondjuk (a helyközzel elválasztott elemekre, mint tömbelemre is tekinthetünk), ekkor a változó minden elemét szeretnénk feldolgozni, akkor a következő szintaxisnak megfelelő kódot kell módosítani a feladatnak megfelelően:
A fenti példákból látható, hogy a for ciklus egy adatsorból veszi a ciklusváltozó adatait, és ahány adat van, annyiszor lefut a ciklus. A for ciklushoz gyakran társítjuk a számlálásos ciklus elnevezést is, így mi is szeretnénk ilyen jellegű ciklust készíteni. Ehhez a seq parancsot találjuk a shell környezetünkben, ami a számlálás feladatát végzi el, és ennek a programnak az eredményét, a számokat adjuk a for ciklus paraméterének. Ha kiadjuk a man seq parancsot a terminálon, akkor a manuál eleje a következőt fogja adni:
A seq parancs egy szám szekvenciát hoz létre, amelynek 3 féle paraméterezése lehet:
Ezt akkor használjuk, ha egy bizonyos feltételig akarjuk futtatni a ciklust.
Az elöltesztelő ciklus szintaxisa:
A while-ciklus tipikus példája egy állomány beolvasása, hiszen ott addig fut a ciklus, ameddig tud belőle olvasni, vagy egy könyvtár listázása. Ha üres a fájl, akkor egyszer sem fog lefutni a ciklusmag.
A feltétel bármilyen aritmetikai, szöveges ellenőrzés lehetséges, amelyeket a test parancsnál is használhatunk.
A C nyelvekhez hasonlóan a ciklusból break kulcsszóval léphetünk ki és continue-val ugorhatunk a ciklus elejére.
A hátultesztelő ciklus működése eltérő, mivel a feltételvizsgálat a ciklusmag után történik, ezért a hátultesztelő ciklus legalább egyszer mindenképpen lefut. A konkrét programnyelvi megvalósítástól függ, hogy a hátultesztelő ciklusban a folytatás vagy a kilépés feltételét kell-e megadni. A ciklus az első esetben addig fut, amíg a ciklusvégben megadott feltétel igaz (ennek tipikus kulcsszava a while), a másik esetben pedig addig, amíg igazzá nem válik (tipikus kulcsszava az until). A Unix világ shell scriptjében ez a klasszikus hátul tesztelő ciklus nincs, van helyette egy fordított while ciklus.
Az until ciklus felépítése a shell szkriptekben teljesen megegyezik a korábban megismert while ciklussal, két apró eltéréssel:
Az until ciklus alakja a következő:
Ez addig fog futni, amíg a feltétel nem igaz, avagy mondhatjuk, hogy akkor fog kilépni, ha igazzá válik.