web-dev-qa-db-fra.com

utiliser Python pour supprimer une ligne spécifique dans un fichier

Disons que j'ai un fichier texte plein de pseudonymes. Comment puis-je supprimer un surnom spécifique de ce fichier en utilisant Python?

103
SourD

En supposant que votre fichier ait le format d’un pseudo par ligne, utilisez ceci.

Tout d'abord, ouvrez le fichier:

f = open("yourfile.txt","r")

Ensuite, récupérez toutes les lignes du fichier:

lines = f.readlines()

Maintenant vous pouvez fermer le fichier:

f.close()

Et rouvrez-le en mode écriture:

f = open("yourfile.txt","w")

Ensuite, écrivez vos lignes, sauf celle que vous souhaitez supprimer. Vous voudrez peut-être remplacer le "\n" par la ligne utilisée par votre fichier.

for line in lines:
  if line!="nickname_to_delete"+"\n":
    f.write(line)

A la fin, fermez à nouveau le fichier.

f.close()
150
houbysoft

Solution à ce problème avec une seule ouverture:

f = open("target.txt","r+")
d = f.readlines()
f.seek(0)
for i in d:
    if i != "line you want to remove...":
        f.write(i)
f.truncate()
f.close()

Cette solution ouvre le fichier en mode r/w ("r +") et utilise search pour réinitialiser le pointeur f, puis tronquer pour tout supprimer après la dernière écriture.

76
Lother

L'option la meilleure et la plus rapide, plutôt que de tout stocker dans une liste et de rouvrir le fichier pour l'écrire, est à mon avis de réécrire le fichier ailleurs.

with open("yourfile.txt", "r") as input:
    with open("newfile.txt", "w") as output: 
        for line in input:
            if line!="nickname_to_delete"+"\n":
                output.write(line)

C'est tout! En une boucle et une seule, vous pouvez faire la même chose. Ce sera beaucoup plus rapide.

18
Barnabe

Ceci est un "fork" de la réponse de @Lother (qui, selon moi, devrait être considérée comme la bonne réponse).


Pour un fichier comme celui-ci:

$ cat file.txt 
1: october Rust
2: november rain
3: december snow

Cette fourchette de la solution de Lother fonctionne bien:

#!/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()

Améliorations: 

  • with open, qui rejette l'utilisation de f.close()
  • plus clair if/else pour évaluer si une chaîne n'est pas présente dans la ligne en cours
16
ivanleoncz

Le problème avec la lecture des lignes dans la première passe et la modification (suppression de lignes spécifiques) dans la deuxième passe est que si la taille des fichiers est énorme, vous manquerez de RAM. Une meilleure approche consiste plutôt à lire les lignes une par une et à les écrire dans un fichier séparé, en éliminant celles dont vous n’avez pas besoin. J'ai utilisé cette approche avec des fichiers de 12 à 50 Go et l'utilisation de RAM reste presque constante. Seuls les cycles de la CPU indiquent le traitement en cours.

3
Kingz

Si vous utilisez Linux, vous pouvez essayer l'approche suivante.
Supposons que vous ayez un fichier texte nommé animal.txt

$ cat animal.txt  
dog
pig
cat 
monkey         
elephant  

Supprimer la première ligne:

>>> import subprocess
>>> subprocess.call(['sed','-i','/.*dog.*/d','animal.txt']) 

puis 

$ cat animal.txt
pig
cat
monkey
elephant
3
Ren

Je pense que si vous lisez le fichier dans une liste, faites-le ensuite, parcourez la liste pour rechercher le pseudo que vous souhaitez supprimer. Vous pouvez le faire beaucoup plus efficacement sans créer de fichiers supplémentaires, mais vous devrez écrire le résultat dans le fichier source.

Voici comment je pourrais faire ceci:

import, os, csv # and other imports you need
nicknames_to_delete = ['Nick', 'Stephen', 'Mark']

Je suppose que nicknames.csv contient des données telles que:

Nick
Maria
James
Chris
Mario
Stephen
Isabella
Ahmed
Julia
Mark
...

Puis chargez le fichier dans la liste:

 nicknames = None
 with open("nicknames.csv") as sourceFile:
     nicknames = sourceFile.read().splitlines()

Ensuite, parcourez la liste pour faire correspondre vos entrées à supprimer:

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

Enfin, écrivez le résultat dans le fichier:

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()
2
A Malik

Pas une bonne solution si vous mettez un fichier entier en mémoire, je sais qu’à présent tout le monde a des tonnes de mémoire, mais considérez si le fichier contient plusieurs Go de journaux ou quelque chose du genre.

Mieux vaut le copier ligne par ligne dans un nouveau fichier, plutôt que de supprimer le premier ou quelque chose comme ça

2
user3063349

J'ai aimé l'approche d'input de fichier comme expliqué dans cette réponse: Suppression d'une ligne d'un fichier texte (python)

Disons par exemple que j'ai un fichier qui contient des lignes vides et que je veux supprimer les lignes vides, voici comment je l'ai résolu:

import fileinput
import sys
for line_number, line in enumerate(fileinput.input('file1.txt', inplace=1)):
    if len(line) > 1:
            sys.stdout.write(line)

Note: Les lignes vides dans mon cas avaient une longueur de 1

1
Deep

En général, vous ne pouvez pas; vous devez réécrire l'intégralité du fichier (du moins du point de modification à la fin).

Dans certains cas spécifiques, vous pouvez faire mieux que cela -

si tous vos éléments de données ont la même longueur et sans ordre particulier, et que vous connaissez le décalage de celui dont vous souhaitez vous débarrasser, vous pouvez copier le dernier élément sur celui à supprimer et tronquer le fichier avant le dernier. ;

ou vous pouvez simplement écraser le bloc de données avec la valeur "il s'agit de données incorrectes, l'ignorer" ou conserver l'indicateur "cet élément a été supprimé" dans vos éléments de données enregistrés, de manière à pouvoir le marquer comme supprimé sans modifier autrement le fichier.

Ceci est probablement excessif pour les documents courts (moins de 100 Ko?).

1
Hugh Bothwell

Enregistrez les lignes de fichier dans une liste, supprimez de la liste la ligne à supprimer et écrivez les lignes restantes dans un nouveau fichier. 

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)
0
Henrique Andrade

voici une autre méthode pour supprimer une/des ligne (s) d'un fichier:

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

Vous avez probablement déjà obtenu une réponse correcte, mais voici le mien… .. Au lieu d'utiliser une liste pour collecter des données non filtrées (quelle méthode readlines() utilise), j'utilise deux fichiers. L'une concerne les données principales et l'autre, le filtrage des données lorsque vous supprimez une chaîne spécifique. Voici un code:

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

J'espère que vous trouverez cela utile! :)

0
andrii1986

J'aime cette méthode en utilisant fileinput et la méthode 'inplace':

import fileinput
for line in fileinput.input(fname, inplace =1):
    line = line.strip()
    if not 'UnwantedWord' in line:
        print(line)

C'est un peu moins verbeux que les autres réponses et est assez rapide pour

0
Ru887321

Vous pouvez utiliser la bibliothèque re

En supposant que vous puissiez charger votre fichier txt complet. Vous définissez ensuite une liste de pseudonymes indésirables, puis vous les remplacez par une chaîne vide "".

# 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)
0
mrk