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