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 :

Expression régulière et enlever un groupe [Python 3.X]


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    bm
    bm est déconnecté
    Membre extrêmement actif

    Homme Profil pro
    Freelance
    Inscrit en
    Octobre 2002
    Messages
    874
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Freelance
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2002
    Messages : 874
    Billets dans le blog
    6
    Par défaut Expression régulière et enlever un groupe
    Bonjour,

    <div id='p1'><u>Mercredi 22 Février 2017 :</u></div>
    Début 2015 était plus froid que début 2017.<br>
    Je veux sélectionner que les lignes avec 201x et ne pas tenir compte de la ligne avec </div>.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for t in fic:
        if re.search(r"201[5-8](?!(</div>))", t) is not None :
            print(t)
    Cette exclusion de donne rien avec re.search

    @+

  2. #2
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 815
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 815
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par bm Voir le message
    Je veux sélectionner que les lignes avec 201x et ne pas tenir compte de la ligne avec </div>.
    Bonjour

    Je ne suis pas expert des regex donc si je devais faire ça, je commencerais par
    1. exclure les lignes contenant "</div>"
    2. ne prendre de ce qui reste que les lignes contenant "201X"

    Et donc utiliser une regex dédiée à chaque action...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    bm
    bm est déconnecté
    Membre extrêmement actif

    Homme Profil pro
    Freelance
    Inscrit en
    Octobre 2002
    Messages
    874
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Freelance
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2002
    Messages : 874
    Billets dans le blog
    6
    Par défaut
    En cherchant un peu c'est basique :

    Par exemple, Isaac (?!Asimov) correspondra à la chaîne 'Isaac' seulement si elle n’est pas suivie par 'Asimov'.
    [Résolu]

  4. #4
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 815
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 815
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par bm Voir le message
    Par exemple, Isaac (?!Asimov) correspondra à la chaîne 'Isaac' seulement si elle n’est pas suivie par 'Asimov'.
    Alors il se trouve que je ne suis tout de même pas resté à rien faire suite à ton topic. J'ai donc moi aussi hier lu cette doc et moi aussi vu cet exemple (d'autant plus que j'adore les livres d'Isaac Asimov que j'ai tous donc il m'a sauté aux yeux). Puis ai tenté de l'appliquer mais n'ai pas réussi.
    Les exemples que j'ai tentés
    • print(re.search(r"(?!123)", "to123to")) en me disant que je cherchais quelque chose qui ne contiendrait pas "123"
    • print(re.search(r".{0,}(?!123)", "to123to")) en me disant que je cherchais n'importe quelle suite de caractères mais qui ne serait pas suivie de "123"

    et dans les deux cas n'ai pas réussi (mais comme je l'avais dit je ne suis pas expert des regex)

    Citation Envoyé par bm Voir le message
    En cherchant un peu c'est basique
    Ben t'aurais cherché dès le départ tu n'aurais pas eu besoin de venir ici demander de l'aide. Accessoirement il est tout de même d'usage assez courant que quand on est venu demander de l'aide sur un forum et qu'on finit par trouver (soit parce que l'aide a été utile, soit qu'on ait trouvé tout seul) qu'on montre la solution. C'est un minimum de politesse vis à vis de ceux qui se sont intéressés à ton problème.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 988
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 988
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    print(re.search(r"(?!123)", "to123to")) en me disant que je cherchais quelque chose qui ne contiendrait pas "123"
    (?!123) est une assertion comme ^ ou \b qui ne consomme aucun caractère, ce qui fait que la pattern réussit dés le début de la chaîne (puisque cette position est suivie par "to123to" et donc pas par "123") mais la correspondance est la chaîne vide.

    print(re.search(r".{0,}(?!123)", "to123to")) en me disant que je cherchais n'importe quelle suite de caractères mais qui ne serait pas suivie de "123"
    Oui et c'est précisément ce qui est renvoyé. Au début de la chaîne, .{0,} consomme tous les caractères jusqu'à la fin de la ligne (car les quantificateurs sont gourmands par défaut) et à la fin de la ligne, donc après "to123to", il n'y a pas "123", il n'y a rien. Comme dans le cas précédent la pattern réussit dés le début de la chaîne mais renvoie toute la chaîne.
    Pour trouver tous les bouts de chaîne qui ne soient pas immédiatement suivis par "123", il faudrait contrôler les caractères un par un et écrire:(?:.(?!123))+.

    Pour trouver une chaîne sur une ligne n'en contenant pas une autre, on peut ancrer le test avant au début de la chaîne, mais en laissant à la sous-pattern qu'il contient le loisir de parcourir toute la ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> print(re.search(r"^(?!.*123).*(to)", "to123to"))
    None
    >>> print(re.search(r"^(?!.*13).*(to)", "to123to"))
    <_sre.SRE_Match object; span=(0, 7), match='to123to'>
    >>> print(re.search(r"^(?!.*13).*(to)", "to123to").group(1))
    to
    >>> print(re.search(r"^(?!.*13).*?(to)", "to123to"))
    <_sre.SRE_Match object; span=(0, 2), match='to'>
    >>> print(re.search(r"^(?!.*13).*?(to)", "to123to").group(1))
    to
    Mais le problème avec cette méthode, c'est qu'il n'est pas possible d'obtenir toutes les occurrences de "to" avec re.findall ou re.finditer car l'ancre ^ échouera dés la 2e tentative (on obtient ['to'] et pas ['to', 'to']) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    >>> print(re.findall(r"^(?!.*13).*?(to)", "to123to"))
    ['to']
    Il n'y a à actuellement aucun moyen de trouver toutes les occurrences (dont on ne connaît pas le nombre à l'avance) d'une chaîne n'en contenant pas une autre avec le module re. (Sauf si on sait à l'avance que ce qu'on recherche est toujours avant la chaîne interdite; dans ce cas il suffit d'écrire to(?!.*123) ou \b201[5-8]\b(?!.*</div>))
    Donc le plus simple reste à faire un if '123' not in s: au préalable, ou d'utiliser une autre regex si la partie interdite est plus complexe.

    Ou alors, il faut se tourner vers le module pypi/regex qui lui a toutes les fonctionnalités dont on puisse rêver et qui permettent de faire ça, dont:
    • les tests arrière de taille variable: (?<!123.*)to(?!.*123)
    • l'ancre \G pour forcer les correspondances à être contiguë: \G(?:(?!123).)*(to)(?!.*123)
    • les verbes de contrôle du backtracking: ^.*123.*(*SKIP)(*F)|to (la première alternative consomme toute la chaîne, (*F) force l'échec, et (*SKIP) marque la position à partir de laquelle le moteur de regex peut faire une autre tentative (mais comme c'est la fin de la chaîne...)
    • les captures répétées: ^(?!.*123)(?:.*?(to))+ (avec re chaque répétition de la capture écrase la précédente, là elles sont stockées).

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 815
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 815
    Billets dans le blog
    1
    Par défaut
    Magnifique explications. Toi on voit que tu es un expert des regex

    Le seul détail c'est que tu t'es focalisé sur mon exemple "to123to" alors que moi j'avais monté cet exemple juste pour essayer de trouver comment utiliser la solution "(?!xxx)" pour ensuite l'appliquer au sujet initial de ce topic c'est à dire les lignes contenant "201X" et ne contenant pas "</div>".

    Bon bref tes explications m'ont enchantées et je les ai lues plusieurs fois... mais ne résolvent pas le pb initial

    Citation Envoyé par CosmoKnacki Voir le message
    Citation Envoyé par Sve@r Voir le message
    ...donc si je devais faire ça, je commencerais par
    1. exclure les lignes contenant "</div>"...
    Donc le plus simple reste à faire un if '123' not in s: au préalable
    Et là on retombe sur ma première préconisation
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 23/06/2011, 18h34
  2. extraction de groupe d'une expression régulière
    Par TaymouWan dans le forum C#
    Réponses: 9
    Dernier message: 22/05/2009, 18h09
  3. extraction des groupe des expression régulières
    Par TaymouWan dans le forum C#
    Réponses: 4
    Dernier message: 22/05/2009, 12h27
  4. Expressions régulières et groupes capturants
    Par ®om dans le forum Langage
    Réponses: 1
    Dernier message: 09/01/2008, 15h37
  5. [Regex] Expressions régulières: sous groupe
    Par debdev dans le forum Collection et Stream
    Réponses: 12
    Dernier message: 07/07/2005, 14h10

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