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.