El lenguaje AWK

AWK es un lenguaje para procesar ficheros de texto, línea a línea. Resulta apropiado para extraer datos individuales, realizar recuentos, modificar el formato de los datos, generar resúmenes, etc. La potencia del lenguaje reside en el uso extensivo de expresiones regulares para seleccionar los fragmentos de información apropiados, y la posibilidad de combinar los estilos de programación declarativo e imperativo.

En realidad existen distintas variantes de AWK, dependiendo del procesador utilizado:

awk – lenguaje original

awk – POSIX

nawk – AWK renovado

gawk – AWK de GNU

mawk – Mike’s AWK

tawk – AWK de Thompson Automation

…etc. …

En los ejemplos se usará gawk.

Algunas cuestiones básicas

  • Un programa consiste en una colección de cláusulas o reglas, cada una de las cuales sigue el esquema:

patrón { acción }

  • Cada cláusula indica que si se cumple el patrón se debe realizar la correspondiente acción sobre los datos de un fichero o un input de entrada. Por ejemplo:

awk ’/li/ { print $0 }’ listado

imprime todas las líneas que contienen la cadena “li”. print $0 impica toda la linea.

  • El patrón puede omitirse. Es este caso es como si hubiera un patrón que se cumple siempre.

echo uno dos | awk ‘{print $1}’

# uno
echo uno dos | awk ‘{print $2}’
#dos
# Pero que es $0?
echo uno dos | awk ‘{print $0}’
# uno dos
# Todos los campos!

  • La acción puede omitirse. En este caso es como si hubiera una acción {print} (imprimir línea).
  • La ejecución de un programa AWK consiste en leer los ficheros de entrada línea por línea y aplicar a cada línea la colección de cláusulas, por su orden.

Por ejemplo:

  • Imprime las lineas que tienen más de 80 caracteres del fichero data:

awk ’length($0) > 80’ data

  • Imprime siete números aleatorios de 0 a 100:

awk ’BEGIN { for (i = 1; i <= 7; i++) print int(101 * rand()) }’

Con la palabra clave BEGIN, la condición se cumple al principio del programa, antes de leer los datos de entrada.

  • Imprime el número total de bytes usado por un fichero:
    ls -l fichero | awk ’{ x += $5 } END { print “total bytes: ” x }’

Con la palabra clave END, la condición se cumple al final de todo el proceso, después de procesar todos los datos de entrada y justo antes de terminar.

Operadores

Son similares a los del lenguaje C. Los más importantes son:

  • Operadores aritméticos: + – * / % ^
  • Operadores de comparación: == != > >= < <=
  • Operadores de asignación: = += -= *= /=
  • Operadores de incremento o decremento, en sus formas prefija y postfija: ++ —
  • Operadores lógicos: ! && ||
  • Operador de ajuste de patrón: ~
  • La operación de concatenación usa un operador implícito: “uno” “dos” “unodos”
  • También existe la expresión condicional: x ? y : z

Los valores numéricos y de texto son convertidos automáticamente de un tipo a otro cuando sea necesario. Cuando se quiera forzar una conversión se puede escribir:

  • x + 0 →valor de x convertido a tipo numérico
  • x “” →valor de x convertido a texto

 Funciones predefinidas

Entre otras, las siguientes:

  • Funciones matemáticas (numéricas): sqrt(), sin(), cos(), exp(), …
  • Funciones de texto: length(), substr(), index(), toupper(), tolower(), gsub(), match(), …
  • Otras funciones: system(), getline, systime(), …

Campos en las líneas de entrada

Cada línea de texto de la entrada se descompone automáticamente en campos. Por defecto, los campos se separan por espacio en blanco. Los campos pueden referenciarse por separado, mediante el operador $.

  • $n →n-simo campo
  • $0 →toda la línea
  • $expresión →la referencia a un campo puede ser calculada

Ejemplo:

  • $0 = “ejemplo de línea de texto”
  • $1 = “ejemplo”
  • $2 = “de”
  • $3 = “línea”
  • $4 = “de”
  • $5 = “texto”
  • k = 3 $k = “línea”

Variables simples

Una variable simple puede contener un valor numérico o de texto. Las variables no se declaran, simo que empiezan a existir cuando se usan por primera vez. Inicialmente tienen valor nulo.

Variables simples predefinidas

Existen variables predefinidas que sirven de comunicación entre el código del usuario y el propio intérprete de AWK. Entre otras las siguientes:

  • NF →número de campos
  • NR →número de la línea (global, aunque haya varios ficheros de entrada)
  • FNR →número de la línea (local al fichero)
  • FILENAME →nombre del fichero actual

Las variables anteriores toman valor automáticamente con cada línea. Otras variables son asignadas por el usuario para controlar el funcionamiento del intérprete. Por ejemplo:

  • FS →separador de campos de entrada (por defecto ” “)
  • RS →separador de líneas de entrada (por defecto “\n”)
  • OFS →separador de campos en la salida (por defecto ” “)
  • ORS →separador de líneas en la salida (por defecto “\n”)

Acciones

Las acciones son sentencias o secuencias de sentencias que se escriben como en lenguaje C. El código de una sentencia termina implícitamente con el fin de línea o explícitamente con punto y coma (;). Algunas sentencias de uso frecuente son:

Sentencia Significado
var = expresión asignación de valor a una variable
expresión evaluación de la expresión (la asignación anterior es realmente un caso particular de expresión, usando el operador de asignación)
if (condición) acción acción condicional
if (condición) acción else acción acciones alternativas
while (condición) acción bucle WHILE
for (k=ini; k<=fin; k++) acción-con-k bucle FOR (como en C)
{ sentencia; sentencia … } acción compuesta
print expresión, expresión … imprime valores separados por espacio en blanco
print equivale a print $0
printf( formato, expresión, expresión … ) impresión con formato (como en C)
print … > fichero redirige la salida al fichero
getline variable < fichero lee explícitamente una línea de un fichero
close( fichero ) libera el fichero
next termina el proceso de la línea de entrada actual
exit termina la lectura de la entrada y da control a las acciones END (o bien termina definitivamente)