awk

A Wikipédiából, a szabad enciklopédiából

Az awk egy olyan programozási nyelv, amit szöveges állományok feldolgozására terveztek. Egy tipikus awk programot (szkript) egy interpreter olvas be és hajt végre. A szkript végrehajtása során a feldolgozott szöveges állomány(ok)at (tartalmának változatlanul hagyásával) másféle kimenetté formálja át. A bemeneti adatok változatlanul hagyása biztosítja, hogy ugyanazon adatokra (például szövegfájlok) többféle awk program is futtatható egymás után, vagyis ugyanazon fájl(ok)ból többféle adat is kinyerhető legyen.

Története[szerkesztés | forrásszöveg szerkesztése]

Elnevezése a megalkotói – Alfred Aho, Peter Weinberger és Brian Kernighan – családneveinek kezdőbetűiből született. Az eredeti awk az 1977-ben az AT&T Bell laboratóriumában készült. Ideális szöveges állományok szűrésére, átformálására és kiértékelésére. Ma is minden Unix rendszeren van legalább egy awk változat. A Free Software Foundation a gawk nevű változatot gondozza, a Linux disztribúciókkal is jellemzően a gawk implementációt szállítják. Windows rendszerekhez is letölthető a gawk például a Cygwin részeként. Elérhető MS-DOS, Atari és Amiga operációs rendszerek alatt is. Megszületése óta számos bővítése létezik, például QTAwk[1], Xgawk (awk+xml), Jawk (Java alapú)[2], stb. Az awk nyelv ereje, rövidsége, de az awk szkriptek határainak felismerése adta Larry Wallnak az ötletet a Perl nyelv kifejlesztésére. A futási sebesség növelése miatt kísérletek történtek awk programok fordítására is, azonban az eltérő utasításkészlet miatt például csak a tawk-szkript fordítható le futtatható kóddá.[3]

Egy awk program működése[szerkesztés | forrásszöveg szerkesztése]

Egy awk szkript futtatásához szükség van egy awk nyelvet feldolgozó (gawk, nawk, stb.) interpreterre, a megfelelő szövegállomány(ok)ra és többnyire egy szkriptre, amely a tevékenységeket írja le. A nyelv tömörsége miatt néhány program olyan rövid, hogy parancssori paraméterként is beadható az interpreter részére.[4] Alapértelmezés szerint az interpreter a szabványos bemenetről olvassa a feldolgozandó adatokat (stdin) és az eredményeket a szabványos kimenetre írja (stdout), azonban átirányításokkal a működése kiterjeszthető.

Az awk adatvezérelt nyelv: minták és tevékenységek sorozatából áll. Beolvas egy sort, automatikusan mezőkre (szavakra) darabolja és a megadott feltételek szerint elvégzi a minta egyezőségének vizsgálatát. Ha van egyezés, akkor a mintához tartozó egy vagy több tevékenységet hajtja végre, majd a szabványos kimenetre írja. Ezután a következő sor feldolgozása történik a fentiek szerint, míg csak a fájl végére nem ér.

Egy awk program részei[szerkesztés | forrásszöveg szerkesztése]

Egy awk program a következő részekből állhat:

  • előkészítő rész;
  • saját függvénydefiníciók;
  • programtörzs;
  • befejező rész.

Fenti részekből a program sajátosságai szerint tetszőleges részek elhagyhatóak, ha az adott program nem igényli (például nincs előkészítésre szükség vagy nincsenek saját függvények, stb.).

Előkészítő rész[szerkesztés | forrásszöveg szerkesztése]

Jellemzően értékadó, vagy programfutást előkészítő parancsok találhatók ebben a részben.

BEGIN { ''parancs(ok)'' }
#Adatbeolvasás előtt BEGIN kapcsos zárójelei közötti parancsokat hajtja végre.
#A BEGIN speciális mintaként is értelmezhető.

Saját függvénydefiníciók[szerkesztés | forrásszöveg szerkesztése]

A programok szerkesztését, futtatását megkönnyíti, ha a felhasználó új utasításokat hozhat létre a meglévő nyelvi elemek felhasználásával.

Programtörzs[szerkesztés | forrásszöveg szerkesztése]

A legegyszerűbb awk-programok csak a programtörzset tartalmazzák és általában mintából és a mintához tartozó parancs(ok)ból, más néven tevékenységből állnak:

 /''1. minta ''/ { ''parancs(ok)'' }
 /''2. minta ''/ { ''parancs(ok)'' }
/''minta''/
# Ha nincs külön parancs megadva, a mintának megfelelő sort kinyomtatja  a standard outputra.
{ ''tevékenység(ek)'' }
# Ha nincs minta megadva, a tevékenység(ek)et minden sorra egymás után végrehajtja.

Az awk soronként olvassa a bemenetet, ezért az awk program működéséhez kis operatív memória is elegendő. Minden beolvasott sort összehasonlít a mintákkal, és abban az esetben, ha illeszkedést talál, a mintához tartozó parancso(ka)t végrehajtja. A mintákat a szabályos kifejezések szabályai szerint fejti ki, vagyis a minták reguláris kifejezéseket is tartalmazhatnak.

Befejező rész[szerkesztés | forrásszöveg szerkesztése]

Az összes adat feldolgozása és a többi parancs végrehajtása után a befejező rész parancsait hajtja végre. Jellemzően összegző- és formázó utasítások találhatók ebben a részben. Az END speciális mintaként is értelmezhető.

END {tevékenységek}

Jelkészlet[szerkesztés | forrásszöveg szerkesztése]

Egy awk program nyelvi elemei az angol abc kis- és nagybetűit, számokat, írásjeleket és az aláhúzásjelet tartalmazhatják. A kis- és nagybetűvel jelölt azonosítók különbözőek.

Nyelvi elemek[szerkesztés | forrásszöveg szerkesztése]

Az awk számos nyelvi elemet használ a programozás megkönnyítésére, így például:

  • változók,
  • rekordok és mezők,
  • tömbök,
  • minták,
  • tevékenységek,
  • operátorok,
  • vezérlő utasítások,
  • be- és kimeneti utasítások,
  • belső függvények,
  • saját függvények.
  • konstansok.

Változók[szerkesztés | forrásszöveg szerkesztése]

Egy awk szkript változói lehetnek

  • felhasználó által létrehozott változók és
  • előre definiált (belső) változók.

Az awk változói globális változók és azáltal jönnek létre, hogy használni kezdik őket, tehát dinamikus változók. A változók értéke lehet sztring vagy lebegőpontos szám, a használat módjától függően. Léteznek lokális változók is, amelyek csak az adott saját függvényen belül láthatóak, ezeket a függvény paraméterlistája után kell felsorolni. [5]

Belső változók

A belső változók mindig globálisak és a program működését befolyásolják. Megállapodás szerint a belső változókat mindig nagybetűkkel jelölik. Példák belső változókra:

  • NR (Number of Records) A beolvasott rekordok (sorok) számát tartja nyilván.
  • NF (Number of Fields) A beolvasott és feldolgozás alatt lévő rekord (sor) mezőinek (szavainak száma) Az utolsó mező a $NF.
  • FILENAME A feldolgozás alatt álló fájl neve.
  • FS (Field Separator) A mezőelválasztó karaktert tartalmazza, amely mentén az awk elvégzi a $0 tartalmának darabolását, alapértelmezés szerint a szóköz és a tabulátor jele. FS ="," hatására a mezők szétvágása nem szóközök mentén történik, hanem a vesszőkig (például CDF-formátum feldolgozása). A beolvasott rekord mezőelválasztó karakterei nem kerülnek feldolgozásra és tárolásra, csupán egy jelzés a feldolgozónak.
  • RS (Record separator) Alapértelmezés szerint a sorvége jel, de tetszés szerint megváltoztatható.
  • OFS (Output Field Separator) a kiírt mezőket (szavakat) elválasztó karakter. Alapértelmezés szerint a szóköz.
  • ORS: (Output Record Separator) a kiírt rekordok (sorok) közötti határolójel. Alapértelmezés szerint az újsor jel.
  • OFMT (Output Format) A számok kiírási formátumát tartalmazza. Alapértelmezés szerint OFMT = "%.6g".

Rekordok és mezők[szerkesztés | forrásszöveg szerkesztése]

A feldolgozott szövegfájl egy sorát rekordnak nevezik. Egy rekord az RS belső változó által meghatározott karakterig tart. RS = "." esetén a rekord hossza éppen egy mondat, függetlenül az újsor jeltől. Vannak előre megadott belső változók, amelyek minden rekord (sor) feldolgozásakor automatikusan értéket kapnak. Például:

  • $0 az éppen feldolgozás alatt álló rekordot tartalmazza, vagyis a alapértelmezés szerint a feldolgozás alatt álló sort;
  • $1, $2, …$n :a sor egyes elemei, más szavakkal a rekord mezői; alapértelmezés szerint egymástól szóközzel vagy tabulátorjellel elválasztott részei (szavak). A mezők automatikusan jönnek létre a rekord beolvasása során. Ez az automatikus felbontás nagyon egyszerűvé és hatékonnyá teszi az adatfeldolgozást. A mezőkre hivatkozni sorszámukkal lehet:
t = $2 *5
# a t változó a második mező ötszörös értékét veszi fel
k = $1 + $3
# a k változóban az első és a harmadik mező összege tárolódik

A mezők indexe csak pozitív egész lehet, negatív mezőhivatkozások (például $-2) fatális hibát okoznak. Az aktuális rekordban lévő mezők számát az NF belső változó tartalmazza. Értéke rekordról rekordra változhat.

Tömbök[szerkesztés | forrásszöveg szerkesztése]

A tömböket az awk-ban szögletes zárójelekkel []jelölik és minden tömb asszociatív (azaz sztringekkel indexelt). A tömb egyes részeit elválasztó karakter a SUBSEP belső változóban tárolódik. Lehetséges többdimenziós tömbök használata is.

Minták[szerkesztés | forrásszöveg szerkesztése]

Az awk minták a következők lehetnek:

  • /reguláris kifejezés/
  • relációs kifejezés
  • minta && minta
  • minta || minta
  • minta ? minta : minta
  • (minta)
  •  ! minta
  • minta1, minta2

A legtöbb leírás speciális mintaként tárgyalja a BEGIN és az END részeket. Sajnos ezek végrehajtása kötött és nem keverhetők más mintákkal, továbbá nem érvényes rájuk az awk mintákra jellemző inputfüggés sem: a BEGIN törzse azelőtt hajtódik végre, mielőtt a bemeneti adatok feldolgozása elkezdődne, az END törzse pedig azután, ha minden bemeneti adat feldolgozása befejeződött. Ezért néhány leírás nem is tekinti őket mintáknak, hanem előkészítő és befejező részként tárgyalja. A BEGIN és az END részek törzse nem hiányozhat.

Tevékenységek[szerkesztés | forrásszöveg szerkesztése]

A tevékenységek utasításai kapcsos zárójelek között szerepelnek.

Operátorok[szerkesztés | forrásszöveg szerkesztése]

Az awk operátorai között is érvényes a műveleti sorrend (precedencia), amely szerint összetett kifejezésekben először a magasabb precedenciájú műveletek értékelődnek ki. Az AWK operátorai csökkenő precedencia szerint:

Operátor Jelentése
() Csoportosítás.
$ Mezőhivatkozás.
++ -- Inkrementálás és dekrementálás, lehet prefix és postfix.
^ Hatványozás (** szintén, **= pedig értékadó operátorként).
+ - ! Egyoperandusú plusz/mínusz és logikai tagadás.
* / % Szorzás, osztás és maradékképzés.
+ - Összeadás és kivonás.
szóköz Sztringek összekapcsolása (konkatenáció).
< > <= >= != == Relációs operátorok.
~ !~ Reguláris kifejezés illeszkedése és nem-illeszkedése.
in Tömbhöz tartozás vizsgálata.
&& Logikai ÉS.
|| Logikai VAGY.
 ?: Feltételes kifejezés.
= += -= *= /= %= ^= Értékadás.

Vezérlő utasítások[szerkesztés | forrásszöveg szerkesztése]

Legegyszerűbb esetben a vezérlő utasítás(oka)t kapcsos zárójelben lehet elhelyezni. Egy sorban több utasítás is elhelyezhető, ha használják az utasításokat lezáró pontosvesszőt. Példák:

{ print $1 }
{ print $1, $3; print i}

Vezérlő utasításokkal feltételek vizsgálata is elvégezhető vagy ciklusok, ugrások hajthatók végre vagy a tömb(ök) elemei vizsgálhatók, törölhetőek:

  • if (feltétel) utasítás [ else utasítás ]
  • while (feltétel) utasítás
  • do utasítás while (feltétel)
  • for (kif1; kif2; kif3) utasítás
  • for (var in array) utasítás
  • break
  • continue
  • delete array[index]
  • delete array
  • exit [ kifejezés ]

Be- és kimeneti utasítások[szerkesztés | forrásszöveg szerkesztése]

Az awk mindössze néhány be- és kimeneti utasítással rendelkezik, mint például a getline, print, printf, next.

Belső függvények[szerkesztés | forrásszöveg szerkesztése]

A belső függvények numerikus- sztring- és időfüggvények.

Saját függvények[szerkesztés | forrásszöveg szerkesztése]

Saját függvény definiálása a function kulcsszó segítségével történhet. Néhány awk-változat elfogadja a rövidebb, négybetűs func alakot is. Például a valami nevű függvény definíciója a következők szerint épül fel:

function valami(paraméterek__és_lokális_változók)
{
  függvénytörzs
}

Paraméterek és lokális változók

Ha a saját függvény egy vagy több paramétert vesz át, akkor azokat a függvény neve utáni zárójelben kell megadni, vesszővel elválasztva, hasonlóan a c-nyelvhez. A következő példa három paramétert vár (a,b,és c)és egy lokális paramétere van (az i):

function add(a,b,c,      i)
{
  függvénytörzs
}

Függvénytörzs

A függvény törzsében minden awk-művelet megengedett, beleértve a szabályos kifejezést, értékadást, függvényhívást, mintakeresést és feldolgozást, stb. A függvénytörzsben a rekurzió megengedett. Visszatérési érték a return utasítás után adható meg. Előrehivatkozás megengedett, mivel az interpreter először beolvassa az egész programot, és – hibamentes program esetén – csak a teljes program beolvasása után kezdi el végrehajtani. Egy saját függvény definíciója tehát bárhol előfordulhat az awk program szabályai szerint.

Egy egyszerű függvénydefiníció lehet például a következő:

 function add_three (number, temp) {
   temp = number + 3
   return temp
 }

Egy így definiált függvény az alábbi szintaxissal hívható meg. Ennek a parancsnak a hatására 39 íródik a kimenetre:

print add_three(36)

Konstansok[szerkesztés | forrásszöveg szerkesztése]

Az awk kizárólag sztring konstansokat használ, amelyek vezérlésre szolgálnak. A sztring konstansokat idézőjelben kell megadni, például az újsor jele "\n"

Awk parancsok[szerkesztés | forrásszöveg szerkesztése]

Az awk nyelv szintaxisa hasonlít a C nyelvéhez, ami nem csoda, hiszen az awk nyelv egyik szerzője, Brian W. Kernighan a C nyelv megalkotója. Elemi parancsok a változóknak való értékadás, a változók összehasonlítása, az elágazás (if…else) és a ciklus (for, while). Emellett belső függvényeket, illetve saját implementálású függvényeket is meg lehet hívni. Az adatokat a "print" paranccsal lehet kinyomtatni, azaz a kimenetre írni. Például egy sor második mezője a

 print $2

paranccsal íratható ki a szabványos kimenetre.

Példák[szerkesztés | forrásszöveg szerkesztése]

Helló, világ![szerkesztés | forrásszöveg szerkesztése]

A „Helló, világ!” program awk-ban a következőképpen implementálható:

 BEGIN { print "Helló, világ!" }

Adott karakterszámnál hosszabb sorok kiíratása[szerkesztés | forrásszöveg szerkesztése]

A következő programmal a 80 karakternél hosszabb sorokat írja ki. Vegyük észre, hogy az alapértelmezett akció a sor kiírása:

length > 80

Minden n. sor kiírása[szerkesztés | forrásszöveg szerkesztése]

Adatsorok egyenletes ritkítására is felhasználható az awk. Az alábbi programot végrehajtva az awk minden 4. sort ír a kimenetre [6]:

awk '{if (count++%4==0) print $0;}' adatsorom.csv

vagy egyszerűbben:

awk '!(count++%4)' adatsorom.csv

Sorok, szavak és karakterek megszámlálása[szerkesztés | forrásszöveg szerkesztése]

Az alábbi awk program megszámolja, majd kiírja a bemeneti fájlban lévő sorok, szavak és karakterek számát úgy, mint a wc nevű program:

# cnt.awk -- szamlalo
 {
     w += NF
     c += length + 1
 }
 END { print NR, w, c }

Néhány sortól terjedelmesebb awk programokat szokás szövegfájlba (szkript) menteni. Futtatásuk a következő módon is lehetséges:

awk -f cnt.awk < valami.txt

Hatására az interpreter beolvassa az -f kapcsoló után álló szkriptet (cnt.awk), majd feldolgozza a valami.txt nevű szövegfájlt a szkript szabályai szerint. Az eredményeket (szavak számát) a képernyőre írja (stdout).

Szavak előfordulási gyakoriságának kiszámítása[szerkesztés | forrásszöveg szerkesztése]

Szavak gyakoriságáról készít statisztikát asszociatív tömb felhasználásával a következő példa:

#stat.awk
 BEGIN { RS="[^a-zA-Z]+"} 
 
 { words[tolower($0)]++ }
 
 END { for (i in words)
     print i, words[i]
 }

Fentieken kívül még számos bonyolultabb program is készíthető awk nyelven, például LISP-interpreter[7], PRAG a groff részére[8], stb.

Jegyzetek[szerkesztés | forrásszöveg szerkesztése]

  1. http://mysite.verizon.net/terrypearl/QTAwk/qtawk.html
  2. http://awk.info/?jawk Jawk: Awk in Java
  3. http://www.tasoft.com/tawk.html TAWK Compiler
  4. Egyes operációs rendszereken a megfelelő futtatási jogosultsággal is rendelkezni kell.
  5. http://hup.hu/old/gawk/tobb/gawk_14.html#SEC129 Felhasználó által definiált függvények
  6. UNIX : Cat every nth (third, fourth, fifth ...) line of a text file using AWK. (Hozzáférés: 2009. június 9.)
  7. http://awk.info/?dsl/awklisp AWKLISP
  8. https://searchcode.com/codesearch/view/11528209/

Kapcsolódó szócikkek[szerkesztés | forrásszöveg szerkesztése]

További információk[szerkesztés | forrásszöveg szerkesztése]