Come rimuovo determinate righe (usando i numeri di riga) in un file?


27

Ci sono linee specifiche che voglio rimuovere da un file. Diciamo che è la riga 20-37 e quindi la riga 45. Come lo farei senza specificare il contenuto di quelle righe?


Quanto è grande il tuo file? Potrebbe essere caricato in memoria?
Faheem Mitha,

Alcuni kilobyte.
Tshepang,

Risposte:


29

Con sed, in questo modo:

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

Se volessi farlo sul posto:

sed --in-place '20,37d; 45d' file.txt

C'è un modo per farlo sul posto?
Tshepang,

Suggerisco sed -i file
enzotib il


3
Mi sono spesso interrogato sul termine probabilmente fuorviante sul posto , quando mi riferivo a 'sed', quindi l'ho cercato in 'man sed': --in-place [= SUFFIX] This option specifies that files are to be edited in-place. GNU sed 'lo fa creando un file temporaneo e invio dell'output a questo file piuttosto che all'output standard. ... Non conosco nessun altro 'sed' ma la logistica dell'aggiornamento "in atto" con un editor di stream non "calcola" :)
Peter.O

2
La maggior parte dei metodi "sul posto" utilizzano un file temporaneo, secondo la mia esperienza.
Faheem Mitha,

5

Se il file si adatta comodamente alla memoria, è possibile utilizzare anche ed.
I comandi sono abbastanza simili a sedquello sopra con una notevole differenza : è necessario passare l'elenco dei numeri di riga / intervalli da eliminare in ordine decrescente (dal numero di riga / intervallo più alto a quello più basso). Il motivo è che quando si elimina / inserisce / si divide / unisce le righe ed, il buffer di testo viene aggiornato dopo ogni sottocomando, quindi se si eliminano alcune righe, le restanti righe seguenti non saranno più nella stessa posizione nel buffer quando il il sottocomando successivo viene eseguito. Quindi devi iniziare indietro 1 . Modifica sul
posto :

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

Sostituisci write con ,print se vuoi stampare l'output risultante invece di scrivere su file. Se si desidera mantenere intatto il file originale e scrivere su un altro file, è possibile passare il nome del nuovo file al wsottocomando rite:

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

1 A meno che tu non sia disposto a calcolare i nuovi numeri di riga dopo ogni delete, il che è abbastanza banale per questo caso particolare (dopo aver eliminato le righe 20-37, ovvero 18 righe, la riga 45 diventa riga 27) in modo da poter eseguire:

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

Tuttavia, se devi eliminare più numeri di riga / intervalli, lavorare all'indietro è un gioco da ragazzi.


Il qcomando è utile alla fine? Immagino che esca in entrambi i modi.
Tom Fenech,

@TomFenech - non tutte le implementazioni escono in entrambi i modi (anche se la maggior parte lo fa ... non riesco più a trovare il thread in cui è stato discusso ...)
don_crissti

1

Basta leggerlo in memoria, modificarlo, quindi riscriverlo. Puoi fare qualcosa del genere

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()

Testato con un file a 5 righe. Crediti a http://pleac.sourceforge.net/pleac_python/fileaccess.html , vedere la sezione "Modifica di un file in atto senza un file temporaneo". Vedi anche /programming/125703/how-do-i-modify-a-text-file-in-python

Alcune note:

  1. Si potrebbe prima troncare il file, quindi scrivere su di esso, piuttosto che scrivere, quindi troncare, come sopra. Tuttavia, non conosco un flag Python che consente di leggere e quindi di scrivere in modo troncato. Ma forse mi manca qualcosa, poiché il documento non è poi così chiaro. Il che mi porta a

  2. A volte i documenti di Python fanno davvero schifo. Vedi http://docs.python.org/library/functions.html#open

    Le modalità 'r +', 'w +' e 'a +' aprono il file per l'aggiornamento (si noti che 'w +' tronca il file).

    Questo significa qualcosa per te? Cosa diavolo è "aperto per l'aggiornamento"?

  3. Non so se farlo in Python al contrario di qualcosa di unico come l'editor di stream sia migliore. Potrebbe essere più portatile, ma non so quanto sia portatile sed. L'ho appena scritto in questo modo perché mi sento più a mio agio con la programmazione di basso livello rispetto all'utilizzo dei classici strumenti unix, che sono buoni se fanno esattamente quello che vuoi, ma (penso) sono generalmente meno flessibili.

  4. Questo approccio (manipolazione del file in memoria) scambia memoria con spazio su disco. Dovrebbe funzionare bene su macchine con pochi GB di memoria per file fino a poche centinaia di Mb. Python non gestisce le stringhe in modo molto efficiente, quindi il passaggio a C / C ++, ad esempio, aumenterebbe leggermente le prestazioni e ridurrebbe notevolmente l'utilizzo della memoria.


0

Puoi usare Vim in modalità Ex:

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

  2. x salva e chiudi

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.