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 :

Regex - capture nommé dupliquée [Python 3.X]


Sujet :

Python

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    72
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Mai 2010
    Messages : 72
    Points : 70
    Points
    70
    Par défaut Regex - capture nommé dupliquée
    Bonjour,

    J'ai un script python chargé de traiter des fichiers et récupérer différentes données, via des regex configurable.
    Je tente dans la mesure du possible de récupérer les données avec un nombre de regex minimum.
    Mais là je coince car je dois utiliser des capture nommée avec des formats différents.
    En php, à priori une option permet de le faire, pas en python et je ne trouve pas d'alternative.
    Au pire je fait deux passes, en utilisant deux regex, mais pas optimum ;-).

    Plus concrètement (avec données fictives)...

    Exemples de data à traiter :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    Dans un fichier....
    12:00 ROUTEUR01 Démarrage : version 1.2 test 03
    12:01 ROUTEUR01 Test version 1.2
     
     
    Dans un autre fichier...
    12:00 ROUTEUR02 Démarrage
    15:01 ROUTEUR02 Test version 1.3
    Pour chaque routeur, je dois récupérer la version et le numéro de test si présent. Le script va écraser les infos des routeurs à chaque nouvelle entrée qui corresponds (pour précision avec des captures nommées est indispensable pour des raisons de souplesse non illustrée ici).
    Idéalement via une seule regex. Ici, je devrais avoir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    ROUTEUR01;1.2;03
    ROUTEUR02;1.3
    Ma regex précédente ne sortait pas les nouvelles version 1.3 : pas de problème, j'ai modifié comme cela...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    .*(?P<Routeur>ROUTEUR\d{2}).*version\sv*(?P<Valeur>\d{1,2}.\d{2})(?:.*test.*(?P<Valeur2>\d{2}))*
    Et là, j'ai découvert que la ligne indiquant la version 1.3 existait aussi avant! C'est le drame, mon script n'indique plus les valeurs test des 1.2 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    ROUTEUR01;1.2
    ROUTEUR02;1.3
    Facile, la solution logique serait de faire soit l'un soit l'autre, en une seule regex....
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    .*(?P<Routeur>ROUTEUR\d{2}).*version\s(?:v(?P<Valeur>\d{1,2}.\d{2}).*test.*(?P<Valeur2>\d{2})|(?P<Valeur>1.30))
    En PHP, avec l'option /J ça marche. En Python... quoi, il n'y a pas cette option????

    ... et depuis je pleure en remaniant dans tous les sens ;-) ...

    Alors, oui, je pourrais modifier le code autour de la regex mais ce n'est pas le but et c'est démesuré.
    Oui, je peux faire deux regex. Mon script saura le traiter... en analysant chaque ligne deux fois au lieu d'une, et ça me chiffonne!

    Alors, existe-t-il une solution? Une option cachée (pas trouvée...)? Une formulation différente de ma regex (j'avoue, je ne maitrise pas certaines méthodes)?
    Ou c'est mort en Python...

    Merci pour vos lumières et votre temps .

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Salut,

    Ce que j'en ai compris c'est qu'on veut avoir un groupe optionnel nommé (test 03) qui est là ou pas. Ce que je ferais comme çà:
    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
    >>> data = '''12:00 ROUTEUR01 Démarrage : version 1.2 test 03
    12:01 ROUTEUR01 Test version 1.2
    12:00 ROUTEUR02 Démarrage
    15:01 ROUTEUR02 Test version 1.3'''
    >>> lines = data.splitlines()
    >>> rg = r'.*(?P<routeur>ROUTEUR\d{2}) .*version (?P<version>\d\.\d)(?: test (?P<test>\d+))?'
    >>> for line in lines:
    ...     print ('test: /%s/' % line)
    ...     m = re.match(rg, line)
    ...     if m: print(m.group('routeur'), m.group('version'), m.group('test'))
    ...
    test: /12:00 ROUTEUR01 Démarrage : version 1.2 test 03/
    ROUTEUR01 1.2 03
    test: /12:01 ROUTEUR01 Test version 1.2/
    ROUTEUR01 1.2 None
    test: /12:00 ROUTEUR02 Démarrage/
    test: /15:01 ROUTEUR02 Test version 1.3/
    ROUTEUR02 1.3 None
    >>>
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    72
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Mai 2010
    Messages : 72
    Points : 70
    Points
    70
    Par défaut
    Merci wiztricks mais non ;-).

    Comme précisé "Le script va écraser les infos des routeurs à chaque nouvelle entrée" (via un INSERT OR UPDATE).
    Pas besoin du code python (sauf s'il y a un paramètres qui permet d'autoriser les doublons des groupes nommés), il est en prod, optimisé et ressemble effectivement à ce que tu propose (en plus complet, l'exemple donné est simplifié).

    Ce qu'il me faudrait c'est ne récupérer que les lignes en vert dans l'ensemble ci-dessous, avec des groupes nommés pour récupérer les données en gras.
    12:00 ROUTEUR01 Démarrage : version 1.2 test 03
    12:01 ROUTEUR01 Test version 1.2
    12:00 ROUTEUR02 Démarrage
    15:01 ROUTEUR02 Test version 1.3

    En 2 regex, je sais faire. En un regex sous PHP, je sais faire (option /J). En une regex sous Python... je ne sais pas faire .

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Citation Envoyé par Shampra Voir le message
    En 2 regex, je sais faire. En un regex sous PHP, je sais faire (option /J). En une regex sous Python... je ne sais pas faire .
    Dans mon code, il n y a qu'une seule regex.
    note: et comme vous faites abstraction du contexte d'utilisation....

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Expert éminent Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 035
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 035
    Points : 8 400
    Points
    8 400
    Par défaut
    salut,

    perso j'ai pas compris un broc de ce que le PO essaye d'expliquer, est-ce que la regex est appliquée sur chaque ligne ? sur l'intégralité du fichier avec un flag re.DOTALL ? avec re.match() ? avec re.search() ? le propos c'est de recouvrir les données ? de prendre la correspondance la plus longue possible ? de récupérer l'intégralité des correspondances ?

    la seule piste c'est cette option /J qui ne semble pas exister dans le module re et dont on peut lire ici et là qu'on peut obtenir plus ou moins la même chose avec les branch reset qui eux sont au moins disponibles dans le module regex
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #!/usr/bin/env python3
    import re
    reg = re.compile('(?P<Routeur>ROUTEUR\d+).*?version\s*v?(?P<Valeur>\d+\.\d+)(?:.*?test.*?(?P<Valeur2>\d+))?', re.DOTALL)
    for fichier in ['fichier1', 'fichier2']:
       with open(fichier, 'r') as f:
          z = re.search(reg, f.read())
          print ('{}: {}'.format(fichier, ';'.join(i for i in z.groups() if i)))
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $ ./pouet.py
    fichier1: ROUTEUR01;1.2;03
    fichier2: ROUTEUR02;1.3

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    72
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Mai 2010
    Messages : 72
    Points : 70
    Points
    70
    Par défaut
    Merci pour le DOTALL, ça ne me parle pas du tout alors je vais regarder de plus près.

    Il me semblait que ""Le script va écraser les infos des routeurs à chaque nouvelle entrée" était explicite pour expliquer pourquoi la solution ne convient pas.
    Surtout que la question portait idéalement uniquement sur la regex (comment contourner ce problème de champ nommé qui ne peuvent être présent qu'une fois).
    Ce n'est pas le cas... je reformule tout.

    On a des journaux remontés par des routeurs (quelques Go/jours).
    Pour des besoins d'analyse, j'ai mis en place un script qui récupère des informations dans les journaux pour les enregistrer en BDD, soit en mode "historique" (chaque information est enregistré) soit en mode "état" (cas qui nous intéresse : on n'enregistre pour chaque routeur que la dernière information récupérées).
    Une visualisation permet d'afficher les données stockées.
    Afin d'être souple, il est possible de configurer plusieurs recherches en indiquant pour chaque un titre et une regex.
    Chacune récupère le nom du routeur, l'horodate, une ou deux valeurs (nommées VALEUR et VALEUR2).


    Côté code Python, ça donne ça :
    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
     
    #.......#
     
    # On compile les différentes regex fournies  
    # 
    patterns = []
    for groupe in config.sections():
        textPattern=config[groupe]['Regex']
        if textPattern.find("Valeur2") == -1:
            textPattern=textPattern+'(?P<Valeur2>)'
        item=[config[groupe]['TypeResult'], config[groupe]['Nom'], re.compile(textPattern)]
        patterns.append(item)
     
    #........#
     
    # et on traite les fichiers
    for file in list_files:  
        try:
            for line in open(file, errors="ignore"):
                for typeTraitement, titre, pat in patterns:                
                    for match in re.finditer(pat, line):
                       count=0
                       if typeTraitement=='MAJ':
                            logger.debug("{}, {}, {}, {}, {}, {}".format(typeTraitement, titre,numRouteur,match.group('Date'),match.group('Valeur'),match.group('Valeur2')))
                            count = bdd.updateString(titre,numRouteur,match.group('Date'),match.group('Valeur'),match.group('Valeur2')) 
                             # updateString est une fonction effectuant un UPDATE d'une table, basé sur le numéro routeur et le titre de la recherche; requête utilisée :
                             # req ="UPDATE analyse SET ELEMENT1='%s', ELEMENT2='%s', DATE_ELEMENT='%s', DATE_MODIF='%s' WHERE ID_ROUTEUR=%s and TYPE_ELEMENT='%s'" % (newValue, oldValue, dateElt,time.strftime('%Y-%m-%d %H:%M:%S'), numET, titreRecherche )                                                                                                                                   
                            totalins+=1 
                       else :
                            # Traitement de type historique, hors sujet #
                       if (count==0):
                            logger.error("L'enregistrement a échoué")
        except:
            #....

    L'un des besoins est "pour chaque routeur, récupérer sa version et le cas échéant sa phase de test" pour avoir un tableau des versions et test en cours.
    Les logs à traiter ressemblent à ça pour une version 1.2 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    ....
    12:00 ROUTEUR01 Démarrage : version 1.2 test 03
    12:01 ROUTEUR01 Test version 1.2
    ....
    Et depuis peu voici pour une 1.3
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    ....
    15:00 ROUTEUR02 Démarrage
    15:01 ROUTEUR02 Test version 1.3
    ....
    Comment via une regex récupérer ça?
    Comme le montre le code, les valeurs doivent être récupérées nominativement avec VALEUR et VALEUR2
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    ID_ROUTEUR   VALEUR   VALEUR2
    ROUTEUR01    1.2         03
    ROUTEUR02    1.3
    Ma regex suivante est jetée car "A subpattern name must be unique".
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    .*(?P<Routeur>ROUTEUR\d{2}).*version\s(?:v(?P<Valeur>\d{1,2}.\d{2}).*test.*(?P<Valeur2>\d{2})|(?P<Valeur>1.30))
    Si vraiment ce n'est pas jouable directement via une superbe REGEX, je suis aussi intéressé si des options existent (équivalent au /J de PHP... je vais voir le re.DOTALL merci).
    Pas de refonte du code (à moins que ça n'optimise le résultat sur un grand nombre de fichiers/lignes).

    En espérant avoir été plus clair, merci.

  7. #7
    Expert éminent Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 035
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 035
    Points : 8 400
    Points
    8 400
    Par défaut
    histoire d'être synchros sur le contexte, le résumé tel que je le comprends :

    Citation Envoyé par Shampra Voir le message
    cas qui nous intéresse : on n'enregistre pour chaque routeur que la dernière information récupérées

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for file in list_files:  
       for line in open(file, errors="ignore"):
          for match in re.finditer(pat, line):
    Les logs à traiter ressemblent à ça pour une version 1.2 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    12:00 ROUTEUR01 Démarrage : version 1.2 test 03
    12:01 ROUTEUR01 Test version 1.2
    Comment via une regex récupérer ça?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ID_ROUTEUR   VALEUR   VALEUR2
    ROUTEUR01    1.2         03
    Ma regex suivante est jetée car "A subpattern name must be unique".
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    .*(?P<Routeur>ROUTEUR\d{2}).*version\s(?:v(?P<Valeur>\d{1,2}.\d{2}).*test.*(?P<Valeur2>\d{2})|(?P<Valeur>1.30))
    pour chaque fichier la regex est appliquée pour chaque ligne, c'est très différent d'avoir une regex qu'on applique sur l'ensemble du fichier, en l'occurrence l'emploi de re.finditer() ne sert à rien à moins d'avoir dans les logs une ligne du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    12:00 ROUTEUR01 Démarrage : version 1.2 test 03 TOTO COINCOIN ROUTEUR01 version 1.2 test 42
    par ailleurs si on ne conserve que la dernière information récupérée, et au vu du log d'exemple que tu fournis, on ne peut certainement pas obtenir ROUTEUR;01;03 à la fin, la dernière ligne traitée est 12:01 ROUTEUR01 Test version 1.2, pour quelle raison aurait-on conservé le groupe Valeur2 récupéré par la précédente regex ?? (et ça m'étonnerait fort qu'un quelconque switch permette de faire ça)

    et c'est à mon sens un problème distinct, la question des noms de groupes qui ne sont pas uniques; à ça wiztricks et moi avons fourni sensiblement la même réponse à savoir qu'en rendant la partie .*test.*(?P<Valeur2>\d{2}) optionnelle ((?:...)?) tu récupères dans le pire des cas un groupe Valeur2 à None qu'il est donc facile de filtrer après coup
    en clair TOTO (?:POUET|POUET COIN) peut très bien s'écrire TOTO POUET(?: COIN)? et on a plus besoin de nommer X groupes avec le même identifiant

    en étudiant d'un peu plus près ta regex qui se fait jeter, je remarque un détail .*version\s(?:v(?P<Valeur>..., ce "v" qui correspond donc à une ligne contenant version v1.2, sauf qu'il n'est pas optionnel dans la regex que tu donnes, et que là encore si on s'en tient au log d'exemple que tu fournis on se rend bien compte qu'elle ne matchera jamais rien

    enfin, et en admettant que le finditer() puisse trouver son utilité (dans le cas d'une ligne bizarrement foutue comme décrite plus haut ou dans le cas d'une regex sur l'ensemble du fichier avec re.DOTALL pour inclure les fins de ligne par exemple) il faut également faire attention aux opérateurs .* et .+ qui sont qualifiés de gourmands, à quoi on oppose .*? et .+? qualifiés de non-gourmands (non-greedy in english)
    en pratique :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    regex : "ROUTEUR.*version"
    match : "ROUTEUR_version_1.6_test_54_(sur_OS_version_8)"
    VS.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    regex : "ROUTEUR.*?version"
    match : "ROUTEUR_version_1.6_test_54_(sur_OS_version_8)"

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Salut,

    Citation Envoyé par BufferBob Voir le message
    par ailleurs si on ne conserve que la dernière information récupérée, et au vu du log d'exemple que tu fournis, on ne peut certainement pas obtenir ROUTEUR;01;03 à la fin, la dernière ligne traitée est 12:01 ROUTEUR01 Test version 1.2, pour quelle raison aurait-on conservé le groupe Valeur2 récupéré par la précédente regex ?? (et ça m'étonnerait fort qu'un quelconque switch permette de faire ça)
    Ce que j'en comprend, c'est que çà fonctionnait bien lorsque la ligne à matcher était de la forme "ROUTEUR01 Démarrage : version 1.2 test 03". Maintenant, qu'il y a des versions 1.3 dans la nature, on doit se contenter d'informations sous la forme "ROUTEUR02 Test version 1.2".
    Et si on s'amuse à récupérer les deux formats, on perd des informations.

    Si le propos du P.O. est de conserver l'existant autant que possible, le plus simple sera d'ajouter un test de version pour savoir quel format retenir dans le code ou la regexp, car de toutes façons, si on s'amuse à lire plusieurs lignes non seulement on va casser les autres regexp mais en plus on ne respecte pas la nature d'un "log" qui est d'avoir un enregistrement par ligne.
    note: en supposant qu'il y ait un équivalent du /J de PHP, le soucis est qu'on ne saura pas combien de lignes lire pour appliquer la regexp et encore moins ce que çà va donner pour les autres.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    72
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Mai 2010
    Messages : 72
    Points : 70
    Points
    70
    Par défaut
    Désolé pour le v de la regex, un oubli dans la simplification (la regex en place traite beaucoup plus de format, puisque qu'à chaque version les devs s'amusent à changer un détail dans le format des logs... pour le fun je suppose....).

    Le traitement se fait bien par ligne, et effectivement je ne souhaite pas le changer (entre autre pour des raisons de perf, même s'il est possible que je me trompe).

    Le /J de PHP s'applique sans changer le traitement par ligne/global. Il permets simplement d'avoir un groupe nommé présent plusieurs fois.
    Par exemple la REGEX suivante est fonctionnelle, Valeur sera récupéré dans le 1er format OU dans le 2ème: ((?P<Valeur>Version v.1)|(?P<Valeur>version 02)).

    Un équivalent en Python traiterait chaque ligne, récupèrerait mes valeurs suivant le format qui match.
    Ce qui me permettrait de ne garder que strictement ROUTEUR01 Démarrage : version 1.2 test 03 ou 15:01 ROUTEUR02 Test version 1.3.

    Et oui , c'est bien le numéro de test que l'on perds avec l'arrivée des 1.03 dans un format différent : le tableau retourné si je tente de prendre en compte tous les formats récupère "None" pour les 1.02 .
    Et perdre des données est le pire des cas et n'est pas souhaitable, je tiens à avoir un résultat fiable (et les utilisateurs encore plus ).
    Le pire des cas acceptable est une perte en performance...


    Pour le test de version, je suppose que c'est à faire dans le code? Dans ce cas, pas possible. Le script est générique, la récupération des versions et n° test n'est qu'un cas d'utilisation parmi d'autres (et pour une période limitée en plus).
    A défaut de pouvoir traiter tous les cas en une seule regex, j'ai séparé en deux. Légère perte de performance mais au moins j'ai tout.
    Et si jamais il y a une autre piste, je suis toujours intéressé bien sûr .

    Au passage, merci pour les informations sur les opérateurs gourmands, j'ai testé des versions du code jusqu'à avoir quelque chose d'efficace, je me suis moins inquiété des regex elles-mêmes, du coup ça m'intéresse merci!
    Et totalement HS : merci pour la balise [ c ] utilisé dans les messages, c'est pratique et elle manque à l'éditeur du forum!

  10. #10
    Expert éminent Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 035
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 035
    Points : 8 400
    Points
    8 400
    Par défaut
    ok j'ai fini par comprendre ce que tu voulais, auquel cas comme indiqué plus haut, le module re de Python ne permet pas de faire des captures avec plusieurs fois le même nom, le module regex le peut en revanche
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    import regex as re
     
    reg = re.compile('(?P<Routeur>ROUTEUR\d+).*?(?:version 1.(?P<Valeur>02) test (?P<Valeur2>\d+)|version 1.(?P<Valeur>03))')
    for fichier in ['fichier1', 'fichier2']:
       for line in open(fichier, 'r'):
          z = re.search(reg, line)
          if z:
             print ('{}: {}'.format(fichier, ';'.join(i for i in z.groups() if i)))
    et le résultat sur la base des fichiers fournis plus haut :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    fichier1: ROUTEUR01;02;03
    fichier2: ROUTEUR02;03
    note malgré tout que la solution fournie en première instance fonctionnait tout aussi bien (regex unique, groupe test facultatif), au détail près qu'elle était capable de match version 1.03 test xx, mais si ce genre de ligne n'existe pas ça n'était pas réellement un problème, voire j'aurais tendance à penser que ça permettait d'anticiper sur les versions

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

Discussions similaires

  1. Regex captures et boucles
    Par HardBlues dans le forum Langage
    Réponses: 1
    Dernier message: 22/04/2014, 16h55
  2. [RegEx] [Regex] Capturer du texte pour l'interpreter
    Par LaChips60 dans le forum Langage
    Réponses: 4
    Dernier message: 31/05/2011, 14h10
  3. regex : capture d'accents - \p{L} ne marche pas
    Par Phonatacid dans le forum Débuter avec Java
    Réponses: 1
    Dernier message: 23/04/2009, 10h38
  4. Posix regex : capture d'une sous chaine
    Par flo_k dans le forum C
    Réponses: 1
    Dernier message: 10/06/2008, 18h36
  5. [regex] groupe nommé non capturante.
    Par maa dans le forum C#
    Réponses: 3
    Dernier message: 22/10/2007, 02h19

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