Tartalom További vezérlő valamint számításokat megkönnyítő szerkezetek 1. A case szerkezet...1 2. A select szerkezet...3 3. Aritmetikai kiértékelés: számítások a (( )) szerkezettel...4 4. A C stílusú for ciklus...6 5. Műveletek karakterláncokkal...6 A shell programozását támogató megoldások száma elég nagy, az alábbiakban bemutatunk még néhányat, amelyek igen megkönnyítik a feladatok automatizálását. 1. A case szerkezet A case vezérlési struktúra hasonló a programozási nyelvek "switch" vezérléséhez: alternatív végrehajtási ágakra bontja a program parancsait. Az alternatívát egy karakterlánc mintákra való illesztése szerint hajtja végre. A következőképpen adjuk meg általános használati formáját: case valtozó in minta1 ) parancsok ;; minta2 ) parancsok ;;... mintan ) parancsok ;; esac A szerkezetet case és esac kulcsszavak határolják. A szerkezet a megatt változóra illeszti a következő sorok elején található mintákat. Ahol a minta talál, ott végrehajtja a jobb zárójel utáni parancssorozatot amelyet két ; karakter zár le. Csak az első találatnak megfelelő alternatívát hajtja végre. A minta tulajnképpen a shell minta: karaktereket illetve az állománynevek megadásánál használatos metakaraktereket lehet használni: *? [], valamint két minta "vagy" logikával való összekapcsolására a -at. Példák: abc pontosan abc-re illeszkedik * bármire illeszkedik?bc bármi az első karakter pozíción, és utána pontosan ab ab cd ab vagy cd láncokra illeszkedik Példaként álljon itt egy állományokat könyvtárakba szortírozó program: #Leiras: #pelda a case alkalmazasara: szetvalogatja egy konytarbol a #pdf, mp3, avi, jpg, gif tipusu allomanyokat kulon konyvtarakba #egy argumentumot var: a konyvtarnevet ahol az allomanyok vannak #a celkonyvtarakat az alabbi valtozokban am meg 1
PDF=pdf MP3=mp3 AVI=avi KEPEK=kepek #pontosan 1 parameter if [ -z "$1" ];then echo hasznalat: case.sh konyvtarnev exit 1 #megnezem, hogy a celkonyvtarak leteznek-e, #ha nem letrehozom oket #ha van pdf konyvtar, akkor az elso feltetel utan #abbahagyja a tesztet for konyvtar in "$PDF" "$MP3" "$AVI" "$KEPEK" if! [ -d "$konyvtar" ] &&! mkdir "$konyvtar" 2>/dev/null then echo nem lehet a $konyvtar konyvtarat letrehozni exit 1 #vegigjarom a konyvtar allomanyneveit for f in $( ls "$1" ) #itt hasznaljuk a case-t #a case-el valasztom es masolom kulonbozo helyekre #ha egy le egyik kategoriaba sem esik akkor a *-al #jelolt agra fut case "$f" in *.mp3 ) mv "$1/$f" "$MP3" ;; *.avi ) mv "$1/$f" "$AVI" ;; *.pdf ) mv "$1/$f" "$PDF" ;; *.jpg *.gif ) mv "$1/$f" "$KEPEK" ;; * ) echo a $f nem tartozik egyik kategoriaba sem, marad. ;; esac Az alábbi kis program a parancssor kapcsolóit elemzi. Ha betartjuk azt a feltételt, hogy egy program hívásakor először a kapcsolókat, utána pedig az argumentumokat adjuk meg, akkor ez a szerkezet alkalmas kis programok kapcsolóinak kezelésére. while [ -n "$1" ] case $1 in -f ) echo f kapcsolo ;; -c ) echo c kapcsolo ;; -* ) echo ismeretlen kapcsolo: $1;; #ha elérkeztünk az első argumentumhoz, amely nem kapcsoló: * ) break;; esac 2
shift #eltoljuk a paramétereket, $1 a következő echo az elso kapcsolók utáni paraméter: $1 A program a -c és -f kapcsolót ismeri fel, ha futtatjuk: $bash switch.sh -c -f -g a b c kapcsolo f kapcsolo ismeretlen kapcsolo: -g az elso kapcsolók utáni paraméter: a $ Ha a kapcsolóknak is lenne paramétere, azok átvehetők a case ágaiban, de átvétel után még egy shift parancsot kellene végrehajtani. Megjegyzés: A shellnek van sokkal jobb megoldása az argumentumok kezelésére, a getopts függvény. De kis programoknál a fenti is megteszi. 2. A select szerkezet A select szerkezetet kis interaktív programok esetében használjuk. Használati módja: select valtozo in lista parancsok A select kulcsszót tartalmazó sor végrehajtásakor a parancs egy kis menüt ír ki a lista (ez egy karakterlánc lista) segítségével. Ezek után készenléti jelet (prompter) ír ki (ezt a $PS3 shell változóból veszi). Válaszként a menü egyik sorát kell kiválasztani úgy, hogy a sorrendjének megfelelő számot ütjük le. Ezek után a select belsejében a valtozo értéke felveszi a listából kiválasztott karakterlánc értékét, és ezt fel lehet használni valamilyen parancsvégrehajtásra. Működését az alábbi kis példával illusztráljuk: #a PS3 értékét ajánlatos valamilyen ismerős prompt-ra #cserelni PS3='>>' select valtozo in Elso Masodik Harmadik Vege echo $valtozo echo a '$REPLY' valtozo erteke ilyenkor: "$REPLY" #itt barmilyen parancsot vegre lehet hajtani, felhasznalva #a $valtozo es $REPLY ertekeit if [ "$valtozo" = 'Vege' ];then echo "...es jon a kilepes a select-bol" break 3
Működése pedig az alábbi: $ bash select.sh 1) Elso 2) Masodik 3) Harmadik 4) Vege >>1 Elso a $REPLY valtozo erteke ilyenkor: 1 >>2 Masodik a $REPLY valtozo erteke ilyenkor: 2 >> $ Addig ismétli a ciklust, amíg az állomány vége jelet (^D) ütjük le vagy kiválasztjuk a 'Vége' opciót. 3. Aritmetikai kiértékelés: számítások a (( )) szerkezettel Amint láttuk, az expr segítségéve elég kényelmetlen számolni. Az utóbbi évek fejlesztése során egyes shell értelmezők tartalmaznak néhány olyan kiterjesztést, amely könnyűvé teszi az egész számokkal való számítást (a POSIX szabvány is tartalmazza ezt, így a Korn shell is, valamint 2.04 verziótól kezdve a Bash is). Jelenlétére tehát nem lehet mindig számítani és elvileg horzható programok esetén kerülni kell. Ezen kiterjesztések közül a két zárójellel határolt aritmetikai kiértékelést emeljük ki. Használata az alábbi: valtozo=$(( aritmetikai műveletek )) pontosabban, használat közben: $ x=$(( 22 + 6 )) A két határoló közti területen aritmetikai műveleteket lehet végezni, ugyanolyan szintaxissal mint a C nyelven történő programozásnál. A szerkezetet a teszteknél is lehet használni egész számokkal végzett tesztek esetében: i=4 while (( i > 2 )) echo $i (( i-- )) Szabályok: -az operátorok a C nyelvből valóak, minden operátor használható 4
-kiértékeléskor a Korn shell dupla pontosságú valós számokat használ (a Korn shell tud valós változókkal lgozni). A Bash csak egész számokkal lgozik. -a $ jelet nem kell változók előtt használni, de lehet. Kivételt képeznek a shell speciális változói, azok előtt viszont kell. Tehát: b=$(( a + 2 )), de: b=$(( $a + 2 )) is helyes. A b=$(( $1 + 2 )) összeadást viszont már csak a $ jel segítségével tudjuk elvégezni. -a dupla zárójelen belül nem érvényesek a shell behelyettesítések és metakarakterek, tehát * például használható szorzásra -a C hozzárendelő operátorai is használhatóak, pl. (( x+=2 )) ebben az esetben viszont a $ jel nem használható a változó neve előtt: (( $x+=2 )) #helytelen!!! -zárójelezés használható -a relációs operátorok esetében az igaz értéke 1 de csak a (( )) belsejében. A tesztek esetében a (( )) -ből való kilépés után a shell $? -t fordított értékre állítja. Tehát: $ (( 2 > 1 )) $ echo $? 0 így programban az alábbi món használható: i=4 while (( i > 2 )) echo $i (( i-- )) -nem kell feltétlenül ügyelni a szigorú, shell-nél megszokott szóköz elválasztóra operátorok és változók között, tehát írhatunk ((2+2)) -t vagy (( 2 + 2 )) -t is. -a hatványozás operátora a **, ebben az esetben a két * karakternek egymás mellett kell állnia. Az alábbi szkript néhány példát tartalmaz: #peldak szamitasokra es kifejezes kiertekelesre a (( )) -tel #nehany segedvaltozo a=1 b=2 z=0 #hasznalhatok a C nyelv operatorai, a valtozonevek elott nem kell #a $ szimbolumot hasznalni 5
echo $(( a + 1)) #az sem szamit, ha nem tartjuk be feltetlenul a shell altal #kert szokozoket echo $((a+1)) echo $(( a++ )) #van egy eset, amikor kell $ szimbolumot hasznalni a nevek elott: #ha a shell specialis valtozoit hasznaljuk if [ -n "$1" ];then echo $(( $1 + 2 )) #a hatvany operator a ** echo $(( a**2 )) if (( 1 < b )) then echo '1 < b feltetel igaz' 4. A C stílusú for ciklus Az említett (( )) zárójeles szerkezet for ciklusok előállítására is használható, éspedig a C nyelv for utasításához hasonlóan. A szintaxis az alábbi: for (( i=0; i<10; i++ )) shell parancsok #ezekben használható a $i változó... Egy egészen egyszerű for ciklust tehát így írhatunk: for (( i=1; i<=10; i++ )) echo $i Látható, hogy a tisztán egész számok végigjárására épülő ciklusokban ez kényelmesebben alkalmazható, mint az előző változatú, sztring lista végégjárására épülő for. 5. Műveletek karakterláncokkal A karakterláncok kezelésénél néha igen hasznos gyorsan elvégezni kis műveleteket, mint például: levágni egy karakterlánc elejét/végét vagy átírni egy részt a karakterláncban. Ezért amikor egy változót kiválasztunk a ${valtozo} szintaxissal, akkor a két {} zárójel közt operátorokat használhatunk erre. Az operátorok az alábbiak: ${valt#minta} ${valt##minta} ha a minta illeszkedik a változóban levő karakterlánc elejére, akkor letörli a legkisebb illeszkedést és úgy téríti vissza a ha a minta illeszkedik a változóban levő karakterlánc elejére, akkor letörli a legnagyobb illeszkedést és úgy téríti vissza a 6
${valt%minta} ${valt%%minta} Operációs rendszerek I. - UNIX felhasználói ismeretek és héjprogramozás ha a minta illeszkedik a változóban levő karakterlánc végére, akkor letörli a legkisebb illeszkedést és úgy téríti vissza a ha a minta illeszkedik a változóban levő karakterlánc végére, akkor letörli a legnagyobb illeszkedést és úgy téríti vissza a ${valt/minta/behelyetesít} behelyettesíti a változóban a mintának megfelelő részt a ha minta #-el kezdődik a karakterlánc elején, ha % -al akkor a karakterlánc végén. Példák: $ a=abcxyzabc $ echo ${a#abc} xyzabc $ echo ${a%abc} abcxyz $ echo ${a/xyz/abc} abcabcabc A duplázott %% és ## használata akkor inkolt, ha olyan mintát adunk meg, amelybe metakarakterek (*,?) is vannak. Ezek egy karakterlánc esetében rövidebb vagy hosszabb illesztést is meghatározhatnak. Például, az: abcxyzabcxyz karakterlánc elejére a *abc minta (bármi és utána abc) rövidebben: abc (hiszen az üres karaktereklánc is bármi) vagy hosszabban: abcxyzabc is illeszkedhet. Így a # operátor a legrövidebb illesztést, a ## pedig a leghosszabbat fogja levágni. $ valtozo=abcxyzabcxyz $ echo ${valtozo#*abc} xyzabcxyz $ echo ${valtozo##*abc} xyz Ezeket az operátorokat elég nehéz megjegyezni, a következőt szokták javasolni: A # jelet az angolok mindig valamilyen számosság jelölésére használják, és a szám elé teszik, pl. #10, a % jelet pedig mindig a szám után tesszük, pl. 100% (innen a lánc elejére illetve végére utalás). 7