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

Langage PHP Discussion :

Optimisation d'une regex [RegEx]


Sujet :

Langage PHP

  1. #1
    Nouveau membre du Club
    Inscrit en
    Octobre 2009
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Octobre 2009
    Messages : 52
    Points : 25
    Points
    25
    Par défaut Optimisation d'une regex
    Bonjour à tous,

    Je viens à vous car je manque de recul. Je suis sur un gros fichier d'expressions que je dois enrichir afin d'obtenir de nouveaux attributs dans des liens. Concrètement et simplement, je dois ajouter des groupe de capture.
    J'ajoute que je suis relativement débutant en la matière.

    Ma problématique est que dans mon application mes extractions fonctionnent de $1 à $9. la $10 ne prend pas car ce qui est interprété est $1 suivi de 0.

    Bref, on m'a conseillé une optimisation, mais je me rends compte (après avoir réalisé une grosse optimisation) que cela ne fonctionne pas !

    Concrètement, voici la chaîne de caractère que je veux valider par exemple :

    Cass., Avis, 1er janvier 2012, n° 12-45.644

    Expression de base :

    Cass\.(,\s+(Avis|QPC))?,\s+(\d{1,2})e?r?(\s|  )+(\w+\.?)\s+(\d{4}),\s+n(°|°|o)s?(\s|  )+(\d{2}-\d{2}\.?\d{3})
    (j'ai mis une espace entre le ; et le ) pour éviter le )

    optimisée en

    Cass\.(,\s+(Avis|QPC))?,\s+(\d{1,2})e?r?[\s| ]+(\w+\.?)\s+(\d{4}),\s+n[°|°|o]s?[\s| ]+(\d{2}-\d{2}\.?\d{3})

    J'ai mis en couleur les 4 seuls groupes de capture dont j'ai besoin réellement.
    Le problème est donc que dans la première expression régulière, j'ai trop de groupe de capture, or, en remplaçant (\s|  ) par [\s| ] par exemple, le rendu n'est pas bon. (  étant une espace insécable).
    par exemple, si j'écris 1er septembre, mon 4e groupe de capture ne va pas renvoyer "septembre" mais "eptembre" car avant il y a [\s| ]+ qui prend le s de septembre...

    Je commence à être un peu perdu, savez-vous si il y une méthode pour écrire cette expression avec le moins de () possible mais tout en faisant le job ?
    Merci d'avance si je ne suis pas clair n'hésitez pas à me le faire remarquer.

    Romain

  2. #2
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 912
    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 912
    Points : 6 705
    Points
    6 705
    Par défaut
    Ce n'est pas un problème d'optimisation, c'est plutôt un problème de comment faire. Si tu es débutant, je te conseille de suivre un tutoriel comme par exemple celui de Guillaume Rossolini qui est sur ce site. Ça t'évitera de perdre du temps à inventer je ne sais quoi.

    Pour aller au delà de 9 avec les groupes de captures numérotés, il suffit de placer le numéro entre accolades dans le motif de remplacement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $str = 'abcdefghijklmnopqrstuvwxyz';
    $re = '/' . str_repeat('(.)', 26) . '/';
     
    echo preg_replace($re, '${26}', $str); // z
    Sinon pour éviter de créer des groupes de captures lorsque ce n'est pas nécessaire, il suffit d'utiliser un groupe non-capturant (?:...):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $str = 'abzcad';
    $re = '/(?:a|z)(.)/';
     
    echo preg_replace($re, '$1', $str); // acd
    NB: [\s| ] n'est pas un groupe mais une classe de caractères au sein de laquelle | n'a aucun sens spécial et où l'ordre des caractères n'a pas d'importance (sauf pour les séquences d'échappements, le tiret qui définit un rang, le caractère de négation ^ et quelques autres exceptions qui peuvent prêter à confusion). On pourrait réécrire la même classe de cette manière: [bnps;\s|].

    NB2: pour éviter les smileys dans les posts, il suffit de cocher la case Désactiver les smileys dans le message (et de placer le code entre les balises [code]).

  3. #3
    Nouveau membre du Club
    Inscrit en
    Octobre 2009
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Octobre 2009
    Messages : 52
    Points : 25
    Points
    25
    Par défaut
    Un grand merci CosmoKnacki, je vais potasser les tutos !
    Je découvre effectivement que l'on peut faire des groupes non_capturants et cela va me changer la vie !


    Merci encore,
    Romain

  4. #4
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 912
    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 912
    Points : 6 705
    Points
    6 705
    Par défaut
    Pour ta pattern d'exemple tu peux procéder comme ç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
     // on se débarrasse des entités html pour alléger la pattern
    $str = html_entity_decode ($str, ENT_COMPAT | ENT_HTML401, 'UTF-8');
     
    $re = '~ 
        # le modificateur x autorise les commentaires inline et ignore les espaces de la pattern.
        # le modificateur u précise que la pattern et le sujet sont en utf-8 et élargit les classes \w, \s, \d aux caractères unicode.
     
        # entre \Q et \E les caractères sont pris pour eux-mêmes
        \QCass.\E (?: , \s+ (?: Avis | QPC ) )? , \s+
     
        # avec le modificateur u on utilise [0-9] plutôt que \d pour exclure les chiffres des autres alphabets
        ( [0-9]{1,2} ) (?:er)? \s+ 
     
        # la classe \p{Latin} contient toutes les lettres de l\'alphabet latin avec ou sans accents
        ( \p{Latin}+ \.? ) \s+
     
        ( [0-9]{4} ) , \s+ 
     
        n [°o] s? \s+ ( [0-9]{2} - [0-9]{2} \.? [0-9]{3} )
    ~xu';

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

Discussions similaires

  1. Un souci d'optimisation avec une "petite" Regex
    Par Sehnsucht dans le forum Général Dotnet
    Réponses: 0
    Dernier message: 17/05/2010, 19h29
  2. [DB2] Optimisation d'une requête
    Par ahoyeau dans le forum DB2
    Réponses: 7
    Dernier message: 11/03/2005, 18h54
  3. Optimisation d'une recherche et mise à jour
    Par gandf dans le forum C++Builder
    Réponses: 4
    Dernier message: 07/01/2005, 19h38
  4. Réponses: 17
    Dernier message: 03/12/2004, 12h17
  5. [Debutant] Optimisation d'une boucle
    Par Javatator dans le forum Langage
    Réponses: 3
    Dernier message: 25/10/2004, 19h50

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