Tengo un poco de problemas para hacer que una expresión regular de Python funcione cuando se compara con texto que abarca varias líneas. El texto de ejemplo es ('\ n' es una nueva línea)
some Varying TEXT\n
\n
DSJFKDAFJKDAFJDSAKFJADSFLKDLAFKDSAF\n
[more of the above, ending with a newline]\n
[yep, there is a variable number of lines here]\n
\n
(repeat the above a few hundred times).
Me gustaría capturar dos cosas: la parte 'some_Varying_TEXT' y todas las líneas de texto en mayúsculas que vienen dos líneas debajo en una captura (puedo eliminar los caracteres de nueva línea más adelante). Lo intenté con algunos enfoques:
re.compile(r"^>(\w+)$$([.$]+)^$", re.MULTILINE) # try to capture both parts
re.compile(r"(^[^>][\w\s]+)$", re.MULTILINE|re.DOTALL) # just textlines
y muchas variaciones del mismo sin suerte. El último parece coincidir con las líneas de texto una por una, que no es lo que realmente quiero. Puedo captar la primera parte, no hay problema, pero parece que no puedo captar las 4-5 líneas de texto en mayúsculas. Me gustaría que match.group (1) sea some_Varying_Text y group (2) sea line1 + line2 + line3 + etc hasta que se encuentre la línea vacía.
Si alguien tiene curiosidad, se supone que es una secuencia de aminoácidos que forman una proteína.
>
carácter principal . ¿Deberia?Respuestas:
Prueba esto:
Creo que su mayor problema es que usted está esperando el
^
y$
anclajes para que coincida con los avances de línea, pero no lo hacen. En el modo multilínea,^
coincide con la posición inmediatamente siguiente a una nueva línea y$
coincide con la posición inmediatamente anterior a una nueva línea.También tenga en cuenta que una nueva línea puede consistir en un salto de línea (\ n), un retorno de carro (\ r) o un retorno de carro + salto de línea (\ r \ n). Si no está seguro de que su texto de destino use solo avances de línea, debe usar esta versión más inclusiva de la expresión regular:
Por cierto, no quieres usar el modificador DOTALL aquí; confía en el hecho de que el punto coincide con todo excepto con las nuevas líneas.
fuente
Esto funcionará:
Alguna explicación sobre esta expresión regular puede ser útil:
^(.+?)\n\n((?:[A-Z]+\n)+)
^
) significa "comenzando al principio de una línea". Tenga en cuenta que no coincide con la nueva línea en sí (lo mismo para $: significa "justo antes de una nueva línea", pero no coincide con la nueva línea).(.+?)\n\n
significa "hacer coincidir la menor cantidad de caracteres posible (se permiten todos los caracteres) hasta llegar a dos nuevas líneas". El resultado (sin las nuevas líneas) se coloca en el primer grupo.[A-Z]+\n
significa "coincidir con tantas letras mayúsculas como sea posible hasta llegar a una nueva línea. Esto define lo que llamaré una línea de texto" .((?:
línea de texto)+)
significa hacer coincidir una o más líneas de texto pero no poner cada línea en un grupo. En su lugar, coloque todas las líneas de texto en un grupo.\n
en la expresión regular si desea aplicar un salto de línea doble al final.\n
o\r
o\r\n
), simplemente corrija la expresión regular reemplazando cada aparición de\n
por(?:\n|\r\n?)
.fuente
Si cada archivo solo tiene una secuencia de aminoácidos, no usaría expresiones regulares en absoluto. Algo como esto:
fuente
encontrar:
\ 1 = algún_texto_variado
\ 2 = líneas de todas las MAYÚSCULAS
Editar (prueba de que esto funciona):
fuente
La siguiente es una expresión regular que coincide con un bloque de texto de varias líneas:
fuente
Mi preferencia.
En este punto, tiene someVaryingText como una cadena y los ácidos como una lista de cadenas. Puedes hacer
"".join( acids )
para hacer una sola cuerda.Encuentro esto menos frustrante (y más flexible) que las expresiones regulares de varias líneas.
fuente