Risposte:
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
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" :)
Se il file si adatta comodamente alla memoria, è possibile utilizzare anche ed
.
I comandi sono abbastanza simili a sed
quello 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 w
rite con ,p
rint 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 w
sottocomando 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 d
elete, 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.
q
comando è utile alla fine? Immagino che esca in entrambi i modi.
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:
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
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"?
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.
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.
Puoi usare Vim in modalità Ex:
ex -sc '20,37d|45d|x' file
d
Elimina
x
salva e chiudi