AWK & SED — Cheatsheet Completo 
AWK y SED son las herramientas de procesamiento de texto más poderosas del ecosistema Unix, disponibles en prácticamente todos los sistemas GNU/Linux, macOS y BSD. SED (Stream EDitor) es un editor de flujos que aplica transformaciones a cada línea de texto mediante expresiones regulares. AWK es un lenguaje de programación completo orientado al procesamiento de registros y campos de texto estructurado. Juntas, son los pilares de cualquier pipeline de automatización, análisis de logs y manipulación de datos en la línea de comandos.
1. 🌟 Conceptos Clave y Fundamentos
1.1. SED — Conceptos Base
- Stream Editor: Procesa texto línea a línea desde stdin o archivos. No modifica el archivo original a menos que se use
-i. - Ciclo de Ejecución: Para cada línea, SED la carga en el espacio de patrón (pattern space), aplica los comandos y la imprime automáticamente al final del ciclo.
- Espacio de retención (Hold Space): Área de almacenamiento secundaria donde se puede guardar texto entre ciclos de líneas.
- Dirección: Especifica en qué líneas actúa un comando. Puede ser un número de línea, una regex, o un rango (
/inicio/,/fin/). - -n (silencioso): Suprime la impresión automática. Úsalo con
ppara imprimir solo lo que quieres.
1.2. AWK — Conceptos Base
- Registro (Record): Por defecto, cada línea del archivo es un registro. Separador:
RS(Record Separator, por defecto\n). - Campo (Field): Cada token separado por el separador de campo.
$1,$2, …,$NF. Separador:FS(Field Separator, por defecto espacio/tab). $0: El registro completo (toda la línea actual).NR: Número del registro actual (número de línea global).NF: Número de campos en el registro actual.FNR: Número de registro dentro del archivo actual (útil con múltiples archivos).- Bloque
BEGIN: Código que se ejecuta UNA VEZ antes de procesar cualquier línea. - Bloque
END: Código que se ejecuta UNA VEZ después de procesar todas las líneas. - Patrón: Condición que debe cumplir un registro para que se ejecute la acción asociada.
2.
Sintaxis Básica
2.1. Sintaxis de SED
# Forma general
sed [opciones] 'comando' archivo(s)
sed [opciones] -f script.sed archivo(s)
# Opciones esenciales
# -n Supprime la salida automática (modo silencioso)
# -e Permite múltiples expresiones en la misma invocación
# -i Edición in-place (modifica el archivo directamente)
# -i.bak In-place con backup (sufijo .bak)
# -E Usa ERE (Extended Regular Expressions), equivale a -r en GNU sed
# Estructura de un comando SED
# [dirección][!]comando[argumentos]
# Ejemplos de direcciones:
# 3 Solo la línea 3
# $ Última línea
# 1,5 Líneas 1 a 5 (rango)
# /patrón/ Líneas que coincidan con el patrón
# /ini/,/fin/ Rango entre dos patrones
# 1~2 Líneas impares (GNU sed): línea 1, 3, 5...
# 0~2 Líneas pares (GNU sed): línea 2, 4, 6...
2.2. Sintaxis de AWK
# Forma general
awk [opciones] 'programa' archivo(s)
awk [opciones] -f script.awk archivo(s)
# Opciones esenciales
# -F ':' Define el separador de campo
# -v var=valor Define una variable antes de procesar
# Estructura de un programa AWK
# patrón { acción }
awk 'BEGIN { ... } /patrón/ { acción } END { ... }' archivo
# Separador de campo
awk -F ':' '{ print $1 }' /etc/passwd # Separador ':'
awk -F ',' '{ print $2, $3 }' data.csv # CSV separado por comas
3. 📝 SED — Sustitución de Texto
El comando s (substitute) es el más usado de SED.
# Sintaxis: s/patrón/reemplazo/flags
# Flags: g (global), i (case-insensitive), p (print si coincide), N (N-ésima ocurrencia)
# Reemplazar primera ocurrencia por línea
sed 's/error/ERROR/' log.txt
# Reemplazar TODAS las ocurrencias (flag g)
sed 's/foo/bar/g' archivo.txt
# Case-insensitive
sed 's/error/ALERTA/gi' log.txt
# Solo imprimir líneas modificadas (combinado con -n y p)
sed -n 's/error/ERROR/gp' log.txt
# Sustitución solo en rango de líneas
sed '5,10s/texto/TEXTO/g' archivo.txt
# Sustitución solo en líneas que coincidan con patrón
sed '/^#/s/.*/#---COMENTARIO ARCHIVADO---/' config.txt
# Usar delimitadores alternativos (útil con rutas)
sed 's|/usr/local|/opt|g' paths.txt
sed 's,/home/usuario,/home/nuevo,g' paths.txt
# Grupos de captura y referencias a grupos (\1, \2, etc.)
# Intercambiar nombre y apellido (Juan García -> García, Juan)
sed 's/\([A-Za-z]*\) \([A-Za-z]*\)/\2, \1/' nombres.txt
# Con ERE (-E) la sintaxis es más limpia
sed -E 's/([A-Za-z]+) ([A-Za-z]+)/\2, \1/' nombres.txt
# Reemplazar espacios múltiples por uno solo
sed 's/ */ /g' archivo.txt
sed -E 's/ +/ /g' archivo.txt # ERE más clara
# Eliminar texto (reemplazar por nada)
sed 's/comentario//' archivo.txt # Eliminar primera ocurrencia
sed 's/<[^>]*>//g' pagina.html # Eliminar tags HTML
sed 's/[[:space:]]*$//' archivo.txt # Eliminar espacios al final de línea
4. ✂️ SED — Eliminación, Inserción y Selección de Líneas
# Eliminar líneas (comando d)
sed '3d' archivo.txt # Eliminar línea 3
sed '1,5d' archivo.txt # Eliminar líneas 1 a 5
sed '$d' archivo.txt # Eliminar última línea
sed '/patrón/d' archivo.txt # Eliminar líneas que coincidan
sed '/^$/d' archivo.txt # Eliminar líneas vacías
sed '/^[[:space:]]*$/d' archivo.txt # Eliminar líneas en blanco (con espacios)
sed '/^#/d' config.txt # Eliminar comentarios
# Negación con !: actúa en las que NO coinciden
sed '/importante/!d' log.txt # Mantener solo líneas con 'importante'
# Imprimir líneas específicas (con -n)
sed -n '5p' archivo.txt # Imprimir solo línea 5
sed -n '10,20p' archivo.txt # Imprimir líneas 10 a 20
sed -n '/inicio/,/fin/p' archivo.txt # Imprimir entre dos patrones
# Insertar texto (comando i = antes, a = después)
sed '3i\Nueva línea antes de la 3' archivo.txt
sed '3a\Nueva línea después de la 3' archivo.txt
sed '/patrón/a\Texto insertado después del patrón' archivo.txt
# Cambiar líneas completas (comando c)
sed '5c\Esta línea reemplaza la línea 5' archivo.txt
# Duplicar líneas (comando p sin -n)
sed '/importante/p' archivo.txt # Duplica líneas que coincidan
# Edición in-place con backup
sed -i.bak 's/version: 1.0/version: 2.0/g' config.yaml
# Crea config.yaml.bak y modifica config.yaml
5.
AWK — Procesamiento de Campos y Columnas
# Imprimir campos específicos
awk '{ print $1 }' archivo.txt # Primera columna
awk '{ print $NF }' archivo.txt # Última columna
awk '{ print $1, $3 }' archivo.txt # Columnas 1 y 3
awk '{ print NR, $0 }' archivo.txt # Numerar líneas
# Separador de campo personalizado
awk -F ':' '{ print $1, $7 }' /etc/passwd # Usuario y shell
awk -F ',' '{ print $1, $2 }' datos.csv # Columnas de CSV
awk -F '\t' '{ print $2 }' datos.tsv # TSV
# Cambiar el separador de salida (OFS — Output Field Separator)
awk -F ',' 'BEGIN { OFS="|" } { print $1, $2, $3 }' datos.csv
# Reformatear con printf
awk -F ':' '{ printf "%-20s %s\n", $1, $7 }' /etc/passwd
# Salida alineada: columna usuario de 20 caracteres, luego shell
# Calcular longitud y manipular strings
awk '{ print length($0), $0 }' archivo.txt # Longitud de cada línea
awk '{ print toupper($1) }' archivo.txt # Primera columna en mayúsculas
awk '{ print tolower($2) }' archivo.txt # Segunda columna en minúsculas
awk '{ gsub(/patrón/, "reemplazo"); print }' archivo.txt # Global substitution
# Reordenar o construir nueva estructura
awk -F ',' '{ print $3 "," $1 "," $2 }' datos.csv # Reordenar columnas
6. 🔎 AWK — Filtrado y Patrones
# Filtrar líneas por patrón (regex)
awk '/error/' log.txt # Líneas con 'error'
awk '!/^#/' config.txt # Líneas que NO empiezan con #
awk '/inicio/,/fin/' archivo.txt # Rango de patrones
# Filtrar por condición en campo (más potente)
awk '$3 > 100' datos.txt # Tercera columna mayor a 100
awk '$2 == "activo"' usuarios.csv # Segunda columna igual a "activo"
awk 'NF > 3' archivo.txt # Líneas con más de 3 campos
awk 'NR >= 10 && NR <= 20' log.txt # Líneas 10 a 20
# Combinar múltiples condiciones
awk '$1 == "ERROR" && $3 > 500' log.txt
awk '/timeout/ || /connection refused/' log.txt
# Filtrar columnas vacías o nulas
awk '$2 != ""' archivo.txt # Segunda columna no vacía
awk 'NF == 5' archivo.txt # Líneas con exactamente 5 campos
# Extraer campo específico de línea con patrón
awk '/^Version:/ { print $2 }' package.json
awk -F '=' '/^PORT/ { print $2 }' .env # Leer valor del .env
7. 📊 AWK — Cálculos y Agregaciones
# Sumar una columna numérica
awk '{ suma += $3 } END { print "Total:", suma }' ventas.csv
# Contar líneas que cumplen una condición
awk '/ERROR/ { count++ } END { print "Errores:", count }' log.txt
# Calcular promedio
awk '{ suma += $2; n++ } END { print "Promedio:", suma/n }' datos.txt
# Valor máximo y mínimo
awk 'NR==1 { max=$1; min=$1 }
{ if ($1 > max) max=$1; if ($1 < min) min=$1 }
END { print "Max:", max, "Min:", min }' numeros.txt
# Contar ocurrencias de cada valor (frecuencia)
awk '{ count[$1]++ } END { for (k in count) print count[k], k }' log.txt | sort -rn
# Agrupar y sumar por categoría
awk -F ',' '{ ventas[$1] += $3 }
END { for (cat in ventas) print cat, ventas[cat] }' ventas.csv
# Desviación estándar
awk '{ x += $1; x2 += $1^2; n++ }
END { media = x/n; print "Desv. est.:", sqrt(x2/n - media^2) }' datos.txt
8. ⚡ One-Liners Esenciales
Estos comandos de una sola línea resuelven problemas comunes del día a día:
# ===== SED ONE-LINERS =====
# Eliminar líneas vacías
sed '/^$/d' archivo.txt
# Eliminar espacios al inicio y final de cada línea (trim)
sed 's/^[[:space:]]*//;s/[[:space:]]*$//' archivo.txt
# Convertir CRLF (Windows) a LF (Unix)
sed 's/\r//' archivo.txt
# O in-place:
sed -i 's/\r//' archivo.txt
# Numerar líneas (alternativa a nl)
sed = archivo.txt | sed 'N;s/\n/\t/'
# Imprimir entre dos patrones (inclusivo)
sed -n '/INICIO/,/FIN/p' archivo.txt
# Insertar línea en blanco cada N líneas
sed 'n;G' archivo.txt # Línea en blanco cada 2 líneas
# Invertir el orden de las líneas
sed -n '1!G;h;$p' archivo.txt
# Eliminar comentarios y líneas vacías de un archivo de configuración
sed '/^[[:space:]]*#/d;/^$/d' config.txt
# Reemplazar primera línea del archivo
sed '1s/.*/NUEVA PRIMERA LÍNEA/' archivo.txt
# ===== AWK ONE-LINERS =====
# Imprimir número de líneas (como wc -l)
awk 'END { print NR }' archivo.txt
# Imprimir línea más larga
awk '{ if (length > max) { max = length; linea = $0 } } END { print linea }' archivo.txt
# Eliminar columna N (ej: eliminar columna 2)
awk '{ $2=""; print }' datos.txt
# Imprimir columnas en orden inverso
awk '{ for(i=NF; i>=1; i--) printf "%s%s", $i, (i>1?OFS:"\n") }' datos.txt
# Sumar todos los números de un archivo
awk '{ for(i=1;i<=NF;i++) total+=$i } END { print total }' datos.txt
# Eliminar líneas duplicadas (manteniendo orden, a diferencia de sort -u)
awk '!visto[$0]++' archivo.txt
# Extraer columna N de un CSV con cabecera
awk -F ',' 'NR==1 { for(i=1;i<=NF;i++) if($i=="email") col=i } NR>1 { print $col }' datos.csv
# Imprimir líneas entre la N y la M
awk 'NR>=10 && NR<=20' archivo.txt
# Convertir CSV a JSON básico
awk -F ',' 'NR==1 { split($0,header,",") }
NR>1 { printf "{"; for(i=1;i<=NF;i++) printf "\"%s\":\"%s\"%s",header[i],$i,(i<NF?",":""); print "}" }' datos.csv
9. 🔗 Combinando SED y AWK en Pipelines
# Extraer errores de Apache log y contar por IP
grep "ERROR" access.log | awk '{ print $1 }' | sort | uniq -c | sort -rn | head -20
# Limpiar CSV: eliminar comillas, espacios extra, y extraer columnas
sed 's/"//g' datos.csv | awk -F ',' '{ print $1, $4 }'
# Procesar archivo de configuración: extraer solo valores activos
grep -v '^#' config.txt | sed '/^$/d' | awk -F '=' '{ print $1, "=", $2 }'
# Análisis de log de Nginx: top 10 IPs por peticiones
awk '{ print $1 }' access.log | sort | uniq -c | sort -rn | head -10
# Extraer y formatear tiempos de respuesta de log
awk '/request_time/ { match($0, /request_time=([0-9.]+)/, arr); print arr[1] }' app.log | \
awk '{ s+=$1; n++ } END { printf "Promedio: %.3fs\n", s/n }'
# Comparar dos columnas de dos archivos diferentes
awk 'FNR==NR { a[$1]=$2; next } { if ($1 in a) print $1, a[$1], $2 }' archivo1.txt archivo2.txt
# Generar reporte de errores agrupado por hora
awk '/ERROR/ { match($0, /\[([0-9]{2}):[0-9]{2}:[0-9]{2}\]/, t); errores[t[1]]++ }
END { for (h in errores) printf "Hora %s: %d errores\n", h, errores[h] }' app.log | sort
# Reemplazar variables de entorno en una plantilla
sed "s/\${APP_VERSION}/$APP_VERSION/g;s/\${APP_PORT}/$APP_PORT/g" template.yaml
10. 🎯 Expresiones Regulares en SED y AWK
# Clases de caracteres POSIX (portables entre sistemas)
# [[:alpha:]] Letras (a-z, A-Z)
# [[:digit:]] Dígitos (0-9)
# [[:alnum:]] Alfanumérico
# [[:space:]] Espacios y tabs
# [[:upper:]] Mayúsculas
# [[:lower:]] Minúsculas
# [[:punct:]] Signos de puntuación
# [[:blank:]] Espacio y tab (solo)
# Anclas
# ^ Inicio de línea
# $ Fin de línea
# \b Frontera de palabra (AWK: \< inicio, \> fin)
# Cuantificadores (ERE con -E en sed, AWK los soporta de forma nativa)
# * Cero o más
# + Uno o más
# ? Cero o uno
# {n} Exactamente n veces
# {n,m} Entre n y m veces
# Ejemplos prácticos
# Validar formato IP (básico)
awk '/^([0-9]{1,3}\.){3}[0-9]{1,3}$/ { print "IP válida:", $0 }' ips.txt
# Extraer emails
grep -oE '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' archivo.txt
# Extraer URLs
sed -n 's/.*\(https\?:\/\/[^ ]*\).*/\1/p' archivo.txt
# Extraer números de versión semver
awk 'match($0, /[0-9]+\.[0-9]+\.[0-9]+/, arr) { print arr[0] }' CHANGELOG.md
# Validar fechas formato YYYY-MM-DD
awk '/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/ { print "Fecha válida:", $0 }' fechas.txt
11. ⚠️ Errores Comunes y Pitfalls
-
No usar
-isin backup en producción:sed -i 's/a/b/g' archivo_critico.txtmodifica el archivo de forma irreversible. Siempre usa-i.baken scripts de producción o crea un backup primero.- ✅
sed -i.bak 's/a/b/g' archivo.txt
- ✅
-
Confundir BRE y ERE en SED: Por defecto, SED usa BRE (Basic Regular Expressions). En BRE,
+,?,|,{n}deben escaparse:\+,\?,\|,\{n\}. Con-Eactivas ERE y la sintaxis es más natural.- ❌
sed 's/[0-9]+/NUM/'(no funciona en BRE) - ✅
sed -E 's/[0-9]+/NUM/'
- ❌
-
División por cero en AWK: Si calculas promedios u otras divisiones, verifica que el divisor no sea cero.
- ✅
END { if (n > 0) print suma/n; else print "Sin datos" }
- ✅
-
$0en AWK se regenera al modificar campos: Cuando asignas$2 = "nuevo", AWK reconstruye$0usando OFS. Si OFS es un espacio y el separador original era tab, pierdes el formato original.- ✅ Establece
BEGIN { OFS="\t" }antes de modificar campos.
- ✅ Establece
-
Olvidar que AWK compara como string por defecto:
$1 > 10se evalúa como string si$1contiene letras. Asegúrate de que los campos sean numéricos o usaint($1) > 10. -
Glob de archivos en SED:
sed 's/a/b/' *.txtfunciona, pero si hay demasiados archivos supera el límite del shell. Usafind . -name "*.txt" | xargs sed -i 's/a/b/g'. -
Diferencias entre GNU sed y BSD sed (macOS): En macOS,
sed -irequiere un argumento de sufijo obligatorio.-i ''para sin backup o-i .bakpara backup.- macOS:
sed -i '' 's/a/b/g' archivo.txt - Linux:
sed -i 's/a/b/g' archivo.txt
- macOS:
-
printvsprintfen AWK:printagregaORS(output record separator, por defecto\n) automáticamente.printfno agrega nada — debes gestionar\nmanualmente.
12.
Buenas Prácticas y Consejos Pro
-
Prueba antes de modificar in-place: Ejecuta el comando SED sin
-iprimero para revisar que la salida es correcta. Agrega-isolo cuando estés seguro. -
Usa variables AWK en
BEGINpara hacer tus scripts configurables sin hardcodear valores:awk -v umbral=100 '$3 > umbral { print }'. -
Combina
sedyawkconxargspara procesamiento masivo:find . -name "*.log" | xargs awk '/ERROR/ { count++ } END { print FILENAME, count }'. -
Usa
gawk(GNU AWK) para features avanzados: Arrays multidimensionales (arr[key1,key2]), funciones de tiempo (systime(),strftime()), y soporte nativo de Unicode son exclusivos degawk. -
mawkpara rendimiento máximo en scripts de big data:mawkes 2-10x más rápido quegawkpara pipelines de procesamiento masivo de texto. Úsalo cuando el rendimiento es crítico. -
Aprovecha
FNRvsNRcon múltiples archivos:NRcuenta líneas globalmente;FNRreinicia por archivo.awk 'FNR==NR { ... } FNR!=NR { ... }'es el patrón clásico para hacer joins de archivos.
1
2 -
Documenta tus one-liners complejos: AWK permite escribir código en múltiples líneas con
-f script.awk. Un script de AWK bien comentado de 20 líneas es infinitamente más mantenible que un one-liner de 200 caracteres. -
Para transformaciones muy complejas, considera Python: Si el one-liner de AWK se extiende a más de 5 líneas, a veces es más legible y mantenible usar
python3 -c "..."o un script Python completo.
Este cheatsheet proporciona una referencia exhaustiva de AWK y SED, cubriendo desde los conceptos fundamentales de ambas herramientas hasta patrones avanzados de procesamiento de texto, expresiones regulares POSIX, one-liners esenciales para el día a día y las mejores prácticas para escribir pipelines de texto robustos y portables en sistemas Unix/Linux.