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.
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.
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.
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).
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.
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.
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.
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 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.
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
+ x
x ^ y
x ** y
x * y
x / y
awk
-ban, ezért az eredmény nem
lesz egészre kerekítve: `3 / 4' eredménye 0.75.
x % y
b * int(a / b) + (a % b) == aEgy 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 = -1Az eredmény elôjele más
awk
implementációkban eltérô lehet.
x + y
x - y
A maximális hordozhatóság érdekében ne használd a `**' operátort.
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.
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
lvalue
-ban.
lvalue -= decrement
lvalue *= coefficient
lvalue /= divisor
lvalue %= modulus
lvalue ^= power
lvalue **= power
Maximális hordozhatóság érdekében ne használd a `**=' operátort.
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
lvalue++
--lvalue
lvalue--
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.).
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.
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.
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
x <= y
x > y
x >= y
x == y
x != y
x ~ y
x !~ y
subscript in array
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
"abc" >= "xyz"
1.5 != " +2"
"1e2" < "3"
a = 2; b = "2"
a == b
a = 2; b = " +2"
a == b
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.
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
if ($0 ~ /2400/ && $0 ~ /foo/) printA 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
if ($0 ~ /2400/ || $0 ~ /foo/) printA 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
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.
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ó.
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
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é:
(...)
$
++ --
^ **
+ - !
* / %
+ -
Összefűzés
< <= == !=
> >= >> |
~ !~
in
&&
||
?:
= += -= *=
/= %= ^= **=
Go to the first, previous, next, last section, table of contents.