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.