Risposte:
Innanzitutto, apri il file e ottieni tutte le linee dal file. Quindi riaprire il file in modalità di scrittura e riscrivere le righe, ad eccezione della riga che si desidera eliminare:
with open("yourfile.txt", "r") as f:
lines = f.readlines()
with open("yourfile.txt", "w") as f:
for line in lines:
if line.strip("\n") != "nickname_to_delete":
f.write(line)
È necessario strip("\n")
il carattere di nuova riga nel confronto perché se il file non termina con un carattere di nuova riga line
, neanche l' ultimo sarà.
Soluzione a questo problema con una sola apertura:
with open("target.txt", "r+") as f:
d = f.readlines()
f.seek(0)
for i in d:
if i != "line you want to remove...":
f.write(i)
f.truncate()
Questa soluzione apre il file in modalità r / w ("r +") e fa uso di seek per resettare il puntatore f quindi troncare per rimuovere tutto dopo l'ultima scrittura.
for
loop, finirai con un file parzialmente sovrascritto, con linee duplicate o una linea tagliata a metà. Potresti voler f.truncate()
subito dopo f.seek(0)
. In questo modo se ricevi un errore finirai con un file incompleto. Ma la vera soluzione (se si dispone dello spazio su disco) è l'output in un file temporaneo e quindi utilizzare os.replace()
o pathlib.Path(temp_filename).replace(original_filename)
scambiarlo con l'originale dopo che tutto è riuscito.
i.strip('\n') != "line you want to remove..."
come indicato nella risposta accettata, che risolverebbe perfettamente il mio problema. Perché proprio i
non ha fatto nulla per me
L'opzione migliore e più veloce, piuttosto che archiviare tutto in un elenco e riaprire il file per scriverlo, secondo me è di riscrivere il file altrove.
with open("yourfile.txt", "r") as input:
with open("newfile.txt", "w") as output:
for line in input:
if line.strip("\n") != "nickname_to_delete":
output.write(line)
Questo è tutto! In un ciclo e solo uno puoi fare la stessa cosa. Sarà molto più veloce.
(output.write(line) for line in input if line!="nickname_to_delete"+"\n")
subprocess.call(['mv', 'newfile.txt', 'yourfile.txt'])
os.replace
(novità in python v 3.3) è più multipiattaforma di una chiamata di sistema a mv
.
Questo è un "fork" dalla risposta di @Lother (che credo debba essere considerata la risposta giusta).
Per un file come questo:
$ cat file.txt
1: october rust
2: november rain
3: december snow
Questa forcella della soluzione di Lother funziona perfettamente:
#!/usr/bin/python3.4
with open("file.txt","r+") as f:
new_f = f.readlines()
f.seek(0)
for line in new_f:
if "snow" not in line:
f.write(line)
f.truncate()
miglioramenti:
with open
, che scartano l'utilizzo di f.close()
if/else
per valutare se la stringa non è presente nella riga correnteIl problema con la lettura delle righe nel primo passaggio e le modifiche (eliminazione di righe specifiche) nel secondo passaggio è che se le dimensioni del file sono enormi, si esaurisce la RAM. Invece, un approccio migliore è leggere le righe, una per una, e scriverle in un file separato, eliminando quelle che non ti servono. Ho adottato questo approccio con file grandi come 12-50 GB e l'utilizzo della RAM rimane quasi costante. Solo i cicli della CPU mostrano l'elaborazione in corso.
Mi è piaciuto l'approccio fileinput come spiegato in questa risposta: eliminazione di una riga da un file di testo (python)
Ad esempio, ho un file che contiene righe vuote e voglio rimuovere righe vuote, ecco come l'ho risolto:
import fileinput
import sys
for line_number, line in enumerate(fileinput.input('file1.txt', inplace=1)):
if len(line) > 1:
sys.stdout.write(line)
Nota: le righe vuote nel mio caso avevano lunghezza 1
Se usi Linux, puoi provare il seguente approccio.
Supponiamo di avere un file di testo chiamato animal.txt
:
$ cat animal.txt
dog
pig
cat
monkey
elephant
Elimina la prima riga:
>>> import subprocess
>>> subprocess.call(['sed','-i','/.*dog.*/d','animal.txt'])
poi
$ cat animal.txt
pig
cat
monkey
elephant
Penso che se leggi il file in un elenco, quindi fai l'iterazione sull'elenco per cercare il soprannome di cui vuoi sbarazzarti. Puoi farlo in modo molto efficiente senza creare file aggiuntivi, ma dovrai riscrivere il risultato nel file di origine.
Ecco come potrei farlo:
import, os, csv # and other imports you need
nicknames_to_delete = ['Nick', 'Stephen', 'Mark']
Presumo nicknames.csv
contenga dati come:
Nick
Maria
James
Chris
Mario
Stephen
Isabella
Ahmed
Julia
Mark
...
Quindi caricare il file nell'elenco:
nicknames = None
with open("nicknames.csv") as sourceFile:
nicknames = sourceFile.read().splitlines()
Successivamente, scorrere per elencare in modo che corrisponda agli input da eliminare:
for nick in nicknames_to_delete:
try:
if nick in nicknames:
nicknames.pop(nicknames.index(nick))
else:
print(nick + " is not found in the file")
except ValueError:
pass
Infine, riscrivi il risultato nel file:
with open("nicknames.csv", "a") as nicknamesFile:
nicknamesFile.seek(0)
nicknamesFile.truncate()
nicknamesWriter = csv.writer(nicknamesFile)
for name in nicknames:
nicknamesWriter.writeRow([str(name)])
nicknamesFile.close()
In generale, non puoi; devi riscrivere l'intero file (almeno dal punto di modifica alla fine).
In alcuni casi specifici puoi fare di meglio -
se tutti i tuoi elementi di dati hanno la stessa lunghezza e in nessun ordine specifico e conosci l'offset di quello che vuoi eliminare, puoi copiare l'ultimo elemento su quello da eliminare e troncare il file prima dell'ultimo elemento ;
oppure potresti semplicemente sovrascrivere il blocco di dati con un valore 'this is bad data, skip it' o mantenere un flag 'this item was cancelled' nei tuoi elementi di dati salvati in modo da poterlo contrassegnare cancellato senza modificare in altro modo il file.
Questo è probabilmente eccessivo per i documenti brevi (qualcosa di meno di 100 KB?).
Probabilmente hai già una risposta corretta, ma ecco la mia. Invece di usare un elenco per raccogliere dati non filtrati (quale readlines()
metodo fa), io uso due file. Uno è per contenere i dati principali e il secondo per filtrare i dati quando si elimina una stringa specifica. Ecco un codice:
main_file = open('data_base.txt').read() # your main dataBase file
filter_file = open('filter_base.txt', 'w')
filter_file.write(main_file)
filter_file.close()
main_file = open('data_base.txt', 'w')
for line in open('filter_base'):
if 'your data to delete' not in line: # remove a specific string
main_file.write(line) # put all strings back to your db except deleted
else: pass
main_file.close()
Spero che lo troverai utile! :)
Salvare le righe del file in un elenco, quindi rimuovere dall'elenco la riga che si desidera eliminare e scrivere le righe rimanenti in un nuovo file
with open("file_name.txt", "r") as f:
lines = f.readlines()
lines.remove("Line you want to delete\n")
with open("new_file.txt", "w") as new_f:
for line in lines:
new_f.write(line)
ecco qualche altro metodo per rimuovere una / alcune righe da un file:
src_file = zzzz.txt
f = open(src_file, "r")
contents = f.readlines()
f.close()
contents.pop(idx) # remove the line item from list, by line number, starts from 0
f = open(src_file, "w")
contents = "".join(contents)
f.write(contents)
f.close()
Puoi usare la
re
biblioteca
Supponendo che sia possibile caricare il file txt completo. Quindi si definisce un elenco di soprannomi indesiderati e li si sostituisce con una stringa vuota "".
# Delete unwanted characters
import re
# Read, then decode for py2 compat.
path_to_file = 'data/nicknames.txt'
text = open(path_to_file, 'rb').read().decode(encoding='utf-8')
# Define unwanted nicknames and substitute them
unwanted_nickname_list = ['SourDough']
text = re.sub("|".join(unwanted_nickname_list), "", text)
Per eliminare una riga specifica di un file dal suo numero di riga :
Sostituisci le variabili nomefile e line_to_delete con il nome del tuo file e il numero di riga che desideri eliminare.
filename = 'foo.txt'
line_to_delete = 3
initial_line = 1
file_lines = {}
with open(filename) as f:
content = f.readlines()
for line in content:
file_lines[initial_line] = line.strip()
initial_line += 1
f = open(filename, "w")
for line_number, line_content in file_lines.items():
if line_number != line_to_delete:
f.write('{}\n'.format(line_content))
f.close()
print('Deleted line: {}'.format(line_to_delete))
Esempio di output :
Deleted line: 3
for nb, line in enumerate(f.readlines())
Prendi il contenuto del file, dividerlo per newline in una tupla. Quindi, accedi al numero di riga della tua tupla, unisciti alla tua tupla risultante e sovrascrivi al file.
tuple(f.read().split('\n'))
?? (2) "accedi al numero di riga della tua tupla" e "unisciti alla tua tupla risultante" suona piuttosto misterioso; il codice Python effettivo potrebbe essere più comprensibile.
fileinput
come descritto da @ jf-sebastian qui . Sembra che ti permetta di lavorare riga per riga, tramite un file temporaneo, il tutto con una semplicefor
sintassi.