Archivos en la Categoría: awk

Un Tutorial de AWK

EL PRIMER PROGRAMA EN AWK
Los usuarios de las computadoras pasan mucho tiempo realizando tareas de manipulación de datos que son mecánicas y laboriosas, cambiando el formato de un archivo, encontrando elementos con cierta característica, añadiendo números, etc., y sin embargo sería impensable realizar un programa en C o Pascal para realizar esas tareas cada vez que se presentan.
Más o menos con estas palabras presentan Alfred V. Aho, Brian W. Kernighan y Peter J. Weinberger su libro The AWK Programming Language. Esta entrada, que se corresponde con los temas y la estructura de el primer capítulo, está basada principalmente en ese libro. El lenguaje AWK fue creado para realizar esas tareas.

Supongamos que tenemos un archivo llamado ArchivoAwk.dat con el contenido siguiente:

Jose    4.00   0
Pedro   7.00   1
Rosa   23.30   5
Maria  28.10   6
Juan   29.32   0

ArchivoAwk.dat contiene los nombres de 5 personas (Jose, Pedro, Rosa, Maria, Juan), el salario por hora que recibien (4.00, 7.00, 23.30, 28.10, 29.32) y el número de horas que han trabajado (0, 1, 5, 6, 0). El lenguaje de programación AWK sólo reconoce esos dos tipos de datos: números y cadenas de caracteres. Supongamos que queremos imprimir el nombre y el salario total (número de horas por el salario por hora) de todas las personas que laboraron más de 0 horas. Ese es el tipo de trabajo para el que AWK está hecho. Basta con escribir lo siguiente en la consola:

awk '$3 > 0 {print $1, $2 * $3}' ArchivoAwk.dat

Y se obtendrá como salida

Pedro 7
Rosa 116.5
Maria 168.6

La instrucción consta de 3 elementos: 1) una llamada al comando Unix AWK, 2) un programa y 3) el archivo de entrada.
1) basta con imprimir el comando awk
2) Todo lo que está contenido dentro de las comillas simples (‘) es el programa en AWK
3) El archivo se enlaza simplemente escribiendo su nombre o ruta completa.
La llamada a AWK y al archivo no tienen mayor complicación. El programa requiere una explicación adicional.
La primera parte es un condicional. La condición en lenguaje humano es:

¿Es el valor de la columna 3 mayor que 0?

La condición en lenguaje AWK es

 $3 > 0 

Para hacer referencia a una columna usamos el signo de peso $. Así, $3 hace referencia a la columna 3, $1 hace referencia a la columna 1; $0 hace referencia a TODA la línea. En particular $3 a lo que vale la columna 3 en el renglón actual.
Lo que viene a continuación (encerrado entre llaves) es lo que ha de realizarse en caso de que la condición se cumpla:

{print $1, $2 * $3}

La instrucción print (imprimir, en inglés) es clara. Se debe imprimir algo. ¿Qué se imprime? Lo que viene justo a continuación, es decir, el valor de la columna 1, o sea el nombre del trabajador y el salario, el cual es el producto del salario por hora (columna 2) por el número de horas (columna 3). En AWK el signo para indicar multiplicación es el asterisco (*). La coma que aparece justo después de el número 1, indica que ha de dejarse un espacio en blanco entre el valor de la columna 1 y el producto de las columnas 2 y 3. AWK repite la instrucción entre corchetes para todas las líneas del archivo, por lo tanto el resultado desplegado arriba muestra, como queríamos, el salario de los trabajadores que sí recibirán una paga.
¿Que pasa si más bien queremos imprimir los nombres de las personas que no recibirán salario?
Basta con escribir lo siguiente:

awk '$3 == 0 {print $1}' ArchivoAwk.dat

lo cual da como salida

Jose
Juan

De nuevo, esta instrucción consta de tres partes: 1) La llamada a awk, 2) el programa y 3) el archivo
Tanto 1) como 2) son fáciles de llamar y enlazar. 3) Requiere de una explicación.
El programa en AWK es todo lo que aparece encerrado entre comillas simples (‘). Ese programa a su vez está dividido en 2 partes, un condicional y una instrucción. La condición es, en lenguaje humano

¿Es el valor de la columna 3 igual a 0?

Y esa instrucción, convertida a lenguaje AWK es

 $3 == 0 

Ya hemos visto que para hacer referencia a una columna, necesitamos usar el símbolo de pesos $. El número 3 nos dice que se trata de la tercera. Lo siguiente es también claro, el signo doble igual (==) se usa en muchos lenguajes de programación (C y derivados, por ejemplo) para indicar comparación, por contraposición a el simple igual (=), que se usa para asignación. Muchos problemas pueden surgir si se se confunden los signos = y == en esos lenguajes. Tantos problemas causa esa confusión, que el creador de Pascal, un lenguaje diseñado para estudiantes, decidió que las asignaciones, en ese lenguaje, deberían de hacerse con el símbolo :=, lo cual evita estos errores sutiles. AWK usa == para comparaciones. Así pues, la instrucción en AWK equivale a la instrucción en español.
Si tenemos además otro archivo llamado ArchivoAwk2.dat con otra lista de trabajadores y salarios similar a la anterior

Ernesto  12    0
Raquel    5    3
Gabriela  3    5
Carolina  3    8

podemos imprimir los salarios para las dos listas simplemente con modificar la llamada:

awk '$3 >0 {print $1, $2*$3}' ArchivoAwk.dat ArchivoAwk2.dat

y la salida que se obtiene es

Pedro 7
Rosa 116.5
María 168.6
Raquel 15
Gabriela 15
Carolina 24

PARA EJECUTAR UN PROGRAMA EN AWK

Hay varias formas:
Escribiendo en línea de comandos una orden del tipo

awk 'programa' archivos de entrada

Escribiendo la misma orden, pero sin archivos de entrada:

awk 'programa'

En este caso el programa se ejecutará sobre todo lo que se teclee a continuación hasta la aparición de una tecla de fin de archivo (EOF) Ctrl + d para los Unix.
Creando un archivo que contenga el programa.
Si el programa es chico, entonces es práctico escribirlo directamente en la línea de comandos, mientras que si se trata de un programa grande, conviene escribirlo en un editor de texto y guardarlo en un archivo con un nombre arbitrario. Supongamos que queremos guardar el programa anterior en un archivo llamado Programa.awk (el nombre es totalmente arbitrario, y la extensión también. Yo uso .awk para fines de administración solamente) Ese archivo contiene lo que antes pusimos entre comillas simples ‘.

$3 >0 {print $1, $2*$3}

Para ejecutarlo necesitamos simplemente escribir la siguiente línea:

awk -f Programa.awk ArchivoAwk.dat

Esta instrucción consta de 3 partes principales 1) la llamada a awk, 2) la llamada al código fuente del programa y 3) El enlace al archivo que queremos analizar.
1) y 3) ya son conocidos. 2) Requiere una explicación.
Para llamar al código fuente simplemente debemos agregar la opción -f antes del nombre del archivo que contiene el código. La opción -f avisa que el programa se recibirá de un archivo, y no de la línea de comandos. Eso es todo. El resultado es el mismo que se presenta arriba.
IMPRESIONES SIMPLES
Como se ha dicho, AWK sólo tiene dos tipos de datos: números y cadenas de caracteres. Cada línea es separada por AWK en campos, siendo cada campo el número o la cadena completa que aparecen sin un espacio en blanco de por medio.
IMPRIMIR CADA LÍNEA
Con la simple instrucción print en el cuerpo del programa, se presentan todas las líneas del archivo

 awk '{print}' ArchivoAwk.dat

Otra forma de imprimir cada línea completa es mediante la referencia al campo $0, que como vimos es el nombre de toda la línea.

awk '{print $0}' ArchivoAwk.dat

En ambos casos el resultado es el mismo:

Jose    4.00   0
Pedro   7.00   1
Rosa   23.30   5
Maria  28.10   6
Juan   29.32   0

IMPRESIÓN DE ALGUNOS CAMPOS
Es posible imprimir sólo algunos campos de la línea, por ejemplo la columna 1 y la columna 3 mediante la instrucción:

awk '{print $1, $3}' ArchivoAwk.dat

la cual produce la salida

Jose 0
Pedro 1
Rosa 5
Maria 6
Juan 0

Es bueno recordar que la coma después del 1 deja un espacio en blanco. En caso de faltar, las dos columnas aparecerían juntas.
NF, EL NÚMERO DE CAMPOS
Awk cuenta el número de columnas de la presente línea y lo almacena en una variable llamada NF.
Por ejemplo, si el ArchivoAwk.awk

Jose    4.00   0
Pedro   7.00   1
Rosa   23.30   5
Maria  28.10   6
Juan   29.32   0

aplicamos el código

awk -f'{print NF,$NF}' ArchivoAwk.dat

el resultado es:

3 0
3 1
3 5
3 6
3 0

En cada caso presentando el número de columnas de cada línea y a continuación el último elemento.
NR, EL NÚMERO DE lÍNEA
La variable NR guarda el número de línea actual. Como ejemplo, en el ArchivoAwk.dat se puede indicar el número de renglón mediante la línea

awk '{printf NR, $0}' ArchivoAwk.dat

y se produce la salida

1 Jose    4.00   0
2 Pedro   7.00   1
3 Rosa   23.30   5
4 Maria  28.10   6
5 Juan   29.32   0

IMPRESIÓN DE TEXTO
La línea

awk '{print "El pago total para " $1 " es: " $2*$3}' ArchivoAwk.dat

imprime:

El pago total para Jose es: 0
El pago total para Pedro es: 7
El pago total para Rosa es: 116.5
El pago total para Maria es: 168.6
El pago total para Juan es: 0

Así que para imprimir una cadena con print es necesario incluir la cadena entre comillas.
IMPRESIÓN CON FORMATO
La siguiente línea es un ejemplo de uso de la instrucción printf

awk '{printf("El pago total para %s es: %.2f\n", $1, $2*$3)}' ArchivoAwk.dat

y el resultado es el siguiente:

El pago total para Jose es: 0.00
El pago total para Pedro es: 7.00
El pago total para Rosa es: 116.50
El pago total para Maria es: 168.60
El pago total para Juan es: 0.00

El formato de printf es muy parecido a el que tiene en el lenguaje de Programación C:
Todas las cadenas que aparezcan dentro de las comillas dobles se imprimen literalmente. Las excepciones son las secuencias de escape (\n, salto de línea). %s hace referencia a la cadena que se encuentra en la columna 1, $1; %.2f hace referencia a que se imprimirá un número flotante con 2 decimales después del punto ($2*$3).

Anuncios