---
title: "Sed Buscar y Reemplazar: Domina las Técnicas Avanzadas"
description: "Domina buscar y reemplazar con sed con ejemplos prácticos: el comando de sustitución (s), patrones regex, edición in-place y consejos de portabilidad GNU vs BSD para 2026."
date: 2023-11-24
categories: ["linux"]
tags: ["sed","linux","regex"]
---

import Notice from "@components/widgets/Notice.astro";
import Tabs from "@components/widgets/Tabs.astro";
import Tab from "@components/widgets/Tab.astro";

¿Necesitas buscar y reemplazar texto en archivos sin abrir un editor? El comando `s` de sed maneja la búsqueda y el reemplazo en una sola línea. Útil para actualizaciones de configuración, limpieza de datos o ediciones por lotes dentro de los flujos de trabajo de los [comandos esenciales de Linux](/es/comandos-linux/).

## ¿Qué es sed?

**sed** (Stream Editor) procesa texto línea a línea sin cargar el archivo completo en memoria. Útil para:
- Automatización y scripts
- Archivos grandes
- Hacer piping con otras herramientas Unix
- Procesamiento por lotes

Esta guía se centra en GNU sed (el predeterminado en Linux) pero cubre las diferencias de macOS/BSD y Alpine/busybox en una sección de portabilidad dedicada.

Otras guías de sed:
- [Borrar líneas con sed](/es/sed-eliminar-lineas/)
- [Insertar o añadir texto con sed](/es/sed-insertar-anadir-texto/)
- [Cambiar mayúsculas con sed](/es/sed-cambiar-mayusculas-minusculas/)

## Sintaxis básica

### El comando de sustitución (s)

```sh
sed 's/old/new/' file.txt        # Replace first occurrence per line
sed 's/old/new/g' file.txt       # Replace all occurrences (global)
sed 's/old/new/I' file.txt       # Ignore case (use capital I, portable)
```

<Notice type="info" title="Usa I mayúscula, no i minúscula">
La `i` minúscula funciona en GNU sed pero es ambigua con el comando insert y falla en macOS/BSD. La `I` mayúscula es la forma portable. Funciona en GNU sed y en macOS Big Sur (11.0) y posteriores.
</Notice>

### Delimitadores

Usa delimitadores diferentes cuando tu patrón contiene barras:
```sh
sed 's|/old/path|/new/path|g' config.txt
sed 's#http://old#https://new#g' urls.txt
```

### Opciones clave

| Opción | Función | Ejemplo |
|--------|---------|---------|
| `-i` | Edita archivos in-place | `sed -i 's/old/new/g' file.txt` |
| `-i.bak` | Edición in-place con backup | `sed -i.bak 's/old/new/g' file.txt` |
| `-n` | Suprime la salida por defecto | `sed -n 's/old/new/p' file.txt` |
| `-e` | Comandos múltiples | `sed -e 's/old/new/' -e 's/foo/bar/' file.txt` |

<Notice type="warning" title="-n + -i trunca archivos">
Nunca combines `-n` y `-i` en la misma invocación de sed. `sed -ni 's/foo/bar/' FILE` trunca FILE a cero bytes silenciosamente. El flag `-n` suprime la salida, y `-i` escribe esa salida (vacía) de vuelta al archivo. Usa `-i.bak` solo para una edición in-place segura.
</Notice>

**Importante**: Prueba sin `-i` primero. Sed escribe a stdout por defecto.

## Ejemplos comunes

**Archivos de configuración:**
```sh
sed 's/localhost/production-server/g' config.ini
sed 's/port=8080/port=80/g' server.conf
```

**Refactorización de código:**
```sh
sed 's/oldFunction/newFunction/g' script.js
sed 's/var /let /g' legacy.js
```

**Limpieza de datos:**
```sh
sed 's/,/;/g' data.csv              # Change delimiter
sed 's/  / /g' document.txt         # Fix double spaces
sed 's/\t/ /g' file.txt             # Tabs to spaces (GNU-only, see portability section)
```

### Operaciones con archivos

```sh
sed 's/old/new/g' file.txt > newfile.txt   # Save to new file
sed -i 's/old/new/g' file.txt              # Edit in place
sed -i.bak 's/old/new/g' file.txt          # Edit with backup
```

### Reemplazos múltiples

```sh
sed -e 's/old1/new1/g' -e 's/old2/new2/g' file.txt
sed 's/old1/new1/g; s/old2/new2/g' file.txt
```

### Consejos de seguridad

1. Prueba sin `-i` primero
2. Usa `-i.bak` para backups
3. Verifica con `diff original.txt modified.txt`
4. Nunca combines `-n` con `-i` (trunca el archivo, mira la advertencia de arriba)

## GNU vs BSD vs busybox: sed portable

Tu portátil de desarrollo probablemente corre macOS (BSD sed), tu VPS de producción corre Linux (GNU sed), y tu CI/CD podría correr contenedores Alpine (busybox sed). Un script de sed que funciona en uno puede fallar silenciosamente en otro. Esta sección cubre las diferencias que de verdad rompen cosas.

<Notice type="info" title="¿Qué sed estás usando?">
Ejecuta `sed --version` en Linux (GNU sed) o `sed --version 2>&1 | head -1` en macOS (BSD sed). En Alpine: `sed --help 2>&1 | head -1`. Saber qué sabor tienes es el primer paso para escribir scripts portables.
</Notice>

<Tabs>
<Tab name="El flag -i">

**Esta es la ruptura de portabilidad #1 con la que la gente tropieza.**

GNU y busybox aceptan un sufijo pegado o `-i` a secas:
```sh
sed -i 's/foo/bar/g' file.txt           # GNU/busybox: works
sed -i.bak 's/foo/bar/g' file.txt       # GNU/busybox: works, creates backup
```

BSD/macOS requiere el sufijo como **argumento separado**:
```sh
sed -i '' 's/foo/bar/g' file.txt        # macOS: no backup
sed -i '.bak' 's/foo/bar/g' file.txt    # macOS: with backup
```

Correr `sed -i 's/foo/bar/g' file.txt` en macOS se traga el script como sufijo y da el error "invalid command code."

**Patrón universal seguro (funciona en todas partes):**
```sh
sed -i.bak 's/foo/bar/' config.conf && rm config.conf.bak
```

</Tab>
<Tab name="Extensiones regex">

Estas extensiones GNU no hacen nada silenciosamente o se comportan mal en otros sed:

| Característica | GNU sed | BSD/macOS | busybox | Alternativa portable |
|----------------|---------|-----------|---------|----------------------|
| `\b` (límite de palabra) | Sí | No (no-op silencioso) | No (no-op silencioso) | Ancla con caracteres circundantes |
| `\w`, `\s` | Sí | No | No | `[[:alnum:]]`, `[[:space:]]` |
| `\<`, `\>` | Sí | No | No | `[[:<:]]`/`[[:>:]]` solo en BSD |
| `\+` en BRE | Sí | No (`+` literal) | No | Usa `-E` y `+` |
| `\t` en regex | Sí | No (`t` literal) | No | Usa tab literal o `[[:space:]]` |
| `\d` | No | No | No | Usa `[0-9]` o `[[:digit:]]` |

`\b` es la trampa más desagradable. Silenciosamente no coincide con nada, así que tu sustitución parece funcionar pero no hace nada. Sin error, sin advertencia.

</Tab>
<Tab name="Flags y opciones">

| Característica | GNU sed | macOS/BSD | busybox |
|----------------|---------|-----------|---------|
| `I` (insensible a mayúsculas) | Sí | Sí (Big Sur 11.0+) | Parcial |
| `-E` (regex extendida) | Sí | Sí (10.13+) | Mayormente |
| `--debug` | Sí (4.6+) | No | No |
| `--sandbox` | Sí | No | No |
| `-z` (delimitado por nulo) | Sí | No | No |

</Tab>
</Tabs>

### Wrapper universal de in-place para scripts

Si escribes scripts de sed que corren en múltiples plataformas (CI/CD, dotfiles compartidos, [comandos de Docker](/es/comandos-docker/) en Alpine), usa este patrón:

```sh
# Works on GNU, macOS, and Alpine busybox
sed -i.bak 's/foo/bar/' config.conf && rm config.conf.bak
```

Para pipelines de CI, envuélvelo en una función:
```sh
sed_inplace() {
    sed -i.bak "$@" && rm -f "${@: -1}.bak"
}
```

## Coincidencia avanzada de patrones con expresiones regulares

Las expresiones regulares son donde sed pasa de simple buscar-y-reemplazar a procesamiento de texto real. Los patrones de abajo cubren lo que de verdad vas a usar.

### Elementos básicos de expresiones regulares

**Carácter comodín (`.`):**
```sh
sed 's/t.st/test/g' filename        # Matches "test", "tast", "t3st", etc.
sed 's/c.t/cat/g' pets.txt          # Matches "cat", "cut", "cot", etc.
```

**Clases de caracteres:**
```sh
sed 's/[aeiou]/X/g' filename        # Replace any vowel with X
sed 's/[0-9]/N/g' filename          # Replace any digit with N
sed 's/[A-Z]/L/g' filename          # Replace uppercase letters with L
```

**Clases de caracteres predefinidas:**
```sh
sed 's/[[:digit:]]/N/g' filename    # Replace digits (same as [0-9])
sed 's/[[:alpha:]]/L/g' filename    # Replace letters
sed 's/[[:space:]]/X/g' filename    # Replace whitespace characters
```

### Cuantificadores

**Cero o más (`*`):**
```sh
sed 's/ab*c/X/g' filename          # Matches "ac", "abc", "abbc", "abbbc"
sed 's/[0-9]*/NUM/g' filename      # Matches empty string or any digits
```

**Uno o más (`\+` en BRE):**
```sh
sed 's/[0-9]\+/NUM/g' filename     # Matches one or more digits (GNU BRE extension)
sed 's/a\+/A/g' filename           # Matches "a", "aa", "aaa", etc.
```

<Notice type="info" title="Cuantificador uno-o-más portable">
`\+` en regex básica es una extensión GNU. Para scripts portables, usa `-E` (regex extendida) donde `+` funciona sin backslash: `sed -E 's/[0-9]+/NUM/g' filename`.
</Notice>

**Ocurrencias exactas (`\{n\}`):**
```sh
sed 's/[0-9]\{3\}/XXX/g' filename  # Matches exactly 3 digits
sed 's/a\{2,4\}/A/g' filename      # Matches 2 to 4 'a' characters
```

### Anclas y límites

**Anclas de línea:**
```sh
sed 's/^Error/WARNING/' filename    # Replace "Error" at line start
sed 's/end$/END/' filename          # Replace "end" at line end
sed 's/^$/EMPTY/' filename          # Replace empty lines
```

**Límites de palabra:**
```sh
sed 's/\bcat\b/dog/g' filename      # Replace whole word "cat" only
sed 's/\btest\b/exam/g' filename    # Avoids matching "testing" or "retest"
```

<Notice type="warning" title="\b es una extensión de GNU">
En BSD/macOS y busybox sed, `\b` se trata como un backslash literal + `b`. La sustitución no hace nada silenciosamente. Sin error, sin advertencia. En macOS, usa `[[:<:]]` y `[[:>:]]` para los límites de palabra. Para scripts portables, ancla con caracteres circundantes (espacios, puntuación, límites de línea).
</Notice>

### Ejemplos avanzados prácticos

**Formateo de números de teléfono:**
```sh
# Transform (123) 456-7890 to 123-456-7890
sed 's/(\([0-9]\{3\}\)) \([0-9]\{3\}\)-\([0-9]\{4\}\)/\1-\2-\3/g' contacts.txt
```

**Extracción y enmascaramiento de emails:**
```sh
# Replace email addresses with [EMAIL]
sed 's/[a-zA-Z0-9._%+-]\+@[a-zA-Z0-9.-]\+\.[a-zA-Z]\{2,\}/[EMAIL]/g' data.txt
```

**Conversión de formato de fecha:**
```sh
# Convert MM/DD/YYYY to YYYY-MM-DD
sed 's/\([0-9]\{2\}\)\/\([0-9]\{2\}\)\/\([0-9]\{4\}\)/\3-\1-\2/g' dates.txt
```

**Actualización de protocolos URL:**
```sh
# Change HTTP to HTTPS
sed 's|http://\([^[:space:]]*\)|https://\1|g' urls.txt
```

### Agrupación y referencias hacia atrás

**Grupos de captura con `\(\)` y referencias hacia atrás con `\1`, `\2`:**
```sh
# Swap first and last names
sed 's/\([A-Za-z]*\) \([A-Za-z]*\)/\2, \1/g' names.txt

# Duplicate words detection and removal (GNU-only: uses \b and \+)
sed 's/\b\([a-zA-Z]\+\) \1\b/\1/g' text.txt

# Extract filename from path
sed 's/.*\/\([^\/]*\)$/\1/' paths.txt
```

### Ejemplos de patrones complejos

**Procesamiento de logs:**
```sh
# Extract timestamp from log entries
sed 's/^\[\([0-9-: ]*\)\] .*/\1/' server.log

# Replace IP addresses with [IP]
sed 's/\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}/[IP]/g' access.log
```

**Refactorización de código:**
```sh
# Update function calls: oldFunc(param) -> newFunc(param)
sed 's/oldFunc(\([^)]*\))/newFunc(\1)/g' code.js

# Convert 'single-quoted' strings to "double-quoted" (simple case)
sed -E "s/'([^']*)'/\"\1\"/g" script.js
```

El ejemplo de comillas simples a dobles de arriba maneja casos simples. No maneja comillas simples escapadas (`\'`) dentro de strings. Para eso, usa un parser de verdad o `perl`.

### Expresiones regulares extendidas

**Usando el flag `-E` para patrones mejorados:**
```sh
# Alternation with |
sed -E 's/(cat|dog|bird)/animal/g' pets.txt

# Simplified quantifiers (no escaping needed)
sed -E 's/[0-9]{3}-[0-9]{2}-[0-9]{4}/XXX-XX-XXXX/g' ssn.txt

# Matching URL protocols
sed -E 's/(http|https):\/\/[^[:space:]]*/[URL]/g' text.txt
```

Nota: ERE de sed no tiene grupos sin captura (`(?:...)`). Todo grupo `()` captura. Usa `-E` por una sintaxis más limpia, no por comportamiento sin captura.

### Prueba y depuración de expresiones regulares

**Previsualiza coincidencias antes de reemplazar:**
```sh
# Show what would be matched
grep 'pattern' filename

# Show line numbers with matches
grep -n 'pattern' filename

# Test with sed's print flag
sed -n 's/pattern/replacement/p' filename
```

**Construye patrones incrementalmente:**
```sh
# Start simple
sed 's/[0-9]/X/' filename

# Add complexity gradually
sed 's/[0-9]\+/NUM/' filename

# Final complex pattern
sed 's/[0-9]\{3\}-[0-9]\{2\}-[0-9]\{4\}/XXX-XX-XXXX/' filename
```

**Usa `--debug` para trazar la ejecución (GNU sed 4.6+):**
```sh
echo 1 | sed --debug 's/1/3/'
```

Esto imprime el programa sed, anota cada línea de entrada mostrando el espacio PATTERN, y traza cada comando. Es la herramienta más útil para el "¿por qué mi comando sed hizo eso?". El flag `--debug` es maduro en GNU sed 4.10. Se arregló un crash que ocurría cuando una etiqueta precedía a la opción.

**Debugger externo:** [sedsed](https://github.com/aureliojargas/sedsed) es un depurador y formateador para scripts de sed. Útil para recorrer paso a paso scripts complejos de múltiples comandos.

**Advertencia sobre testers online:** regex101 y herramientas similares usan PCRE, no POSIX BRE/ERE. Características como lookarounds, cuantificadores no-greedy (`*?`), y `\d` no se transfieren a sed. Verifica siempre los patrones con sed de verdad.

## Técnicas avanzadas de sed y mejores prácticas

### Procesamiento dirigido de líneas

**Limita operaciones a rangos de línea específicos:**
```sh
sed '1,10s/old/new/g' file.txt      # Replace only in lines 1-10
sed '5,$s/old/new/g' file.txt       # Replace from line 5 to end
sed '10s/old/new/g' file.txt        # Replace only on line 10
```

**Apunta líneas por patrón:**
```sh
sed '/pattern/s/old/new/g' file.txt     # Replace only in lines containing "pattern"
sed '/^#/s/old/new/g' file.txt          # Replace only in comment lines
sed '/ERROR/s/old/new/g' log.txt        # Replace only in error lines
```

### Técnicas de previsualización y prueba

**Previsualiza cambios antes de aplicar:**
```sh
sed -n 's/old/new/p' file.txt           # Show only changed lines
sed 's/old/new/g' file.txt | head -20   # Preview first 20 lines
sed 's/old/new/g' file.txt | diff file.txt -  # Show differences
```

**Prueba con números de línea:**
```sh
nl file.txt | sed 's/old/new/g'        # Show line numbers for context
```

### Trabajando con caracteres especiales

**Escapa caracteres literales:**
```sh
sed 's/\./DOT/g' file.txt              # Escape literal dots
sed 's/\*/STAR/g' file.txt             # Escape literal asterisks
sed 's/\$/DOLLAR/g' file.txt           # Escape literal dollar signs
sed 's/\//SLASH/g' file.txt            # Escape literal forward slashes
```

**Usa delimitadores alternativos:**
```sh
sed 's|/old/path|/new/path|g' file.txt     # Use | for paths
sed 's#http://old#https://new#g' file.txt  # Use # for URLs
sed 's@old@new@g' file.txt                 # Use @ as delimiter
```

**Escapa `&` en el string de reemplazo:**

`&` en el reemplazo significa "toda la coincidencia". Un `&` literal en una URL o una reescritura de query-string corromperá tu salida:
```sh
echo 'foo' | sed 's/foo/A & B/'    # → "A foo B" (probably not intended)
echo 'foo' | sed 's/foo/A \& B/'   # → "A & B" (literal ampersand)
```

Esto muerde a la gente cuando reescribe URLs con parámetros de query (`&param=value`). Escapa siempre el `&` literal en el reemplazo con `\&`.

### Quoting de shell y sustitución de variables

Cuando los patrones de sed vienen de variables (común en scripts de actualización de config), el quoting del shell se vuelve delicado:

```sh
# Single quotes: no variable expansion (safe for literal patterns)
sed 's/old/new/g' file.txt

# Double quotes: variables expand, but /, &, \ in values collide with sed
KEY="old/path"
VAL="new/path"
sed "s|$KEY|$VAL|g" config.txt      # Use | delimiter when values contain /

# Always quote filenames in batch loops
for file in *.txt; do
    sed -i.bak 's/old/new/g' "$file"
done

# Use -- to stop option parsing for filenames starting with -
sed -i.bak 's/old/new/g' -- "-weird-name.txt"
```

Para más sobre las diferencias de quoting del shell, mira [el quoting entre Bash y Zsh](/es/fish-shell-vs-bash-vs-zsh-comparacion/).

### Procesamiento por lotes de múltiples archivos

**Procesa todos los archivos de un tipo:**
```sh
find . -name "*.txt" -exec sed -i 's/old/new/g' {} \;
find . -name "*.conf" -exec sed -i.bak 's/old/new/g' {} \;
```

**Usando xargs para eficiencia:**
```sh
find . -name "*.txt" | xargs sed -i 's/old/new/g'
find . -name "*.js" -print0 | xargs -0 sed -i 's/console.log/logger.debug/g'
```

**Bucle por los archivos:**
```sh
for file in *.txt; do
    sed -i.bak 's/old/new/g' "$file"
    echo "Processed: $file"
done
```

<Notice type="info" title="Archivos de config con symlink">
`sed -i` reemplaza el symlink con un archivo regular, rompiendo el enlace. Usa `sed -i --follow-symlinks 's/old/new/' /path/to/symlink` en GNU sed para editar el archivo destino. Esto importa para directorios de configuración como `/etc/nginx/sites-enabled/`. GNU sed 4.10 arregló una condición de carrera TOCTOU en `--follow-symlinks`.
</Notice>

Para más consejos de procesamiento de texto en Linux, mira cómo [extraer texto en la línea de comandos de Linux](/es/extraer-texto-pdf-linux/).

### Técnicas avanzadas de patrones

**Usando referencias hacia atrás para reemplazos complejos:**
```sh
# Swap two words
sed 's/\(foo\) \(bar\)/\2 \1/g' file.txt

# Duplicate text
sed 's/\(important\)/\1 \1/g' file.txt

# Rearrange data fields
sed 's/\([^,]*\),\([^,]*\),\([^,]*\)/\3,\1,\2/' data.csv
```

**Operaciones múltiples en secuencia:**
```sh
sed -e 's/old1/new1/g' -e 's/old2/new2/g' -e 's/old3/new3/g' file.txt
```

**Reemplazos condicionales:**
```sh
# Replace only if line contains specific pattern
sed '/contains_this/{s/old/new/g;}' file.txt

# Replace in specific sections
sed '/START/,/END/{s/old/new/g;}' file.txt
```

### Optimización de rendimiento

**Usa el locale C para trabajo pesado en ASCII:**
```sh
LC_ALL=C sed -E 's/[0-9]+/NUM/g' bigfile.txt
```

El locale por defecto hace coincidencia de caracteres consciente de Unicode, que es más lenta. Poner `LC_ALL=C` fuerza coincidencia de bytes ASCII y puede ser significativamente más rápido en archivos grandes con sustituciones pesadas en regex. Haz benchmark con tus propios datos.

**Otros consejos de rendimiento:**
```sh
# Skip the g flag when you only need the first match per line
sed 's/old/new/' file.txt

# One sed pass with semicolons beats multiple sed processes
sed 's/old1/new1/g; s/old2/new2/g; s/old3/new3/g' file.txt

# Use specific patterns to reduce processing
sed '/pattern/s/old/new/g' file.txt
```

### Estrategias de seguridad y backup

**Haz backup siempre de los archivos importantes:**
```sh
cp original.txt original.txt.backup
sed -i.$(date +%Y%m%d) 's/old/new/g' original.txt
```

**Prueba primero con datos de muestra:**
```sh
head -100 largefile.txt > sample.txt
sed 's/old/new/g' sample.txt          # Test your pattern
# If good, apply to original:
sed -i.backup 's/old/new/g' largefile.txt
```

**Edición in-place atómica (temp + mv):**

`sed -i` no es verdaderamente atómico. Escribe a un archivo temporal y renombra. Para archivos de configuración críticos, el patrón explícito temp + mv te da más control:
```sh
sed 's/old/new/' config.conf > config.conf.tmp && mv config.conf.tmp config.conf
```

Envuélvelo con un trap para limpieza en caso de fallo:
```sh
trap 'rm -f config.conf.tmp' EXIT
sed 's/old/new/' config.conf > config.conf.tmp && mv config.conf.tmp config.conf
trap - EXIT
```

Compensación: `mv` cambia el inodo, lo que importa si otro proceso tiene el archivo en `mmap` o si un file watcher monitoriza cambios de inodo.

**Usa control de versiones:**
```sh
git add file.txt                      # Stage current version
sed -i 's/old/new/g' file.txt         # Make changes
git diff                              # Review changes
```

Mira los [comandos de Git](/es/comandos-git/) para más sobre usar el control de versiones como red de seguridad.

### CI/CD e idempotencia

<Notice type="info" title="Sed idempotente en CI/CD">
`s/old/new/g` **no** es idempotente si `new` contiene `old`. Por ejemplo, `s/foo/foobar/g` corrido dos veces produce `foobarbar`. Para ediciones de config en CI/CD que se re-ejecutan en cada deploy, protégelo con un patrón de dirección, comprueba primero con `grep`, o usa una herramienta que sea idempotente de forma nativa.
</Notice>

**Códigos de salida:**
- `0`: éxito
- `1`: comando o regex inválido
- `2`: no puede abrir el archivo de entrada
- `4`: error de E/S o error de runtime grave

Puedes poner códigos de salida personalizados con `q N` o `Q N` (extensión GNU):
```sh
# Exit with code 2 if "ERROR" is found
sed '/ERROR/{q 2;}' logfile.txt
```

**Modo sandbox (GNU sed):**
```sh
sed --sandbox 's/old/new/g' untrusted.txt
```

`--sandbox` rechaza los comandos `e` (ejecutar), `w` (escribir) y `r` (leer). Úsalo cuando corres sed sobre entrada no confiable en pipelines.

**Procesamiento delimitado por nulo:**
```sh
find . -name "*.txt" -print0 | xargs -0 sed -i.bak 's/old/new/g'
```

El flag `-z` / `--null-data` (GNU sed) procesa entrada delimitada por NUL, que combina con `find -print0` y `sort -z` para manejar con seguridad nombres de archivo con espacios.

### Ejemplos prácticos de flujo de trabajo

**Actualizaciones de archivos de configuración:**
```sh
# Update server configuration across multiple files
find /etc/nginx -name "*.conf" -exec sed -i.backup \
    -e 's/old-server.com/new-server.com/g' \
    -e 's/port 8080/port 80/g' {} \;
```

**Refactorización de código:**
```sh
# Update function names in JavaScript files
find ./src -name "*.js" -exec sed -i \
    's/oldFunction/newFunction/g' {} \;
```

**Procesamiento de logs:**
```sh
# Clean and standardize log files
sed -e 's/DEBUG/[DEBUG]/g' \
    -e 's/ERROR/[ERROR]/g' \
    -e 's/INFO/[INFO]/g' app.log > standardized.log
```

### Errores comunes a evitar

1. **Olvidar escapar caracteres especiales.** `.`, `*`, `$`, `[`, `\` tienen todos significado especial en regex.
2. **No probar los patrones antes de aplicarlos a archivos importantes.** Previsualiza siempre con stdout primero.
3. **Usar reemplazo global cuando solo quieres la primera ocurrencia.** Omite el flag `g`.
4. **No hacer backup de archivos antes de la edición in-place.** Usa `-i.bak` o `cp`.
5. **Hacer patrones demasiado amplios.** Coincidir texto no deseado con `.*` o un `.` sin escapar.
6. **Usar escapes solo-GNU en scripts portables.** `\b`, `\t`, `\+` fallan silenciosamente en macOS/Alpine.
7. **Combinar `-n` con `-i`.** Trunca el archivo a cero bytes.
8. **Olvidar que `&` en el reemplazo significa "toda la coincidencia".** Escapa el `&` literal como `\&`.

### Consejos pro

- Empieza con patrones simples y añade complejidad gradualmente
- Usa `grep` para probar tus patrones antes de usarlos en `sed`
- Usa `--debug` (GNU sed 4.6+) para trazar la ejecución cuando los patrones se comportan mal
- Usa `LC_ALL=C` para procesamiento más rápido de datos ASCII
- Mantén una colección de patrones sed probados para reutilizar
- Documenta las expresiones regulares complejas para referencia futura
- Sabe cuándo dejar de usar sed. Para ramificaciones, hold space, o slurps multilínea, usa `awk` o Python.

## Conclusión

El comando `s` de sed es la herramienta correcta para ediciones de texto de una línea orientadas a líneas. Maneja actualizaciones de configuración, limpieza de datos y reemplazos por lotes sin cargar el archivo completo en memoria.

Lo clave a recordar: prueba sin `-i` primero, usa `-i.bak` para backups, y sabe qué sabor de sed estás corriendo. GNU sed en Linux, BSD sed en macOS, y busybox sed en Alpine se comportan todos diferente para `-i`, `\b`, `\t`, y el flag `I`. Escribe el sed para la máquina donde corre.

Para transformaciones complejas que involucren ramificaciones, hold space, o procesamiento multilínea, usa `awk` o Python en su lugar. Haz siempre backup de tus datos antes de ediciones in-place, y practica incrementalmente con archivos de muestra.