Ciklust akkor alkalmazunk, ha egy műveletet vagy műveletsort többször kell végrehajtani. Shell szkriptekben a for, a while és az until ciklusokat is alkalmazhatjuk.
A for ciklust akkor alkalmazzuk, ha pontosan tudjuk, hányszor kell végrehajtani az adott műveletsorozatot. Az alábbi egyszerű szkript az i változónak ad 1, 3, 5, 7, 9 értékeket és végrehajtja a do és done kulcsszavak közötti parancsokat. Értelemszerűen annyiszor hajtja végre ahány elem van a felsorolásban:
#!/bin/bash for i in 1 3 5 7 9 do echo "$i a négyzeten = `expr $i '*' $i`" done
A do és a done közötti sorokat ciklusmagnak is nevezzük.
palferi@lizi:~/proba$ ./c1.sc 1 a négyzeten = 1 3 a négyzeten = 9 5 a négyzeten = 25 7 a négyzeten = 49 9 a négyzeten = 81
A lista helyett bármilyen parancsot is írhatunk aminek a kimenete fog listát meghatározni. Gyakran alkalmazzák a seq (sequence, sorozat) parancsot:
for i in `seq 1 3 25` do echo "$i a négyzeten = `expr $i '*' $i`" done
Itt a seq 1 3 25
parancs egytől huszonötig listát hoz létre hármas lépéssel:
palferi@lizi:~/proba$ ./c1.sc 1 a négyzeten = 1 4 a négyzeten = 16 7 a négyzeten = 49 10 a négyzeten = 100 ...
Az alábbi program a proba
könyvtár fájljainak neveit és tartalmát listázza ki. Minden fájl 3 másodpercig látható és köztük 1 másodpercig sötét a terminál. Ezek után kiírja a proba
könyvtár állományinak számát.
#!/bin/bash N=0 for i in `ls ~/proba` do clear sleep 1 echo "A fájl neve: $i" cat ~/proba/"$i" sleep 3 N=`expr $N '+' 1` done clear echo "A ~/proba könytárban $N fájl van"
A while ciklusnál az ismétlést egy feltételhez kötjük. Amennyiben a feltétel igaz, a ciklusmag végrehajtódik. A ciklusfeltétel a ciklusmag végrehajtása előtt értékelődik ki, ezért elképzelhető, hogy a ciklusmag egyszer sem hajtódik végre.
Az alábbi szkript kiszámítja a paraméterében megadott egész szám faktoriálját.
#!/bin/bash I=1 F=1 while test $1 -ge $I do F=`expr $F '*' $I` I=`expr $I '+' 1` done echo "$1! = $F"
Vizsgáljuk meg a program működését. Az alábbi táblázat a változók értékeit mutatja a ciklusmag három ismétlődésekor és a ciklus végét, ha a paraméter 3:
1. ellenőrzés | 2. ellenőrzés | 3. ellenőrzés | 4. ellenőrzés |
---|---|---|---|
a feltétel igaz: 3>=1 | a feltétel igaz: 3>=2 | a feltétel igaz: 3>=3 | a feltétel HAMIS: 3>=4 |
F=1*1=1 | F=1*2=2 | F=2*3=6 | |
I=1+1=2 | I=2+1=3 | I=3+1=4 | |
F=6 |
Az alábbi, c4.sc
néven létrehozott szkript a paraméterbe megadott egész szám osztóit írja ki. Meghatározza az osztók számát, és ha ez a szám kettő, a prímszám szöveg jelenik meg.
#!/bin/bash I=1 ; F=1 ; OT=1 while test $1 -gt $I do F=`expr $1 '%' $I` if test $F -eq 0 then echo " $I" OT=`expr $OT '+' 1` fi I=`expr $I '+' 1` done echo " $1" if test $OT -eq 2 then echo "$1 - prímszám!" else echo "$1 -- $OT osztója van" fi
Indítsuk a szkriptet különböző paraméterekkel és ellenőrizzük működését:
palferi@lizi:~/proba$ ./c4.sc 719 1 719 719 - prímszám! palferi@lizi:~/proba$ ./c4.sc 81 1 3 9 27 81 81 -- 5 osztója van
A until ciklus felépítésben hasonlít a while-hoz, azonban ebben az esetben a do és done közötti utasítások addig hajtódnak végre, míg a feltétel igazzá nem válik.
Shell szkriptekben használhatunk egydimenziós tömböket. A tömbök elemeinek indexe egész szám, a sorszámozás nullától indul. A B tömb hármas indexű eleme: B[3]
A tömb hármas indexű elemének értéke pedig: ${B[3]}
A tömb összes elemére hivatkozhatunk a *
karakterrel: ${B[*]}
A következő feladat a tömbök használatát és az until ciklust mutatja be.
Írjunk szkriptet c5.sc
néven ami beolvas tömbbe n egész számot. Az n értékét az első paraméterben adjuk meg. Az until ciklus használatával határozzuk meg a tömb legkisebb elemét.
#!/bin/bash for i in `seq 1 $1` do echo -n "$i. szam: ?" read TOMB[$i] done echo "A tömb $1 elemből áll: ${TOMB[*]}" MIN=${TOMB[1]} H=2 until test $H -gt $1 do if test ${TOMB[H]} -lt $MIN then MIN=${TOMB[H]} fi H=`expr $H '+' 1` done echo "A tömb legkisebb eleme: $MIN"
A programban a for ciklus változója az i, egytől az első paraméterben megadott számig veszi fel az értékeket. A ciklus magja megjeleníti a sorszámot és a read paranccsal beolvassa a tömb megfelelő elemeit. Ezután kiírja a tömb elemeinek számát és a minden elemét.
A MIN
változó fogja a tömb legkisebb elemét tartalmazni, de először az első elem értékét kapja. A H
változó kezdeti értéke 2, hiszen a tömb második elemétől kell mindegyiket összehasonlítani a MIN
változó értékével.
Ezt az until ciklus végzi. A ciklus magjában az adott elemet összehasonlítjuk a MIN
értékével, és ha kisebb annál, akkor az adott elem lesz a MIN
. A H
értékét is növeljük eggyel a ciklusmagban, amikor olyan értéket kap, hogy a H
nagyobb lesz mint a paraméterben megadott szám, a ciklus véget ér. A ciklus végeztével a MIN
változó tartalmazza a tömb legkisebb elemét:
palferi@lizi:~/proba$ ./c5.sc 4 1. szam: ?54 2. szam: ?3 3. szam: ?9 4. szam: ?7 A tömb 4 elemből áll: 54 3 9 7 A tömb legkisebb eleme: 3
Módosítsuk az előző szkriptet hogy a tömb elemeit rendezze buborék algoritmussal. Az algoritmusról részletesen itt olvashatunk: Wikipédia - Buborékrendezés
Az algoritmus pseudokódja a következő:
FOR J=1 TO N-1 STEP 1 FOR I=1 TO N-J STEP 1 IF A[I]>A[I+1] THEN SWAP A[I],A[I+1] NEXT I NEXT J
A csere (SWAP) parancsot megvalósíthatjuk az alábbi sorokkal:
TEMP=A[I] A[I]=A[I+1] A[I+1]=TEMP
Ezek alapján a szkript:
#!/bin/bash for i in `seq 1 $1` do echo -n "$i. szam: " read TOMB[$i] done echo "A tömb $1 elemből áll: ${TOMB[*]}" # rendez JJ=`expr $1 '-' 1` for J in `seq 1 $JJ` do KK=`expr $1 '-' $J` for K in `seq 1 $KK` do KN=`expr $K '+' 1` if test "${TOMB[K]}" -gt "${TOMB[KN]}" then TEMP=${TOMB[K]} TOMB[K]=${TOMB[KN]} TOMB[KN]=$TEMP fi done done echo "A rendezett tömb: ${TOMB[*]}"
Próbáljuk ki a működését:
palferi@lizi:~/proba$ ./c6.sc 7 1. szam: 23 2. szam: 7 3. szam: 3 4. szam: 9 5. szam: -9 6. szam: 0 7. szam: 2 A tömb 7 elemből áll: 23 7 3 9 -9 0 2 A rendezett tömb: -9 0 2 3 7 9 23