Skip to content

AWK y SED Avanzado

AWK y SED son herramientas fundamentales para el procesamiento de texto en Linux. Esta guía cubre desde conceptos básicos hasta técnicas avanzadas para análisis de logs, manipulación de datos y tareas de pentesting.

SED es un editor de flujo que permite realizar transformaciones básicas en texto de manera eficiente.

Terminal window
sed [opciones] 'comando' archivo
sed [opciones] -e 'comando1' -e 'comando2' archivo
Terminal window
# Sustitución básica (primera ocurrencia)
sed 's/old/new/' archivo.txt
# Sustitución global (todas las ocurrencias)
sed 's/old/new/g' archivo.txt
# Sustitución case-insensitive
sed 's/old/new/gi' archivo.txt
# Usar diferentes delimitadores
sed 's|/path/old|/path/new|g' archivo.txt
sed 's#old#new#g' archivo.txt
# Sustitución con backreferences
sed 's/\([0-9]*\)/Number: \1/g' archivo.txt
# Sustitución condicional (solo en líneas que coincidan)
sed '/pattern/s/old/new/g' archivo.txt
Terminal window
# Eliminar líneas específicas
sed '3d' archivo.txt # Línea 3
sed '2,5d' archivo.txt # Líneas 2 a 5
sed '$d' archivo.txt # Última línea
# Eliminar líneas que coincidan con patrón
sed '/pattern/d' archivo.txt
# Eliminar líneas vacías
sed '/^$/d' archivo.txt
# Eliminar líneas que empiecen con #
sed '/^#/d' archivo.txt
Terminal window
# Insertar antes de línea específica
sed '3i\Nueva línea' archivo.txt
# Agregar después de línea específica
sed '3a\Nueva línea' archivo.txt
# Insertar antes de patrón
sed '/pattern/i\Nueva línea' archivo.txt
# Agregar después de patrón
sed '/pattern/a\Nueva línea' archivo.txt
Terminal window
# Múltiples comandos con -e
sed -e 's/old1/new1/g' -e 's/old2/new2/g' archivo.txt
# Múltiples comandos con punto y coma
sed 's/old1/new1/g; s/old2/new2/g' archivo.txt
# Script de SED
cat > script.sed << 'EOF'
s/old1/new1/g
s/old2/new2/g
/^#/d
EOF
sed -f script.sed archivo.txt
Terminal window
# Aplicar comando en rango de líneas
sed '2,5s/old/new/g' archivo.txt
# Desde patrón hasta línea específica
sed '/start/,10s/old/new/g' archivo.txt
# Entre dos patrones
sed '/start/,/end/s/old/new/g' archivo.txt
# Desde línea específica hasta el final
sed '5,$s/old/new/g' archivo.txt
Terminal window
# Intercambiar líneas (h, g, x)
sed -n '1h;2g;p' archivo.txt
# Agregar línea siguiente al pattern space
sed -n 'N;s/\n/ /;p' archivo.txt
# Imprimir línea anterior
sed -n 'x;p;g;h' archivo.txt

AWK es un lenguaje de programación completo para procesamiento de texto estructurado.

Terminal window
awk 'pattern { action }' archivo
awk -F'delimiter' 'program' archivo
Terminal window
# Estructura completa
awk '
BEGIN {
# Código de inicialización
}
/pattern/ {
# Código para líneas que coincidan
}
{
# Código para todas las líneas
}
END {
# Código de finalización
}
' archivo
Terminal window
# Variables principales
NR # Número de registro (línea) actual
NF # Número de campos en la línea actual
FS # Separador de campos (por defecto: espacio)
OFS # Separador de campos de salida
RS # Separador de registros (por defecto: nueva línea)
ORS # Separador de registros de salida
FILENAME # Nombre del archivo actual
Terminal window
# Imprimir campos específicos
awk '{print $1, $3}' archivo.txt
# Imprimir último campo
awk '{print $NF}' archivo.txt
# Imprimir penúltimo campo
awk '{print $(NF-1)}' archivo.txt
# Cambiar separador de campos
awk -F':' '{print $1, $3}' /etc/passwd
# Múltiples separadores
awk -F'[,:]' '{print $1, $2}' archivo.txt
Terminal window
# Líneas que coincidan con patrón
awk '/pattern/ {print}' archivo.txt
# Líneas que NO coincidan
awk '!/pattern/ {print}' archivo.txt
# Condiciones numéricas
awk '$3 > 100 {print}' archivo.txt
# Condiciones de string
awk '$1 == "admin" {print}' archivo.txt
# Múltiples condiciones
awk '$1 == "admin" && $3 > 100 {print}' archivo.txt
Terminal window
# Variables definidas por usuario
awk '{sum += $3} END {print "Total:", sum}' archivo.txt
# Arrays asociativos
awk '{count[$1]++} END {for (i in count) print i, count[i]}' archivo.txt
# Array multidimensional
awk '{arr[$1,$2] = $3} END {for (key in arr) print key, arr[key]}' archivo.txt
Terminal window
# Funciones de string
awk '{print length($1)}' archivo.txt # Longitud
awk '{print substr($1, 2, 3)}' archivo.txt # Substring
awk '{print toupper($1)}' archivo.txt # Mayúsculas
awk '{print tolower($1)}' archivo.txt # Minúsculas
awk '{gsub(/old/, "new", $1); print}' archivo.txt # Sustitución global
# Funciones matemáticas
awk '{print sqrt($1)}' archivo.txt # Raíz cuadrada
awk '{print int($1)}' archivo.txt # Entero
awk '{print rand()}' archivo.txt # Número aleatorio
Terminal window
# Condicionales
awk '{
if ($3 > 100)
print "Alto:", $1
else if ($3 > 50)
print "Medio:", $1
else
print "Bajo:", $1
}' archivo.txt
# Bucles
awk '{
for (i = 1; i <= NF; i++)
print "Campo " i ": " $i
}' archivo.txt
# While loop
awk '{
i = 1
while (i <= NF) {
print $i
i++
}
}' archivo.txt
Terminal window
# Top 10 IPs por número de requests
awk '{print $1}' access.log | sort | uniq -c | sort -nr | head -10
# Códigos de estado HTTP
awk '{print $9}' access.log | sort | uniq -c | sort -nr
# URLs más solicitadas
awk '{print $7}' access.log | sort | uniq -c | sort -nr | head -20
# Requests por hora
awk '{print substr($4, 2, 11)}' access.log | sort | uniq -c
# User agents sospechosos
awk -F'"' '{print $6}' access.log | sort | uniq -c | sort -nr
# Detectar posibles ataques
awk '$7 ~ /\.\.|\/etc\/|\/proc\/|union|select|script/ {print $1, $7}' access.log
Terminal window
# Errores SSH por IP
awk '/Failed password/ {print $(NF-3)}' /var/log/auth.log | sort | uniq -c | sort -nr
# Intentos de login por usuario
awk '/Failed password/ {print $9}' /var/log/auth.log | sort | uniq -c | sort -nr
# Conexiones exitosas SSH
awk '/Accepted password/ {print $9, $11}' /var/log/auth.log
# Análisis de logs de firewall
awk '/DROP/ {print $12}' /var/log/kern.log | sed 's/SRC=//' | sort | uniq -c | sort -nr

Procesamiento de Archivos de Configuración

Section titled “Procesamiento de Archivos de Configuración”
Terminal window
# Extraer usuarios del sistema
awk -F':' '$3 >= 1000 {print $1, $5}' /etc/passwd
# Servicios activos
awk '/^[^#]/ && NF > 0 {print $1}' /etc/services | sort | uniq
# Configuración de red
awk '/inet / {print $2}' <(ip addr show)
# Procesos por usuario
ps aux | awk '{user[$1] += $3} END {for (u in user) print u, user[u]}'
Terminal window
# Análisis de netstat
netstat -an | awk '$1 == "tcp" && $6 == "ESTABLISHED" {print $5}' | cut -d: -f1 | sort | uniq -c
# Conexiones por puerto
netstat -an | awk '$1 == "tcp" {print $4}' | cut -d: -f2 | sort | uniq -c | sort -nr
# Análisis de tcpdump
tcpdump -n | awk '{print $3}' | cut -d. -f1-4 | sort | uniq -c | sort -nr
log_analyzer.sh
#!/bin/bash
LOG_FILE=${1:-/var/log/apache2/access.log}
echo "=== ANÁLISIS DE LOG: $LOG_FILE ==="
echo -e "\n--- Top 10 IPs ---"
awk '{print $1}' "$LOG_FILE" | sort | uniq -c | sort -nr | head -10
echo -e "\n--- Códigos de Estado ---"
awk '{status[$9]++} END {
for (code in status)
printf "%-3s: %d\n", code, status[code]
}' "$LOG_FILE" | sort
echo -e "\n--- URLs Sospechosas ---"
awk '$7 ~ /\.\.|\/etc\/|\/proc\/|union|select|<script/ {
printf "%-15s %s\n", $1, $7
}' "$LOG_FILE" | head -20
echo -e "\n--- Requests por Hora ---"
awk '{
time = substr($4, 2, 14)
gsub(/:/, " ", time)
hour = substr(time, 1, 13)
requests[hour]++
} END {
for (h in requests)
printf "%s: %d\n", h, requests[h]
}' "$LOG_FILE" | sort
process_monitor.sh
#!/bin/bash
ps aux | awk '
BEGIN {
printf "%-10s %-8s %-8s %-8s %s\n", "USER", "CPU%", "MEM%", "PID", "COMMAND"
printf "%-10s %-8s %-8s %-8s %s\n", "----", "----", "----", "---", "-------"
}
NR > 1 {
if ($3 > 5.0 || $4 > 5.0) {
printf "%-10s %-8.1f %-8.1f %-8s %s\n", $1, $3, $4, $2, $11
}
}
END {
print "\nProcesos con alto uso de recursos (>5%)"
}'
security_report.sh
#!/bin/bash
echo "=== REPORTE DE SEGURIDAD $(date) ==="
echo -e "\n--- Intentos de Login Fallidos ---"
awk '/Failed password/ {
ip = $(NF-3)
user = $9
attempts[ip][user]++
} END {
for (ip in attempts) {
for (user in attempts[ip]) {
if (attempts[ip][user] > 5) {
printf "IP: %-15s Usuario: %-10s Intentos: %d\n", ip, user, attempts[ip][user]
}
}
}
}' /var/log/auth.log
echo -e "\n--- Conexiones de Red Sospechosas ---"
netstat -an | awk '
$1 == "tcp" && $6 == "ESTABLISHED" {
split($5, remote, ":")
ip = remote[1]
port = remote[2]
if (port == "22" || port == "23" || port == "3389") {
printf "Conexión sospechosa: %s:%s\n", ip, port
}
}'
echo -e "\n--- Archivos Modificados Recientemente ---"
find /etc -type f -mtime -1 -exec ls -la {} \; | awk '{
printf "%-20s %s %s %s\n", $9, $6, $7, $8
}'
Terminal window
# Usar -n con p para imprimir solo líneas específicas
sed -n '10,20p' archivo.txt
# Salir después de encontrar patrón
sed '/pattern/q' archivo.txt
# Procesar solo las primeras N líneas
sed '100q' archivo.txt
Terminal window
# Salir temprano cuando sea posible
awk '/pattern/ {print; exit}' archivo.txt
# Usar next para saltar procesamiento
awk '/skip/ {next} {print}' archivo.txt
# Procesar solo campos necesarios
awk '{print $1, $3}' archivo.txt # Más rápido que procesar todos los campos
Terminal window
# Eliminar líneas duplicadas manteniendo orden
awk '!seen[$0]++' archivo.txt
# Normalizar espacios en blanco
sed 's/[[:space:]]\+/ /g' archivo.txt
# Eliminar caracteres no imprimibles
sed 's/[^[:print:]]//g' archivo.txt
# Convertir CSV a formato tabular
awk -F',' '{printf "%-20s %-15s %-10s\n", $1, $2, $3}' archivo.csv
Terminal window
# JSON simple a CSV
awk -F'"' '/"name":/ {name=$4} /"value":/ {value=$4; print name","value}' data.json
# Log de Apache a formato personalizado
awk '{printf "%s|%s|%s|%s\n", $1, $4, $7, $9}' access.log
# Convertir timestamps
awk '{
cmd = "date -d @" $1 " +\"%Y-%m-%d %H:%M:%S\""
cmd | getline formatted_date
close(cmd)
print formatted_date, $2, $3
}' timestamps.txt

Nota de Rendimiento: Para archivos muy grandes, considera usar herramientas especializadas como mawk (más rápido que gawk) o GNU parallel para procesamiento en paralelo. AWK y SED son extremadamente eficientes para la mayoría de tareas de procesamiento de texto.