IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

effacement de ligne dans un fichier en python


Sujet :

Python

  1. #1
    Membre averti
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2008
    Messages
    37
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Novembre 2008
    Messages : 37
    Par défaut effacement de ligne dans un fichier en python
    salut
    J'aimerai savoir si il est possible d'écrire un script qui permettrai d,effacer dans un fichier texte toutes les lignes qui contienne une chaîne de caractère donné.
    par exemple mon fichier originel:

    w:\blabla
    d:\blabla
    c:\windows
    w:\fgfgd

    Je voudrai qu'à la fin le fichier ressemble à ça:

    w:\blabla
    d:\blabla
    w:\fgfgd

    Le script effacerai toutes les lignes comportant c:\windows

    merci d'avance

  2. #2
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Par défaut
    bonjour

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    J'aimerai savoir si il est possible d'écrire un script qui permettrai d,effacer dans un fichier texte toutes les lignes qui contienne une chaîne de caractère donné.
    oui c'est possible.

    on peut faire la lecture du fichier et écrire ce que l'on souhaite garder dans un autre, puis donner à cet autre fichier le nom du premier après l'avoir effacé.

    à ma connaissance, il n'est pas possible de procéder à un changement directement dans le fichier sans passer par un fichier intermédiaire.

  3. #3
    Membre émérite
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Par défaut
    c'est possible, mais c'est affreusement chiant... faut jouer avec seek(), tell(), write(), len() et truncate() (hormis len(), toutes des méthode d'objets ficher)

    http://docs.python.org/library/stdty...n-file-objects

    Bon courage

  4. #4
    Membre averti
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2008
    Messages
    37
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Novembre 2008
    Messages : 37
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    import glob
    import os
     
    chaine = "C:\windows" #Texte à rechercher
    contenu = "Nom Fichier"
     
    fichier = open("mod.txt","r")
    for ligne in fichier:
        if not(chaine in ligne):
           contenu = contenu + "\n" + fichier.readline(ligne)
    fichier.close()
     
     
    fichier = open('mod.txt', 'w')
    fichier.write(contenu)
    fichier.close()
     
    #voici mon script test qui ne marche pas
    mais je ne trouve pas d'erreur

  5. #5
    Membre émérite
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    import shutil, os
    filename='c:\\myfilename'
    shutil.copy(filename,filename+'.tmp')
    with file(filename+'.tmp') as f_in:
        with file(filename,'w') as f_out:
            for line in f_in:
                if 'c:\\windows'!=line.rstrip().lower():
                    f_out.write(line)
    os.remove(filename+'.tmp')

  6. #6
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Citation Envoyé par reillyc Voir le message
    par exemple mon fichier originel:

    w:\blabla
    d:\blabla
    c:\windows
    w:\fgfgd

    Je voudrai qu'à la fin le fichier ressemble à ça:

    w:\blabla
    d:\blabla
    w:\fgfg
    C'est un bon choix...

  7. #7
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Correction de ton code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    chaine = r"c:\windows" #Texte à rechercher
    contenu = ""
     
    fichier = open("mod.txt","r")
    for ligne in fichier:
        if not(chaine in ligne):
            contenu += ligne
    fichier.close()
     
    fichier = open('mod2.txt', 'w')
    fichier.write(contenu)
    fichier.close()
    Détails:

    - chaine = r"c:\windows" => Il faut utiliser r"" pour éviter que python n'interprète le '\w' comme un caractère spécial. Autre solution, doubler le '\'. Par ailleurs, faire attention aux majuscules/minuscules: le 'C:' du code ne permet pas de trouver le 'c:' du fichier. Ou alors, mettre tout en majuscule au moment du test.

    - for ligne in fichier: => ici, ligne est déjà la ligne extraite du fichier. On n'a donc pas besoin du readline en plus.

    - contenu += ligne => ligne contient déjà une fin de ligne, ce n'est donc pas nécessaire de la rajouter. Par ailleurs, contenu += ligne est identique à contenu = contenu + ligne.

    Tyrtamos

  8. #8
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    Les programmes ci-dessus font un recopiage de la totalité du fichier avec élimination de certaines lignes.

    Imaginons un fichier d’une nature telle qu’on y fait seulement des ajouts de lignes et, de temps à autre, des modifications n’affectant que la fin du fichier, et que ce fichier soit très volumineux.
    Imaginons par exemple un fichier de gestion prévisionnelle d’horaires de travail faisant 20 MB (!) dont on veut éliminer dans l’extrême fin les lignes consacrées à MATTHIAS, HENG et GUILLAUME à partir du 14 mars.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    JAMES             : 01 janvier     09h30 - 17h45
    GIOVANNI          : 07 janvier     10h45 - 19h00
    HENG              : 07 janvier     10h00 - 15h15
    GIOVANNI          : 08 janvier     09h00 - 15h00
    HERBERT           : 08 janvier     08h00 - 14h15
    TRUONG            : 08 janvier     11h00 - 18h00
    AHMED             : 08 janvier     12h15 - 17h30
    HERBERT           : 08 janvier     12h15 - 19h00
    MATTHIAS          : 09 janvier     12h15 - 17h15
    HENG              : 09 janvier     10h15 - 19h45
    COLETTE           : 12 janvier     11h15 - 14h45
    GIOVANNI          : 13 janvier     11h30 - 14h00
    NADIA             : 13 janvier     09h30 - 19h30
    NADIA             : 13 janvier     09h45 - 16h15
    GIOVANNI          : 15 janvier     09h15 - 14h00
    GUILLAUME         : 15 janvier     08h15 - 19h00
    MIGUEL            : 15 janvier     10h30 - 13h45
    HERBERT           : 16 janvier     12h30 - 14h30
    HERBERT           : 16 janvier     11h30 - 16h45
    JAMES             : 18 janvier     10h30 - 15h15
    HENG              : 20 janvier     11h15 - 19h45
    TRUONG            : 21 janvier     12h30 - 17h00
    HERBERT           : 21 janvier     12h15 - 19h15
    AHMED             : 23 janvier     12h15 - 19h45
    GUILLAUME         : 23 janvier     09h30 - 19h45
    COLETTE           : 23 janvier     11h30 - 17h45
    AHMED             : 23 janvier     11h15 - 17h15
    HENG              : 24 janvier     08h45 - 13h45
    TRUONG            : 26 janvier     08h15 - 16h45
    MATTHIAS          : 27 janvier     08h45 - 19h00
    MARTINE           : 28 janvier     08h45 - 16h30
    GUILLAUME         : 28 janvier     08h15 - 17h45
    AHMED             : 02 fevrier     12h15 - 17h45
    HENG              : 03 fevrier     12h15 - 17h00
    COLETTE           : 05 fevrier     09h45 - 15h45
    JAMES             : 06 fevrier     09h15 - 14h45
    GUILLAUME         : 07 fevrier     12h30 - 17h45
    MIGUEL            : 07 fevrier     11h30 - 15h00
    HENG              : 07 fevrier     11h00 - 13h30
    GUILLAUME         : 07 fevrier     08h30 - 13h45
    NADIA             : 08 fevrier     12h30 - 16h15
    HERBERT           : 08 fevrier     08h15 - 17h00
    MATTHIAS          : 10 fevrier     09h00 - 14h15
    MIGUEL            : 13 fevrier     08h00 - 17h15
    MARTINE           : 14 fevrier     09h30 - 18h00
    MATTHIAS          : 15 fevrier     09h00 - 17h30
    JAMES             : 15 fevrier     08h15 - 14h30
    GIOVANNI          : 18 fevrier     08h30 - 18h15
    MIGUEL            : 20 fevrier     10h00 - 13h45
    GUILLAUME         : 20 fevrier     12h15 - 19h45
    TRUONG            : 21 fevrier     09h45 - 15h15
    GUILLAUME         : 27 fevrier     11h45 - 14h45
    AHMED             : 27 fevrier     10h00 - 15h15
    NADIA             : 27 fevrier     11h45 - 14h00
    COLETTE           : 28 fevrier     09h30 - 18h15
    MIGUEL            : 28 fevrier     10h30 - 19h30
    MARTINE           : 02 mars        10h15 - 14h15
    NADIA             : 03 mars        09h15 - 18h15
    HERBERT           : 07 mars        11h00 - 18h00
    MIGUEL            : 07 mars        09h30 - 17h45
    NADIA             : 08 mars        08h00 - 14h00
    MATTHIAS          : 12 mars        08h45 - 18h45
    GUILLAUME         : 12 mars        12h30 - 14h00
    AHMED             : 13 mars        10h30 - 13h45
    GIOVANNI          : 14 mars        11h15 - 18h30
    COLETTE           : 20 mars        10h15 - 15h45
    TRUONG            : 21 mars        11h15 - 13h30
    GIOVANNI          : 25 mars        08h15 - 15h45
    TRUONG            : 26 mars        11h00 - 14h00
    AHMED             : 27 mars        08h45 - 15h45
    AHMED             : 28 mars        09h30 - 17h30
    MATTHIAS          : 28 mars        11h45 - 17h15
    HERBERT           : 01 avril       08h15 - 16h30
    COLETTE           : 03 avril       08h30 - 16h00
    GUILLAUME         : 07 avril       12h15 - 16h15
    NADIA             : 10 avril       09h00 - 13h30
    MARTINE           : 10 avril       09h30 - 18h00
    MATTHIAS          : 12 avril       09h45 - 15h15
    HENG              : 15 avril       12h00 - 17h00
    AHMED             : 17 avril       09h30 - 18h45
    Va-t-on vraiment recopier chaque fois 20 MB pour ne modifier que les derniers 5000 octets ?








    Pour diminuer ce labeur, le code de reillyc peut être adapté pour en faire un code de réécriture partielle avec élimination de certaines lignes:
    on n’enregistre (avec les éliminations voulues) dans l’objet de nom ’contenu’ que la fin à partir d’une position atteinte par seek() , et on la réécrit sur elle même en l’écrasant à partir de cette même position atteinte par seek()

    Pour éviter de devoir fermer et réouvrir le fichier, il faut ouvrir le fichier directement en mode ’r+’ .
    Pour que find() trouve avec exactitude les positions correctes dans le fichier, il faut de plus que l’ouverture se fasse en mode binaire spécifié par un ’b’

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    chaine = r"c:\windows" # Texte à rechercher
    contenu = ""
     
    with open("mod.txt","r+b") as fichier:
     
        ch = f.read()
        x = ch.find(chaine)
        x = ch[0:x].rfind('\n') + 1
     
        fichier.seek(x)
        for ligne in fichier[x:]:
            if not(chaine in ligne):
                contenu += ligne
     
        fichier.seek(x)
        fichier.write(contenu)









    On peut aller plus loin:
    afin déviter d’enregistrer provisoirement dans un objet ’contenu’ ou un fichier temporaire (hormis le buffer de liaison avec le DD),
    il suffit de mettre à profit la possibilité d’ouvrir plusieurs pointeurs de fichier sur un même fichier pour procéder par recopie immédiate de lignes avec élimination de certaines lignes

    Par exemple, avec le fichier donné au dessus:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # programme d'effacement de lignes dans un fichier
    noms_a_effacer, a_partir_de = ('MATTHIAS','HENG','GUILLAUME'), '14 mars'
     
    with open('previsionnel.txt','rb') as f:
        with open('previsionnel.txt','r+b') as g:
            ch = f.read()
            x = ch.find(a_partir_de)
            x = ch[0:x].rfind('\n') + 1
            f.seek(x)
            g.seek(x)
            [ g.write(ln) for ln in f if ln.split()[0] not in noms_a_effacer ]
            g.truncate()
    Comme il n’y a plus de ligne contenu += ligne , on peut écrire le transfert sous forme de list comprehension (les list comprehensions n’accpetant pas des opérations +).



    Ce genre de code permet aussi bien:

    - de modifier (éliminer n’est qu’un cas particulier, mais il faut que les modifications n’entrainent pas une augmentation du nombre de caractères d’une ligne recopiée) seulement la fin d’un gros fichier sans toucher à la majeure partie du fichier

    - que de faire la même chose sur l’ensemble d’un fichier trop volumineux pour pouvoir être recopié en mémoire: si on faisait le même genre de recopie immédiate, mais avec deux fichiers différents (et non pas 2 pointeurs dans un même fichier), on ferait croître le fichier de recopie sans que le fichier d’origine diminue.

  9. #9
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    .........suite du précédent post


    J’ai en fait créé le fichier “prévisionnel d’horaires“ de mon post précédent pour mettre en application de façon simple une instance de la classe mmap.mmap dans un programme de mise à jour (updating) de fichier, et non plus simplement d’élimination.


    En fixant les lignes toutes identiquement formatées et en mettant de coté volontairement toute procédure de vérification des données entrées à la main, le code sans complication, permettant de modifier les heures de matin (située entre les positions 35 et 40 dans chaque ligne) et/ou les heures d’après-midi (situées entre les positions 43 et 48) d’une ou plusieurs lignes de ce fichier "previsionnel.txt", est le suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    import mmap
     
    with open('previsionnel.txt','r+b') as f:
        mapper = mmap.mmap(f.fileno(),0)
        print mapper[-699:] # visualisation de la fin du fichier
     
        print '\nEntrez les repérages des lignes à modifier (RIEN pour clore):'
        while 1:
     
            pjm = raw_input('\n  prenom et date, séparés par blanc/s : ')
            if not pjm:  break
            prenom,j,m = pjm.split()
            horaire = raw_input('  une heure HHhMM, ou deux, de remplacement, séparés par blanc/s : ').split()
     
            x = mapper.find(prenom.upper().ljust(18)+': '+j+' '+m)
     
            for heure in horaire:
                if heure[0:2] in ('08','09','10','11','12'):
                    mapper[x+35:x+40] = heure
                elif heure[0:2] in ('13','14','15','16','17','18','19'):
                    mapper[x+43:x+48] = heure
                else:
                    print "  Erreur dans l'heure entrée "+heure+' . Modification non effectuée'
     
        mapper.flush()
        mapper.close()

    L’usage d’une instance de mmap donne une grande souplesse:
    on peut par exemple entrer les données pour modifier des lignes sans tenir compte de l’ordre de ces lignes dans le fichier.

    Ce serait possible aussi sans mmap mais en devant utiliser à la fois un ch = f.read() et le pointeur de fichier f :
    une instance de mmap fournit en fait la même chaîne qu’un ch = f.read() qui doit être utilisée pour faire de recherches du genre x = ch.find(’COLETTE’) , mais elle apporte en plus une facilité d’action qui évite de devoir faire ensuite de laborieux f.seek() pour translater le pointeur de fichier aux bonnes positions suivis de f.write(quelque_chose) pour écrire.

    Au lieu de cela, on groupe en une même instruction le positionnement et l’écriture:
    une seule instruction mapper[x+35 : x+40] = heure indique que l’écriture se fait entre les positions x+35 et x+40 et déclenche cette écriture.

    C’est à dire qu’une instance de mmap est une “chaîne mutable“: on peut y appliquer les techniques de chaîne, mais en plus elle est mutable et ses modifications se répercutent dans le fichier dont elle est l’émanation.





    ---------------------------------------------


    J’espère montrer par ces codes que pour intervenir sur des fichiers, on n’est pas assujetti à devoir toujours procéder par recopiage total de fichier, et que lorsqu’on y est obligé on peut dans certains cas ne même pas avoir à créer un double qui croît progressivement.

    J’espère couper ainsi l’herbe sous les pieds à cette fâcheuse légende urbaine selon laquelle les manipulations de fichiers sont obligatoirement compliquées.

    Python serait il vraiment bon s’il ne permettait pas de faire les choses mieux qu’invariablement par recopie de fichier en entier ?

  10. #10
    Membre émérite
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Par défaut
    cool... merci eyquem

  11. #11
    Membre averti
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2008
    Messages
    37
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Novembre 2008
    Messages : 37
    Par défaut
    merci
    grâce à vous j'ai résolu mon problème et même plus!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [CSV] Effacer une ligne dans un fichier CSV
    Par poulepexo dans le forum Langage
    Réponses: 1
    Dernier message: 22/04/2009, 12h12
  2. Effacer des lignes dans un fichier ?
    Par Instanton dans le forum Général Python
    Réponses: 5
    Dernier message: 31/12/2007, 13h22
  3. [Debutant]Effacer des lignes dans un fichier
    Par smutmutant2003 dans le forum Linux
    Réponses: 13
    Dernier message: 10/10/2007, 21h49
  4. [FSO] Effacer une ligne dans un fichier
    Par Johnbob dans le forum ASP
    Réponses: 4
    Dernier message: 30/05/2007, 16h23
  5. [langage] Effacer une ligne dans un fichier
    Par sebi77 dans le forum Langage
    Réponses: 2
    Dernier message: 01/01/2005, 12h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo