1. Introducción a los entornos de trabajo UNIX

1.9. Acceder al contenido de los ficheros

1.9.3. Edición de archivos con el editor de flujo sed (stream editor)

El nombre del comando sed proviene de stream editor (‘editor de flujo’). Aquí, stream se refiere a los datos que se pasan mediante tuberías de shell. Por lo tanto, la funcionalidad principal del comando es actuar como un editor de texto para los datos de entrada de la entrada estándar (stdin), con la salida estándar (stdout) como el destino de salida. También podéis editar la entrada de un archivo y guardar los cambios en el mismo archivo si es necesario.

La sintaxis básica de sed es  sed [options] {commands} {input-file}

La manera de trabajar de sed es la siguiente. El comando sed lee la primera línea del {archivo-de-entrada} y ejecuta los {comandos} en la primera línea. Luego lee la segunda línea del {archivo-de-entrada} y ejecuta los {comandos} en la segunda línea. El comando sed repite este proceso hasta que llega al final del {archivo-de-entrada}.

Editad con vi el fichero test.bed y realizad cada una de las operaciones que se muestran a continuación para entender la potencia del comando sed.

$ cat test.bed
chr1 100 200

chr1 300 500

chr2 240 440

chr2 400 600

chr3 0 150

 Sustitución

 # Sustituye todos los strings que coincidan con chr1 por chr2

$ sed 's/chr1/chr2/' test.bed
chr2 100 200

chr2 300 500

chr2 240 440

chr2 400 600

chr3 0 150

# Sustituye todos los strings que coincidan con chr1 por chr2 solo si la línea contiene 300

$sed '/300/s/chr1/chr2/' test.bed
chr1 100 200

chr2 300 500

chr2 240 440

chr2 400 600

chr3 0 150

# Sustituye todos los strings que coincidan con chr1 por chr2 solo si la línea no contiene 300

$sed '/300/! s/chr1/chr2/' test.bed
chr2 100 200

chr1 300 500

chr2 240 440

chr2 400 600

chr3 0 150

# Reemplaza todos los strings que coincidan con chr si son los primeros caracteres de la línea

$ sed 's/^chr//' test.bed
1 100 200

1 300 500

2 240 440

2 400 600

3 0 150

# Sustituye la primera ocurrencia en cada una de las líneas

$ sed 's/00/55/' test.bed
chr1 155 200

chr1 355 500

chr2 240 440

chr2 455 600

chr3 0 150

# Sustituye todas las ocurrencias que coincidan en el patrón

$ sed 's/00/55/g' test.bed
chr1 155 255

chr1 355 555

chr2 240 440

chr2 455 655

chr3 0 150

# Imprime la línea donde coincida la sustitución

$ sed -n 's/00/55/p' test.bed
chr1 155  200

chr1 355  500

chr2 455  600

# Se pueden realizar sustituciones con diferentes flags simultáneamente

$ sed -n 's/00/55/pg' test.bed
chr1 155  255

chr1 355  555

chr2 455  655

Eliminar

# Elimina la segunda línea del fichero

$ sed '2 d' test.bed
chr1 100 200

chr2 240 440

chr2 400 600

chr3 0 150

# Elimina de la línea 2 a la 4

$ sed '2,4 d' test.bed
chr1 100 200

chr3 0 150

# Elimina desde que encuentres el string chr1 a la línea 4

$ sed '/chr1/, 4 d' test.bed
chr3 0 150

# Elimina desde la primera línea que encuentres con chr1 hasta la primera vez que encuentres chr2

$ sed '/chr1/, /chr2/ d' test.bed
chr2 400 600

chr3 0 150

Edición implícita

El fichero de entrada y de salida es el mismo. Hazlo cuando estés seguro del cambio.

$ sed -i 's/00/55/g' test.bed
$ cat test.bed
chr1 155 255

chr1 355 555

chr2 240 440

chr2 455 655

chr3 0 150

¡Porque el fichero original ha cambiado!

Sustituciones regexp

Las expresiones regulares son muy útiles, y vale la pena tomarse el tiempo para aprender los conceptos básicos. Se pueden ampliar conocimientos utilizando herramientas en línea para construir y probar expresiones regulares (por ejemplo, https://regex101.com/ A continuación se enumeran algunas de las importantes:

Anclas:

^ restringe la coincidencia al inicio de la cadena.

$ restringe la coincidencia al final de la cadena.

Metacaracteres y cuantificadores

  • . coincide con cualquier carácter, incluyendo el carácter de nueva línea.
  • ? coincide 0 o 1 vez.
  • * coincide 0 o más veces.
  • + coincide 1 o más veces.
  • {m,n} coincide de m a n veces.
  • {m,} coincide al menos m veces.
  • {,n} coincide hasta n veces (incluyendo 0 veces).
  • {n} coincide exactamente n.

Clases de caracteres:

  • [set123] coincide con cualquiera de estos caracteres una vez.
  • [^set123] coincide excepto con cualquiera de estos caracteres una vez.
  • [3-7AM-X] rango de caracteres desde 3 hasta 7, A, otro rango desde M hasta X.
  • [[:digit:]] similar a [0-9] [[:alnum:]_] similar a \w

# Elimina la primera columna: . define cualquier carácter después de chr

$ sed 's/^chr.//' test.bed
      100  200

      300  500

      240  440

      400  600

      0    150

# Elimina todos los ceros presentes en el fichero

$ sed 's/0*//g' test.bed
chr1 1    2

chr1 3    5

chr2 24   44

chr2 4    6

chr3      15

# Elimina todos los números entre el 1 y el 3

$sed 's/[1-3]//g' test.bed
chr  00   00

chr  00   500

chr  40   440

chr  400  600

chr  0    50

# Sustituye el string ch por nada

$sed 's/[cr]//g' test.bed
h1   100  200

h1   300  500

h2   240  440

h2   400  600

h3   0    150

# Sustituye cualquier letra entre la a y la z por nada

$sed 's/[a-z]//g' test.bed
1    100  200

1    300  500

2    240  440

2    400  600

3              0     150

# sustituye por la cadena que coincide con el patrón

$ sed 's/^chr[0-9]/[&]/' test.bed
[chr1] 100 200

[chr1] 300 500

[chr2] 240 440

[chr2] 400 600

[chr3] 0 150

# Sustituye todas las ocurrencias que encajan en el patrón y escribe al final de la línea '+'

$ sed 's/00/55/g ; s/$/\+/' test.bed
chr1 155 255 +

chr1 355 555 +

chr2 240 440 +

chr2 455 655 +

chr3 0 150 +

# Sustituye la ocurrencia que coincide exactamente con 2 ceros

$ sed 's/0\{2\}/match/g' test.bed
chr1 1match    2match

chr1 3match    5match

chr2 240  440

chr2 4match    6match

chr3 0    150

# Sustituye la ocurrencia que coincide con 1 o 2 ceros

$ sed 's/0\{1,2\}/match/g' test.bed
chr1 1match    2match

chr1 3match    5match

chr2 24match   44match

chr2 4match    6match

chr3 match 15match

# Elimina todas las líneas en blanco del fichero

sed '/^$/ d' text.bed or sed '/^#/ d' test.bed