Usos avanzados de sed: múltiples líneas, direcciones complejas y scripts reutilizables
Introducción
¿Alguna vez te encontraste necesitando modificar archivos de texto de forma masiva, pero los comandos básicos de sed no alcanzaban porque necesitabas trabajar con varias líneas a la vez o aplicar patrones más complejos? Si trabajás con logs, archivos de configuración o cualquier tipo de dato textual, dominar los usos avanzados de sed te va a ahorrar horas de trabajo manual y te va a permitir crear pipelines de transformación potentes y reproducibles.
Este tutorial está dirigido a desarrolladores, administradores de sistemas y cualquiera que tenga que procesar texto en entornos Unix/Linux. Aprenderás a:
- Usar direcciones complejas (rangos, patrones, pasos) para seleccionar exactamente las líneas que querés.
- Trabajar con múltiples líneas mediante el espacio de patrón y el espacio de retención.
- Aplicar los comandos más útiles como d (delete), s (sustitución) y y (transformación) en contextos avanzados.
- Guardar y reutilizar scripts de sed en archivos para ejecutarlos de forma repetida.
- Combinar sed con otras herramientas (grep, awk, find) para flujos de trabajo más poderosos.
Al final, vas a ver ejemplos concretos de transformación de texto, con la entrada y la salida esperada, para que puedas copiar y adaptar los comandos a tus propios casos.
1. Repaso rápido: cómo funciona sed
Antes de avanzar, recordemos el modelo básico de sed: lee línea por línea, coloca cada línea en el patrón space, aplica los comandos especificados y, por defecto, imprime el resultado. El hold space es un búfer adicional donde podés guardar temporalmente líneas para procesarlas más tarde.
2. Direcciones complejas: más allá de los números de línea
2.1 Rangos y pasos
Podés especificar un rango de líneas con la sintaxis inicio,fin. Por ejemplo, para aplicar un comando solo entre las líneas 10 y 20:
sed '10,20s/foo/bar/g' archivo.txtSi querés aplicar un comando a cada quinta línea empezando desde la primera, usá el paso ~:
sed '1~5s/^/>>> /' archivo.txt # agrega >>> al inicio de cada 5ª línea2.2 Patrones como direcciones
En lugar de números, podés usar expresiones regulares para seleccionar líneas que coincidan con un patrón. Por ejemplo, borrar todas las líneas que contengan la palabra TODO:
sed '/TODO/d' archivo.txtCombiná patrones y números: aplicar una sustitución solo en las líneas que empiecen con # y estén entre la línea 5 y el final:
sed '5,$/^#/s/# //' archivo.txt2.3 Direcciones anidadas y múltiplos
Podés especificar varias direcciones separadas por coma para crear lógica AND, o usar {} para agrupar comandos bajo una misma dirección:
sed '/^ERROR/,/^$/ { s/ERROR/ALERTA/g; d }' archivo.logEste ejemplo borra el bloque que comienza con una línea que tiene ERROR y termina con una línea vacía, pero antes de borrar reemplaza ERROR por ALERTA.
3. Trabajando con múltiples líneas
Por defecto, sed procesa una línea a la vez, lo que limita patrones que cruzan el salto de línea. Para superar esto, usamos el comando N (añadir próxima línea al patrón space) y D (borrar la primera línea del patrón space y volver a cargar la siguiente). También el comando G (añadir hold space al pattern space) y H (añadir pattern space al hold space) son fundamentales.
3.1 Unir líneas separadas por un guion
Supongamos que tenés un archivo donde algunas palabras están divididas por un guion y un salto de línea, y querés unirlas:
Entrada (texto.txt):
Este es un ejemplo-
de texto dividido-
en varias líneas.Queremos obtener:
Este es un ejemplo de texto dividido en varias líneas.Comando:
sed ':a; /-$/ { N; s/-
//; ba }' texto.txtExplicación:
:acrea una etiqueta de salto./-$/selecciona líneas que terminan con -.Nagrega la próxima línea al pattern space (incluye el
).s/- //elimina el guion y el salto de línea.basalta de vuelta a la etiqueta:asi aún termina con -.
3.2 Eliminar bloques de comentario multilínea
Muchos lenguajes usan /* ... */ para comentarios de bloque. Queremos borrar todo lo que esté entre esos delimitadores, incluyendo el salto de línea.
Entrada (codigo.c):
/* Este es un
comentario de bloque */
int main() {
return 0;
}Comando:
sed -e ':a' -e '/\\*\// { N; /\\*\//! ba; s/\\*[^*]*\\*//g; ta }' -e 'P; d' codigo.cEste script es más complejo; lo desglosaremos en la sección de scripts.
3.3 Duplicar líneas que contienen una palabra clave
Queremos duplicar cada línea que contenga la palabra IMPORTANTE, dejando la original y agregando una copia justo después.
Entrada (notas.txt):
Reunión a las 10.
IMPORTANTE: revisar el informe.
Llamar al cliente.
IMPORTANTE: enviar el contrato.Salida esperada:
Reunión a las 10.
IMPORTANTE: revisar el informe.
IMPORTANTE: revisar el informe.
Llamar al cliente.
IMPORTANTE: enviar el contrato.
IMPORTANTE: enviar el contrato.Comando:
sed '/IMPORTANTE/ { p; }' notas.txtEl comando p imprime el pattern space; como sed ya imprime automáticamente cada línea, al agregar p estamos imprimiendo una segunda copia.
3.4 Intercambio de dos columnas usando hold space
Imaginemos un archivo CSV sencillo con dos columnas separados por coma y queremos invertir el orden.
Entrada (datos.csv):
nombre,edad
Ana,30
Luis,25
Marta,28Salida esperada:
edad,nombre
30,Ana
25,Luis
28,MartaComando:
sed '1s/\([^,]*\),\([^,]*\)/\2,\1/; t; :a; N; s/\([^
]*\)
\([^,]*\),\([^,]*\)/\2,\3
\1/; ta; P; d' datos.csvEsto es avanzado; mejor usar un script.
4. Comandos esenciales en profundidad
4.1 d – borrar líneas
Además de borrar por patrón, podés usar d dentro de un bloque para borrar todo lo que haya acumulado en el pattern space luego de ciertas operaciones.
Ejemplo: borrar todo el contenido entre dos marcadores START y END, inclusive.
sed '/START/,/END/d' archivo.txtSi querés borrar solo lo que está entre los marcadores, dejando los marcadores:
sed '/START/,/END/{/START/b; /END/b; d}' archivo.txtAquí b hace un salto (branch) al final del script cuando se encuentra el marcador, evitando que d actúe sobre él.
4.2 s – sustitución con flags avanzados
Además del global g, podés usar:
en la parte de reemplazo para insertar un salto de línea (requiere que el pattern space tenga más de una línea).\Ly\Upara convertir a minúsculas o mayúsculas la porción reemplazada.¶ referirse al texto completo que coincidió con el patrón.
Ejemplo: envolver cada número entre corchetes y convertirlo a hexadecimal (solo como demostración de &).
sed 's/[0-9]\+/[&]/g' archivo.txtPara cambiar a mayúsculas la primera letra de cada palabra:
sed 's/\b\([a-z]\)/\U\1/g' archivo.txt4.3 y – transformación de caracteres
El comando y funciona como el operador tr: reemplaza cada carácter de la primera lista por el correspondiente en la segunda.
Ejemplo: pasar todo el texto a modo "leet speak" básico (a→4, e→3, i→1, o→0, s→5).
sed 'y/aeios/43105/' archivo.txt5. Scripts de sed en archivos
Cuando los comandos se vuelven largos o necesitás reutilizarlos, es mejor guardarlos en un archivo de script y ejecutarlos con -f.
5.1 Estructura básica de un script
Un archivo de script contiene una línea por comando (o bloque). Los comentarios empiezan con #.
Ejemplo de script limpiar.sed:
# Eliminar líneas en blanco
/^$/d
# Reemplazar múltiples espacios por uno solo
s/ */ /g
# Quitar comentarios de línea que empiecen con #
/^#/dUso:
sed -f limpiar.sed entrada.txt > salida.txt5.2 Script para unir líneas divididas por guion (reutilizable)
Guardemos el script anterior en join-hyphen.sed:
:a
/-$/ {
N
s/-
//
ba
}Uso:
sed -f join-hyphen.sed fragmento.txt5.3 Script avanzado: borrar comentarios de bloque C
Este script maneja comentarios /* ... */ que pueden abarcar varias líneas.
Archivo rm-c-comments.sed:
# Etiqueta de inicio
:start
# Si encontramos /*
/\*\/ {
# Traemos líneas hasta encontrar */
:loop
N
/\*\//! b loop
# Ahora tenemos el comentario completo en pattern space
s/\*[^*]*\*//g
# Si después de borrar queda algo que aún comienza con /*, repetimos
/\*\/ b start
}Uso:
sed -f rm-c-comments.sed codigo.c > codigo_limpio.c5.4 Debugging de scripts
Para ver qué está haciendo sed en cada paso, usá el comando l (lista) que muestra el contenido del pattern space con caracteres no imprimibles escapados.
sed -n 'l' script.sed archivo.txtO bien usar el debug de GNU sed con --debug.
6. Ejemplos prácticos de transformación de texto
A continuación, varios casos de uso reales con entrada, comando y salida esperada.
6.1 Formatear un archivo de log de Apache
Supongamos un log donde cada línea tiene:
[10/Oct/2023:13:55:36 +0000] GET /index.html HTTP/1.1 200 1024Queremos extraer solo la ruta y el código de estado, separados por una tabulación.
Entrada (access.log):
[10/Oct/2023:13:55:36 +0000] GET /index.html HTTP/1.1 200 1024
[10/Oct/2023:13:56:01 +0000] POST /api/data HTTP/1.1 500 0
[10/Oct/2023:13:57:12 +0000] GET /static/style.css HTTP/1.1 304 0Comando:
sed -E 's/.* [A-Z]+ ([^ ]+) HTTP/[^ ]+ ([0-9]{3}) .*/\1 \2/' access.logSalida esperada:
/index.html 200
/api/data 500
/static/style.css 3046.2 Normalizar nombres de archivo en un listado
Tenés un listado de archivos con mayúsculas y minúsculas mezcladas, y querés que todo sea minúsculo y los espacios se reemplacen por guiones bajos.
Entrada (lista.txt):
Informe Final.pdf
Foto de Vacaciones.JPG
datos de prueba.pngComando:
sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/; s/ /_/g' lista.txtSalida esperada:
informe_final.pdf
foto_de_vacaciones.jpg
datos_de_prueba.png6.3 Extraer bloques de código Markdown
Querés extraer únicamente los bloques de código delimitados por triple backticks (```) de un archivo Markdown, incluyendo los delimitadores.
Entrada (readme.md):
Este es un ejemplo.
```bash
echo 'Hola Mundo'Algunos comentarios.
def suma(a, b):
return a + b
Comando:
```bash
sed -n '/^```/,/^```/ p' readme.mdSalida esperada:
```bash
echo 'Hola Mundo'def suma(a, b):
return a + b
### 6.4 Convertir fechas de formato europeo a ISO
Tenés fechas en formato dd/mm/aaaa y querés aaaa-mm-dd.
Entrada (fechas.txt):01/02/2023
15/08/2022
31/12/2021
Comando:
```bash
sed -E 's#([0-9]{2})/([0-9]{2})/([0-9]{4})#\3-\2-\1#' fechas.txtSalida esperada:
2023-02-01
2022-08-15
2021-12-316.5 Anonimizar direcciones IP en un archivo de configuración
Querés reemplazar cualquier dirección IPv4 por X.X.X.X.
Entrada (config.ini):
listen = 192.168.1.10:8080
allow = 10.0.0.0/24Comando:
sed -E 's/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/X.X.X.X/g' config.iniSalida esperada:
listen = X.X.X.X:8080
allow = X.X.X.X/247. Buenas prácticas y errores comunes
7.1 Siempre probar con -n y p o con una copia de seguridad
Antes de ejecutar un sed que modifica archivos en sitio (-i), hacé una prueba en pantalla o con una copia de seguridad:
sed -i.bak 's/foo/bar/g' archivo.txt7.2 Tener cuidado con los delimitadores en s
Si el patrón contiene el delimitador que elegiste (usualmente /), cambiá a otro carácter para evitar escape innecesario. Por ejemplo, usando |:
sed 's|/ruta/antigua|/ruta/nueva|g' rutas.txt7.3 Recordar que `
en la parte de reemplazo solo funciona si hay más de una línea en el pattern space Si intentás insertar un salto de línea conen una sustitución simple sobre una línea única, no va a funcionar. UsáGoN` para crear líneas múltiples antes.
7.4 Evitar la codicia excesiva con .*
En expresiones regulares, .* es codicioso y puede consumir más de lo esperado. Usá [^]]* para evitar consumir corchetes de cierre.
Ejemplo: extraer texto entre corchetes sin consumir corchetes internos:
sed -n 's/\[([^]]*)\]/\1/p' texto.txt7.5 Comentá tus scripts
Cuando guardes scripts en archivos, usá # para explicar cada bloque. Esto facilita el mantenimiento y la reutilización por otros miembros del equipo.
7.6 Usá archivos de prueba
Mantené un pequeño archivo de muestra con los casos edge (líneas vacías, solo delimitadores, etc.) y probá tus scripts allí antes de aplicarlos a producción.
8. Conclusión
Dominar los usos avanzados de sed te brinda una herramienta ligera pero increíblemente poderosa para manipular texto directamente desde la línea de comandos. Has visto cómo:
- Seleccionar líneas con direcciones complejas (rangos, patrones, pasos).
- Trabajar con múltiples líneas usando N, G, H y etiquetas de salto.
- Aplicar comandos como d, s y y en contextos avanzados.
- Guardar y reutilizar scripts en archivos para tareas repetitivas.
- Combinar sed con otras utilidades para construir pipelines de procesamiento de datos.
Con estos conocimientos, podés automatizar tareas que antes requerían scripts en Python o Perl, reduciendo dependencias y aumentando la velocidad de ejecución. Te animo a experimentar con los ejemplos proporcionados, adaptarlos a tus propios archivos y crear tu biblioteca personal de scripts sed. Cada vez que te enfrentes a un desafío de transformación de texto, recordá que sed probablemente tenga una solución elegante y eficiente.
Próximos pasos:
- Explorar la variante
gsed(GNU sed) para acceder a flags como-z(tratar el archivo completo como una sola línea) y expresiones regulares Perl-compatibles. - Integrar sed en tus pipelines de CI/CD para validar y formatear archivos de configuración automáticamente.
- Combinar sed con
awkpara situaciones donde necesites hacer cálculos además de sustituciones.
¡Manos al teclado y que el flujo de texto esté siempre a tu favor!
DUGLAS MORENO
Comentarios (0)
Sé el primero en comentar.