¿Cómo elimino ciertas líneas (usando números de línea) en un archivo?

27

Hay líneas específicas que quiero eliminar de un archivo. Digamos que es la línea 20-37 y luego la línea 45. ¿Cómo haría eso sin especificar el contenido de esas líneas?

tshepang
fuente
¿Qué tan grande es tu archivo? ¿Se podría cargar en la memoria?
Faheem Mitha
Unos kilobytes.
tshepang

Respuestas:

29

Con sed, así:

sed '20,37d; 45d' < input.txt > output.txt

Si quisieras hacer esto en el lugar:

sed --in-place '20,37d; 45d' file.txt
pdo
fuente
¿Hay alguna manera de hacerlo en el lugar?
tshepang
Sugiero sed -i file
enzotib
1
@Tshepang: Use ed, o GNU sed -i, o sponge, o un método de archivo grande .
Gilles 'SO- deja de ser malvado'
3
A menudo me he preguntado sobre el término posiblemente engañoso en el lugar , cuando me refería a 'sed', así que lo busqué en 'man sed': --in-place [= SUFFIX] This option specifies that files are to be edited in-place. GNU sed 'hace esto creando un archivo temporal y enviando la salida a este archivo en lugar de a la salida estándar. ... No conozco ningún otro 'sed' pero la logística de actualizar "en el lugar" con un editor de flujo no "computa" :)
Peter.O
2
La mayoría de los métodos "in situ" utilizan un archivo temporal, en mi experiencia.
Faheem Mitha
5

Si el archivo se adapta cómodamente a la memoria, también puede usarlo ed.
Los comandos son bastante similares al sedanterior con una diferencia notable : debe pasar la lista de números / rangos de línea que se eliminarán en orden descendente (desde el número / rango de línea más alto al más bajo). La razón es que cuando elimina / inserta / divide / une líneas con ed, el búfer de texto se actualiza después de cada subcomando, por lo que si elimina algunas líneas, el resto de las siguientes líneas ya no estarán en la misma posición en el búfer cuando el Se ejecuta el siguiente subcomando. Entonces tienes que comenzar hacia atrás 1 . Edición en el
lugar :

ed -s in_file <<IN
45d
20,37d
w
q
IN

o

ed -s in_file <<< $'45d\n20,37d\nw\nq\n'

o

printf '%s\n' 45d 20,37d w q | ed -s in_file

Reemplace write con ,print si desea imprimir la salida resultante en lugar de escribir en el archivo. Si desea mantener el archivo original intacto y escribir en otro archivo, puede pasar el nuevo nombre de archivo al wsubcomando rite:

ed -s in_file <<IN
78,86d
65d
51d
20,37d
w out_file
q
IN

1 A menos que esté dispuesto a calcular los nuevos números de línea después de cada delección, lo cual es bastante trivial para este caso particular (después de eliminar las líneas 20-37, es decir, 18 líneas, la línea 45 se convierte en la línea 27) para que pueda ejecutar:

ed -s in_file <<IN
20,37d
27d
w
q
IN

Sin embargo, si tiene que eliminar múltiples números / rangos de línea, trabajar hacia atrás es obvio.

don_crissti
fuente
¿Es qútil el comando al final? Supongo que existe de cualquier manera.
Tom Fenech
@TomFenech: no todas las implementaciones salen de ninguna manera (aunque la mayoría sí ... ya no puedo encontrar el hilo donde se discutió esto ...)
don_crissti
1

Simplemente léalo en la memoria, modifíquelo y luego vuelva a escribirlo. Puedes hacer algo como

filename = "foo"
f = open(filename, 'r+')                                                                                                                                 
linenums = [1, 3]                                                                                                                                            
s = [y for x, y in enumerate(f) if x not in [line-1 for line in linenums]]                                                                                                                                          
f.seek(0)
f.write(''.join(s))
f.truncate(f.tell())
f.close()

Probado con un archivo de 5 líneas. Créditos a http://pleac.sourceforge.net/pleac_python/fileaccess.html , consulte la sección "Modificación de un archivo en su lugar sin un archivo temporal". Ver también /programming/125703/how-do-i-modify-a-text-file-in-python

Algunas notas:

  1. Primero se puede truncar el archivo, luego escribir en él, en lugar de escribir, y luego truncar, como se indicó anteriormente. Sin embargo, no conozco una bandera de Python que permita leer, y luego escribir de forma truncada. Pero tal vez me falta algo, ya que el documento no está tan claro. Lo que me lleva a

  2. A veces, los documentos de Python realmente apestan. Ver http://docs.python.org/library/functions.html#open

    Los modos 'r +', 'w +' y 'a +' abren el archivo para actualizarlo (tenga en cuenta que 'w +' trunca el archivo).

    ¿Esto significa algo para ti? ¿Qué demonios está "abierto para actualizar"?

  3. No sé si hacer esto en Python en lugar de algo unixy como el editor de flujo es mejor. Puede ser más portátil, pero no sé qué tan portátil es sed. Lo escribí así porque me siento más cómodo con la programación de bajo nivel que con las herramientas clásicas de Unix, que son buenas si hacen exactamente lo que quieres, pero (creo) generalmente son menos flexibles.

  4. Este enfoque (manipular el archivo en la memoria) cambia la memoria por espacio en disco. Debería funcionar bien en máquinas con unos pocos GB de memoria para archivos de hasta unos cientos de Mb. Python no maneja cadenas de manera muy eficiente, por lo que cambiar a C / C ++, por ejemplo, aumentaría ligeramente el rendimiento y reduciría en gran medida el uso de la memoria.

Faheem Mitha
fuente
0

Puede usar Vim en modo Ex:

ex -sc '20,37d|45d|x' file
  1. d borrar

  2. x guardar y cerrar

Steven Penny
fuente