1.9. Accedir al contingut dels fitxers
1.9.3. Edició d’arxius amb l’editor de flux sed (stream editor)
El nom de l’ordre sed
prové de stream editor (‘editor de flux’). Aquí, stream es refereix a les dades que es passen mitjançant tubs de shell. Per tant, la funcionalitat principal de l’ordre és actuar com un editor de text per a les dades d’entrada de l’entrada estàndard (stdin), amb la sortida estàndard (stdout) com el destí de sortida. També podem editar l’entrada d’un arxiu i guardar els canvis en el mateix arxiu si és necessari.
La sintaxi bàsica de sed
és sed [options] {commands} {input-file}
La manera de treballar de sed
és la següent: l’ordre sed llegeix la primera línia de l’{arxiu-de-entrada} i executa les {ordres} a la primera línia. Després llegeix la segona línia de l’{arxiu-de-entrada} i executa les {ordres} a la segona línia. L’ordre sed
repeteix aquest procés fins que arriba al final de l’{arxiu-de-entrada}.
Editeu amb vi el fitxer test.bed i realitzeu cadascuna de les operacions que es mostren a continuació per entendre la potència de l’ordre sed:
$ cat test.bed
chr1 100 200 chr1 300 500 chr2 240 440 chr2 400 600 chr3 0 150
Alternativa:
chr1 100 200
chr1 300 500
chr2 240 440
chr2 400 600
chr3 0 150
Substitució
# Substitueix tots els strings que coincideixen amb chr1 per chr2
$ sed 's/chr1/chr2/' test.bed
chr2 100 200
chr2 300 500
chr2 240 440
chr2 400 600
chr3 0 150
# Substitueix tots els strings que coincideixen amb chr1 per chr2 només si la línia conté 300
$sed '/300/s/chr1/chr2/' test.bed
chr1 100 200 chr2 300 500 chr2 240 440 chr2 400 600 chr3 0 150
# Substitueix tots els strings que coincideixen amb chr1 per chr2 només si la línia no conté 300
$sed '/300/! s/chr1/chr2/' test.bed
chr2 100 200 chr1 300 500 chr2 240 440 chr2 400 600 chr3 0 150
# Reemplaça tots els strings que coincideixen amb chr si són els primers caràcters de la línia
$ sed 's/^chr//' test.bed
1 100 200 1 300 500 2 240 440 2 400 600 3 0 150
# Substitueix la primera ocurrència en cadascuna de les línies
$ sed 's/00/55/' test.bed
chr1 155 200 chr1 355 500 chr2 240 440 chr2 455 600 chr3 0 150
# Substitueix totes les ocurrències que coincideixin en el patró
$ sed 's/00/55/g' test.bed
chr1 155 255 chr1 355 555 chr2 240 440 chr2 455 655 chr3 0 150
# Imprimeix la línia on coincideix la substitució
$ sed -n 's/00/55/p' test.bed
chr1 155 200 chr1 355 500 chr2 455 600
# Es poden realitzar substitucions amb diferents flags simultàniament
$ sed -n 's/00/55/pg' test.bed
chr1 155 255 chr1 355 555 chr2 455 655
Eliminar
# Elimina la segona línia del fitxer
$ 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 des de l’string chr1 a la línia 4
$ sed '/chr1/, 4 d' test.bed
chr3 0 150
# Elimina des de la primera línia que troba amb chr1 fins a la primera vegada que troba chr2
$ sed '/chr1/, /chr2/ d' test.bed
chr2 400 600 chr3 0 150
Edició implícita
El fitxer d’entrada i de sortida és el mateix. Feu-lo quan estiguis segur del canvi.
$ 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
Perquè el fitxer original ha canviat!
Substitucions regexp
Les expressions regulars són molt útils, i val la pena dedicar el temps per aprendre els conceptes bàsics. Es poden ampliar coneixements utilitzant eines en línia per construir i provar expressions regulars (per exemple, https://regex101.com/). A continuació enumerem algunes de les importants:
Àncores:
^
restringeix la coincidència a l’inici de la cadena.
$
restringeix la coincidència al final de la cadena.
Metacaràcters i quantificadors
.
coincideix amb qualsevol caràcter, incloent-hi el caràcter de nova línia.?
coincideix 0 o 1 vegada.*
coincideix 0 o més vegades.+
coincideix 1 o més vegades.{m,n}
coincideix de m a n vegades.{m,}
coincideix almenys m vegades.{,n}
coincideix fins a n (incloent-hi 0 vegades).{n}
coincideix exactament n.
Classes de caràcters:
[set123]
coincideix amb qualsevol d’aquests caràcters una vegada.[^set123]
coincideix excepte amb qualsevol d’aquests caràcters una vegada.[3-7AM-X]
rang de caràcters des de 3 fins a 7, A, un altre rang des de M fins a X.[[:digit:]]
similar a[0-9] [[:alnum:]_]
semblant a\w
# Elimina la primera columna: . defineix qualsevol caràcter després de chr
$ sed 's/^chr.//' test.bed
100 200 300 500 240 440 400 600 0 150
# Elimina tots els zeros presents al fitxer
$ sed 's/0*//g' test.bed
chr1 1 2 chr1 3 5 chr2 24 44 chr2 4 6 chr3 15
# Elimina tots els números entre l’1 i el 3
$sed 's/[1-3]//g' test.bed
chr 00 00 chr 00 500 chr 40 440 chr 400 600 chr 0 50
# Substitueix l’string ch per res
$sed 's/[cr]//g' test.bed
h1 100 200 h1 300 500 h2 240 440 h2 400 600 h3 0 150
# S’utilitza qualsevol lletra entre la a i la z per res
$sed 's/[a-z]//g' test.bed
1 100 200 1 300 500 2 240 440 2 400 600 3 0 150
# Substitueix per la cadena que coincideix amb el patró
$ sed 's/^chr[0-9]/[&]/' test.bed
[chr1] 100 200 [chr1] 300 500 [chr2] 240 440 [chr2] 400 600 [chr3] 0 150
# Substitueix totes les ocurrències que encaixen en el patró i escriu al final de la línia '+'
$ sed 's/00/55/g ; s/$/\+/' test.bed
chr1 155 255 + chr1 355 555 + chr2 240 440 + chr2 455 655 + chr3 0 150 +
# Substitueix l’ocurrència que coincideix exactament amb 2 zeros
$ sed 's/0\{2\}/match/g' test.bed
chr1 1match 2match chr1 3match 5match chr2 240 440 chr2 4match 6match chr3 0 150
# Substitueix l’ocurrència que coincideix amb 1 o 2 zeros
$ 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 totes les línies en blanc del fitxer
sed '/^$/ d' text.bed or sed '/^#/ d' test.bed