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 :

Aide sur les regex


Sujet :

Langage Perl

  1. #1
    Membre actif Avatar de etranger
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    333
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Septembre 2004
    Messages : 333
    Points : 268
    Points
    268
    Par défaut Aide sur les regex
    Bonjour

    j'essay de creer une fonction qui qui me renvoie le nombre d'occurances d'une sous chaine de N caractaires dans une chaine donnée.

    je fait cela de la maniere suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    sub make_histogramm{
                     my ($text, $size) = @_;
                     my %result;
     
                     while ($text =~ /(\S{$size})/g){
                            $result{$1}++;
                            #print $1;  #pour le debogage
                            #<STDIN>;
                     }
     
                     return %result;
     
    }
    le probleme c'est que si je passe a cette fonction une chaine comme "abcdefgh", avec une longeure de sous chaine de 2, l'expression reguliaire me renvoie "ab" = 1, "cd"=1 ... alors que ce qu'il me faudrait c'est que l'expression reguliaire me detecte egualement le "bc" , "de" ...

    Donc y a t-il une facon de faire cela uniquement avec une expression reguliaire, ou alors je devrait bidouiller un peut avec des boucles ?

    Merci d'avance, j'aurait surment d'autres questions sur les expressions reguliaire, je les poserait donc ici

  2. #2
    Membre éprouvé Avatar de MarneusCalgarXP
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    911
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 911
    Points : 1 118
    Points
    1 118
    Par défaut
    Personnellement, je procédèrerais de la manière suivante:
    1. suppression des espaces de la chaine à l'aide d'une regexp
    2. avec une boucle $i allant de 0 à length($str) - $size
      • Je récupère la sous-chaine substr($str, $i, $size)
      • j'incrémente le compteur de cette sous-chaine

    Je ne répond à aucune question technique par MP.

    Si votre problème est réglé, n'oubliez pas Dans tous les cas

  3. #3
    Membre actif Avatar de etranger
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    333
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Septembre 2004
    Messages : 333
    Points : 268
    Points
    268
    Par défaut
    effectivement c'est une solution, mais je voulait savoir (par curiosité) si c'était possible de le faire avec une regex

    P.S : genre une variable $^%\!2# à activer

  4. #4
    Membre éprouvé Avatar de MarneusCalgarXP
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    911
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 911
    Points : 1 118
    Points
    1 118
    Par défaut
    Peut-être (j'ai pas testé) en faisant:

    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
    sub make_histogramm{
                     my ($text, $size) = @_;
                     my %result;
                     $size--;
                     
                     while ( $text =~ s/(\S)(\S{$size})/$2/ ) {
                            $result{$1.$2}++;
                            #print $1;  #pour le debogage
                            #<STDIN>;
                     }
                    
                     return %result;
    				 
    }

    Je ne répond à aucune question technique par MP.

    Si votre problème est réglé, n'oubliez pas Dans tous les cas

  5. #5
    Rédacteur

    Inscrit en
    Septembre 2004
    Messages
    626
    Détails du profil
    Informations forums :
    Inscription : Septembre 2004
    Messages : 626
    Points : 848
    Points
    848
    Par défaut
    Bonjour,


    Je ne suis pas sûr d'avoir bien saisi, mais je pense qu'on peut faire comme ca avec une regexp :

    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
     
    my %len;
     
    $chaine = "toto AAA XXX XXXX AA";
     
    $chaine =~ s/\b\S+\b/&f($&)/eg;
     
    foreach (keys %len)
    {
       print "Length $_ => ", $len{$_}, "\n";
    }
     
    sub f
    {
       my ($match) = @_;
     
       $len{length($match)}++;
     
       return $match;
    }
    Qui produit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Length 4 => 2
    Length 3 => 2
    Length 2 => 1

    Laly.
    In the heart of the truly greats, perfection is never achieved but endlessly pursued.

    Mon article sur les fonctions analytiques d'Oracle (calcul de moyennes mobiles, de quartiles et bien d'autres...)

  6. #6
    Membre actif Avatar de etranger
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    333
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Septembre 2004
    Messages : 333
    Points : 268
    Points
    268
    Par défaut
    Merci a vous deux pour vous etre pencher sur mon probleme

    MarneusCalgarXP, ta methode a l'air de fonctioner, il faudra que je la test encore un peu.

    lalystar, se n'est pas vraiment ce que je voulais faire, ta fonction me renvoi combien de fois un mots de N lettres apparet dans ma chaine, alors que ce que je cherche a faire c'est de trouver tout les anagrames differents de N lettres (N doit etre choisi par l'utilisateur) dans mon texte, avec la frequence d'apparition de chaque anagrames. Les espaces peuvent ou non etre pris en comte.

    Maintenant ce n'est pas d'y arriver qui est difficile, c'est plutot de le faire de la maniere la plus eleguante.

    J'ai appris que c'est le meta-caractaire \G qui contient l'index de la recherche (la position ou la recherche est arrivee), y aurait il une maniere pour modifier cest index ?

  7. #7
    Rédacteur

    Inscrit en
    Septembre 2004
    Messages
    626
    Détails du profil
    Informations forums :
    Inscription : Septembre 2004
    Messages : 626
    Points : 848
    Points
    848
    Par défaut
    Ok, j'espère avoir compris cette fois.

    En une regexp, je propose :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    $chaine = "toto AAA XXX XXXX AA";
    $n = 3;
     
    print "Chaine BEFORE : $chaine\n";
     
    $chaine =~ s/\b\S{$n}\b/{$match{$&}++; $&}/eg;
     
    print "Chaine AFTER  : $chaine\n";
     
    foreach (keys %match)
    {
       print "Match $_ => ", $match{$_}, "\n";
    }
    Ce qui donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Chaine BEFORE : toto AAA XXX XXXX AA
    Chaine AFTER  : toto AAA XXX XXXX AA
    Match XXX => 1
    Match AAA => 1

    Laly.
    In the heart of the truly greats, perfection is never achieved but endlessly pursued.

    Mon article sur les fonctions analytiques d'Oracle (calcul de moyennes mobiles, de quartiles et bien d'autres...)

  8. #8
    Membre éprouvé Avatar de MarneusCalgarXP
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    911
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 911
    Points : 1 118
    Points
    1 118
    Par défaut
    Citation Envoyé par lalystar
    Chaine BEFORE : toto AAA XXX XXXX AA

    Match XXX => 1
    Match AAA => 1
    Si j'ai bien compris, ce n'est pas tout à fait ce qu'il veut... Pour une longueur de 3, il veut:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    tot => 1
    oto => 1
    toA => 1
    oAA => 1
    AAA => 1
    AAX => 1
    AXX => 1
    XXX => 5
    XXA => 1
    XAA => 1

    Je ne répond à aucune question technique par MP.

    Si votre problème est réglé, n'oubliez pas Dans tous les cas

  9. #9
    Membre chevronné
    Avatar de Woufeil
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 1 076
    Points : 2 004
    Points
    2 004
    Par défaut
    Bande de bourrin
    Vous vous compliquez la vie pour rien !
    Voilà ma solution :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    sub reg
    {
    	my ($chaine, $size) = @_;
    	my $sc = substr ($chaine, 1);
    	my %h;
    	$chaine =~ s/(.{$size})/{$h{$1}++}/eg;
    	$sc =~ s/(.{$size})/{$h{$1}++}/eg;
            return %h;
    }
    Elle est quand même bien plus facile que tous vos machins non ?
    "En essayant continuellement, on finit par réussir. Donc : plus ça rate, plus on a de chances que ça marche" (devise Shadock)
    Application :

    ainsi qu'à regarder la avant de poser une question.

    La rubrique Perl recrute, contactez-moi.

  10. #10
    Membre actif Avatar de etranger
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    333
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Septembre 2004
    Messages : 333
    Points : 268
    Points
    268
    Par défaut
    J'ai deja pensé a ta solution mais cela pose probléme :

    1.Si la logueur de l'anagram est different que 2.

    2.Si la chaine contient des espaces (et elle devrait).

    Pour utiliser ta mhetode il faudrait creer une boucle qui suprime N premieres lettre en fonction de la longueure de l'anagram.

    Et avant ca, faire un split pour traiter chaques chaine de caractaire sans espace seul.

    Par contre la methode de MarneusCalgarXP fonctione, c'est probablement du au fait que l'index de recherche est remis a zero après chaque substitution, en fin j'imagine.

  11. #11
    Membre chevronné
    Avatar de Woufeil
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 1 076
    Points : 2 004
    Points
    2 004
    Par défaut
    Ah merde, j'avais zappé que l'index pouvait être différent de deux... Effectivement, ma solution ne marche pas, désolé...
    Mais bon, si celle de MarneusCalgarXP te conviens, tu peux rajouter résolu
    "En essayant continuellement, on finit par réussir. Donc : plus ça rate, plus on a de chances que ça marche" (devise Shadock)
    Application :

    ainsi qu'à regarder la avant de poser une question.

    La rubrique Perl recrute, contactez-moi.

  12. #12
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Voir la doc de la fonction pos() :
    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
     
    #! /usr/bin/perl
    use strict;
    use warnings;
     
    my $test = "abcdefi yuvh";
     
    my %hist = histogram( 4, $test );
    {
        local $, ="\n";
        print keys %hist;
    }
     
    sub histogram {
        my ($size, $text) = @_;
        my %h;
     
        while( $text =~ m/(\S{$size})/g ){
            $h{$1}++;
            pos($text) -= ($size - 1);
        }
     
        return %h;
    }
    --
    Jedaï

  13. #13
    Membre actif Avatar de etranger
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    333
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Septembre 2004
    Messages : 333
    Points : 268
    Points
    268
    Par défaut
    Merci beaucoup Jedai, c'est bien la fonction pos() qu'il me fallait

    J'ai appris quelque chose de nouveau, Merci

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

Discussions similaires

  1. [Débutant] Aide sur les regex
    Par SpeedHunter dans le forum C#
    Réponses: 2
    Dernier message: 03/01/2012, 23h18
  2. Aide sur les groupes (ADO)
    Par portu dans le forum QuickReport
    Réponses: 3
    Dernier message: 18/08/2004, 16h13
  3. Filemaker ... besoin d'aide sur les Plugin
    Par joange dans le forum Autres SGBD
    Réponses: 3
    Dernier message: 22/04/2004, 10h16
  4. Petite aide sur les triggers ?
    Par krimson dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 16/04/2004, 16h28
  5. [CR] besoin d'aide sur les formules
    Par GuillaumeDSA dans le forum Formules
    Réponses: 4
    Dernier message: 10/07/2003, 12h19

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