buscar y eliminar líneas en el archivo python 3

Yo uso python 3

Bien, tengo un archivo que se bloquea así:

id:1
1
34
22
52
id:2
1
23
22
31
id:3
2
12
3
31
id:4
1
21
22
11

¿Cómo puedo encontrar y eliminar solo esta parte del archivo?

id:2
1
23
22
31

He estado tratando mucho de hacer esto, pero no puedo hacerlo funcionar.

preguntado el 12 de junio de 12 a las 20:06

3 Respuestas

¿Se usa la identificación para la decisión de eliminar la secuencia, o se usa la lista de valores para la decisión?

Puede crear un diccionario en el que el número de identificación sea la clave (convertido a int debido a la clasificación posterior) y las siguientes líneas se conviertan en la lista de cadenas que es el valor de la clave. Luego, puede eliminar el elemento con la clave 2, y recorrer los elementos ordenados por la clave, y generar la nueva id: clave más la lista formateada de las cadenas.

O puede construir la lista de listas donde se protege la orden. Si la secuencia de los id debe protegerse (es decir, no volver a numerarse), también puede recordar el id:n en la lista interna.

Esto se puede hacer para un archivo de tamaño razonable. Si el archivo es enorme, debe copiar el origen al destino y omitir la secuencia no deseada sobre la marcha. El último caso puede ser bastante fácil también para el archivo pequeño.

[agregado después de la aclaración]

Recomiendo aprender el siguiente enfoque que es útil en muchos de estos casos. Utiliza los llamados autómata finito que implementa acciones ligadas a transiciones de un estado a otro (ver Máquina de comidas).

La línea de texto es el elemento de entrada aquí. Los nodos que representan el estado del contexto están numerados aquí. (Mi experiencia es que no vale la pena darles nombres, manténgalos solo números estúpidos). Aquí solo se usan dos estados y el status podría ser fácilmente reemplazada por una variable booleana. Sin embargo, si el caso se vuelve más complicado, conduce a la introducción de otra variable booleana y el código se vuelve más propenso a errores.

El código puede parecer muy complicado al principio, pero es bastante fácil de entender cuando sabes que puedes pensar en cada if status == number por separado. Este es el contexto mencionado que capturó el procesamiento anterior. No intentes optimizar, deja el código así. En realidad, puede ser decodificado por humanos más tarde, y puede dibujar una imagen similar a la Ejemplo de máquina harinosa. Si lo hace, entonces es mucho más comprensible.

La funcionalidad deseada está un poco generalizada: se puede pasar un conjunto de secciones ignoradas como primer argumento:

import re

def filterSections(del_set, fname_in, fname_out):
    '''Filtering out the del_set sections from fname_in. Result in fname_out.'''

    # The regular expression was chosen for detecting and parsing the id-line.
    # It can be done differently, but I consider it just fine and efficient.
    rex_id = re.compile(r'^id:(\d+)\s*$')

    # Let's open the input and output file. The files will be closed
    # automatically.
    with open(fname_in) as fin, open(fname_out, 'w') as fout:
        status = 1                 # initial status -- expecting the id line
        for line in fin:
            m = rex_id.match(line) # get the match object if it is the id-line

            if status == 1:      # skipping the non-id lines
                if m:              # you can also write "if m is not None:"
                    num_id = int(m.group(1))  # get the numeric value of the id
                    if num_id in del_set:     # if this id should be deleted
                        status = 1            # or pass (to stay in this status)
                    else:
                        fout.write(line)      # copy this id-line
                        status = 2            # to copy the following non-id lines
                #else ignore this line (no code needed to ignore it :)

            elif status == 2:      # copy the non-id lines
                if m:                         # the id-line found
                    num_id = int(m.group(1))  # get the numeric value of the id
                    if num_id in del_set:     # if this id should be deleted
                        status = 1            # or pass (to stay in this status)
                    else:
                        fout.write(line)      # copy this id-line
                        status = 2            # to copy the following non-id lines
                else:
                    fout.write(line)          # copy this non-id line


if __name__ == '__main__':
    filterSections( {1, 3}, 'data.txt', 'output.txt')
    # or you can write the older set([1, 3]) for the first argument.

Aquí, las líneas de identificación de salida se dieron con el número original. Si desea renumerar las secciones, puede hacerlo mediante una simple modificación. Pruebe el código y solicite detalles.

Cuidado, los autómatas finitos tienen un poder limitado. No se pueden usar para los lenguajes de programación habituales, ya que no pueden capturar estructuras emparejadas anidadas (como paréntesis).

PD Las 7000 líneas son en realidad un archivo diminuto desde una perspectiva informática ;)

Respondido el 13 de junio de 12 a las 19:06

la identificación se usa para la decisión de eliminar la secuencia y el archivo contiene 7.000 líneas, por lo que es grande. Lamento haber dado menos información. - user1229391

@user1229391: Después de eliminar la secuencia, ¿deberían las siguientes secuencias mantener el número original o debería corregirse (disminuirse) su identificación? - PEPR

Lea cada línea en una matriz de cadenas. El número de índice es el número de línea: 1. Verifique si la línea es igual a "id: 2" antes de leer la línea. En caso afirmativo, deje de leer la línea hasta que la línea sea igual a "id: 3". Después de leer la línea, borre el archivo y vuelva a escribir la matriz en el archivo hasta el final de la matriz. Esta puede no ser la forma más eficiente, pero debería funcionar.

Respondido el 12 de junio de 12 a las 20:06

si no hay valores intermedios que interfieran, esto funcionaría....

import fileinput 
...
def deleteIdGroup( number ):
    deleted = False
    for line in fileinput.input( "testid.txt", inplace = 1 ):
        line = line.strip( '\n' )
        if line.count( "id:" + number ): # > 0
            deleted = True;
        elif line.count( "id:" ): # > 0
            deleted = False;
        if not deleted:
            print( line )

EDIT:

lo siento, esto elimina id: 2 e id: 20 ... podrías modificarlo para que el primero si verifique - línea == "id:" + número

Respondido el 13 de junio de 12 a las 19:06

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.