Una guía para principiantes de Gawk

quedarse sin palabras es la implementación GNU de Awk Lenguaje de programación, desarrollado por primera vez para el sistema operativo UNIX en la década de 1970. El lenguaje de programación Awk se especializa en manejar datos de formato en archivos de texto, especialmente datos de texto organizados en columnas.
Usando el lenguaje de programación Awk, puede manipular o extraer datos, generar informes, combinar modelos, realizar cálculos, etc. con gran flexibilidad. Awk le permite realizar tareas algo difíciles con solo una línea de código. Lograr los mismos resultados usando lenguajes de programación tradicionales como C o Python requeriría un esfuerzo adicional y muchas líneas de código.
gawk
También hace referencia a la utilidad de línea de comandos disponible de forma predeterminada con la mayoría de las distribuciones de Linux. La mayoría de las distribuciones también proporcionan un enlace simbólico para awk
apuntando a gawk
. En aras de la simplicidad, de ahora en adelante, nos referiremos a la utilidad solo como awk
.
awk
procesa datos directamente desde la entrada estándar - STDIN. Un patrón común es canalizar la salida de otros programas hacia awk
para extraer e imprimir datos, pero awk
también puede procesar datos de archivos.
En este artículo usarás awk
para analizar datos en un archivo con columnas separadas por espacios. Comencemos mirando los datos de muestra.
Data de muestra
Para los ejemplos de esta guía, usemos la salida del comando ps ux
guardado en archivo psux.out
. Aquí hay un ejemplo de los datos en el archivo:
$ head psux.out
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
ricardo 1446 0.0 0.2 21644 11536 ? Ss Sep10 0:00 /usr/lib/systemd/systemd --user
ricardo 1448 0.0 0.1 49212 5848 ? S Sep10 0:00 (sd-pam)
ricardo 1459 0.0 0.1 447560 7148 ? Sl Sep10 0:00 /usr/bin/gnome-keyring-daemon --daemonize --login
ricardo 1467 0.0 0.1 369144 6080 tty2 Ssl+ Sep10 0:00 /usr/libexec/gdm-wayland-session /usr/bin/gnome-session
ricardo 1469 0.0 0.1 277692 4112 ? Ss Sep10 0:00 /usr/bin/dbus-broker-launch --scope user
ricardo 1471 0.0 0.1 6836 4408 ? S Sep10 0:00 dbus-broker --log 4 --controller 11 --machine-id 16355057c7274843823dd747f8e2978b --max-bytes 100000000000000 --max-fds 25000000000000 --max-matches 5000000000
ricardo 1474 0.0 0.3 467744 14132 tty2 Sl+ Sep10 0:00 /usr/libexec/gnome-session-binary
ricardo 1531 0.0 0.1 297456 4280 ? Ssl Sep10 0:00 /usr/libexec/gnome-session-ctl --monitor
ricardo 1532 0.0 0.3 1230908 12920 ? S<sl Sep10 0:01 /usr/bin/pulseaudio --daemonize=no
Puede descargar el archivo completo desde aquí, usando este comando:
$ curl -o psux.out https://gitlab.com/-/snippets/2013935/raw?inline=false
Si decide utilizar la salida de ps ux
en su sistema, ajuste los valores que se muestran en los ejemplos para que coincidan con sus resultados.
Entonces usemos awk
para mostrar los datos del archivo de muestra.
Uso básico
Un basico awk
El programa consta de un patrón seguido de una acción rodeada de llaves. Puede proporcionar un horario para awk
utilidad en línea encerrándola entre comillas simples, así:
$ awk 'pattern { action }'
awk
procesa los datos de entrada (entrada estándar o archivo) fila por fila, realizando la acción dada para cada fila o registro que coincida con el patrón. Si se omite el patrón, awk
realiza la acción en todos los registros. Una acción puede ser tan simple como imprimir datos de fila o tan compleja como un programa completo. Por ejemplo, para imprimir todas las líneas del archivo de muestra, use este comando:
$ awk '{ print }' psux.out
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
ricardo 1446 0.0 0.2 21644 11536 ? Ss Sep10 0:00 /usr/lib/systemd/systemd --user
.... OUTPUT TRUNCATED ....
Aunque este ejemplo no es realmente útil, ilustra la awk
uso básico del comando.
Si usas el comando ps ux
en su máquina, puede dirigir su salida directamente a awk
, en lugar de proporcionar el nombre del archivo de entrada:
$ ps ux | awk '{ print }'
Entonces usemos awk
Capacidades de procesamiento de columnas para extraer parte de los datos del archivo de muestra.
Imprimir campos
El poder de awk
comienza a ser evidente cuando utiliza sus funciones de procesamiento de columnas. awk
divide automáticamente cada fila (o registro) en campos. Por defecto, utiliza el espacio carácter para separar cada campo, pero puede cambiar esto proporcionando el parámetro de línea de comando -F
seguido del separador deseado.
Después de la separación, awk
asigna a cada campo una variable numerada, comenzando con el carácter $
. Por ejemplo, el primer campo es $1
, la segunda $2
, etc La variable especial $0
contiene toda la grabación antes de dividirla.
Mediante el uso de variables de campo, puede extraer datos de la entrada. Por ejemplo, para imprimir solo el nombre del comando del archivo de muestra, use la variable $11
porque el nombre del comando es la undécima columna de cada fila:
$ awk '{ print $11 }' psux.out
COMMAND
/usr/lib/systemd/systemd
(sd-pam)
/usr/bin/gnome-keyring-daemon
.... OUTPUT TRUNCATED ....
También puede imprimir varios campos separados por comas. Por ejemplo, para imprimir el nombre del comando y el uso de la CPU en la columna tres, use este comando:
$ awk '{ print $11, $3 }' psux.out
COMMAND %CPU
/usr/lib/systemd/systemd 0.0
(sd-pam) 0.0
/usr/bin/gnome-keyring-daemon 0.0
.... OUTPUT TRUNCATED ....
Finalmente, utilice el printf
para formatear la salida y alinear las columnas. Proporcione un relleno de 40 caracteres a la derecha de las primeras columnas para acomodar nombres de comando más largos:
$ awk '{ printf("%-40s %sn", $11, $3) }' psux.out
COMMAND %CPU
/usr/lib/systemd/systemd 0.0
(sd-pam) 0.0
/usr/bin/gnome-keyring-daemon 0.0
/usr/libexec/gdm-wayland-session 0.0
.... OUTPUT TRUNCATED ....
Ahora que puede manipular y extraer campos individuales de cada registro, apliquemos la función de plantilla para filtrar los registros.
Coincidencia de patrones
Además de manipular campos, awk
le permite filtrar los registros en los que realizar acciones con una potente función de coincidencia de patrones. En su uso más básico, proporcione una expresión regular rodeada por una barra inclinada /
caracteres para hacer coincidir los registros. Por ejemplo, para filtrar por registros que coincidan, use /firefox/
:
$ awk '/firefox/ { print $11, $3 }' psux.out
/usr/lib64/firefox/firefox 66.2
/usr/lib64/firefox/firefox 8.3
/usr/lib64/firefox/firefox 15.6
/usr/lib64/firefox/firefox 9.0
/usr/lib64/firefox/firefox 31.5
/usr/lib64/firefox/firefox 20.6
/usr/lib64/firefox/firefox 31.0
/usr/lib64/firefox/firefox 0.0
/usr/lib64/firefox/firefox 0.0
/usr/lib64/firefox/firefox 0.0
/usr/lib64/firefox/firefox 0.0
/usr/lib64/firefox/firefox 0.0
/usr/lib64/firefox/firefox 0.0
También puede utilizar campos y una expresión de comparación como criterios de coincidencia de patrones. Por ejemplo, para imprimir datos de proceso que coincidan con PID 6685, compare el campo $2
, así:
$ awk '$2==6685 { print $11, $3 }' psux.out
/usr/lib64/firefox/firefox 0.0
awk
es lo suficientemente inteligente como para comprender los campos numéricos, lo que le permite usar comparaciones relativas como mayor que o menor que. Por ejemplo, para mostrar todos los procesos usando over, use $3 > 5
:
$ awk '$3 > 5 { print $11, $3 }' psux.out
/usr/bin/gnome-shell 5.1
/usr/lib64/firefox/firefox 66.2
/usr/lib64/firefox/firefox 8.3
/usr/lib64/firefox/firefox 15.6
/usr/lib64/firefox/firefox 9.0
/usr/lib64/firefox/firefox 31.5
/usr/lib64/firefox/firefox 20.6
/usr/lib64/firefox/firefox 31.0
Puede combinar modelos con operadores. Por ejemplo, para mostrar todos los procesos que coinciden y usan, combine los dos modelos con el &&
operador para una lógica AND
:
$ awk '/firefox/ && $3 > 5 { print $11, $3 }' psux.out
/usr/lib64/firefox/firefox 66.2
/usr/lib64/firefox/firefox 8.3
/usr/lib64/firefox/firefox 15.6
/usr/lib64/firefox/firefox 9.0
/usr/lib64/firefox/firefox 31.5
/usr/lib64/firefox/firefox 20.6
/usr/lib64/firefox/firefox 31.0
Finalmente, debido a que está utilizando la coincidencia de patrones, awk
ya no imprime la fila del encabezado. Puede agregar su propia fila de encabezado usando el BEGIN
plantilla para realizar una sola acción antes de procesar los registros:
$ awk 'BEGIN { printf("%-26s %sn", "Command", "CPU%")} $3 > 10 { print $11, $3 }' psux.out
Command CPU%
/usr/lib64/firefox/firefox 66.2
/usr/lib64/firefox/firefox 15.6
/usr/lib64/firefox/firefox 31.5
/usr/lib64/firefox/firefox 20.6
/usr/lib64/firefox/firefox 31.0
A continuación, manipulemos los datos en campos individuales.
Manipulación de campo
Como vimos en el apartado anterior, awk
incluye campos numéricos. Esto le permite realizar la manipulación de datos, incluidos los cálculos numéricos. Por ejemplo, considere imprimir el uso de memoria en la columna seis para todos los procesos:
$ awk '/firefox/ { print $11, $6 }' psux.out
/usr/lib64/firefox/firefox 301212
/usr/lib64/firefox/firefox 118220
/usr/lib64/firefox/firefox 168468
/usr/lib64/firefox/firefox 101520
/usr/lib64/firefox/firefox 194336
/usr/lib64/firefox/firefox 111864
/usr/lib64/firefox/firefox 163440
/usr/lib64/firefox/firefox 38496
/usr/lib64/firefox/firefox 174636
/usr/lib64/firefox/firefox 37264
/usr/lib64/firefox/firefox 30608
/usr/lib64/firefox/firefox 174636
/usr/lib64/firefox/firefox 174660
El comando ps ux
muestra el uso de memoria en kilobytes, que es difícil de leer. Convirtámoslo a megabytes sumergiendo el valor del campo a 1024:
$ awk '/firefox/ { print $11, $6/1024 }' psux.out
/usr/lib64/firefox/firefox 294.152
/usr/lib64/firefox/firefox 115.449
/usr/lib64/firefox/firefox 164.52
/usr/lib64/firefox/firefox 99.1406
/usr/lib64/firefox/firefox 189.781
/usr/lib64/firefox/firefox 109.242
/usr/lib64/firefox/firefox 159.609
/usr/lib64/firefox/firefox 37.5938
/usr/lib64/firefox/firefox 170.543
/usr/lib64/firefox/firefox 36.3906
/usr/lib64/firefox/firefox 29.8906
/usr/lib64/firefox/firefox 170.543
/usr/lib64/firefox/firefox 170.566
También puede redondear los números y agregar el sufijo usando printf
para mejorar la legibilidad:
$ awk '/firefox/ { printf("%s %4.0f MBn", $11, $6/1024) }' psux.out
/usr/lib64/firefox/firefox 294 MB
/usr/lib64/firefox/firefox 115 MB
/usr/lib64/firefox/firefox 165 MB
/usr/lib64/firefox/firefox 99 MB
/usr/lib64/firefox/firefox 190 MB
/usr/lib64/firefox/firefox 109 MB
/usr/lib64/firefox/firefox 160 MB
/usr/lib64/firefox/firefox 38 MB
/usr/lib64/firefox/firefox 171 MB
/usr/lib64/firefox/firefox 36 MB
/usr/lib64/firefox/firefox 30 MB
/usr/lib64/firefox/firefox 171 MB
/usr/lib64/firefox/firefox 171 MB
Finalmente, combina esta idea con la BEGIN
y END
modelos para realizar una manipulación de datos más avanzada. Por ejemplo, calculemos el uso total de memoria para todos los procesos configurando una variable suma en el BEGIN
acción, sumando el valor de la columna seis $6
por cada fila que coincida con el suma variable, luego imprímala con el END
acción en megas:
$ awk 'BEGIN { sum=0 } /firefox/ { sum+=$6 } END { printf("Total Firefox memory: %.0f MBn", sum/1024) }' psux.out
Total Firefox memory: 1747 MB
¿Y después?
gawk
es una herramienta poderosa y flexible para procesar datos textuales, especialmente datos organizados en columnas. Este artículo ha proporcionado algunos ejemplos útiles del uso de esta herramienta para extraer y manipular datos, pero gawk
puede hacer mucho más. Para más información sobre gawk
, consulte las páginas del manual de su distribución de Linux.
El lenguaje Awk tiene muchos más recursos que los que hemos explorado en esta guía. Para obtener información detallada sobre esto, consulte el sitio web oficial Guía del usuario de GNU Awk.
Artículos de interés