A vezérlésátadó kifejezések, mint az if
, a while
és így tovább,
az awk
program végrehajtásának folyamatát befolyásolják. Az awk
vezérlésátadó kifejezései a C programozási nyelv kifejezésein alapulnak.
Minden vezérlésátadó kifejezés egy speciális kulcsszóval kezdôdik, mint az if
és a while
, azért hogy megkülönböztethetôk legyenek az egyszerű
kifejezésektôl.
Sok vezérlésátadó kifejezés magába foglal más kifejezéseket is; például
az if
kifejezés olyan kifejezéseket is tartalmaz, amiket vagy végrehajt
vagy nem. Ezek a kifejezések alkotják a vezérlésátadó kifejezés testét.
Ha egynél több kifejezést akarunk összefogni a vezérlésátadó kifejezés testében
akkor ezt egy összetett kifejezéssel, kapcsos zárójelek között lehet
megtenni. A kifejezéseket új sorral vagy a pontos vesszô karakterrel lehet
elválasztani egymástól.
if
-else
kifejezés
Az if
-else
kifejezés az awk
döntéshozó kifejezése és
így néz ki:
if (feltétel) then-test [else else-test]
A feltétel kifejezés befolyásolja, hogy a kifejezés további része
mit csinál. Ha a feltétel igaz, akkor a then-test hajtódik
végre; egyébként a else-test fut le.
A kifejezés else
része opcionális. A feltétel hamis ha az értéke
zérus vagy üres szöveg, egyébként igaz.
Íme egy példa:
if (x % 2 == 0) print "x páros" else print "x páratlan"
Ebben a példában, ha a `x % 2 == 0' kifejezés igaz (vagyis az x
értéke osztható kettôvel), akkor az elsô print
parancs hajtódik végre,
más esetben a második print
fog lefutni.
Ha az else
a then-testel egy sorban jelenik meg és a
then-test nem összetett kifejezés (pl. nincs kapcsos zárójelek között),
akkor egy pontos vesszônek kell elválasztania a then-testet az
else
-tôl. Ennek bemutatására, írjuk át az elôzô példát:
if (x % 2 == 0) print "x páros"; else print "x páratlan"
Ha elfelejtjük a `;' -t kitenni, akkor az awk
nem képes
értelmezni a kifejezést és szintaktikai hibát fog jelezni.
Valójában nem érdemes így írni a példát, mivel egy emberi olvasó lehet,
hogy nem veszi észre az else
kifejezést, ha az nem az elsô szó
a sorban.
while
kifejezésA programozásban a hurok vagy a ciklus azt jelenti, hogy a program egymás után kétszer vagy többször hajtja végre ugyanazt a részt.
A while
kifejezés a legegyszerűbb hurokképzô kifejezés az awk
-ban.
A while
addig hajt végre más kifejezéseket, amíg a feltétel igaz. A
kifejezés formája:
while (feltétel) test
A test tartalmazza a végrehajtandó kifejezéseket, és a feltétel az a kifejezés, ami szabályozza, hogy a hurok hányszor fusson le.
A while
kifejezés elôször kiértékeli a feltétel kifejezést.
Ha a feltétel igaz, akkor végrehajtja a test kifejezést.
Miután a test végrehajtódott, a feltételt újra kiértékeli,
és ha még mindig igaz, akkor a test ismét lefut. Ezt az eljárást
addig ismétli, amíg a feltétel hamis nem lesz. Ha a feltétel
kezdetben hamis, akkor a hurok teste soha nem hajtódik végre, és az awk
a hurok utáni kifejezéssel folytatja a program végrehajtását.
Ez a példa minden rekord elsô három mezôjét nyomtatja ki, egyet egy sorba.
awk '{ i = 1 while (i <= 3) { print $i i++ } }' inventory-shipped
Itt a hurok teste egy összetett kifejezés kapcsos zárójelek között, ami két kifejezésbôl áll.
A hurok valahogy így működik: elôször az i
értéke egy lesz. Ezután
a while
ellenôrzi, hogy az i
kisebb-e mint három vagy egyenlô-e
hárommal. Ez igaz, hiszen az i
értéke egy, így kinyomtatja az
i
-edik mezôt. Ezek után a `i++' kifejezés megnöveli az
i
értékét, majd a hurok megismétli ezt a folyamatot. A hurok
véget ér amikor az i
értéke négy lesz.
Mint látható, új sor nem szükséges a feltétel és kifejezés teste között, de a kifejezés több sorba szedése jobban olvashatóvá teszi a programot. Kivéve persze ha összetett kifejezést használunk vagy nagyon egyszerű kifejezést. Az új sor a nyitó zárójel után, ami az összetett kifejezést elkezdi szintén nem szükséges, de akkor a programot nehezebb olvasni.
do
-while
kifejezés
A do
hurok a while
hurok kifejezés egy változata. A do
hurok kifejezés egyszer végrehajtja a testet, és ezt addig ismétli
amíg a feltétel igaz. A formája az alábbi:
do test while (feltétel)
Még ha a feltétel kezdetben hamis is, a test legalább egyszer
végrehajtódik (és csak egyszer, hacsak a test igazzá nem teszi a
feltételt. Érdemes ezt összehasonlítani az alábbi while
kifejezéssel:
while (feltétel) test
Ez a kifejezés nem hajtja végre a test kifejezést egyszer sem, ha a feltétel hamis kezdetben.
Itt egy példa a do
kifejezésre:
awk '{ i = 1 do { print $0 i++ } while (i <= 10) }'
Ez a program minden rekordot tízszer nyomtat ki. Ez nem egy valós példa,
mivel egy közönséges while
hurok is megtenné. Ugyanakkor egy
tapasztalatot is tükröz, hogy nagyon ritkán van valós indok a
do
kifejezés használatára.
for
kifejezés
A for
kifejezés kényelmessé teszi iterációs ciklusok készítését. A
for
kifejezés általános formája:
for (inicializálás; feltétel; növelés) test
Az inicializálás, a feltétel és a növelés tetszôleges
awk
kifejezések és a test az ismételten végrehajtandó awk
kifejezés.
A for
kifejezés elôször az inicializálás kifejezést hajtja végre.
Ezután, amíg a feltétel igaz, ismételten végrehajtja a testet
majd az növelés kifejezést. Tipikusan az inicializálás a
változót egyre vagy zérusra állítja, a növelés eggyel növeli azt és a
feltétel ellenôrzi, hogy az iterációk száma elérte-e a kívánt értéket.
Itt egy példa a for
kifejezésre:
awk '{ for (i = 1; i <= 3; i++) print $i }' inventory-shipped
A program minden bemeneti rekord elsô három mezôjét kinyomtatja, egy mezôt soronként.
Egynél több változót nem lehet beállítani az inicializálás részben
kivéve a többszörös értékadás, mint `x = y = 0', ami csak akkor
használható ha minden változó kezdeti értéke egyenlô. (Persze a pótlólagos
változóknak külön-külön is értéket adhatunk a for
ciklus elôtt.)
Ugyanez igaz a növelés részre is; ahhoz, hogy egynél több változót
növeljünk meg, a ciklus végén kell ezt elvégezni külön kifejezésekkel. A C
programozási nyelvben az összetett kifejezések kialakítására használható
vesszô operátor az ilyen esetekben hasznos lehet, de az awk
-ban
nem támogatott.
Leggyakrabban a növelés egy növelô kifejezés, mint a fenti példában. De ez nem kötelezô; ez bármilyen kifejezés lehet. Például, ez a kifejezés kinyomtatja a kettes szám egy és száz közé esô hatványait:
for (i = 1; i <= 100; i *= 2) print i
A for
utáni zárójelek közé esô három paraméter közül bármelyik
elhagyható, ha abban a pozícióban nincs mit csinálni. Így a
`for (; x > 0;)' kifejezés egyenértékű a `while (x > 0)'
kifejezéssel. Ha a feltétel nincs megadva, akkor a feltétel mindig
true, vagyis igaz, ami egy végtelen ciklust eredményez (pl.
a ciklus soha nem ér véget).
A legtöbb esetben, egy for
ciklus egy while
hurok rövidítése,
ahogy ezt alább bemutatjuk:
inicializálás while (feltétel) { test növelés }
Az egyetlen kivétel, amikor a continue
kifejezés
(see section A continue
kifejezés)
szerepel a ciklusban. Ebben az esetben ha a for
kifejezést
átalakítjuk while
kifejezésre, akkor a continue
kifejezés
hatását is könnyen megváltoztathatjuk akaratlanul.
A for
ciklusnak van egy alternatív formája, ami egy tömb elemein
megy végig:
for (i in tömb) csinálj valamit az elemmel array[i]
A section Egy tömb elemeinek ellenôrzése,
további információt tartalmaz a for
ciklus ezen verziójáról.
Az awk
nyelv a while
hurokképzô kifejezésen kívül a for
kifejezéssel is rendelkezik, mivel egy for
ciklus begépelése kevesebb
idôt vesz igénybe, és egy természetesebb gondolkodást támogat. Az iterációs
lépések számolása egy természetes feladat a ciklusokban. Egyszerűbb errôl
úgy gondolkodni, hogy ez a számolás a ciklus része, mint hogy a cikluson
belül kelljen ezt elvégezni.
A következô fejezetben bonyolultabb for
ciklusokat mutatunk be.
break
kifejezés
A break
kifejezés a legbelsôbb for
, while
vagy
do
hurokból lép ki. A következô példa egy egész szám legkisebb
osztóját keresi meg, és azonosítja a prímszámokat is:
awk '# legkisebb osztó keresése { num = $1 for (div = 2; div*div <= num; div++) if (num % div == 0) break if (num % div == 0) printf "A %d legkisebb osztója a %d\n", num, div else printf "%d prím\n", num }'
Ha a maradék zérus az elsô if
kifejezésben, az awk
azonnal
kilép a for
ciklusból. Ez azt jelenti, hogy az awk
közvetlenül a ciklus utáni kifejezéssel folytatódik. (Ez teljesen különbözô
az exit
kifejezéstôl, ami az egész awk
programból lép ki.
See section Az exit
kifejezés.)
Itt van még egy program, ami teljesen azonos az elôzôvel és bemutatja, hogy
hogyan lehet a for
vagy a while
kifejezés feltétel
részét lecserélni egy if
és egy break
kifejezéssel:
awk '# find smallest divisor of num { num = $1 for (div = 2; ; div++) { if (num % div == 0) { printf "Smallest divisor of %d is %d\n", num, div break } if (div*div > num) { printf "%d is prime\n", num break } } }'
Mint azt már korábban elmondtuk, a break
kifejezésnek nincs semmi
jelentése egy ciklus testén kívül. Ugyanakkor, bár ez soha nem volt
dokumentálva, az awk
régebbi implementációi a break
kifejezést
egy cikluson kívül úgy kezelték mint egy next
kifejezés
(see section A next
kifejezés).
Az awk
jelenlegi implementációi többé nem támogatják ezt a viselkedést.
A gawk
támogatja a break
ilyen viselkedését ha a parancssorban
a `--traditional' opció is meg van adva
(see section Command Line Options).
Más esetekben hibát eredményez, mivel a POSIX szabvány a break
kifejezést úgy definiálja, hogy csak cikluson belül használható (s.s.).
continue
kifejezés
A continue
kifejezés, mint a break
kifejezés csak a
for
, a while
és a do
cikluson belül használható.
A continue
kifejezés végrehajtása a ciklus további részét
átugorja, aminek
hatására az újabb ciklus elkezdôdik. Ezzel ellentétben a break
kilép a ciklusból.
Egy for
ciklusbeli continue
kifejezés arra utasítja az
awk
-ot, hogy ugorja át a ciklus további részét és a for
kifejezés növelô kifejezés részével folytassa a futtatást. Az alábbi
program ezt a tényt illusztrálja:
awk 'BEGIN { for (x = 0; x <= 20; x++) { if (x == 5) continue printf "%d ", x } print "" }'
Ez a program kinyomtatja a számokat zérustól 20-ig, kivéve az ötös számot,
amikor a printf
kifejezést átugorja. Mivel a növelô `x++'
kifejezést nem ugorja át, az x
változónak nem öt lesz az értéke
ezek után. A fenti for
ciklust érdemes összehasonlítani az alábbi
while
ciklussal:
awk 'BEGIN { x = 0 while (x <= 20) { if (x == 5) continue printf "%d ", x x++ } print "" }'
Ez a program végtelen ciklusba kerül miután az x
változó öt értéket
kap.
Mint azt már korábban elmagyaráztuk, a continue
kifejezésnek nincs
értelme egy cikluson kívül. Ugyanakkor, bár eddig nem volt dokumentálva,
az awk
régi implementációjában a continue
kifejezés
cikluson kívüli használata a next
kifejezésnek felelt meg
(see section A next
kifejezés).
A Unix awk
jelenlegi implementációi nem támogatják ezt a viselkedést.
A gawk
lehetôvé teszi ezt viselkedést ha a `--traditional' opció
szerepel a parancssorban
(see section Command Line Options).
Minden más esetben ez hibát jelent, mivel a POSIX szabvány a continue
ilyen viselkedését nem definiálja (s.s.).
next
kifejezés
A next
kifejezés arra utasítja az awk
-ot, hogy azonnal
fejezze be a jelenlegi rekord feldolgozását és folytassa a következô rekorddal.
A jelenlegi szabály további tevékenység részét sem hajtja végre.
Érdemes ezt összehasonlítani a getline
függvény hatásával
(see section Explicit beolvasás getline
-al). A getline
kifejezés hatására is az awk
azonnal beolvassa a következô rekordot, de nem
változtatja meg a program futási folyamatát semmilyen módon. Így az
aktuális tevékenység az új rekorddal folytatja a feldolgozást.
A legmagasabb szinten egy awk
program végrehajtása egy olyan ciklus,
ami beolvassa a bemeneti rekordokat és minden szabállyal szemben teszteli is
azokat. Ha erre a ciklusra úgy gondolsz, mint egy for
kifejezésre,
aminek a testét a szabályok alkotják, akkor a next
kifejezés megfelel a
continue
kifejezésnek: átugorja a ciklus testének végét és a
növelés kifejezést hajtja végre (ami ebben az esetben beolvassa a következô
rekordot).
Például, ha az awk
programod csak négy mezôbôl álló rekordokon
dolgozik és nem akarod, hogy rossz bemenet esetén felmondja a szolgálatot
akkor egy ilyen szabályt használhatsz a program elején:
NF != 4 { err = sprintf("%s:%d: skipped: NF != 4\n", FILENAME, FNR) print err > "/dev/stderr" next }
így a következô szabályok nem kapják meg a rossz rekordot. A hibaüzenet
át van irányítva a szabványos hibakimenetre, mint ahogy minden
hiba esetén lennie kell.
See section Speciális file nevek gawk
-ban.
A POSIX szabvány szerint, a next
kifejezés viselkedése nem definiált
a BEGIN
és az END
szabályokban. A gawk
szintaktikai
hibát fog jelezni. Bár a POSIX szabvány megengedi, de néhány awk
implementáció nem engedi meg a next
kifejezés használatát egy
függvényben
(see section Felhasználó által definiált függvények).
Mint minden más next
kifejezés, a függvény belsejében elhelyezett
next
kifejezés is beolvassa a következô rekordot és elkezdi
feldolgozni a program elsô szabályával.
Ha a next
kifejezés használatával eléri a bemenet végét, akkor
az END
szabályon belüli kódot hajtja végre.
See section A BEGIN
és az END
speciális minták.
Figyelem: Néhány awk
implementáció futási idôben hibát
generál, ha egy a felhasználó által definiált függvényen belül a next
kifejezést használjuk
(see section Felhasználó által definiált függvények).
A gawk
-nak nincs ilyen problémája.
nextfile
kifejezés
A gawk
a next
kifejezéshez hasonlóan egy nextfile
kifejezést is biztosít. Ugyanakkor az aktuális rekord eldobása helyett
a nextfile
kifejezés arra utasítja a gawk
-ot, hogy
fejezze be az adott adat file feldolgozását.
A nextfile
kifejezés hatására a parancssorbeli következô
file nevével tölti fel a FILENAME
változót, az FNR
változót
egyre állítja, az ARGIND
változót megnöveli és elkezdi a
feldolgozást a program elsô szabályától.
See section Beépített változók.
Ha a nextfile
kifejezés hatására eléri a bemenet végét, akkor az
END
szabály kódja hajtódik végre.
See section A BEGIN
és az END
speciális minták.
A nextfile
kifejezés egy gawk
kiegészítés; (jelenleg)
nem használható más awk
implementációkban.
See section Implementing nextfile
as a Function,
ahol bemutatjuk, hogy a felhasználó által definiált függvénnyel
is szimulálható a nextfile
kifejezés.
A nextfile
kifejezés hasznos lehet ha több adatfile-t kell feldolgozni,
és nem akarod minden file minden rekordját feldolgozni. Normális esetben
ahhoz, hogy a következô file feldogozását elkezdhesd, a szükségtelen
rekordokat is át kellene nézni. A nextfile
kifejezés ezt kerüli el
hatékonyan.
Figyelem: A gawk
3.0-ás verziója elôtt két azonos szó
állt rendelkezésre ugyanarra a kifejezésre, a `next file' és a
nextfile
. Ez megváltozott a 3.0-ás verziótól kezdve, mivel a
file
kulcsszó kezelése így nem volt következetes. Ha a next
után szerepelt akkor kulcsszó volt, egyébként meg egy egyszerű azonosító.
A régi használat még mindig elfogadott. Ugyanakkor a gawk
figyelmeztetô
üzenetet generál és a gawk
jôvôbeli verzióiban a next file
kifejezés nem támogatott.
exit
kifejezés
Az exit
kifejezés hatására az awk
azonnal befejezi az aktuális
szabály végrehajtását, és abbahagyja a bemenet feldolgozását is; minden további
bemenetet figyelmen kívül hagy. A formája az alábbi:
exit [visszatérési érték]
Ha egy exit
kifejezést hajt végre az awk
a BEGIN
szabályban akkor azonnal befejez minden működést. Semmilyen bemenetet
nem olvas be. Ugyanakkor ha egy END
szabály is van a programban,
akkor azt is végrehajtja
(see section A BEGIN
és az END
speciális minták).
Ha egy exit
kifejezés hajtódik végre az END
szabályban,
akkor a program azonnal leáll.
Egy exit
kifejezés ami nem része sem egy BEGIN
sem egy
END
szabálynak azonnal befejezi a további szabályok
végrehajtását az adott rekordra, átugorja a további bemeneti rekordokat
és végrehajtja az END
szabályt, ha van ilyen.
Ha azt akarod, hogy az END
szabály ne fusson le ebben az esetben,
akkor egy változót be kell állítani egy nem zérus értékre az exit
kifejezés elôtt, és ezt a változót ellenôrizni kell az END
szabályon
belül.
See section Assertions,
ami egy példát tartalmaz erre.
Ha egy argumentumot is megadunk az exit
kifejezésnek, akkor ez
az érték lesz az awk
kimeneti státusz kódja, visszatérési
értéke. Ha nincs argumentum
megadva, akkor az exit
státusza zérus lesz (siker). Abban az
esetben amikor elôször az exit
kifejezésnek egy argumentumot adunk
meg, majd a második esetben nem argumentummal hívjuk meg, akkor az elôzô
kimeneti értéket fogja használni (s.s.).
Például, tegyük fel, hogy egy olyan esetet fedezel fel, amit nem tudsz
hogyan kellene kezelni. Hagyományosan a program ezt úgy jelenti neked, hogy
nem zérus státusszal lép ki. Az awk
programod is megteheti ezt,
ha az exit
kifejezést egy nem zérus argumentummal használod.
Íme egy példa erre:
BEGIN { if (("date" | getline date_now) <= 0) { print "Can't get system date" > "/dev/stderr" exit 1 } print "current date is", date_now close("date") }
Go to the first, previous, next, last section, table of contents.