Python Regex: extraer texto entre expresiones (múltiples) en un archivo de texto

Soy un principiante de Python y estaría muy agradecido si pudiera ayudarme con mi problema de extracción de texto.

Quiero extraer todo el texto, que se encuentra entre dos expresiones en un archivo de texto (el principio y el final de una letra). Tanto para el principio como para el final de la letra hay varias expresiones posibles (definidas en las listas “letter_begin” y “letter_end”, por ejemplo, “Dear”, “to our”, etc.). Quiero analizar esto para un montón de archivos, a continuación se muestra un ejemplo de cómo se ve un archivo de texto de este tipo -> Quiero extraer todo el texto desde “Estimado” hasta “Douglas”. En los casos en los que “letter_end” no tiene ninguna coincidencia, es decir, no se encuentra ninguna expresión letter_end, la salida debe comenzar desde letter_beginning y terminar al final del archivo de texto que se analizará.

Edición: el final de “el texto grabado” debe estar después de la coincidencia de “letter_end” y antes de la primera línea con 20 caracteres o más (como es el caso de “Texto aleatorio aquí también” -> len = 24.

"""Some random text here  Dear Shareholders We are pleased to provide you with this semiannual report for Fund for the six-month period ended April 30, 2018. For additional information about the Fund, please visit our website a, where you can access quarterly commentaries. We value the trust that you place in us and look forward to serving your investment needs in the years to come. Best regards Douglas Random text here as well""" 

Este es mi código hasta ahora, pero no puede capturar el texto entre las expresiones (puede haber cualquier cosa (líneas, texto, números, signos, etc.) antes de “letter_begin” y después de “letter_end”)

 import re letter_begin = ["dear", "to our", "estimated"] # All expressions for "beginning" of letter openings = "|".join(letter_begin) letter_end = ["sincerely", "yours", "best regards"] # All expressions for "ending" of Letter closings = "|".join(letter_end) regex = r"(?:" + openings + r")\s+.*?" + r"(?:" + closings + r"),\n\S+" with open(filename, 'r', encoding="utf-8") as infile: text = infile.read() text = str(text) output = re.findall(regex, text, re.MULTILINE|re.DOTALL|re.IGNORECASE) # record all text between Regex (Beginning and End Expressions) print (output) 

Estoy muy agradecido por cada ayuda!

Puedes utilizar

 regex = r"(?:{})[\s\S]*?(?:{}).*(?:\n.*){{0,2}}".format(openings, closings) 

Este patrón dará como resultado una expresión regular como

 (?:dear|to our|estimated)[\s\S]*?(?:sincerely|yours|best regards).*(?:\n.*){0,2} 

Vea la demostración de expresiones regulares . Tenga en cuenta que no debe usar re.DOTALL con este patrón, y la opción re.MULTILINE también es redundante.

Detalles

  • (?:dear|to our|estimated) – cualquiera de los tres valores
  • [\s\S]*? – cualquier 0+ caracteres, el menor número posible
  • (?:sincerely|yours|best regards) – cualquiera de los tres valores
  • .* – cualquier 0+ caracteres distintos de la nueva línea
  • (?:\n.*){0,2} – cero, una o dos repeticiones de una nueva línea seguidas con más de 0 caracteres distintos de la nueva línea.

Código de demostración de Python :

 import re text="""Some random text here Dear Shareholders We are pleased to provide you with this semiannual report for Fund for the six-month period ended April 30, 2018. For additional information about the Fund, please visit our website a, where you can access quarterly commentaries. We value the trust that you place in us and look forward to serving your investment needs in the years to come. Best regards Douglas Random text here as well""" letter_begin = ["dear", "to our", "estimated"] # All expressions for "beginning" of letter openings = "|".join(letter_begin) letter_end = ["sincerely", "yours", "best regards"] # All expressions for "ending" of Letter closings = "|".join(letter_end) regex = r"(?:{})[\s\S]*?(?:{}).*(?:\n.*){{0,2}}".format(openings, closings) print(regex) print(re.findall(regex, text, re.IGNORECASE)) 

Salida:

 ['Dear Shareholders We\nare pleased to provide you with this semiannual report for Fund for the six-month period ended April 30, 2018. For additional information about the Fund, please visit our website a, where you can access quarterly commentaries. We value the trust that you place in us and look forward to serving your investment needs in the years to come.\nBest regards \nDouglas\n']