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 Perl Discussion :

trouver le dernier : expressions régulière


Sujet :

Langage Perl

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2013
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2013
    Messages : 124
    Points : 94
    Points
    94
    Par défaut trouver le dernier : expressions régulière
    bonjour
    j'ai un fichier svg ou je voudrais rendre le dernier point invisible en changeant la classe css
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <!-- datapoint shown -->
            <circle cx="369.95" cy="400" r="2.5" class="dataPoint2"/>
     
                                  <!-- datapoint shown -->
            <circle cx="370.9" cy="400" r="2.5" class="dataPoint2"/>
     
                                  <!-- datapoint shown -->
            <circle cx="371.85" cy="400" r="2.5" class="dataPoint2"/>
     
                                  <!-- datapoint shown -->
            <circle cx="372.8" cy="400" r="2.5" class="dataPoint2"/>
    # et apres autre chose
    il faut donc que je trouve le dernier class="dataPoint2" et le remplace par class="invisible". Il faut savoir que toute les retours lignes sont supprimés au moment du traitement.
    Si vous avez ça, dans vos cartons.

  2. #2
    Membre averti
    Homme Profil pro
    très occupé
    Inscrit en
    Juillet 2014
    Messages
    137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : très occupé

    Informations forums :
    Inscription : Juillet 2014
    Messages : 137
    Points : 411
    Points
    411
    Par défaut
    Salut vidici,

    Si tes retours à la ligne sont supprimés, ou si tu utilises le modificateur //s pour traiter l'information comme si elle était sur une seule ligne, il te suffit de matcher class="dataPoint2" précédé du quantificateur .*, qui va opérer de façon "gourmande", pour atterrir sur le dernier.
    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
    #!/usr/bin/perl
     
    use strict;
    use warnings;
     
    my $st = q(<!-- datapoint shown -->
            <circle cx="369.95" cy="400" r="2.5" class="dataPoint2"/>
     
                                  <!-- datapoint shown -->
            <circle cx="370.9" cy="400" r="2.5" class="dataPoint2"/>
     
                                  <!-- datapoint shown -->
            <circle cx="371.85" cy="400" r="2.5" class="dataPoint2"/>                                                                                                                                                  
     
                                  <!-- datapoint shown -->
            <circle cx="372.8" cy="400" r="2.5" class="dataPoint2"/>
    # et apres autre chose);
     
     
    if ($st =~ /^(.*class=")(dataPoint2)(".*$)/s) {
        print "$1invisible$3";
    } else {
        print 'Erreur : les données ne contiennent ' .
        'aucun class="dataPoint2"\n';
    }
    Eks

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2013
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2013
    Messages : 124
    Points : 94
    Points
    94
    Par défaut
    merci Eks
    en fait j'avais pas vu que tu m'avais donné une solution toute faite dans le bas du déroulant. Mais j'ai suivis la piste de ton intro et j'en suis arrivé à cela
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     my ($captureE)= $gif =~ /(.+)*r="2.5" class="dataPoint1"/;
            my ($captureF)= $gif =~ /.*r="2.5" class="dataPoint1"(.+)/;
            $gif = $captureE.'r="0" class="dataPoint1"'.$captureF;
    je voulais te remercier pour ça quand j'ai vu ta solution... scrogneu gneu j'aurais gagné du temps.

  4. #4
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par vidici Voir le message
    scrogneu gneu j'aurais gagné du temps.
    Bah, tu as sans doute appris quelque chose en le faisant toi-même.

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2013
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2013
    Messages : 124
    Points : 94
    Points
    94
    Par défaut
    Citation Envoyé par Lolo78 Voir le message
    Bah, tu as sans doute appris quelque chose en le faisant toi-même.
    certes ... par contre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    my ($captureE)= $gif =~ /(.+)*r="2.5" class="dataPoint1"/;
    bien que ne faisant pas échouer le programme, et bien que fournissant le resultat attendu, me donne cette erreur
    Complex regular subexpression recursion limit (32766) exceeded at CreateLineGraph.pm
    Je viens de m'en rendre compte.

  6. #6
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    C'est un warning, pas une erreur. Tu peux sans doute le réduire au silence avec le pragma suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    use warnings;
    no warnings qw/regexp/;
    mais je n'ai pas essayé.

    Cela dit, ce warning indique que peut-être ton expression utilise le moteur d'expression régulière de façon un peu inefficace, ou du moins suboptimale (sur une chaîne trop longue). Si c'est juste un fois, ça n'a sans doute pas trop d'importance, mais si tu le fais de très nombreuses fois dans ton programme, il faut peut-être envisager une solution différente: soit un mini-parser, soit une utilisation des fonctions rindex et substr, soit une expression régulière un peu plus subtile empêchant de trop nombreux retours arrière (backtracking) du moteur de regex.

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2013
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2013
    Messages : 124
    Points : 94
    Points
    94
    Par défaut
    Citation Envoyé par Lolo78 Voir le message
    il faut peut-être envisager une solution différente: soit un mini-parser, soit une utilisation des fonctions rindex et substr, soit une expression régulière un peu plus subtile empêchant de trop nombreux retours arrière (backtracking) du moteur de regex.
    ok, je vais tenter de réfléchir à ça, par ce qu'effectivement c'est un bout de code qui va entrer de nombreuses fois en fonction.
    je pensais que ma façon de faire, comportait une erreur.
    merci du retour.

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2013
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2013
    Messages : 124
    Points : 94
    Points
    94
    Par défaut
    pour info j'ai donc remplacé l'expression régulière incriminée par une autre qui matche plus directement et sans utiliser le comportement gourmand , mais qui aura l'inconvenient d'être sensible à toute modification future structurelle du dit svg.

  9. #9
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Il serait intéressant de montrer ce que tu as fait. Cela peux donner des idées à des personnes rencontrant le même problème et tombant sur ce thread après une recherche Google sur le texte du warning.

  10. #10
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2013
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2013
    Messages : 124
    Points : 94
    Points
    94
    Par défaut
    je ne sais pas si cela à vraiment de l'intérêt, mais comme un commentaire suivait le dernier point, j'ai juste fait ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    my ($captureE)= $gif =~ /(.+)r="2.5" class="dataPoint1".+<\!--/;
    (il n'y a plus d' etoile (*)!)
    mais comme je l'ai dit, s'il venait à quelqu'un l'idée de supprimer les commentaires, cela ne fonctionnerait bien sur plus. Alors que la solution gourmande aurait continué de fonctionner.

  11. #11
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    C'est l'éternel problème quand on essaie de reconnaître (avec des regex ou autrement) du texte de format relativement libre: où s'arrêter et jusqu'où aller pour éviter les faux positifs et les faux négatifs...

  12. #12
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    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 858
    Points : 6 556
    Points
    6 556
    Par défaut
    je ne sais pas si cela à vraiment de l'intérêt, mais comme un commentaire suivait le dernier point, j'ai juste fait ceci
    C'est effectivement inutile voire contreproductif car devoir trouver .+<!-- ne fera que rajouter des étapes inutiles. Le problème venait uniquement du (.+)* qui est un cas bien connu (quantificateurs imbriqués) pouvant provoquer un "catastrophic backtracking" si la suite de la pattern n'est pas trouvée, car dans ce cas le moteur de regex va utiliser son mécanisme de backtracking et essayer tous les découpages possibles. Schématiquement, si tu as une chaîne "abcd", pour une pattern ^(.+)*k. Le moteur devra en passer par:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    abcd
    abc d
    ab cd
    ab c d
    a bcd
    a bc d
    a b cd
    a b c d
    avant d'échouer (car il n'y a pas de "k"). pour 100 caractères, il y a 2^99 découpages possibles.

    L'idée d'-Eks- d'utiliser le fait que les quantificateurs sont gourmands (greedy) par défaut fonctionne, dans le même genre tu peux écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $svg =~ s/\A.+\sclass="\KdataPoint2\b/invisible/;
    Mais si la sous-chaîne est très longue après le dernier "dataPoint2", ça restera peu efficace car il y aura autant d'étapes de backtracking que de caractères dans la dite sous-chaîne.

    Pour éviter le problème on peut utiliser la ruse qui consiste à retourner la chaîne et à remplacer la premier occurrence de "2tnioPatad"=ssalc:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $svg = reverse($svg);
    $svg =~ s/"2tnioPatad"=ssalc/"elbisivni"=ssalc/;
    $svg = reverse($svg);
    Maintenant le svg est ni plus ni moins du xml, donc tu peux toujours te tourner vers la solution d'un parser xml. Si tu as plusieurs modifications à faire sur le xml, c'est peut être la meilleur solution, car dans ce cas, le coût de construction de l'arbre DOM est amorti.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  13. #13
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    En fait, je n'avais pas vu que tu avais deux quantificateurs:
    et c'était cela (l'astérisque en plus) la cause du problème. Il suffit de l'enlever.

    J'ai essayé de reproduire ton problème et suis arrivé à cela:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    $ perl -e 'use strict; use  warnings; 
    my $c = "foo" x  15000;  $c .= "bar";  $c = $c x 3;  $c .= "foobaz"; $c .= ("foo" x 5000); 
    print $2 if $c =~ /(.+)*(fooba.)/;
    '
    Complex regular subexpression recursion limit (32766) exceeded at -e line 1.
    foobaz
    Et en supprimant l'astérisque qui ne sert à rien:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    $ perl -e 'use strict; use  warnings; 
    my $c = "foo" x  15000;  $c .= "bar";  $c = $c x 3;  $c .= "foobaz"; $c .= ("foo" x 5000); 
    print $2 if $c =~ /(.+)(fooba.)/;
    '
    foobaz
    le warning disparaît.

    A noter que l'exécution est pratiquement instantanée dans les deux cas, malgré l'utilisation d'une chaîne de plus de 150000 caractères:

    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
     
    $ time perl -e 'use strict; use  warnings; 
    my $c = "foo" x  15000;  $c .= "bar";  $c = $c x 3;  $c .= "foobaz"; $c .= ("foo" x 5000); 
    print $2 if $c =~ /(.+)*(fooba.)/;
    '
    Complex regular subexpression recursion limit (32766) exceeded at -e line 1.
    foobaz
    real    0m0.075s
    user    0m0.046s
    sys     0m0.030s
     
    ~
    $ time perl -e 'use strict; use  warnings; 
    my $c = "foo" x  15000;  $c .= "bar";  $c = $c x 3;  $c .= "foobaz"; $c .= ("foo" x 5000); 
    print $1  if $c =~ /.+(fooba.)/;
    '
    foobaz
    real    0m0.061s
    user    0m0.015s
    sys     0m0.030s
    La version sans l'astérisque paraît cependant plus rapide, même si le différence n'est pas énorme.

  14. #14
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2013
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2013
    Messages : 124
    Points : 94
    Points
    94
    Par défaut
    ok, merci à tous les deux pour votre aide. J'avoue que je me suis un peu emmêler les pédales sur ce coup là car au départ j'avais une erreur qui n'avais rien à voir avec une expression régulière somme toute très simple et qui m'a poussé à chercher dans la mauvaise direction.
    à tout hasard je met ma fonction qui me sert à modifier l'apparence d'un svg produit par TT::GRAPH.

    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
    sub fab_graph_css {
            my $self = shift;
            my $adresse = shift;
            my $gif = $self->grapher->burn();
            my $css = $self->txtCss;
            $gif =~ s/\n/~/g;
            my ($captureE)= $gif =~ /(.+)r=".+?" class="dataPoint1"/;
            my ($captureF)= $gif =~ /.*r=".+?" class="dataPoint1"(.+)/;
            $gif = $captureE.'r="0" class="dataPoint1"'.$captureF;
            $gif =~ s/cy="400" r=".+?"/cy="400" r="0"/g;
            $gif =~ s/r=".+?" class="dataPoint3"/r="0" class="dataPoint3"/g;
            my ($captureA) = $gif =~ /(.+?)\/\* Copy from here for external style sheet \*\//;
            my ($captureB) = $gif =~ /.+?\/\* End copy for external style sheet \*\/(.+)/;
            my $return = $captureA.$css.$captureB;
            $return =~ s/~//g;
            open my $in, '>', $adresse or die "Impossible d'écrire dans $adresse";
            say $in $return;
            close $in;
     
    }

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

Discussions similaires

  1. Trouver la bonne expression régulière
    Par Marvelll dans le forum Débuter avec Java
    Réponses: 1
    Dernier message: 09/04/2010, 08h13
  2. [REGEX] trouver le max à l'aide d'une expression régulière
    Par miketidy dans le forum Collection et Stream
    Réponses: 3
    Dernier message: 20/06/2008, 15h17
  3. Expression régulière : Trouver exactement un mot
    Par Drannor dans le forum Collection et Stream
    Réponses: 2
    Dernier message: 09/05/2008, 15h42
  4. [RegEx] Expression régulière pour trouver des mots
    Par cbroissa dans le forum Langage
    Réponses: 7
    Dernier message: 26/05/2006, 23h39

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