AWK es un lenguaje de programación versátil diseñado específicamente para el procesamiento y análisis de texto. Actúa tanto como un comando de Linux/Unix como un lenguaje de scripting completo, especializado en manipular datos estructurados en archivos de texto.
AWK destaca por su capacidad para:
Procesar archivos línea por línea
Dividir cada línea en campos
Aplicar operaciones sobre campos específicos
Generar reportes personalizados
Es una herramienta fundamental en el arsenal de cualquier profesional de ciberseguridad, especialmente útil para:
Análisis de logs y archivos de registro
Procesamiento de datos durante pruebas de penetración
Filtrado y extracción de información sensible
Automatización de tareas de procesamiento de texto
Sintaxis Básica
awk 'patrón { acción }' [archivo(s)]
Componentes principales:
patrón: Condición opcional que determina cuándo ejecutar la acción
acción: Comandos que se ejecutan cuando el patrón coincide (o en cada línea si no hay patrón)
archivo(s): Archivos de entrada (si se omite, lee de stdin)
El modelo de procesamiento de AWK
AWK trabaja con un modelo de patrón-acción. Para cada línea de entrada:
Verifica si cumple con el patrón
Si coincide (o no hay patrón), ejecuta la acción
Continúa con la siguiente línea
flowchart TD
A[Entrada] --> B[Leer línea]
B --> C{¿Coincide con\nel patrón?}
C -->|Sí o no hay patrón| D[Ejecutar acción]
C -->|No| E[Siguiente línea]
D --> E
E --> F{¿Fin de archivo?}
F -->|No| B
F -->|Sí| G[Fin]
awk '{sum+=$1} END {print "Total:", sum}' archivo.txt
/regex/
Coincide líneas que contienen la expresión regular
awk '/error/ {print}' logs.txt
expresión
Evalúa la expresión (verdadero si es != 0)
awk '$3 > 100 {print $1, $3}' datos.txt
patrón1, patrón2
Rango de líneas entre patrones
awk '/inicio/,/fin/ {print}' archivo.txt
Operaciones Comunes con AWK
1. Selección de Campos
Extraer información específica
# Imprimir el primer y tercer campo de cada líneaawk '{print $1, $3}' archivo.txt# Imprimir el primer campo y el último campoawk '{print $1, $NF}' archivo.txt# Imprimir todos los campos excepto el primeroawk '{$1=""; print $0}' archivo.txt
2. Cambiar el Separador de Campos
Trabajar con diferentes formatos
# CSV: Separador por comasawk -F ',' '{print $2}' datos.csv# Archivos de contraseñas: Separador por dos puntosawk -F ':' '{print $1, $3}' /etc/passwd# Múltiples separadores (espacio o coma)awk -F '[, ]' '{print $1, $3}' archivo_mixto.txt
3. Filtrar Datos
Filtrado por contenido o condiciones
# Mostrar líneas que contienen "error"awk '/error/ {print $0}' registro.log# Mostrar entradas donde el tercer campo es mayor que 1000awk '$3 > 1000 {print $1, $3}' datos.txt# Filtrar por longitud de líneaawk 'length($0) > 80 {print "Línea larga:", NR}' codigo.c
4. Cálculos y Estadísticas
Operaciones matemáticas con datos
# Sumar valores de la columna 3awk '{sum += $3} END {print "Total:", sum}' datos.txt# Calcular promedio de valoresawk '{sum += $2; count++} END {print "Promedio:", sum/count}' mediciones.txt# Encontrar valor máximoawk 'BEGIN {max = 0} $3 > max {max = $3; linea = $0} END {print "Máximo:", max, "en línea:", linea}' datos.txt
# Convertir salida de netstat a formato CSVnetstat -tuln | awk 'NR>2 {print $4 "," $1 "," $6}' > puertos.csv# Extraer sólo direcciones IP de una salidaifconfig | awk '/inet / {print $2}' | awk -F ':' '{print $2}'
Estructuras de Control
Condicionales
# Uso de if-else para clasificar valoresawk '{ if ($3 > 100) { print $0, "Alto" } else if ($3 > 50) { print $0, "Medio" } else { print $0, "Bajo" }}' datos.txt
Bucles
# Recorrer todos los campos de una líneaawk '{ for (i=1; i<=NF; i++) { if (length($i) > 5) { print "Campo", i, ":", $i } }}' archivo.txt
Funciones Definidas por el Usuario
# Definir función para convertir a mayúsculasawk 'function mayusculas(texto) { return toupper(texto)}{ print mayusculas($1), $2}' nombres.txt
Ejemplos Avanzados
Manipulación Compleja de Datos
Extraer y procesar datos de múltiples fuentes
# Unir datos de dos archivos por un campo común (como JOIN en SQL)awk 'FNR==NR {usuarios[$1]=$2; next} $3 in usuarios {print $0, usuarios[$3]}' usuarios.txt logs.txt
Script AWK Completo
Análisis de tráfico web desde logs de Apache
#!/usr/bin/awk -fBEGIN { print "Análisis de logs de Apache" print "-------------------------" FS=" " contador_total = 0 errores_404 = 0}{ # Contar peticiones por IP ip_count[$1]++ # Contar códigos de estado status = $9 codigo[status]++ # Contar peticiones por hora split($4, tiempo, ":") hora[substr(tiempo[1], 2)]++ # Contar errores 404 if (status == 404) { errores_404++ url_404[$7]++ } contador_total++}END { # Mostrar IPs más frecuentes print "\nTop 5 IPs por número de peticiones:" for (ip in ip_count) { print ip_count[ip], ip | "sort -rn | head -5" } # Mostrar códigos de estado print "\nCódigos de estado HTTP:" for (c in codigo) { printf "%s: %d (%.2f%%)\n", c, codigo[c], (codigo[c]/contador_total)*100 } # Mostrar URLs con más errores 404 print "\nTop URLs con error 404:" for (url in url_404) { print url_404[url], url | "sort -rn | head -5" } # Distribución por hora print "\nDistribución de peticiones por hora:" for (h=0; h<24; h++) { hora_str = sprintf("%02d", h) count = hora[hora_str] ? hora[hora_str] : 0 printf "%s:00 - %s:59: %d\n", hora_str, hora_str, count } print "\nTotal peticiones analizadas:", contador_total}
graph LR
A[Archivo de entrada] --> B[Bloque BEGIN]
B --> C{Para cada línea}
C --> D{¿Coincide con\nalgún patrón?}
D -->|Sí| E[Ejecutar acción\nasociada]
D -->|No| F[Siguiente línea]
E --> F
F --> G{¿Más líneas?}
G -->|Sí| C
G -->|No| H[Bloque END]
H --> I[Salida procesada]
subgraph "Flujo de procesamiento por línea"
J[Leer línea] --> K[Dividir en campos]
K --> L[Aplicar patrones]
L --> M[Ejecutar acciones]
end
Integración con Otras Herramientas
AWK funciona excepcionalmente bien en combinación con otras herramientas de línea de comandos:
Pipeline con grep, sort y uniq
# Encontrar las IPs que más intentos fallidos de login han realizadogrep "Failed password" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -nr | head -10
Procesamiento de salida JSON (con jq)
# Extraer campos específicos de una respuesta JSONcurl -s https://api.ejemplo.com/datos | jq -r '.items[]' | awk '{print $3, $1}'
Integración con scripts de shell
# Uso en script bash para automatizar tareas#!/bin/bashTOTAL=$(awk '{sum+=$5} END {print sum}' datos.txt)if [ "$TOTAL" -gt 1000 ]; then echo "Alerta: Valor total excede el umbral: $TOTAL"fi