Awk

De Viquipèdia
Dreceres ràpides: navegació, cerca

El llenguatge de programació awk és un llenguatge interpretat especialment dissenyat per al tractament de fitxers de text (o text procedent d'un filtre o pipe). El nom del llenguatge ve de les inicials del cognoms dels seus tres autors originals: Aho, Weinberger i Kernighan; a la pràctica el nom es pren pel nom en anglès de l'alca (un ocell àrtic), per exemple tal com apareix a la portada del llibre de referència The AWK Programming Language.

L'awk fa servir strings, expressions regulars (regexp), i arrays associatius (hash). Incorpora tot de conceptes implícits com el bucle principal d'entrada, delimitador de camp i delimitador de registre, parsing automàtic de camps, obrir i tancar fitxers, etc. Això facilita la creació de programes molt compactes d'una sola línia.

L'awk és l'antecessor directe del perl, i tot i que és un llenguatge força senzill, resulta molt potent i ràpid per al tractament de fitxers de text. L'intèrpret d'awk demana molt pocs recursos al sistema, i la càrrega i interpretació del programa és més ràpida que amb un intèrpret de perl (és clar que aquest altre pot fer moltes altres coses com accedir a una base de dades o establir connexions de xarxa).

L'awk és una utilitat present en qualsevol entorn Unix estàndard. Existeixen implementacions d'awk per a gairebé tots els sistemes operatius (unix, linux, ms-windows, hp-mpe, etc.). Existeix una versió GNU anomenada gawk, que incorpora algunes extensions interessants al llenguatge estàndard.

Estructura típica d'un programa awk[modifica | modifica el codi]

Un programa awk típic és una sèrie de regles que especifiquen què cal fer amb el text d'entrada.

Cada regla típicament és una parella de condició (opcionalment delimitada entre () o parèntesis) i d'acció (delimitada entre {} o claus). Encara que una regla pot tenir només la condició (llavors s'aplica l'acció per defecte que és llistar el mateix registre de l'entrada a la sortida) o només l'acció (llavors s'aplica la condició per defecte que és aplicar l'acció sempre per a tots els registres de l'entrada).

Per exemple:

/hola/ # llista totes les ratlles que contenen "hola"
{ print length($0) } # llista llargada en caràcters de cada ratlla llegida
/hola/ { print length($0) } # llista llargada en caràcters de les ratlles que contenen "hola"

Un programa awk pot incloure regles de dues menes de condicions especials:

  • BEGIN: regles que s'apliquen abans de començar a llegir l'entrada
  • END: regles que s'apliquen després d'acabar de llegir l'entrada

Per exemple:

/hola/ { quantes++ } # compta ratlles que contenen "hola"
END { print 0+quantes } # llista el comptador al final

Sintaxi[modifica | modifica el codi]

El format del codi awk és força lliure.

Cada sentència ve separada en una ratlla (ratlles cabades en \n (salt de línia). Per partir una sentència llarga i continuar-la en una altra ratlla cal acabar la ratlla partida amb un caràcter \ (antibarra o backslash). Per incloure més d'una sentència en una mateixa ratlla, es poden separar amb; (punt-i-coma). El text a la dreta d'un # (sostingut o hash) es considera un comentari i és ignorat per l'intèrpret.


Tipus de dades, constants i variables, expressions[modifica | modifica el codi]

  • ...
  • ... constants numèriques
  • El text d'una constant string està delimitat entre "" (dobles cometes).
  • El text d'una constant expressió regular està delimitat entre // (barres).
  • variables escalars: numèriques, string...
  • arrays associatius...
  • ... variables predefinides i de control
  • ... accés als arguments de la línia d'ordres
  • ... accés a les variables d'entorn

Estructures de control i subprogrames[modifica | modifica el codi]

  • ...
  • assignació
  • sentència composta {...}
  • crida a funció
  • definició de funció: function ...(...); return
  • if(...) {...} else {...}
  • cicle de lectura implícit; next; exit
  • while() {...}
  • do {...} while ()
  • for(...;...;...) {...}
  • for (... in ...) {...}
  • continue, break

Entrada i sortida[modifica | modifica el codi]

  • ...
  • entrada implícita
  • getline explicit
  • print
  • system()
  • operadors de redirecció: < > |

Operacions predefinides[modifica | modifica el codi]

  • ...
  • operadors d'assignació: = += -=
  • operadors lògics: && || !
  • operadors relacionals: == != <= >= < >
  • operador ternari: ? :
  • operadors numèrics: + - * / % ++ --
  • operacions amb strings: substr(), length(), index(), concatenació implícita, sprintf(), toupper(), tolower()
  • operacions amb dates: time(), strftime()
  • operacions amb expressions regulars: ~, !~, match(), sub(), gsub(), split()
  • operacions amb arrays associatius: in, delete

Programes d'exemple[modifica | modifica el codi]

Programa que escriu Hola Món per la sortida estàndard.

#!/usr/bin/awk -f
BEGIN { 
print "Hola, món!" # salt de línia implícit
exit 
}

Cal destacar que la primera línia inclou la ubicació del binari gawk, que pot variar segons el sistema operatiu, o la seva configuració.


Calcular freqüència de les paraules d'un text[modifica | modifica el codi]

Una versió simple, fent servir un array associatiu:

BEGIN { FS="[^a-zA-ZçÇàèòÀÈÒéóíúÉÓÍÚïüÏÜ·]+" }
{ for (i=1; i<=NF; i++) paraules[tolower($i)]++ }
END { for (i in paraules) print i, paraules[i] }

El bloc BEGIN (que s'interpreta abans de començar la lectura) determina com a delimitador de camp (variable predefinida FS) qualsevol seqüència de caràcters que no formin paraules (enumerem els caràcters que formen paraules en català). Els delimitadors de camp poden ser expressions regulars, no només strings literals.

Després, posem l'acció que cal fer sobre cada línia d'entrada (cicle d'entrada implícit). En concret, per cada camp (en aquest cas serà cada paraula delimitada), comptem quantes vegades apareix la paraula (després de passar-la a minúscules). La creació de cada element de l'array associatiu, identificat amb la paraula com a clau, també és implícita. La variable predefinida NF conté automàticament el nombre de camps del registre llegit en curs. La sintaxi $i permet referir-se al camp d'ordre i (base 1) del registre llegit en curs.

Finalment, al bloc END (que s'interpreta després de finalitzar la lectura), es llista l'array associatiu: les claus dels elements (les paraules) i els valors associats (els comptadors acumulats de nombre d'ocurrències). L'estructura for (i in paraules) permet iterar sobre totes les claus d'índex definides d'un array associatiu (en un ordre indefinit, dependent de la implementació).