Tutorial de awk: separadores, patrones, variables y ejemplos prácticos
Introducción
Awk es una de esas herramientas clásicas de Unix que sigue siendo indispensable para cualquiera que trabaje con texto estructurado: logs, CSV, archivos de configuración o cualquier lista de datos en columnas. Si tenés que extraer información, hacer cálculos simples o transformar columnas sin escribir un script completo en Python o Bash, awk suele ser la solución más rápida y ligera.
Este tutorial está dirigido a desarrolladores, administradores de sistemas y analistas de datos que ya manejan la línea de comandos y quieren profundizar en el uso de awk. Aprenderás a definir separadores de campo, a combinar patrones y acciones, a aprovechar variables integradas como NR, NF, FS y OFS, y a aplicar todo eso en ejemplos concretos: sumar columnas, extraer datos específicos, cambiar el formato de salida y más. Cada script incluye la salida esperada para que puedas verificarlo al instante.
Al final, tendrás un repertorio de patrones que podés copiar y pegar en tu terminal, además de una base sólida para explorar funciones más avanzadas de awk.
¿Qué es awk y cómo se invoca?
Awk interpreta cada línea de entrada como un registro y la divide en campos según un separador (por defecto, cualquier secuencia de espacios o tabs). Luego vos podés especificar un patrón (una condición) y una acción (qué hacer cuando el patrón coincide). La sintaxis básica es:
awk 'patrón { acción }' archivo
Si el patrón se omite, la acción se ejecuta en todas las líneas. Si la acción se omite, awk simplemente imprime la línea completa (equivalente a { print $0 }).
Los comandos se pueden pasar directamente entre comillas simples para que el shell no interprete los signos como caracteres especiales. Dentro de esas comillas simples podés usar comillas dobles para cadenas si las necesitás, pero en la mayoría de los ejemplos vamos a evitarlas.
Definiendo el separador de campo
El separador determina cómo awk corta cada línea en campos $1, $2, $3 … $NF. Hay dos formas principales:
1. Usando la variable interna FS
FS (Field Separator) se puede asignar dentro del script, por ejemplo en un bloque BEGIN:
awk 'BEGIN { FS = } { print $1, $3 }' datos.txt
Esto establece el separador como tabulador antes de procesar cualquier línea.
2. Con la opción -F de la línea de comandos
Es más cómodo para pruebas rápidas:
awk -F',' '{ print $2 }' archivo.csv
Aquí el separador es la coma, ideal para archivos CSV simples.
3. Expresiones regulares como separador
FS también puede ser una regex. Por ejemplo, para separar por uno o más espacios o tabs:
awk 'BEGIN { FS = "[ ]+" } { print $1 }' datos.txt
Nota: dentro de BEGIN usamos comillas dobles para que el shell no rompa la cadena; pero como el script completo está entre comillas simples, esas comillas dobles son parte del código awk y no necesitan escape extra.
Variables integradas más usadas
Awk provee varias variables que se actualizan automáticamente. Conocerlas te permite escribir scripts más breves y expresivos.
| Variable | Significado | Ejemplo
|----------|-------------|
| NR | Número de registro (número de línea leída, empieza en 1)
| NF | Número de campos en el registro actual
| FS | Separador de campo de entrada (ver arriba)
| OFS | Separador de campo de salida (por defecto, un espacio)
| RS | Separador de registro (por defecto, salto de línea)
| ORS | Separador de registro de salida (por defecto, salto de línea)
| FILENAME | Nombre del archivo que se está procesando
Un caso típico: imprimir número de línea y cantidad de campos:
awk '{ print NR, NF, $0 }' archivo.txt
Salida esperada (asumiendo que archivo.txt tiene tres líneas con 4, 2 y 5 campos respectivamente):
1 4 linea con cuatro campos
2 2 linea con dos campos
3 5 otra linea con cinco campos
Patrones y acciones
El patrón puede ser una expresión regular, una comparación, un rango o incluso la palabra especial BEGIN/END. La acción es un bloque de código entre llaves.
Patrones simples
- Coincidencia exacta de campo:
$2 == "activo" - Comparación numérica:
$3 > 1000 - Expresión regular:
$0 ~ /error/(la línea contiene la palabra error) - Rango de líneas:
NR >= 10 && NR <= 20(líneas del 10 al 20)
Acciones comunes
printoprintfpara salida- Asignaciones:
$1 = toupper($1) - Acumuladores:
sum += $4 - Salida a archivo:
print > "resultado.txt"
Ejemplo 1: Sumar una columna
Supongamos que tenés un archivo ventas.txt con el formato:
producto cantidad precio
manzana 10 0.5
banana 5 0.3
cereza 2 1.2
Queremos calcular el ingreso total (cantidad * precio).
awk '{ ingreso = $2 * $3; total += ingreso } END { printf "Ingreso total: %.2f
", total }' ventas.txt
Explicación:
- En cada línea calculamos el ingreso y lo vamos acumulando en la variable
total. - En el bloque END (que se ejecuta después de leer todo el archivo) imprimimos el total con dos decimales.
Salida esperada:
Ingreso total: 11.40
Ejemplo 2: Extraer columnas específicas y cambiar el separador de salida
Imaginemos un CSV de empleados:
id,nombre,departamento,sueldo
1,Ana,Contabilidad,3500
2,Luis,IT,4200
3,María,Contabilidad,3800
Queremos obtener solo el nombre y el sueldo, separados por punto y coma (;).
awk -F',' 'NR>1 { print $2 \); OFS=\ \); print $2, $4 }' empleados.csv
Espera, ahí cometimos un error: vamos a corregirlo. La forma correcta es definir OFS antes de usar print:
awk -F',' 'BEGIN { OFS = \); } NR>1 { print $2, $4 }' empleados.csv
-F','establece la coma como separador de entrada.- En BEGIN fijamos OFS a
);. NR>1excluye la cabecera.print $2, $4muestra el segundo y cuarto campo separados por OFS.
Salida esperada:
Ana;3500
Luis;4200
María;3800
Ejemplo 3: Filtrar líneas con un patrón y contar coincidencias
Queremos saber cuántas líneas del archivo log.txt contienen la palabra "FAIL" (mayúsculas o minúsculas).
awk 'tolower($0) ~ /fail/ { contador++ } END { print "Fallos encontrados:" , contador }' log.txt
tolower($0)convierte la línea completa a minúsculas para que la búsqueda sea case‑insensitive.- Cada coincidencia incrementa
contador. - En END mostramos el total.
Supongamos que log.txt tiene:
[INFO] Operación completada
[WARN] Posible retraso
[ERROR] FAIL en módulo auth
[INFO] Reiniciando servicio
[ERROR] fail de red
Salida esperada:
Fallos encontrados: 2
Ejemplo 4: Cambiar el separador de registro (RS) para procesar bloques
Algunos archivos tienen registros separados por líneas en blanco. Por ejemplo, un bloque de datos de sensores donde cada bloque termina con una línea en blanco.
Contenido de sensores.dat:
Temp: 23.5
Hum: 45
Pres: 1013
Temp: 22.1
Hum: 48
Pres: 1010
Temp: 23.9
Hum: 44
Pres: 1012
Queremos imprimir la temperatura y la humedad de cada bloque, una línea por bloque.
awk -v RS='' '{ gsub(/
/, " \); print $2, $4 }' sensores.dat
Explicación:
-v RS=''le indica a awk que el separador de registro es una línea en blanco (dos saltos de línea seguidos). Así cada bloque se convierte en un registro.- Dentro del registro, los saltos de línea siguen siendo caracteres; los reemplazamos por espacios con
gsub(/ /, " \)para que los campos se separen por espacios. - Después de la sustitución, $2 es el valor de Temperatura y $4 el de Humedad.
Salida esperada:
23.5 45
22.1 48
23.9 44
Ejemplo 5: Uso de variables definidas por el usuario
Awk permite crear variables propias. Vamos a calcular el promedio de una columna y mostrar cuántos valores están por encima del promedio.
Archivo notas.txt:
85
92
78
90
88
awk '{ suma += $1; count++ } END { promedio = suma / count; supra = 0; for (i=1; i<=count; i++) if (valor[i] > promedio) supra++; print "Promedio:" promedio; print "Valor(es) arriba del promedio:" supra }' notas.txt
Espera, estamos usando un arreglo valor que no hemos llenado. Vamos a reescribir el script correctamente:
awk '{ suma += $1; valores[NR] = $1; count++ } END { promedio = suma / count; supra = 0; for (i=1; i<=count; i++) if (valores[i] > promedio) supra++; printf "Promedio: %.2f
Valor(es) arriba del promedio: %d
", promedio, supra }' notas.txt
- Guardamos cada valor en el arreglo
valoresindexado por NR. - Después de leer todo, calculamos el promedio.
- Recorremos el arreglo contando cuántos superan el promedio.
Salida esperada:
Promedio: 86.60
Valor(es) arriba del promedio: 3
Buenas prácticas y errores comunes
Buenas prácticas
- Usar comillas simples alrededor del script awk para evitar que el shell expanda variables o caracteres especiales.
- Definir FS y OFS en BEGIN cuando necesites cambiarlos; así se aplican a todo el procesamiento y evitas sorpresas.
- Preferir
printfsobreprintcuando necesites controlar el formato (número de decimales, ancho de campo, etc.). - Acumular en bloques END para resultados globales (sumas, promedios, conteos).
- Comprobar NF antes de acceder a campos si el archivo podría tener líneas con formato variable, por ejemplo:
awk 'NF >= 3 { accion }' archivo - Usar variables descriptivas en lugar de nombres genéricos como
xoy; mejora la legibilidad. - Probar con archivos pequeños primero antes de ejecutar sobre grandes volúmenes de datos.
Errores comunes
- Olvidar que el separador de salida (OFS) afecta a todas las impresiones; si lo cambias en medio del script, todas las siguientes
printlo usarán. - Confundir NR (número de registro) con FNR (número de registro dentro del archivo actual) cuando se procesan varios archivos; FNR se reinicia en cada archivo.
- Asumir que FS solo puede ser un solo carácter; recuerda que puede ser una expresión regex, lo que permite separadores múltiples.
- No inicializar variables de acumulación; si usas
total += $2sin darle un valor inicial, awk lo trata como cero en la primera uso, pero en algunos contextos (como dentro de funciones) puede causar valores inesperados. - Usar
$0dentro de un bloque BEGIN; en BEGIN todavía no se ha leído ningún registro, así que $0 está vacío.
Conclusión
Awk sigue siendo una herramienta poderosa para procesar datos de columna a columna sin salir de la terminal. Ahora sabes cómo:
- Definir el separador de campo con
-Fo la variable FS. - Aprovechar variables integradas como NR, NF, OFS y RS para controlar la entrada y la salida.
- Combinar patrones y acciones para filtrar, transformar y resumir información.
- Aplicar todo esto en ejemplos reales: sumar columnas, extraer datos, cambiar formato de salida y trabajar con bloques de registros separados por líneas en blanco.
Con estos conceptos podés resolver la mayoría de las tareas de extracción y cálculo rápido que aparecen en el día a día de un desarrollador o administrador. La próxima vez que te enfrentes a un log o a un CSV, pensá en awk antes de abrir un editor o escribir un script más largo.
¡A practicar! Probá los ejemplos con tus propios archivos y modificá los scripts para adaptarlos a tus necesidades. Cuanto más los uses, más natural te resultará pensar en términos de registros, campos y patrones.
¿Te quedó alguna duda? Dejála en los comentarios y con gusto te ayudo a afinar tu awk.
DUGLAS MORENO
Comentarios (0)
Sé el primero en comentar.