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 :

edition d'un fichier .txt avec un script python


Sujet :

Python

  1. #1
    Nouveau Candidat au Club
    Inscrit en
    Septembre 2009
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Septembre 2009
    Messages : 4
    Points : 1
    Points
    1
    Par défaut edition d'un fichier .txt avec un script python
    bonjour,

    j'ai besoin d'extraire des données depuis un fichier text en utilisant un script python mais cette extraction s'avere complexe et j'ai du mal a identifier les commandes a utiliser, je sais lire les lignes d'un fichier avec un delimiteur par exemple, mais ici c'est bcp plus compliqué

    ceci est un echantillon du fichier text en question:
    //////////////////////////////////////////////////////////
    // ==============================================================
    // zz_rules
    // ==============================================================
    // zied:produit:etat:series:prix
    // ^prod:chabacha:valeur
    //

    analyse:produit:prix(?aaaaaaaaaaa,?ddddddd,?sssss;?ttttttt)<-
    gggg:yyyyyyyyy:nnnnn(?gggggggg,?llllllll,?iiiiiiii;?oooooooooooo).
    // dddddd:wwwwww
    //aaaaaaaaaa, zzzzzzzzzz:iiiiiiiiiiiiii

    user:chabacha(?cezdczze,?ffffffffffff,?vvvvvvvvv) <-
    ppppppp:uuuuuuu(?nnnn,?ttttt,?kkkkkkk),
    ppppppp:cccccccc:uuuuuuuu(?jjjjjjjj;?uuuuu).

    ///////////////////////////////////////////////////////////

    le but étant de parcourir le fichier et d'extraire "analyse:produit:prix" et "user:chabacha" dans cet exemple et de les mettre ds un autre fichier ligne par ligne, la ligne ou se trouvent les données a extraire est repérée par le symbole <- dans le fichier en question, tout ce qui est entre () doit etre eliminé de la ligne pour ne garder que "user:chabacha" par exemple

    la difficulté est le repérage de la bonne ligne, le code doit omettre tt ce qui commance par "/" lors de son parcours

    deuxieme difficulté est eliminer tt ce qui viens après la parenthèse ds cette ligne

    toute aide serait trés appreciée merci

  2. #2
    Membre averti Avatar de alexdevl
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    265
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2007
    Messages : 265
    Points : 344
    Points
    344
    Par défaut
    Bonjour,
    Pourrais tu utiliser les balises et donner un exemple de fichier de sortie


  3. #3
    Membre extrêmement actif
    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
    Points : 1 658
    Points
    1 658
    Par défaut
    Petite réponse en coup de vent.

    Les deux caractères ’<-’ sont ils présents dans le fichier pour repérer les lignes à exploiter (c’est ce que je comprends),
    ou bien son-ils dans ton message pour nous préciser, à nous, qu’il s’agit de ces deux lignes là ?

    Car les lignes
    gggg:yyyyyyyyy:nnnnn(?gggggggg,?llllllll,?iiiiiiii;?oooooooooooo).
    ppppppp:uuuuuuu(?nnnn,?ttttt,?kkkkkkk),
    ppppppp:cccccccc:uuuuuuuu(?jjjjjjjj;?uuuuu).
    sont dans la forme très semblables aux deux lignes à détecter, à ceci près qu’elles ont un point ou une virgule à la fin.

    Tous les détails comptent quand il s’agit de discriminer deux types de lignes très similaires.


    Quel est la version de Python que tu utilises ?
    Es-tu sous Windows ou Linux ?



    Voici une possibilité:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    chori = 'E:\Catalogue\ori.txt'
    chdest = 'C:\Courriers\dest.txt'
    f = open(chori,'r')
    g = open(chdest,'w')
     
    for ln in f:
        if ln[0:2]!='//' and ln.rstrip('\n')[-2:]=='<-':
            print ln.rstrip('\n')
            x = ln.find('(')
            if x+1: # x vaut -1 quand '(' n'est pas trouve dans ln
                g.write(ln[0:x])
     
    f.close()


    Avec les expressions régulières ce serait plus condensé et net.

  4. #4
    Nouveau Candidat au Club
    Inscrit en
    Septembre 2009
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Septembre 2009
    Messages : 4
    Points : 1
    Points
    1
    Par défaut plus de details
    bonjour,
    la bonne chose c'est que le fichier d'origine comporte bien le symbole "<-" pour chaque ligne qui nous concerne

    le fichier de sortie est tres simple et doit simplement contenir quelque chose qui ressemble a ça:

    analyse:produit:prix
    user:chabacha

    j'utilise python 2.5 sur windows

    j'ai pas encore testé le code que vous avez proposé, je le fais tt de suite, j'espere que ça va marcher

  5. #5
    Nouveau Candidat au Club
    Inscrit en
    Septembre 2009
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Septembre 2009
    Messages : 4
    Points : 1
    Points
    1
    Par défaut le code marche
    j'ai testé le code et j'ai introduit quelques modifications pour eliminer les doublons, il marche parfaitement

    merci infiniment

  6. #6
    Membre extrêmement actif
    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
    Points : 1 658
    Points
    1 658
    Par défaut
    « le fichier d'origine comporte bien le symbole "<-" pour chaque ligne qui nous concerne »
    Super. Ça simplifie




    En faisant l’hypothèse que les sections recherchées ne comportent pas de caractère ’(’ , je propose aussi le code suivant avec expression rationnelle


    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
    import re
     
    chori = 'analyse produit prix.txt'
    chdest = 'zxzxzxzxzx.txt'
    f = open(chori,'r')
    g = open(chdest,'w')
    li = []
    for ln in f:
        try:
            x = re.match('(?!/)([^(]+)\(\?.+\) *<-',ln).group(1)
            if x not in li:
                g.write(x+'\n')
                li.append(x)
        except:
            pass
    f.close()
    g.close()




    EXPLICATION DE LA RE '(?!/)([^(]+)\(\?.+\) *<-'


    (?!/)un tel motif impose que le caractère situé en avant de la position examinée ne soit pas le caractère ’/’


    [...]définit un ensemble de caractères parmi lesquels un caractère situé à la position examinée dans la chaîne traitée doit se trouver pour matcher
    Par exemple [w9 =] indique qu’à une position examinée, le caractère présent doit être soit ’w’ soit ’9’ soit ’ ’ soit ’=’.
    [^k]
    un ensemble de caractères peut être défini par complémentation. C’est le caractère ^ au début qui indique que les caractères qui le suivent doivent NE PAS être trouvés à la position examinée dans une chaîne pour qu’il y ait matching.
    Pour matcher plusieurs fois un caractère pris dans un ensemble il faut écrire [w9 =]+ ou [w9 =]*


    ([^(]+) dans mon code
    indique qu’une suite de caractères matchant avec le motif entre parenthèses sera capturé dans un “groupe“ ( c’est le terme, pas très explicite). Groupe: cela veut dire que la suite capturée peut être ultérieurement utilisée.
    Dans le code, re.match('(?!/)([^(]+)\(\?.+\) *<-',ln) crée un objet Match qui peut être interrogé.
    En l’interrogeant avec la méthode group(0) , on obtient la chaîne matchante en entier.
    group() donne le même résultat que la méthode group(0)
    En interrogeant avec group(1) , on obtient la suite de caractères de la chaîne traitée correspondant au premier groupe défini dans la RE (Regular Expression, la chaîne qui est compilée pour définir l’objet Regex qui sert à faire la recherche de matching). Pour que group(1) ne donne pas d’erreur, il faut évidemment que soit défini au moins un groupe dans la chaîne RE.
    La ’(’ étant un caractère exclu du motif de recherche, quand le moteur de regex rencontre la première ’(’ dans la chaîne traitée, il arrête la capture du groupe, vérifie si la suite de la chaîne traitée matche avec la suite de la RE et quand c’est le cas enregistre ce qu’il vient de trouver comme suite matchante.


    ’\(’
    Il s’agit d’indiquer le caractère ’(’. Comme les parenthèses ont des significations spéciales dans les RE (elles ouvrent et ferment ouvre la définition d’un groupe), on met l’antislash devant pour échapper cette spécialité, quand on veut spécifier simplement le caractère ’parenthèse’.


    '\?'idem pour spécifier le caractère ’?’ sans sa signification spéciale


    '.+'
    indique une suite de caractères quelconques, sauf le newline


    ’\)’Échappement de la signification spéciale de ce caractère, sinon on obtient une erreur “Unbalanced parenthesis“.


    ’ *’C’est le caractère ’ ’ (blanc) multiplié 0 ou x fois.
    Nécessaire parce que la ligne
    user:chabacha(?cezdczze,?ffffffffffff,?vvvvvvvvv) <-
    montre un blanc avant les deux caractères signaux ’<-’


    ’<-’Les deux caractères ’<’ et ’-’ qui se suivent. Bien pratique qu’ils soient là pour signaler les lignes voulues, parce que ça évite de devoir détecter les fins de lignes ou fin de texte



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


    J’ai tenu compte de ta remarque sur des doublons. Je suppose qu’il s’agit de lignes identiques qui se retrouvent dans tout le fichier mais dont tu n’as besoin de recopier qu’un exemplaire.

    Pour chaque ligne ln, le programme essaie de créer un objet Match :
    re.match('(?!/)([^(]+)\(\?.+\) *<-',ln)
    S’il n’y arrive pas, il y a quand même un objet créé mais ce n’est pas un objet Match, c’est tout simplement None.
    Le programme essaie ensuite d’extraire un groupe de l’objet qu’il vient d’obtenir.
    S’il y arrive, avant d’enregistrer ce groupe dans le fichier récepteur, le programme teste si ce groupe est absent de la liste des groupes déjà vus.
    S’il n’arrive pas à extraire un groupe parce qu’il s’agit d’un objet None, l’erreur est prise en charge par l’exception et le programme passe en except: c’est à dire qu’il passe à la suite





    C’est pour montrer la puissance des regex. La gestion des doublons allonge un peu le code, mais la recherche des lignes en elle-même tient en une seule ligne de code.

  7. #7
    Nouveau Candidat au Club
    Inscrit en
    Septembre 2009
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Septembre 2009
    Messages : 4
    Points : 1
    Points
    1
    Par défaut merci pour ton aide
    bonjour,
    le principe du matchage est tres intéressant, merci pour ton aide , j'essaye juste d'automatiser certains trucs et comme je suis pas tres pro dans le développement et surtout l'édition des fichier textes qui me fait perdre mon sang froid, je suis presque arrivé au bout de ma tache , j'en suis a une étape qui est bcp plus simple, j'essaye actuellement de résoudre ce problème:

    j'ai un fichier qui ressemble a ça:

    chjbckbcqdhbsqhc
    fjuifhhuzeripfhazuehpaf
    fzuaihofzeui)

    ezfayhocahfhf
    ezfyafyepzeaffaezfea
    zafkop)

    le but étant de lire les lignes et d'ajouter un "." après chaque parenthèse a la fin de la ligne et avant d'avoir une ligne vide, je vais essayer les fonctions de matching et voir ce que ça va donner

    si j'y arrive ce ticket sera fermé, merci bcp

  8. #8
    Membre extrêmement actif
    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
    Points : 1 658
    Points
    1 658
    Par défaut
    Dans un fichier, il n’existe pas de lignes !

    Il n’existe que des caractères de retour à la ligne qui, lorsqu’il sont lus pour affichage à l’écran, provoquent des passages à la ligne suivante.

    Il faut donc bien se représenter que sur un disque dur, ton fichier ne se présente pas comme ça:

    chjbckbcqdhbsqhc
    fjuifhhuzeripfhazuehpaf
    fzuaihofzeui)

    ezfayhocahfhf
    ezfyafyepzeaffaezfea
    zafkop)

    mais comme ça:

    chjbckbcqdhbsqhc\n
    fjuifhhuzeripfhazuehpaf\n
    fzuaihofzeui)\n
    \n
    ezfayhocahfhf \n
    ezfyafyepzeaffaezfea\n
    zafkop)\n
    ou plutôt, puisqu’un fichier est en réalité une succession linéaire de caractères, comme ça:

    chjbckbcqdhbsqhc\nfjuifhhuzeripfhazuehpaf\nfzuaihofzeui)\n\nezfayhocahfhf \nezfyafyepzeaffaezfea\nzafkop)\n
    (Il y a ou il n’y a pas le dernier \n, cela dépend de la façon dont a été écrit le fichier)



    Ci-dessus, c’est un fichier ayant été écrit sur un disque dur par un système Linux.
    Un système Windows, lui, l’écrit ainsi sur le disque dur:

    chjbckbcqdhbsqhc\r\nfjuifhhuzeripfhazuehpaf\r\nfzuaihofzeui)\r\n\r\nezfayhocahfhf \r\nezfyafyepzeaffaezfea\r\nzafkop)\r\n
    C’est à dire qu’un retour à la ligne est exprimé par \r\n sous Windows et par \n sous Linux, et par \r sous Mac je crois.

    Cependant, il faut savoir que, par défaut, Python lit les fichiers sur disque dur en transformant tous les signaux de passage à la ligne en \n. On peut donc traiter les fichiers lus, c’est à dire les chaîne dans lesquelles les place une lecture, en ne se préoccupant que de la présence de \n.






    Ton problème est simple:
    “ une parenthèse en fin de ligne, une ligne suivante vide“se traduit par
    “)\n\n“

    Il faut voir que tu n’arriveras pas à insérer au burin un caractère point ’.’ entre deux autres caractères inscrits sur le disque dur. Il faut faire passer le fichier du disque dur dans une chaîne, transformer la chaîne et écrire le nouveau fichier sur le disque dur (avec le même nom en ’w’ ça écrase l’ancien).



    Pour transformer la chaîne, tu peux utiliser sub() du module re si tu y tiens, mais replace() suffira.
    Ainsi que read() et write() et c'est tout.

Discussions similaires

  1. Concaténer des fichiers txt avec script shell Unix
    Par tsivery dans le forum Shell et commandes POSIX
    Réponses: 1
    Dernier message: 12/01/2011, 14h39
  2. comparaison de deux fichiers textes avec un script python
    Par zekruss dans le forum Général Python
    Réponses: 1
    Dernier message: 10/11/2009, 05h52
  3. Ouvrir un fichier.txt avec Notepad depuis un script PHP
    Par legastu dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 11/07/2007, 11h40
  4. Imprimer un fichier texte avec un script vbs
    Par Persons dans le forum Windows
    Réponses: 3
    Dernier message: 23/12/2004, 16h47
  5. Pb import fichier txt avec lignes de longueurs diverses
    Par zebulon90 dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 09/12/2004, 08h32

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