sed con cuantificadores numéricos - ¿cómo?
Estoy tratando de editar los encabezados fasta de varios archivos para eliminar una barra inclinada y todo lo que sigue (siempre que "todo lo que sigue" sea igual o inferior a 10 caracteres). Las líneas de encabezado están marcadas con un '>'.
for i in ./*.fa;do sed -r 's/(>.*)\/.\{,10\}\n/\1\n/' "$i"; done
También lo he intentado
for i in ./*.fa;do sed -r 's/(>.*)\/.{,10}\n/\1\n/' "$i"; done
pero no parece ser mejor. Mi corazonada es que es el cuantificador {, 10} el que rompe las cosas. Aunque no estoy seguro. ¡La ayuda será muy apreciada!
Por ejemplo, si lo siguiente estaba en un archivo:
>header1_some_extra_data_here/1-1000
ATGCGGGTACCCCA
>code/header2_some_extra_data
AGGTCCCCGGGAAAAA
Me gustaría que el siguiente fuera el resultado:
>header1_some_extra_data_here
ATGCGGGTACCCCA
>code/header2_some_extra_data
AGGTCCCCGGGAAAAA
Respuestas
Sus sedsustituciones no funcionarán como se esperaba porque nunca podrá hacer coincidir una nueva línea en los datos de entrada. Esto se debe a que sedlee su archivo línea por línea, es decir, con las líneas nuevas como delimitadores, y las expresiones se aplican a las líneas individualmente, sin las líneas nuevas delimitadores.
En cambio, cambiando ligeramente su código:
for fasta in ./*.fa; do
sed 's;^\(>.*\)/.\{0,10\}$;\1;' "$fasta"
done
Los pocos cambios que he realizado son:
- Úselo
;como delimitador para els///comando en lugar del predeterminado/. Esto nos permite no escapar/del patrón. Se puede usar casi cualquier carácter como delimitador, pero probablemente se debería elegir uno que no aparezca en el patrón o en el texto de reemplazo. - Utilice solo la sintaxis de expresión regular básica estándar. En su patrón,
(...)es una sintaxis de expresión regular extendida y\{...\}es una sintaxis de expresión regular básica. Me decidí por usar la sintaxis básica para la portabilidad. Esto también significa eliminar la-ropción que habilita la sintaxis extendida en GNUsed. - Anclar el patrón al principio y al final de la línea con
^y$respectivamente. - No intente insertar una nueva línea en la broca de reemplazo.
Una sedexpresión alternativa y más corta sería
sed '/^>/s;/.\{0,10\}$;;'
Esto aplica una sustitución a todas las líneas que comienzan con el >carácter ( /^>/actúa como la "dirección" para el s///comando posterior ). La sustitución simplemente elimina el /bit y el bit que sigue al final de la línea si ese bit tiene 10 caracteres o menos.
He aquí una forma ligeramente diferente:
Guarde la salida en archivos nuevos:
for file in *fa; do sed -E 's|^\s*(>.{10,}.*)/.*|\1|' "$file" > "$file.fixed"; doneEdite los archivos en su lugar:
sed -i -E 's|^\s*(>.{10,}.*)/.*|\1|' *.fa
La -Eopción habilita expresiones regulares extendidas. Esto nos permite usar ()para capturar y {}para repeticiones sin necesidad de escapar de ellas. También cambié el delimitador a |para mayor claridad y agregué ^\s*(tenga en cuenta que es posible que esto no sea compatible con su sed; si no lo es, puede usarlo ^ *) ya que a veces puede tener espacios >en blanco antes de los archivos en fasta.
Luego, el truco consiste en hacer coincidir a >seguido de 10 o más caracteres hasta que a /, capture estos caracteres con los paréntesis para que se conviertan en \1y reemplace toda la línea con solo la parte correspondiente.
Tenga en cuenta que esto encontrará el tramo más largo de> 10 caracteres hasta el último /. Entonces, si hay varios /en la misma línea, se mantendrán todos menos el último. Por ejemplo:
$ echo ">header1_some_extra_data_here/1-1000/foo/bar/baz" |
sed -E 's|^\s*(>.{10,}.*)/.*|\1|'
>header1_some_extra_data_here/1-1000/foo/bar
Para evitar eso, y eliminar todo después del primero /, siempre que ya haya coincidido con 10 caracteres, use:
sed -E 's|^\s*(>.{10}[^/]*)/.*|\1|'