Pregunta

Estoy teniendo un poco de problemas para conseguir una expresión regular de Python para trabajar cuando se compara contra el texto que abarca varias líneas. El texto ejemplo es ( '\ n' es un salto de 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 se produce dos líneas por debajo de ella en una captura (i puede despojar a cabo los caracteres de nueva línea más adelante). He intentado 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 una gran cantidad de variaciones del presente sin suerte. El último parece coincidir con las líneas de texto uno a uno, que no es lo que realmente quiero. Soy capaz de captar la primera parte, no hay problema, pero me parece que no puede atrapar a los 4-5 líneas de texto en mayúsculas. Me gustaría match.group (1) que se some_Varying_Text y el grupo (2) para ser línea 1 + line2 + línea3 + etc hasta que se encuentra la línea de vacío.

Si alguien tiene curiosidad, se supone que es una secuencia de aminoácidos que forman una proteína.

¿Fue útil?

Solución

Prueba esto:

re.compile(r"^(.+)\n((?:\n.+)+)", re.MULTILINE)

Creo que su mayor problema es que usted está esperando los anclajes ^ y $ para que coincida con los avances de línea, pero no lo hacen. En el modo de multilínea, ^ coincide con la posición inmediatamente siguiente un salto de línea y $ coincida con la posición inmediatamente anterior una nueva línea.

Tenga en cuenta, también, que un salto de línea puede consistir en un avance de línea (\ n), un retorno de carro (\ r), o un retorno de carro + avance de línea (\ r \ n). Si no está seguro de que el texto de destino utiliza sólo los avances de línea, se debe utilizar esta versión más inclusiva de la expresión regular:

re.compile(r"^(.+)(?:\n|\r\n?)((?:(?:\n|\r\n?).+)+)", re.MULTILINE)

Por cierto, usted no desea utilizar el modificador dotall aquí; usted está confiando en el hecho de que el punto coincide con todo lo excepto saltos de línea.

Otros consejos

Esto funciona:

>>> import re
>>> rx_sequence=re.compile(r"^(.+?)\n\n((?:[A-Z]+\n)+)",re.MULTILINE)
>>> rx_blanks=re.compile(r"\W+") # to remove blanks and newlines
>>> text="""Some varying text1
...
... AAABBBBBBCCCCCCDDDDDDD
... EEEEEEEFFFFFFFFGGGGGGG
... HHHHHHIIIIIJJJJJJJKKKK
...
... Some varying text 2
...
... LLLLLMMMMMMNNNNNNNOOOO
... PPPPPPPQQQQQQRRRRRRSSS
... TTTTTUUUUUVVVVVVWWWWWW
... """
>>> for match in rx_sequence.finditer(text):
...   title, sequence = match.groups()
...   title = title.strip()
...   sequence = rx_blanks.sub("",sequence)
...   print "Title:",title
...   print "Sequence:",sequence
...   print
...
Title: Some varying text1
Sequence: AAABBBBBBCCCCCCDDDDDDDEEEEEEEFFFFFFFFGGGGGGGHHHHHHIIIIIJJJJJJJKKKK

Title: Some varying text 2
Sequence: LLLLLMMMMMMNNNNNNNOOOOPPPPPPPQQQQQQRRRRRRSSSTTTTTUUUUUVVVVVVWWWWWW

Algunas explicaciones acerca de esta expresión regular puede ser útil: ^(.+?)\n\n((?:[A-Z]+\n)+)

  • El primer carácter (^) significa "empezando por el principio de una línea". Tenga en cuenta que no coincide con el salto de línea en sí. (Lo mismo para $: significa "justo antes de una nueva línea", pero no coincide con el salto de línea en sí)
  • A continuación, (.+?)\n\n significa "coincide con el menor número de caracteres como sea posible (todos los caracteres están permitidos) hasta llegar a dos saltos de línea". El resultado (sin los saltos de línea) se pone en el primer grupo.
  • [A-Z]+\n significa "coincide con el mayor número de letras mayúsculas como sea posible hasta que llegue una nueva línea. Esto define lo que llamaré un línea de texto .
  • ((?: línea de texto significa )+) partido de uno o más líneas de texto , pero no ponga cada línea en un grupo. En su lugar, poner todos líneas de texto en un grupo.
  • Se podría añadir un \n final en la expresión regular si quiere cumplir un doble salto de línea al final.
  • Además, si usted no está seguro sobre qué tipo de salto de línea obtendrá (\n o \r o \r\n) a continuación, sólo fijar la expresión regular mediante la sustitución de todas las apariciones de \n por (?:\n|\r\n?).

Si cada archivo sólo tiene una secuencia de aminoácidos de, yo no utilizar expresiones regulares en absoluto. Sólo algo como esto:

def read_amino_acid_sequence(path):
    with open(path) as sequence_file:
        title = sequence_file.readline() # read 1st line
        aminoacid_sequence = sequence_file.read() # read the rest

    # some cleanup, if necessary
    title = title.strip() # remove trailing white spaces and newline
    aminoacid_sequence = aminoacid_sequence.replace(" ","").replace("\n","")
    return title, aminoacid_sequence

hallazgo:

^>([^\n\r]+)[\n\r]([A-Z\n\r]+)

\ 1 = some_varying_text

\ 2 = líneas de todos los CAPS

Editar (prueba de que esto funciona):

text = """> some_Varying_TEXT

DSJFKDAFJKDAFJDSAKFJADSFLKDLAFKDSAF
GATACAACATAGGATACA
GGGGGAAAAAAAATTTTTTTTT
CCCCAAAA

> some_Varying_TEXT2

DJASDFHKJFHKSDHF
HHASGDFTERYTERE
GAGAGAGAGAG
PPPPPAAAAAAAAAAAAAAAP
"""

import re

regex = re.compile(r'^>([^\n\r]+)[\n\r]([A-Z\n\r]+)', re.MULTILINE)
matches = [m.groups() for m in regex.finditer(text)]

for m in matches:
    print 'Name: %s\nSequence:%s' % (m[0], m[1])

La siguiente es una expresión regular que coincida con un bloque de varias líneas de texto:

import re
result = re.findall('(startText)(.+)((?:\n.+)+)(endText)',input)

Mi preferencia.

lineIter= iter(aFile)
for line in lineIter:
    if line.startswith( ">" ):
         someVaryingText= line
         break
assert len( lineIter.next().strip() ) == 0
acids= []
for line in lineIter:
    if len(line.strip()) == 0:
        break
    acids.append( line )

En este punto se han someVaryingText como una cadena, y los ácidos como una lista de cadenas. Usted puede hacer "".join( acids ) para hacer una sola cadena.

Me parece menos frustrante (y más flexible) de expresiones regulares de varias líneas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top