AWK, cuyo nombre deriva de la primera letra de los apellidos de sus autores Alfred Aho, Peter Weinberger y Brian Kernighan, es un lenguaje de programación que fue diseñado con el objetivo de procesar datos basados sobre texto y una de las primeras herramientas en aparecer en Unix. Utiliza listas en un índice ordenado por cadenas clave (listas asociativas) y expresiones regulares. Es un lenguaje ampliamente utilizado para la programación de guiones ejecutables pues añade funcionalidad a las tuberías en los sistemas operativos tipo POSIX. Está incluido en las instalaciones básicas de prácticamente todas las distribuciones de GNU/Linux.
AWK utiliza un archivo o emisión de ordenes y un archivo o emisión de entrada. El primero indica como procesar al segundo. El archivo de entrada es por lo general texto con algún formato que puede ser un archivo o bien la salida de otro programa.
La sintaxis general para awk utiliza el siguiente patrón:
awk 'expresión-regular { orden }'
Cuando se utiliza awk, éste examina el archivo de entrada y ejecuta la orden cuando encuentra la expresión regular especificada.
El siguiente modelo ejecutaría la orden al inicio del programa y antes de que sean procesados los datos del archivo de entrada:
awk 'BEGIN { orden }'
El siguiente modelo ejecutaría la orden al final del programa y después de que sean procesados los datos del archivo de entrada:
awk 'END { orden }'
El siguiente modelo ejecutaría la orden por cada una de las líneas del archivo de entrada:
awk '{ orden }'
Procedimientos.
Ejecute lo siguiente para específicar que al inicio se imprima en la salida la frase “Hola mundo” y se termine inmediatamente el procesamiento.
awk 'BEGIN { print "Hola mundo"; exit }'
Lo anterior deberá devolver una salida como la siguiente:
Hola mundo
Ejecute lo siguiente para generar al archivo prueba.txt:
echo -e "Columna1\tColumna2\tColumna3\tColumna4\n" > ejemplo.txt
Visulice el contenido del archivo prueba.txt con cat:
cat ejemplo.txt
Devolverá el siguiente contenido:
Columna1 Columna2 Columna3 Columna4
Ejecute lo siguiente para que awk sólo muestre la columna 1 y la columna 3:
awk '{ print $1, $3}' ejemplo.txt
La salida devolverá lo siguiente:
Columna1 Columna3
Ejecute lo siguiente para que awk sólo muestre la columna 3 y la columna 1 —en ese orden:
awk '{ print $3, $1}' ejemplo.txt
La salida devolverá lo siguiente:
Columna3 Columna1
Si se añaden datos al archivo ejemplo.txt del siguiente modo:
echo -e "Dato1\tDato2\tDato3\tDato4\n" >> ejemplo.txt echo -e "Dato5\tDato6\tDato7\tDato8\n" >> ejemplo.txt echo -e "Dato9\tDato10\tDato11\tDato12\n" >> ejemplo.txt
Visualiza con cat y el nombre del archivo como argumento:
cat ejemplo.txt
Devolverá el siguiente contenido:
Columna1 Columna2 Columna3 Columna4 Dato1 Dato2 Dato3 Dato4 Dato5 Dato6 Dato7 Dato8 Dato9 Dato10 Dato11 Dato12
Ejecute lo siguiente para que awk sólo muestre la columna 1 y la columna 3:
awk '{ print $1, $3 }' ejemplo.txt
La salida devolverá lo siguiente:
Columna1 Columna3 Dato1 Dato3 Dato5 Dato7 Dato9 Dato11
Ejecute lo siquiente para que awk sólo muestre la línea cuya columna contenga la expresión regular Dato5:
awk '/Dato5/ { print }' ejemplo.txt
La salida devolverá lo siguiente:
Dato5 Dato6 Dato7 Dato8
Ejecute lo siguiente para que awk sólo muestre la línea cuya columna contenga la expresión regular Dato5 y además sólo las columnas 1 y 4:
awk '/Dato5/ { print $1, $4}' ejemplo.txt
La salida devolverá lo siguiente:
Dato5 Dato8
Ejecute lo siguiente para que awk sólo muestre las líneas con más de 35 caracteres en el archivo /etc/crontab:
awk 'length > 35' /etc/crontab
La salida devolverá algo similar a lo siguiente:
# | | .---------- day of month (1 - 31) # | | | .------- month (1 - 12) OR jan,feb,mar,apr ... # | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat # * * * * * user-name command to be executed
Ejecute lo siguiente para que awk sólo muestre las líneas con menos de 35 caracteres en el archivo /etc/crontab:
awk 'length < 35' /etc/crontab
La salida devolverá algo similar a lo siguiente:
SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root # For details see man 4 crontabs # Example of job definition: # | .------------- hour (0 - 23) # | | | | |
Utilice vi para crear el archivo usuario.txt:
vi usuario.txt
Añada el siguiente contenido:
Fulano Algo Calle Mengana 123 Colonia Perengana Ciudad de Zutano, C.P. 123456
Para que awk reconozca cada línea como un registro completo, en lugar de considerar cada palabra como una columna, se utiliza 'BEGIN { FS=“\n” ; RS=””}', donde el valor de FS (Field Separator o separador de campo) se establece como un retorno de carro y el valor de RS (Record Separator o separador de registro) se establece como una línea vacía. Ejecute lo siguiente para establecer los valores mencionados para FS y RS y se pide se impriman los valores de cada registro (cada línea) separados por una coma y un espacio:
awk 'BEGIN { FS="\n"; RS="" } \
{ print $1 ", " $2 ", " $3 ", " $4 }' usuario.txt
La salida devolverá lo siguiente:
Fulano Algo, Calle Mengana 123, Colonia Perengana, Ciudad de Zutano, C.P. 123456
AWK puede realizar conteo de líneas, palabras y caracteres. Ejecute lo siguiente para establecer que el valor de w sea igual al número de campos (New Field o NF), c sea igual la longitud de cada campo y que se imprima el número de campos, el valor de w y el valor de c:
awk '{ w += NF; c += length } \
END { print \
"Campos: " NR , "\nPalabras: " w, "\nCaracteres: " c }' \
usuario.txt
La salida devolverá lo siguiente:
Campos: 4 Palabras: 12 Caracteres: 74
Genere el archivo numeros.txt con el siguiente contenido, donde las columnas serán separadas por un tabulador:
1 2 3 4 5 6 7 8 9 10 11 12
AWK también puede realizar operaciones matemáticas. Ejecute lo siguiente para establecer que la variable s sea igual a la suma del valor de los campos de la primera columna del archivo numeros.txt e imprime el valor de s:
awk '{ s += $1 } END { print s }' numeros.txt
La salida devolverá lo siguiente —que corresponde al resultado de la suma de 1+5+9:
15
Puede hacerse lo mismo pero con los valores de la columna 2 ejecutando lo siguiente:
awk '{ s += $2 } END { print s }' numeros.txt
La salida devolverá lo siguiente —que corresponde al resultado de la suma 2+6+10:
18
Para hacer conteo de frecuencia de palabras, se establece que el valor para FS (Field Separator o separador de línea) sea igual a expresiones regulares que van desde la letra a hasta la letra z y desde la letra A hasta la letra Z y se establece que el valor de la variable i sea igual a 1 y menor al número de campos.
awk 'BEGIN { FS="[^a-zA-Z]+" } \
{ for (i=1; i<=NF; i++) words[tolower($i)]++ } \
END { for (i in words) print i, words[i] }' /etc/crontab
La salida devolverá algo similar a lo siguiente:
15 job 1 to 1 usr 2 root 1 shell 1 mon 1 hour 1 bin 3 executed 1 name 1 wed 1 fri 1 details 1 of 3 feb 1 week 1 sun 1 path 1 crontabs 1 or 3 be 1 apr 1 definition 1 month 2 sbin 2 tue 1 jan 1 day 2 command 1 for 1 sunday 1 man 1 mar 1 user 1 minute 1 example 1 see 1 bash 1 sat 1 mailto 1 thu 1