Awk es el omnipresente comando de Unix para escanear y procesar texto que contiene patrones predecibles. Sin embargo, debido a que presenta funciones, también se le llama lenguaje de programación.
Confusamente, hay más de un awk. (O, si cree que solo puede haber uno, entonces hay varios clones). Hay awk , el programa original escrito por Aho, Weinberger y Kernighan, y luego está nawk , mawk , y la versión GNU, gawk . La versión GNU de awk es una versión de software gratuito altamente portátil de la utilidad con varias características únicas, por lo que este artículo trata sobre GNU awk.
Si bien su nombre oficial es gawk, en los sistemas GNU+Linux tiene el alias de awk y sirve como la versión predeterminada de ese comando. En otros sistemas que no incluyen GNU awk, debe instalarlo y referirse a él como gawk, en lugar de awk. Este artículo usa los términos awk y gawk indistintamente.
Al ser tanto un comando como un lenguaje de programación, awk es una herramienta poderosa para tareas que de otro modo podrían quedar para ordenar , cortar , uniq y otras utilidades comunes. Afortunadamente, hay mucho espacio en el código abierto para la redundancia, por lo que si se enfrenta a la pregunta de si debe usar awk o no, la respuesta es probablemente un sólido "tal vez".
La belleza de la flexibilidad de awk es que si ya se comprometió a usar awk para una tarea, entonces probablemente pueda permanecer en awk sin importar lo que surja en el camino. Esto incluye la eterna necesidad de clasificar los datos de una manera diferente a la orden en que se le entregó.
Conjunto de muestra
Antes de explorar los métodos de clasificación de awk, genere un conjunto de datos de muestra para usar. Manténgalo simple para que no se distraiga con los casos extremos y la complejidad no deseada. Este es el conjunto de muestra que utiliza este artículo:
Aptenodytes;forsteri;Miller,JF;1778;Emperor
Pygoscelis;papua;Wagler;1832;Gentoo
Eudyptula;minor;Bonaparte;1867;Little Blue
Spheniscus;demersus;Brisson;1760;African
Megadyptes;antipodes;Milne-Edwards;1880;Yellow-eyed
Eudyptes;chrysocome;Viellot;1816;Sothern Rockhopper
Torvaldis;linux;Ewing,L;1996;Tux
Es un conjunto de datos pequeño, pero ofrece una buena variedad de tipos de datos:
- Un nombre de género y especie, que están asociados entre sí pero se consideran separados
- Un apellido, a veces con las primeras iniciales después de una coma
- Un número entero que representa una fecha
- Un término arbitrario
- Todos los campos separados por punto y coma
Dependiendo de su formación académica, puede considerar esto como una matriz 2D o una tabla o simplemente como una colección de datos delimitada por líneas. Lo que pienses depende de ti, porque awk no espera nada más que texto. Depende de ti decirle awk cómo quieres analizarlo.
El truco de clasificación
Si solo desea ordenar un conjunto de datos de texto por un campo específico y definible (piense en una "celda" en una hoja de cálculo), puede usar el comando ordenar.
Campos y registros
Independientemente del formato de su entrada, debe encontrar patrones en ella para que pueda concentrarse en las partes de los datos que son importantes para usted. En este ejemplo, los datos están delimitados por dos factores:líneas y campos. Cada nueva línea representa un nuevo registro , como probablemente vería en una hoja de cálculo o en un volcado de base de datos. Dentro de cada línea, hay distintos campos (piense en ellas como celdas en una hoja de cálculo) que están separadas por punto y coma (;).
Awk procesa un registro a la vez, por lo que mientras estructura las instrucciones que le dará a awk, puede concentrarse en una sola línea. Establezca lo que quiere hacer con una línea, luego pruébelo (ya sea mentalmente o con awk) en la siguiente línea y algunas más. Terminará con una buena hipótesis sobre lo que debe hacer su secuencia de comandos awk para proporcionarle la estructura de datos que desea.
En este caso, es fácil ver que cada campo está separado por un punto y coma. En aras de la simplicidad, suponga que desea ordenar la lista por el primer campo de cada línea.
Antes de que pueda ordenar, debe poder enfocarse solo en el primer campo de cada línea, así que ese es el primer paso. La sintaxis de un comando awk en una terminal es awk , seguido de las opciones relevantes, seguido de su comando awk y terminando con el archivo de datos que desea procesar.
$ awk --field-separator=";" '{print $1;}' penguins.list
Aptenodytes
Pygoscelis
Eudyptula
Spheniscus
Megadyptes
Eudyptes
Torvaldis
Debido a que el separador de campo es un carácter que tiene un significado especial para el shell de Bash, debe encerrar el punto y coma entre comillas o precederlo con una barra invertida. Este comando es útil solo para demostrar que puede concentrarse en un campo específico. Puede probar el mismo comando usando el número de otro campo para ver el contenido de otra "columna" de sus datos:
$ awk --field-separator=";" '{print $3;}' penguins.list
Miller,JF
Wagler
Bonaparte
Brisson
Milne-Edwards
Viellot
Ewing,L
Aún no se ha solucionado nada, pero este es un buen trabajo preliminar.
Secuencias de comandos
Awk es más que un simple comando; es un lenguaje de programación con índices, matrices y funciones. Eso es significativo porque significa que puede tomar una lista de campos por los que desea ordenar, almacenar la lista en la memoria, procesarla y luego imprimir los datos resultantes. Para una serie compleja de acciones como esta, es más fácil trabajar en un archivo de texto, así que cree un nuevo archivo llamado sorter.awk e introduce este texto:
#!/usr/bin/awk -f
BEGIN {
FS=";";
}
Esto establece el archivo como un script awk que ejecuta las líneas contenidas en el archivo.
El COMIENZO La declaración es una función de configuración especial proporcionada por awk para tareas que deben ocurrir solo una vez. Definición de la variable integrada FS , que significa separador de campo y es el mismo valor que estableció en su comando awk con --field-separator , solo debe ocurrir una vez, por lo que se incluye en BEGIN declaración.
Matrices en awk
Ya sabe cómo recopilar los valores de un campo específico utilizando el $ notación junto con el número de campo, pero en este caso, debe almacenarlo en una matriz en lugar de imprimirlo en la terminal. Esto se hace con una matriz awk. Lo importante de una matriz awk es que contiene claves y valores. Imagina una matriz sobre este artículo; se vería así:autor:"seth",título:"Cómo ordenar con awk",longitud:1200 . Elementos como autor y título y longitud son claves, con los siguientes contenidos siendo valores.
La ventaja de esto en el contexto de la clasificación es que puede asignar cualquier campo como clave y cualquier registro como valor, y luego usar la función awk incorporada asorti() (ordenar por índice) para ordenar por clave. Por ahora, asuma arbitrariamente que solo desea ordenar por el segundo campo.
Declaraciones Awk no precedida por las palabras clave especiales BEGIN o FIN son bucles que ocurren en cada registro. Esta es la parte del script que escanea los datos en busca de patrones y los procesa en consecuencia. Cada vez que awk dirige su atención a un registro, las declaraciones en {} (a menos que esté precedido por BEGIN o FIN ) se ejecutan.
Para agregar una clave y un valor a una matriz, cree una variable (en este script de ejemplo, lo llamo ARRAY , que no es muy original, pero sí muy claro) que contiene una matriz, y luego le asigna una clave entre paréntesis y un valor con un signo igual (= ).
{ # dump each field into an array
ARRAY[$2] = $R;
}
En esta declaración, el contenido del segundo campo ($2 ) se utilizan como término clave y el registro actual ($R ) se utiliza como valor.
La función asorti()
Además de las matrices, awk tiene varias funciones básicas que puede usar como soluciones rápidas y sencillas para tareas comunes. Una de las funciones introducidas en GNU awk, asorti() , ofrece la posibilidad de ordenar una matriz por clave (o índice ) o valor.
Solo puede ordenar la matriz una vez que se haya completado, lo que significa que esta acción no debe ocurrir con cada registro nuevo, sino solo en la etapa final de su secuencia de comandos. Para este propósito, awk proporciona el FIN especial palabra clave. Lo contrario de COMENZAR , un FIN declaración ocurre solo una vez y solo después de que se hayan escaneado todos los registros.
Agregue esto a su secuencia de comandos:
END {
asorti(ARRAY,SARRAY);
# get length
j = length(SARRAY);
for (i = 1; i <= j; i++) {
printf("%s %s\n", SARRAY[i],ARRAY[SARRAY[i]])
}
}
El asorti() función toma el contenido de ARRAY , lo ordena por índice y coloca los resultados en una nueva matriz llamada SARRAY (un nombre arbitrario que inventé para este artículo, que significa ARRAY ordenado ).
A continuación, la variable j (otro nombre arbitrario) se le asignan los resultados de la longitud() función, que cuenta el número de elementos en SARRAY .
Finalmente, use un para bucle para iterar a través de cada elemento en SARRAY usando printf() función para imprimir cada clave, seguida del valor correspondiente de esa clave en ARRAY .
Ejecutando el script
Para ejecutar su script awk, hágalo ejecutable:
$ chmod +x sorter.awk
Y luego ejecútelo contra penguin.list datos de muestra:
$ ./sorter.awk penguins.list
antipodes Megadyptes;antipodes;Milne-Edwards;1880;Yellow-eyed
chrysocome Eudyptes;chrysocome;Viellot;1816;Sothern Rockhopper
demersus Spheniscus;demersus;Brisson;1760;African
forsteri Aptenodytes;forsteri;Miller,JF;1778;Emperor
linux Torvaldis;linux;Ewing,L;1996;Tux
minor Eudyptula;minor;Bonaparte;1867;Little Blue
papua Pygoscelis;papua;Wagler;1832;Gentoo
Como puede ver, los datos están ordenados por el segundo campo.
Esto es un poco restrictivo. Sería mejor tener la flexibilidad de elegir en tiempo de ejecución qué campo desea usar como su clave de clasificación para que pueda usar este script en cualquier conjunto de datos y obtener resultados significativos.
Agregar opciones de comando
Puede agregar una variable de comando a un script awk usando el valor literal var en tu guión. Cambie su secuencia de comandos para que su cláusula iterativa use var al crear su matriz:
{ # dump each field into an array
ARRAY[$var] = $R;
}
Intente ejecutar el script para que ordene por el tercer campo usando -v var opción cuando lo ejecutas:
$ ./sorter.awk -v var=3 penguins.list
Bonaparte Eudyptula;minor;Bonaparte;1867;Little Blue
Brisson Spheniscus;demersus;Brisson;1760;African
Ewing,L Torvaldis;linux;Ewing,L;1996;Tux
Miller,JF Aptenodytes;forsteri;Miller,JF;1778;Emperor
Milne-Edwards Megadyptes;antipodes;Milne-Edwards;1880;Yellow-eyed
Viellot Eudyptes;chrysocome;Viellot;1816;Sothern Rockhopper
Wagler Pygoscelis;papua;Wagler;1832;Gentoo
Arreglos
Este artículo ha demostrado cómo ordenar datos en GNU awk puro. La secuencia de comandos se puede mejorar, así que, si le resulta útil, dedique algún tiempo a investigar las funciones de awk en la página de manual de gawk y personalice la secuencia de comandos para obtener mejores resultados.
Aquí está el guión completo hasta el momento:
#!/usr/bin/awk -f
# GPLv3 appears here
# usage: ./sorter.awk -v var=NUM FILE
BEGIN { FS=";"; }
{ # dump each field into an array
ARRAY[$var] = $R;
}
END {
asorti(ARRAY,SARRAY);
# get length
j = length(SARRAY);
for (i = 1; i <= j; i++) {
printf("%s %s\n", SARRAY[i],ARRAY[SARRAY[i]])
}
}