Go to the first, previous, next, last section, table of contents.


Kifejezések

A kifejezések az awk minták és tevékenységek alap építôkövei. Egy kifejezés kiértékelése egy értéket ad, amit kinyomtathatsz, tesztelhetsz, egy változóban eltárolhatsz vagy egy függvénynek átadhatsz mint argumentumot. Továbbá egy kifejezéssel új értéket rendelhetsz egy változóhoz vagy mezôhöz az értékadó operátorral.

Egy kifejezés önmagában szolgálhat mint egy minta vagy egy tevékenység. A legtöbb kifejezés olyan más kifejezéseket tartalmaz, amelyek adatokon dolgoznak. Mint más nyelvekben, az awk-ban is egy kifejezés tartalmazhat változót, tömb elemre hivatkozást, konstans elemet, függvényhívást és ezek bármilyen kombinációját különbözô operátorral.

Konstans kifejezések

A legegyszerűbb kifejezés egy konstans, aminek mindig ugyanaz az értéke. Háromféle konstans van: számkonstans, szövegkonstans és reguláris kifejezés konstans.

Szám- és szövegkonstansok

Egy számkonstans értéke maga a szám. A szám lehet egész, lebegôpontos vagy exponenciális alakú valós szám.(8) Alább bemutatunk néhány számkonstanst; mindegyiknek ugyanaz az értéke:

105
1.05e+2
1050e-1

A szövegkonstans karakterek sorozatából áll és macskakörmök veszik körül, például:

"parrot"

Ez egy olyan szöveget reprezentál, aminek a tartalma: `parrot'. A gawk-ban a szövegek bármilyen hosszúak lehetnek, és bármely 8 bittel leírható ASCII karaktert tartalmazhatják, az ASCII NUL-t is. Más awk implementációknak néhány speciális karakter problémát okozhat.

Reguláris kifejezés konstansok

Egy reguláris kifejezés konstans egyszerűen a `/' karakterek között leírt reguláris kifejezés, mint a /^beginning and end$/. Leggyakrabban reguláris kifejezés konstansokat használunk, de a `~' és a `!~' operátorokkal "dinamikus" reguláris kifejezéseket is lehet használni (amik egy reguláris kifejezést tartalmazó egyszerű szövegek vagy változók).

Reguláris kifejezés konstansok használata

Ha a reguláris kifejezés konstans a `~' vagy a `!~' operátor jobb oldalán áll, akkor magát a reguláris kifejezést jelenti, amit illeszteni szeretnénk.

A reguláris kifejezés konstansok (mint a /foo/) használhatók mint egyszerű kifejezések is. Ha a reguláris kifejezés konstans önmagában áll, az megegyezik azzal az esettel, mintha a mintában lett volna megadva, például: `($0 ~ /foo/)' (s.s.) (see section Kifejezések mint minták). Ez azt jelenti, hogy az alábbi két programrészlet

if ($0 ~ /barfly/ || $0 ~ /camelot/)
    print "found"

és

if (/barfly/ || /camelot/)
    print "found"

teljesen megegyezik.

Ennek a szabálynak az a furcsa következménye, hogy bár az alábbi kifejezés nem hibás, de nem azt csinálja, mint amit valószínűleg elvárnánk:

# figyelem: a /foo/ nem a ~ operátor bal oldalán van
if (/foo/ ~ $1) print "found foo"

Elméletileg a $1 mezôre a /foo/ reguláris kifejezést próbálja illeszteni. Valójában a `/foo/ ~ $1' kifejezés ezzel egyezik meg: `($0 ~ /foo/) ~ $1'. Más szavakkal, elôször a /foo/ reguláris kifejezést illeszti a teljes rekordra, aminek az eredménye egy vagy zérus attól függôen, hogy az illesztés sikerül-e vagy sem. Azután ezt az eredményt próbálja meg illeszteni az elsô mezôre.

Mivel valószínű, hogy ilyen tesztet soha nem akarsz elvégezni, ezért a gawk figyelmeztet ha ilyen szerkezetet talál a programban.

Egy másik következménye a fenti szabálynak, hogy az alábbi értékadás

matches = /foo/

vagy zérust vagy egyet tárol a matches változóban, attól függôen, hogy mi az aktuális bemeneti rekord értéke.

Ez az awk tulajdonság soha nem volt megfelelôen dokumentálva a POSIX szabvány elôtt.

Reguláris kifejezés konstansok használhatók a gensub, sub és gsub függvények elsô argumentumaként és a match függvény második argumentumaként (see section Szövegmanipuláló beépített függvények). Az awk modern implementációi és a gawk megengedi, hogy a split függvény harmadik argumentuma reguláris kifejezés konstans legyen. Régebbi awk implementációkban ez nem megengedett (s.s.).

Sajnos ez kavarodást okozhat a felhasználó által definiált függvények (see section Felhasználó által definiált függvények) esetén, ha egy reguláris kifejezés konstanst adunk meg mint argumentum, például:

function mysub(pat, repl, str, global)
{
    if (global)
        gsub(pat, repl, str)
    else
        sub(pat, repl, str)
    return str
}

{
    ...
    text = "hi! hi yourself!"
    mysub(/hi/, "howdy", text, 1)
    ...
}

A példában egy reguláris kifejezés konstanst szeretnénk átadni a mysub függvénynek, ami továbbadja azt vagy a sub vagy a gsub függvénynek. Valójában a pat paraméter zérus vagy egy attól függôen, hogy a rekord ($0) tartalmazza-e a /hi/ szöveget.

Mivel nem valószínű, hogy az illesztés eredményét szeretnéd átadni mint argumentum, ezért a gawk figyelmeztet ha egy reguláris kifejezés konstanst talál egy a felhasználó által definiált függvény argumentum listájában.

Változók

A változókban olyan értéket tárolhatunk, amelyet a programban késôbb szeretnénk felhasználni. A változókat teljesen szabadon lehet a programon belül manipulálni. Az awk parancssorában kezdôértéket adhatunk meg a változóknak.

Változók használata egy programban

A változókkal nevet adhatunk egy értéknek, amire késôbb a név segítségével hivatkozhatunk. Már több példában használtunk változókat. A változó neve betűket, számokat és aláhúzás karaktert tartalmazhat, de nem kezdôdhet számjeggyel. A kis- és nagybetűs írásmód fontos, mivel az a és az A két, független változót jelöl.

Önmagában egy változó neve egy érvényes kifejezés; a változó jelenlegi értékét reprezentálja. A változóknak új értéket adhatunk az értékadó operátorral vagy megváltoztathatjuk a növelô vagy csökkentô operátorral. See section Értékadó kifejezések.

Néhány változónak speciális, beépített jelentése van; például FS a mezôelválasztót és az NF a mezôk számát adja meg. A section Beépített változók, tartalmazza a beépített változók listáját. Ezeket a beépített változókat ugyanúgy használhatjuk mint más változókat, de az awk is megváltoztathatja az értéküket. Minden beépített változó neve csupa nagybetűbôl áll.

Az awk változók értéke szám vagy szöveg lehet. Alapesetben minden változó kezdôértéke az üres szöveg, ami zérusnak felel meg ha számmá konvertáljuk. Ezért nincs szükség a változók "inicializálására" az awk-ban, mint például a C programozási nyelvben.

Értékadás változóknak a parancssorban

Bármelyik awk változónak kezdô érték adható a parancssorban az awk parancssori argumentumai között. (see section Other Command Line Arguments). Az értékadás formája:

változó=text

Ilyen formában beállítható egy változó értéke az awk futtatása kezdetén. Az értékadás a bemeneti file-ok között is elhelyezhetô.

Ha az értékadás elôtt a `-v' opciót használjuk, például így:

-v változó=text

akkor a változót állítja be legelôször, még a BEGIN szabály lefutása elôtt. A `-v' opciónak és az értékadásnak meg kell elôznie az összes bemeneti file-t és a program szövegét is. (See section Command Line Options, további információk a `-v' opcióról.)

Ellenkezô esetben az értékadás csak akkor történik meg, amikor az awk a feldolgozásban odaér, vagyis miután feldolgozta a megelôzô bemeneti file-t. Például:

awk '{ print $n }' n=4 inventory-shipped n=2 BBS-list

kinyomtatja az n-edik mezôt mindegyik bemeneti rekordból. Mielôtt az elsô file-t elkezdené olvasni beállítja az n változó értékét négyre. Ennek hatására az `inventory-shipped' file-ból a negyedik mezôt fogja kinyomtatni. Miután befejezte az elsô file feldolgozását és mielôtt elkezdené feldolgozni a másodikat az n változót kettôre állítja, így a `BBS-list' file-ból a második mezôt nyomtatja ki.

$ awk '{ print $n }' n=4 inventory-shipped n=2 BBS-list
-| 15
-| 24
...
-| 555-5553
-| 555-3412
...

A parancssori argumentumokat explicit módon is meg lehet vizsgálni egy awk programban, mivel az ARGV tömbben rendelkezésre állnak (see section Az ARGC és az ARGV változók használata).

Az awk a parancssori értékadásnál is figyelembe veszi az escape szekvenciákat (s.s.) (see section Escape szekvenciák).

Szövegek és számok konverziója

Szövegek számmá és számok szöveggé konvertálhatók ha az awk program úgy kívánja. Például ha vagy a foo vagy a bar értéke a `foo + bar' kifejezésben szöveg értékű, akkor az összeadás elôtt elôször a változó értéke átkonvertálódik számmá. Ha egy szám jelenik meg szöveg összefűzésnél, akkor a számot átkonvertálja szöveggé, így:

two = 2; three = 3
print (two three) + 4

a program a (numerikus) 27-et fogja kinyomtatni. Elôször a two és three változók numerikus értékeit átkonvertálja szöveggé és összefűzi ôket, majd az így kapott szöveget visszaalakítja számmá (23) amihez négyet ad.

Ha valamiért egy számot mindenáron szeretnél szöveggé alakítani, akkor hozzá kell fűzni egy üres szöveget, "". Ha egy szöveget kell átalakítani számmá, akkor hozzá kell adni zérust.

A szöveg számmá konvertálása úgy történik, hogy a szöveg elején elhelyezkedô értelmes numerikus kifejezést alakítja számmá: "2.5" konvertálás után 2.5, "1e3" értéke 1000 és "25fix" numerikus értéke 25. Olyan szöveg, ami nem értelmezhetô számként, a konvertálás után zérus értékű lesz.

A számok szöveggé konvertálását a CONVFMT beépített awk változó kontrollálja (see section Beépített változók). A számokat a sprintf függvénnyel (see section Szövegmanipuláló beépített függvények) alakítja át, ahol a formátum leírót a CONVFMT változó adja meg.

A CONVFMT alapértéke a "%.6g", ami legalább hat értékes jegyre nyomtatja ki a számot. Elôfordulhat, hogy néhány alkalmazás esetén nagyobb pontossággal szeretnél konvertálni, de vedd figyelembe, hogy a dupla (double) pontosság általában csak 16 vagy 17 értékes jegyet képes tárolni.

Furcsa eredményt kaphatsz, ha a CONVFMT-ben nem adod meg a sprintf függvénynek, hogy hogyan nyomtasson lebegô pontos számot. Például ha elfelejted megadni a `%' karaktert a formátumban, akkor minden szám ugyanarra a konstans szövegre lesz konvertálva.

Egy speciális eset, ha a szám egész, akkor a konvertálás eredményeként kapott szöveg mindig egy egész számot fog tartalmazni, attól függetlenül, hogy mi a CONVFMT értéke. Például:

CONVFMT = "%2.2f"
a = 12
b = a ""

b értéke "12" és nem "12.00" (s.s.).

A POSIX szabvány elôtt az awk az OFMT változót használta a számok szöveggé konvertálásánál. Az OFMT azt adja meg, hogy a print milyen formában nyomtasson ki egy számot. A CONVFMT-t pont azért vezették be, hogy elkülönítsék a nyomtatás és a konvertálás formáját. Mindkét változónak (a CONVFMT és a OFMT) ugyanaz az alapértéke: "%.6g". A legtöbb esetben az öreg awk programok viselkedése nem fog megváltozni, de érdemes fejben tartani az OFMT ezen specialitását, ha a programodat más awk implementációkhoz akarod igazítani. Egyébként ebben az esetben a programod módosítása helyett azt tanácsoljuk, hogy magát a gawk-ot fordítsd le és használd. See section A print kifejezés, alatt további információ található a print kifejezésrôl.

Matematikai operátorok

Az awk nyelvben a megszokott matematikai operátorokat lehet használni, a precedenciaszabályok sem különbözôek, és pontosan úgy működnek, ahogy az elvárható.

Az alábbi `grades' file egy osztályba járó tanulók nevét és három teszt eredményét tartalmazza (ez egy kis osztály):

Pat   100 97 58
Sandy  84 72 93
Chris  72 92 89

A program kinyomtatja a tanulók átlagát:

$ awk '{ sum = $2 + $3 + $4 ; avg = sum / 3
>        print $1, avg }' grades
-| Pat 85
-| Sandy 83
-| Chris 84.3333

Az alábbi táblázat felsorolja az awk-ban használható matematikai operátorokat:

- x
Negálás.
+ x
Unáris plusz. A kifejezést számmá konvertálja.
x ^ y
x ** y
Hatványozás: x-et az y-adik hatványra emeli. `2 ^ 3' értéke nyolc. A `**' karakter azonos a `^' karakterrel. (A POSIX szabvány csak a `^' karaktert definiálja hatványozó operátorként.)
x * y
Szorzás.
x / y
Osztás. Mivel minden szám valós az awk-ban, ezért az eredmény nem lesz egészre kerekítve: `3 / 4' eredménye 0.75.
x % y
Maradék számítás. Az osztás eredményét lefelé kerekítve, beszorozva y-al és kivonva x-bôl lesz a végsô eredmény. Ez az operátor úgy is ismert mint "trunc-mod" operátor. Az alábbi reláció mindig igaz:
b * int(a / b) + (a % b) == a
Egy valószínűleg nem kívánatos mellékterméke a fenti definíciónak, hogy ha x negatív, akkor x % y eredménye is negatív lesz, így
-17 % 8 = -1
Az eredmény elôjele más awk implementációkban eltérô lehet.
x + y
Összeadás.
x - y
Kivonás.

A maximális hordozhatóság érdekében ne használd a `**' operátort.

Szövegösszefűzés

Akkor jó ötletnek tünt.
Brian Kernighan

Csak egy szöveg operátor van: összefűzés; viszont nincs karakter ami jelölné. Az összefűzéshez egyszerűen egymás mellé kell írni a kifejezéseket, például:

$ awk '{ print "Field number one: " $1 }' BBS-list
-| Field number one: aardvark
-| Field number one: alpo-net
...

Ha nem lenne szóköz a kettôspont után, akkor az eredmény így nézne ki:

$ awk '{ print "Field number one:" $1 }' BBS-list
-| Field number one:aardvark
-| Field number one:alpo-net
...

Mivel az összefűzésnek nincs explicit operátora, gyakran zárójelek közé kell tenni a kifejezéseket ahhoz, hogy az összefűzés valóban megtörténjen. Például az alábbi példában nem kapcsolja össze a file és a name tartalmát, mint ahogy azt elvárnánk:

file = "file"
name = "name"
print "valami" > file name

Így kell leírni helyesen:

print "valami" > (file name)

Az tanácsoljuk, hogy kivéve a legegyértelműbb helyzeteket, érdemes zárójelek közé tenni az összefűzendô kifejezéseket.

Értékadó kifejezések

Az értékadás egy olyan kifejezés ami új értéket rendel egy változóhoz. Például a z változónak így adjuk meg a numerikus egy értéket:

z = 1

A kifejezés kiértékelése után a z változó értéke egy lesz. A z változó korábbi értéke elveszik, akármi is volt az.

Az értékadásnál megadhatunk szöveg értéket is. Például az alábbi kifejezés a "this food is good" értéket tárolja el a message változóban:

thing = "food"
predicate = "good"
message = "this " thing " is " predicate

(A példa mutatja a szöveg összefűzést is.)

Az `=' (egyenlôség) jel az értékadó operátor. Ez a legegyszerűbb értékadó operátor, mivel a jel jobb oldalán álló értéket változtatás nélkül tárolja a változóban.

A legtöbb operátornak (mint összeadás, összefűzés, stb) nincs más hatása csak az, hogy az adott értéket kiszámolja. Ha nincs szükséged az értékre akkor akár ne is használd az adott operátort. Az értékadó operátor ettôl különbözô; bár a jobb oldal kiértékelésével megkapott értékre elméletileg mondhatod, hogy nincs szükséged, de a változóban mindenképpen el fogja tárolni. Ezt mellékhatásnak hívják.

Az értékadás bal oldalán nem kötelezô egy változónak állnia (see section Változók); ez éppen lehet egy mezô (see section Mezô tartalmának megváltoztatása) vagy egy tömb eleme (see section Tömbök az awk-ban). Ezeket lvalue-nak hívják mivel az értékadó operátor bal oldalán állhatnak. A jobb oldali kifejezés bármilyen kifejezés lehet, ennek az értékét tárolja egy változóban, mezôben vagy egy tömb elemben. (Az ilyen értéket rvalue-nak hívják.)

Fontos megjegyezni, hogy a változóknak nincs állandó típusa. A változó típusát az adja meg, hogy éppen milyen értéket tárol. A következô program részletben a foo változónak elôször szám értéke van majd az értéke szöveg lesz:

foo = 1
print foo
foo = "bar"
print foo

Amikor a második alkalommal a foo egy szöveg értéket kap, akkor az elôzô szám értékét teljesen elfelejti.

Ha egy szöveg nem számmal kezdôdik, akkor a numerikus értéke zérus. Így az alábbi kód végrehajtása után a foo értéke öt:

foo = "a string"
foo = foo + 5

(Figyelem, ha egy változónak néha szám és néha szöveg értéke van, az zavaró lehet és rossz programozási stílus. A fenti példa azt mutatja be, hogy az awk hogyan működik és nem azt, hogy hogyan kell programot írni!)

Az értékadás is egy kifejezés és az értéke megegyezik a jobb oldal kiértékelés utáni értékével. Így a `z = 1' mint kifejezés értéke egy. Ennek egyik következménye, hogy többszörös értékadást is lehet egymás után írni:

x = y = z = 0

eredménye, hogy mind a három változó értéke zérus lesz, mivel a `z = 0' értéke zérus, amit az `y' változóban tárol, majd a `y = z = 0' zérus értékét tárolja el az x változóban.

Értékadás minden olyan helyen használható, ahol kifejezés szerepelhet. Például ez is érvényes `x != (y = 1)', ami elôször egyet rendel az y-hoz, majd ellenôrzi, hogy az x értéke egy-e. Ugyanakkor ezt a programozási stílust nehéz olvasni; az egyszer használatos programok kivételével beágyazott értékadást nem érdemes használni.

Bár az `=' operátor nem, de más operátorok felhasználják a változó régi értékét. Például, a `+=' operátor a változó régi értékéhez hozzáadja a jobb oldal értékét, majd az így kapott új értéket tárolja el a változóban. Így az alábbi kifejezés ötöt ad a foo értékéhez:

foo += 5

ami megegyezik ezzel:

foo = foo + 5

Azt használd, amelyik jobban olvasható/érthetô számodra.

Vannak olyan esetek, amikor a `+=' operátor (vagy bármilyen más értékadó operátor) nem ugyanazt csinálja mint amikor a bal oldali változó a jobb oldalon is szerepel, például:

# Köszönet Pat Rankin-nak ezért a példáért
BEGIN  {
    foo[rand()] += 5
    for (x in foo)
       print x, foo[x]

    bar[rand()] = bar[rand()] + 5
    for (x in bar)
       print x, bar[x]
}

A bar indexei garantáltan különbözôek lesznek, mivel a rand minden alkalommal más értékkel tér vissza. (A tömböket és a rand függvényt eddig még nem tárgyaltuk, see section Tömbök az awk-ban, és lásd még section Numerikus beépített függvények, további információkért).

Ez a példa az értékadás operátorok egy másik fontos tulajdonságát is demonstrálja: a bal oldali kifejezés csak egyszer lesz kiértékelve.

Az implementációtól függ, hogy melyik kifejezés értékelôdik ki elôször, a jobb vagy a bal oldali kifejezés, például:

i = 1
a[i += 2] = i + 1

Az a[3] értéke kettô vagy négy is lehet.

Az alábbi táblázat összefoglalja az értékadó operátorokat. Mindegyik esetben a jobb oldali kifejezést kiértékeli és ha szükséges számmá konvertálja az awk.

lvalue += increment
Hozzáadja az increment-et az lvalue régi értékéhez majd ezt az új értéket tárolja az lvalue-ban.
lvalue -= decrement
Kivonja a decrement-et az lvalue-ból.
lvalue *= coefficient
Az lvalue-t megszorozza a coefficient-el.
lvalue /= divisor
Az lvalue-t elosztja a divisor-al.
lvalue %= modulus
Az lvalue és a modulus osztásának maradékát számítja ki.
lvalue ^= power
lvalue **= power
Az lvalue-t a power hatványra emeli. (Csak a `^=' operátor POSIX kompatíbilis.)

Maximális hordozhatóság érdekében ne használd a `**=' operátort.

Növelô és csökkentô operátorok

A növelô és a csökkentô operátorok eggyel növelik vagy csökkentik a változó értékét. Ugyanezt megteheted értékadó operátorral is, így ez a két új operátor nem ad semmi újat az awk nyelvhez, de kényelmes rövidítése egy gyakran használt műveletnek.

A növelô operátor a `++', használható mielôtt vagy miután a kifejezés értékét megkaptuk.

Ha a `++v'-t használjuk, akkor egyet ad a változóhoz és ez lesz a kifejezés értéke is. Ez teljesen azonos a `v += 1' kifejezéssel.

Ha a `++'-t a változó után írjuk, akkor bár ez is eggyel növeli a változó értékét, de az a különbség, hogy a kifejezés értéke a változó régi értéke lesz. Így, ha a foo értéke négy, akkor a `foo++' kifejezés értéke is négy, de a `foo' változó ötre változik.

A `foo++' majdnem azonos a `(foo += 1) - 1' kifejezéssel. Nem egészen azonos, mivel az awk-ban minden szám lebegôpontos (valós): így `foo + 1 - 1' nem biztos, hogy tökéletesen megegyezik `foo'-val. Ez a különbség nem vehetô észre ha "kis" számokat használsz (kisebb mint 10e12).

Bármilyen `lvalue' növelhetô. Mezôket és tömb elemeit pontosan úgy növel mint változókat. (Ha egy mezôre akarsz hivatkozni és ugyanakkor a változó értékét növelni a `$(i++)' kifejezést használd. A zárójelek fontosak a `$' precedenciája miatt.)

A csökkentô operátor `--' ugyanúgy viselkedik mint a növelô, csak kivon egyet a változóból. Mint a `++', használható az `lvalue' elôtt vagy után.

Az alábbiakban összefoglaljuk a növelô és csökkentô operátorok használatát.

++lvalue
Ez a kifejezés megnöveli az `lvalue' értékét és az új érték lesz a teljes kifejezés értéke is.
lvalue++
Ez a kifejezés megnöveli az `lvalue' értékét és a régi érték lesz a teljes kifejezés értéke.
--lvalue
Ez a kifejezés lecsökkenti az `lvalue' értékét és az új érték lesz a teljes kifejezés értéke is.
lvalue--
Ez a kifejezés lecsökkenti az `lvalue' értékét és az `lvalue' régi értéke lesz a teljes kifejezés értéke.

Igaz és hamis az awk-ban

Sok programozási nyelvben speciális reprezentációja van az "igaz" és a "hamis" értékeknek. Ezek a nyelvek általában speciális konstanst használnak, például true és false vagy TRUE és FALSE.

Az awk ettôl különbözô, ugyanazt az egyszerű megoldást használja mint a C programozási nyelv. Az awk-ban, bármely nem zérus szám vagy nem üres szöveg igaz értéket képvisel. A zérus szám és az üres szöveg "" hamis. Az alábbi program háromszor írja ki a `Egy furcsa igaz érték' szöveget:

BEGIN {
   if (3.1415927)
       print "Egy furcsa igaz érték"
   if ("Four Score And Seven Years Ago")
       print "Egy furcsa igaz érték"
   if (j = 57)
       print "Egy furcsa igaz érték"
}

A "nem zérus vagy nem üres szöveg" szabálynak van egy érdekes következménye: A "0" szöveg konstans valójában igaz, mivel nem üres szöveg (s.s.).

Változó típusok és az összehasonlító kifejezések

Az útikönyv pontos. A valóság gyakran nem egzakt.
Galaxis útikönyv stopposoknak

Más programozási nyelvekkel szemben az awk változóknak nincs fix típusuk, lehetnek számok vagy szövegek, attól függôen, hogy mi az értékük.

Az 1992-es POSIX szabvány bevezette a szám-szöveg (strnum) koncepciót; ez egyszerűen egy szöveg ami úgy néz ki mint egy szám, például " +2". E koncepció segítségével lehet meghatározni a változó típusát.

A változó típusa azért fontos, mert a típus határozza meg, hogy két változó hogyan lesz összehasonlítva.

A gawk-ban az alábbi szabályok érvényesek.

  1. Egy számnak vagy egy matematikai műveletnek szám attribútuma van.
  2. Egy szövegnek vagy egy szöveges műveletnek szöveg attribútuma van.
  3. Mezôknek, a getline input-nak, a FILENAME-nek, az ARGV elemeinek, az ENVIRON elemeinek és a split által készített tömbök olyan elemeinek aminek szám-szöveg értéke van az attribútuma strnum. Minden egyéb esetben az attribútum szöveg. Nem inicializált változók attribútuma is strnum.
  4. Az attribútum átadódik az értékadással, de a változó egyszerű használatával nem változik meg.

Az utolsó szabály különösen fontos. A következô programban a-nak szám értéke van, még akkor is ha késôbb egy szöveges műveletben használjuk.

BEGIN {
         a = 12.345
         b = a " is a cute number"
         print b
}

Amikor két operandust hasonlítunk össze vagy szöveges vagy szám összehasonlítás hajtódik végre, az operandusok típusától függôen, az alábbi szimmetrikus táblázat szerint:

Az alapkoncepció az, hogy a felhasználó által megadott bemenetet ami számnak néz ki, és csak a felhasználói bemenetet, számként kell kezelni még akkor is ha karakterekbôl áll, és ezért szöveg lenne.

Az összehasonlító kifejezések a szövegek és a számok közötti kapcsolatot ellenôrzik, például egyenlôségüket. Az összehasonlító kifejezéseket egy összehasonlító operátorral írjuk le, amelyek a C nyelvben található operátorokkal felülrôl kompatíbilisek. Íme az összehasonlító operátorok táblázata:

x < y
Igaz, ha x kisebb mint y.
x <= y
Igaz, ha x kisebb vagy egyenlô mint y.
x > y
Igaz, ha x nagyobb mint y.
x >= y
Igaz, ha x nagyobb vagy egyenlô mint y.
x == y
Igaz, ha x egyenlô y-al.
x != y
Igaz, ha x nem egyenlô y-al.
x ~ y
Igaz, ha x illeszkedik az y által megadott reguláris kifejezésre.
x !~ y
Igaz, ha x nem illeszkedik az y által megadott reguláris kifejezésre.
subscript in array
Igaz, ha az array tömbnek van subscript indexű eleme.

Az összehasonlító kifejezések értéke egy ha igaz, és zérus ha hamis.

Amikor különbözô típusú komponenseket hasonlítunk össze, akkor a szám értékeket átalakítja szöveggé a CONVFMT változó értékét használva. (see section Szövegek és számok konverziója).

A szövegek összehasonlításánál elôször az elsô karaktereket hasonlítja össze, majd a második karaktereket és így tovább. Így "10" kisebb mint "9". Két olyan szöveg esetén, amikor az egyik szöveg eleje teljesen megegyezik a második szöveggel, akkor a rövidebb szöveg számít kisebbnek. Így "abc" kisebb mint "abcd".

Nagyon könnyü véletlenül elgépelni a `==' operátort és az egyik (`=') egyenlôség jelet elhagyni. Az eredmény szintén érvényes awk kód, de a program nem azt fogja csinálni mint amit szeretnél.

if (a = b)   # hoppá ! a == b kellene
   ...
else
   ...

Hacsak b nem zérus vagy üres szöveg, az if feltételes kifejezés mindig igaz lesz. Az ilyen hibát sajnos nagyon nehéz észrevenni a forráskód átnézése során.

Alább bemutatunk néhány kifejezést, ami bemutatja, hogy a gawk hogyan végzi az összehasonlítást és milyen eredményt kapunk:

1.5 <= 2.0
numerikus összehasonlítás (igaz)
"abc" >= "xyz"
szöveg összehasonlítás (hamis)
1.5 != " +2"
szöveg összehasonlítás (igaz)
"1e2" < "3"
szöveg összehasonlítás (igaz)
a = 2; b = "2"
a == b
szöveg összehasonlítás (igaz)
a = 2; b = " +2"
a == b
szöveg összehasonlítás (hamis)

Ebben a példában,

$ echo 1e2 3 | awk '{ print ($1 < $2) ? "true" : "false" }'
-| false

az eredmény hamis, mivel $1 és $2 szám-szövegek, így mindkettô típusa strnum, ami szám összehasonlítást eredményez.

Az összehasonlítási szabályok és a szám-szövegek célja, hogy a program a "lehetô legkisebb meglepetést" okozva a felhasználó által "elvárt, jó dolgot csinálja".

A szöveg és reguláris kifejezések összehasonlítása teljesen különbözô. Például:

x == "foo"

értéke egy, vagyis igaz, ha az x változó értéke pontosan `foo'. Ezzel ellentétben, az

x ~ /foo/

értéke egy, ha az x változó tartalmazza a `foo' szöveget, úgy mint "Oh, what a fool am I!".

A `~' és `!~' operátorok jobb oldalán álló kifejezés lehet egy regexp konstans (/.../) vagy egy általános kifejezés amikor is a kifejezés értékét mint szöveget használja egy dinamikus reguláris kifejezésként (see section Hogyan használjuk a reguláris kifejezéseket; és see section Dinamikus reguláris kifejezések használata).

Az awk jelenlegi implementációjában egy konstans reguláris kifejezés a `/' jelek között szintén általános kifejezésnek számít. A /regexp/ csak egy rövidítése az összehasonlító kifejezésnek:

$0 ~ /regexp/

Egy speciális eset, amikor a /foo/ nem a `$0 ~ /foo/' kifejezés rövidítése, ha a reguláris kifejezés a `~' vagy a `!~' operátor jobb oldalán áll! See section Reguláris kifejezés konstansok használata, ahol ezt az esetet részletesen tárgyaltuk.

Logikai kifejezések

A logikai kifejezések összehasonlító vagy illesztô kifejezések kombinációja a "vagy" (`||'), az "és" (`&&') és a "negálás" (`!') operátorokkal illetve a zárójelek segítségével. A logikai kifejezések igazság értéke a komponens kifejezések igazság értékének összekombinálásával kapható meg. A logikai kifejezéseket boolean kifejezésnek is hívják. A két név teljesen egyenértékű.

Logikai kifejezés használható minden olyan helyen, ahol összehasonlító és illesztô kifejezés állhat. Szerepelhetnek az if, a while, a do és a for kifejezésekben (see section Vezérlésátadó kifejezések a tevékenységekben). A logikai kifejzés értéke szám (egy ha igaz és zérus ha hamis), ami akkor játszik fontos szerepet ha a logikai kifejezés eredményét egy változóban tároljuk vagy aritmetikai kifejezésben használjuk.

Ráadásul minden logikai kifejezés egy érvényes minta is, így használható mint minta és így képes a szabályok végrehajtását is befolyásolni.

A három logikai operátor leírását néhány példával alább közöljük:

boolean1 && boolean2
Igaz, ha a boolean1 és a boolean2 igaz. Például az alábbi kifejezés kinyomtatja az aktuális rekordot, ha az tartalmaza a `2400' és a `foo' szövegeket.
if ($0 ~ /2400/ && $0 ~ /foo/) print
A második kifejezés (boolean2) csak akkor értékelôdik ki, ha a boolean1 igaz. Ez akkor lehet fontos, ha a boolean2 kiértékelésének van mellékhatása: a `$0 ~ /foo/ && ($2 == bar++)' kifejezés esetén a bar változó nem növelôdik meg ha a foo szöveg nem szerepel a rekordban.
boolean1 || boolean2
Igaz, ha vagy a boolean1 vagy a boolean2 igaz. Például az alábbi kifejezés kinyomtat minden olyan rekordot ami vagy a `2400', vagy a `foo', vagy mind a két szöveget tartalmazza.
if ($0 ~ /2400/ || $0 ~ /foo/) print
A második kifejezés (boolean2) csak akkor értékelôdik ki, ha a boolean1 hamis. Ez akkor lesz fontos ha a boolean2 kifejezés egy olyan kifejezést tartalmaz aminek mellékhatása van.
! boolean
Igaz, ha a boolean kifejezés hamis. Például az alábbi program a `BBS-file' file-ból kinyomtat minden olyan rekordot, ami nem tartalmazza a `foo' szöveget.
awk '{ if (! ($0 ~ /foo/)) print }' BBS-list

A `&&' és a `||' operátorokat rövidre zárható operátoroknak is nevezik. A teljes kifejezés kiértékelése "rövidre záródik", befejezôdik, ha az eredmény a kifejezés egy részének kiértékelésével már meghatározható.

A logikai kifejezések sorokra bonthatók a `&&' és a `||' operátorok után beszúrt új sor karakterrel. Ugyanakkor az új sor karakter nem használható az operátorok elôtt a `\' karakter nélkül (see section awk kifejezések és sorok).

A `!' operátort tartalmazó kifejezések értéke vagy egy vagy zérus lehet, attól függôen, hogy milyen igazságértékű kifejezésre lett alkalmazva az operátor.

A `!' operátor gyakran használható kapcsoló változók átállítására igazról hamisra és fordítva. Például, az alábbi program az egyik módja annak, hogy speciális zárójelek közti sorokat kinyomtassunk:

$1 == "START"   { interested = ! interested }
interested == 1 { print }
$1 == "END"     { interested = ! interested }

Az interested változó, mint minden awk változó, kezdetben zérus értékű, ami hamis értékű. Amikor egy `START' szöveggel kezdôdô sort olvas be, akkor az interested változót átállítja igazra a `!' operátorral. A következô szabály addig nyomtatja ki a sorokat amíg a interested változó igaz. Amikor egy `END' kezdetű sort olvas be, a interested változót visszaállítja hamisra.

Feltételes kifejezések

A feltételes kifejezések olyan speciális kifejezések aminek három operandusa van. Ennek segítségével egy kifejezés értékétôl függôen az egyik vagy egy másik kifejezés hajtódik végre.

A feltételes kifejezés ugyanolyan mint a C nyelvben:

választás ? ha-igaz-kif : ha-hamis-kif

Három alkifejezésbôl áll. Az elsô, a választás, értékelôdik ki legelôször. Ha az értéke "igaz" (nem zérus és nem üres szöveg) akkor a ha-igaz-kif kifejezés lesz kiértékelve és ennek az értéke lesz a teljes kifejezés értéke. Más esetben a ha-hamis-kif lesz kiértékelve és ennek az értéke adja a teljes kifejezés értékét.

Például, ez a kifejezés az x változó abszolút értékét adja meg:

x > 0 ? x : -x

Minden alkalommal, amikor egy feltételes kifejezés kiértékelôdik, pontosan egy kifejezés, vagy a ha-igaz-kif vagy a ha-hamis-kif értékelôdik ki; a másikat nem veszi figyelembe. Ez akkor fontos, ha a kifejezéseknek mellékhatásuk van. Például ez a feltételes kifejezés vagy az a vagy a b tömb i-edik indexét vizsgálja meg és az i-t megnöveli.

x == y ? a[i++] : b[i++]

Ez a kifejezés garantáltan csak egyszer növeli meg a i értékét, mivel minden alkalommal a két növelô kifejezés közül csak az egyik hajtódik végre, és a másik nem. See section Tömbök az awk-ban, további információ a tömbökrôl.

Egy apró gawk módosítás, hogy egy új sor karakter beszúrható a `?:' karakterek bármelyike után, és így több sorba is írható a kifejezés. Ugyanakkor új sor karakter nem használható elôttük kivéve ha a `\' karaktert használjuk (see section awk kifejezések és sorok). Ha a `--posix' opció meg van adva (see section Command Line Options), akkor ez a kiegészítés nem használható.

Függvényhívások

A függvény egy nevet rendel egy adott számításhoz. Mivel névvel rendelkezik, ezért bármikor meghívható a programból. Például az sqrt függvény egy szám négyzetgyökét számítja ki.

Egy adott számú beépített függvény áll rendelkezésre minden awk programban. Az sqrt függvény ezek egyike. See section Beépített függvények, ami a beépített függvények listáját és leírását tartalmazza. Ráadásul saját függvényeket is lehet definiálni. See section Felhasználó által definiált függvények, hogy hogyan kell definiálni új függvényeket.

A függvényeket függvényhíváson keresztül lehet használni, ami a függvény nevét és a közvetlenül utána álló argument listát tartalmazza zárójelekben. Az argumentumok olyan kifejezések, amelyek extra adatot biztosítanak a függvénybeli számításhoz. Ha egynél több argumentum van, akkor az argumentumokat vesszôvel kell elválasztani. Ha a függvénynek nincs argumentuma, akkor egy üres zárójelet kell írni, `()'. Íme néhány példa:

sqrt(x^2 + y^2)        egy argumentum
atan2(y, x)            két argumentum
rand()                 nincs argumentum

Nem szabad szóköz karaktert tenni a függvény neve és a nyitó zárójel közé! A felhasználó által definiált függvény nevek pont úgy néznek ki mint a változók nevei és ezért a szóközzel úgy lenne értelmezve mintha egy változót összefűznénk a zárójelek közti kifejezéssel. Beépített függvények esetén egy szóköz teljesen ártalmatlan a zárójel elôtt, de a legjobb ha nem szoksz hozzá, mert így elkerülheted ezt a hibát az általad definiált függvények esetén.

Minden függvény egy adott számú argumentumot kíván. Például az sqrt függvényt csak egyetlen argumentummal kell meghívni, azt a számot kell megadni, aminek a négyzetgyökét ki akarjuk számolni:

sqrt(argument)

Néhány beépített függvény esetén az utolsó argumentum elhagyható. Ha az utolsó argumentumot nem adod meg, akkor egy ésszerű alapbeállítást használ a program. See section Beépített függvények, a teljes részletekrôl. Ha egy a felhasználó által definiált függvény argumentumaiból elhagyunk néhányat, akkor azok az argumentumok, mint lokális változók lesznek kezelve és üres szöveg lesz a kezdô értékük (see section Felhasználó által definiált függvények).

Mint minden más kifejezésnek, a függvényhívásnak is van értéke, amit a függvény számol ki az argumentumok alapján. Ebben a példában, a `sqrt(argument)' kifejezés kiszámolja az argument négyzetgyökét. A függvénynek is lehet mellékhatása, mint például bizonyos változókhoz értéket rendelni vagy I/O végrehajtása.

Itt egy parancs számok beolvasására, egy szám soronként majd kinyomtatja mindegyik beolvasott szám négyzetgyökét:

$ awk '{ print "The square root of", $1, "is", sqrt($1) }'
1
-| The square root of 1 is 1
3
-| The square root of 3 is 1.73205
5
-| The square root of 5 is 2.23607
Control-d

Operátorok precedenciája (Hogyan ágyazhatók operátorok egymásba)

Az operátorok precedenciája azt határozza meg, hogy az operátorokat hogyan lehet csoportosítani egy kifejezésben. Például a `*' operátornak magasabb a precedenciája mint a `+' operátornak; így, a `a + b * c' kifejezés esetén a b és a c változókat összeszorozza, majd azután hozzáadja az a változót (például: `a + (b * c)').

Az operátorok precedenciáját felül lehet bírálni a zárójelek használatával. Úgy is gondolhatsz a precedenciaszabályokra, mint amelyek meghatározzák azt, hogy a zárójeleknek hol kellene lenniük, ha nem írod ki ôket. Valójában hasznos a zárójeleket mindig használni, ha az operátorok valamilyen szokatlan kombinációját használjuk, mivel más emberek, akik a programodat olvassák, késôbb lehet hogy nem emlékeznének, hogy mi is a helyes precedencia az adott esetben. Lehet, hogy Te is elfelejted; így te is hibázhatsz. A zárójelek használatával az ilyen hibák elkerülhetôk.

Amikor azonos precedenciájú operátorokat használunk, a legbaloldalibb operátor alapján lesz elôször csoportosítva a kifejezés, kivéve persze az értékadás, a feltételes és az exponenciális operátorok, amelyeknél a sorrend fordított. Így a `a - b + c' csoportosítása `(a - b) + c' és a `a = b = c' csoportosítása `a = (b = c)'.

Az unáris operátorok esetén a precedencia nem számít egészen addig amig csak unáris operátorokat használunk, mivel csak egyféleképpen lehet értelmezni ôket -- a legbelsôt elôször. Így a `$++i' azt jelenti, hogy `$(++i)' és a `++$x' jelentése `++($x)'. Ugyanakkor, amikor egy másik operátor áll az operandus után, akkor az unáris operátor precedenciája is fontos. Így `$x^2' jelentése `($x)^2', de `-x^2' azt jelenti, hogy `-(x^2)', mivel a `-' operátornak alacsonyabb precedenciája van mint a `^' operátornak, míg a `$' operátornak magasabb a precedenciája.

Az alábbi táblázat tartalmazza az awk operátorok listáját a legmagasabb precedenciától az alacsonyabb felé:

(...)
Csoportosítás.
$
Mezô.
++ --
Növelés, csökkentés.
^ **
Exponenciális operátor. Ezek az operátorok jobbról balra csoportosíthatók. (A `**' operátor nem POSIX kompatíbilis.)
+ - !
unáris plusz, mínusz, logikai "negálás".
* / %
Szorzás, osztás, maradékképzés.
+ -
Összeadás, kivonás.
Összefűzés
nincs speciális jel az összefűzés jelölésére. Az operátorokat egyszerűen egymás után kell írni.
< <= == !=
> >= >> |
Összehasonlítás és átirányítás. Az összehasonlítás operátornak és az átirányításnak azonos precedenciája van. A `>' karakter mind összehasonlítás operátorként, mind pedig átirányításként szolgál; az adott helyzet határozza meg a jelentését. Az átirányítás operátor nem generál egy újabb kifejezést, amit mint operandus használhatunk egy másik operátorral. Az eredmény az, hogy nincs értelme az átirányítás operátort használni egy alacsonyabb precedenciájú operátor közelében zárójelek nélkül. Az ilyen kombináció, mint például a `print foo > a ? b : c' kifejezés szintaktikus hibát generál. A kifejezés helyes írásmódja `print foo > (a ? b : c)'.
~ !~
Illeszkedés, nem-illeszkedés.
in
Tömbhöz tartozás kifejezése (Tömb eleme).
&&
Logikai "és".
||
Logikai "vagy".
?:
Feltételes kifejezés. Ez az operátor jobbról balra csoportosítható.
= += -= *=
/= %= ^= **=
Értékadás. Ezek az operátorok jobbról balra csoportosíthatók. (A `**=' operátor nem POSIX kompatíbilis.)


Go to the first, previous, next, last section, table of contents.