Estoy usando Python versión 3.6 en una máquina con Windows. Estoy leyendo en un archivo de texto con open() y readlines(). Después de leer en las líneas del archivo de texto, quiero escribir ciertas líneas en un nuevo archivo de texto, pero excluir ciertos rangos de líneas. No sé los números de línea de las líneas para excluir. Los archivos de texto son masivos y el rango de líneas a excluir varía entre los archivos de texto que estoy leyendo. Hay palabras clave conocidas que puedo buscar para encontrar el inicio y el final del rango para excluir del archivo de texto en el que quiero escribir.

He buscado en todas partes en línea, pero parece que no puedo encontrar una solución elegante que funcione. El siguiente es un ejemplo de lo que estoy tratando de lograr.

a  
b  
BEGIN  
c  
d  
e  
END  
f  
g  
h  
i  
j  
BEGIN  
k  
l  
m  
n  
o  
p  
q  
END  
r  
s  
t  
u  
v  
BEGIN  
w  
x  
y  
END  
z 

En resumen, quiero leer lo anterior en Python. Luego, escriba en un nuevo archivo pero excluya todas las líneas que comienzan en BEGIN y terminan en palabras clave END.

El nuevo archivo debe contener lo siguiente:

a  
b  
f  
g  
h  
i  
j  
r  
s  
t  
u  
v  
z  
2
probat 28 oct. 2017 a las 20:58

3 respuestas

La mejor respuesta

Si los archivos de texto son masivos, como usted dice, querrá evitar usar readlines() ya que eso cargará todo en la memoria. En cambio, lea línea por línea y use una variable de estado para controlar si está en un bloque donde se debe suprimir la salida. Algo así como

import re

begin_re = re.compile("^BEGIN.*$")
end_re = re.compile("^END.*$")
should_write = True

with open("input.txt") as input_fh:
    with open("output.txt", "w", encoding="UTF-8") as output_fh:
        for line in input_fh:
            # Strip off whitespace: we'll add our own newline
            # in the print statement
            line = line.strip()

            if begin_re.match(line):
                should_write = False
            if should_write:
                print(line, file=output_fh)
            if end_re.match(line):
                should_write = True
1
Rob Hansen 28 oct. 2017 a las 18:36

Puede usar la siguiente expresión regular para lograr esto:

regex = r"(\bBEGIN\b([\w\n]*?)\bEND\b\n)"

Demostración en vivo aquí

Puede coincidir usando la expresión regular anterior y luego reemplazar con una cadena vacía ('')

Aquí hay un ejemplo de trabajo en Python para lo mismo.

CÓDIGO

result = re.sub(regex, '', test_str, 0) # test_str is your file's content
>>> print(result)
>>> 
a
b
f
g
h
i
j
r
s
t
u
v
z
1
Ashish Ranjan 28 oct. 2017 a las 18:33

Has intentado algo como ésto:

with open("<readfile>") as read_file:
    with open("<savefile>", "w") as write_file:
        currently_skipping = False
        for line in read_file:
            if line == "BEGIN":
                currently_skipping = True
            else if line == "END":
                currently_skipping = False

            if currently_skipping:
                continue

            write_file.write(line)

Eso básicamente debería hacer lo que necesitas hacer. Básicamente, no lea todo en la memoria a través de 'líneas de lectura', pero busque un enfoque más línea por línea, eso también debería ser más ágil para la memoria.

0
actionjezus6 28 oct. 2017 a las 18:24