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 pour une regexp


Sujet :

Langage Perl

  1. #1
    Membre à l'essai
    Homme Profil pro
    Lycéen
    Inscrit en
    Octobre 2021
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Lycéen
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2021
    Messages : 27
    Points : 11
    Points
    11
    Par défaut aide pour une regexp
    Bonjour,

    Je cherche à comparer 2 variables contenant une chaine de caractères.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    my $v1 ="je mange une bonne pomme";
    my $v2 = "je mange une bonne fraise";
    (my $c = "$v1\n$v2" ) =~ /^(.*)(\b.*)\n\1(.*)/;
    print "texte commun\n".$1."\n";
    print "texte diférant1\n".$2."\n";
    print "texte diférant2\n".$3."\n";
    Dans cet exemple tout fonctionne bien, ça retourne bien que "pomme" est différent de "fraise" et que le texte commun est "je mange une bonne".

    Mais voila ce que je voudrais obtenir également.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    my $v1 ="je mange une bonne pomme";
    my $v2 = "mange une bonne fraise";
    (my $c = "$v1\n$v2" ) =~ /^(.*)(\b.*)\n\1(.*)/;
    print "texte commun\n".$1."\n";
    print "texte diférant1\n".$2."\n";
    print "texte diférant2\n".$3."\n";
    Mais là ça fonctionne pas comme je le voudrais.

    Je voudrais qu'il me retourne le texte commun "mange une bonne" et qu'il retourne seulement le texte différent se trouvant après le texte commun.
    donc
    pomme
    fraise

    S'il y a un génie des regexp qui pourrait m'aider, ça serait super sympa!

    merci à vous.

  2. #2
    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
    Le problème c'est que ton premier groupe de capture est ancré au début de la chaîne ^(.*) donc tu ne peux pas espérer qu'il capture quoi que ce soit qui ne commence pas au début de la chaîne. D'autre part, le quantificateur * l'autorise à être vide, ce qui peut aussi être un problème suivant ce que tu souhaites faire.

    Pour ton exemple de chaîne tu peux déjà changer ta pattern comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    /^.*?\b(\w.*)(\b.*)\n\1(.*)/
    ou en supprimant carrément l'ancrage:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    /\b(\w.*)(\b.*)\n\1(.*)/
    Aprés, pour allez plus avant, il faudrait que tu détailles mieux:
    • Les mots peuvent-ils être coupés par les groupes de capture et la référence au groupe 1?
    • si les deux lignes ont plusieurs parties en commun lesquelles choisir et selon quel critère? La plus à gauche, la plus longue, autre et sur quelle ligne ?
    • La partie commune peut-elle être vide?
    • La partie commune doit-elle forcément débuter au début de la deuxième ligne?


    NB: Je n'ai pas voulu compliquer la pattern outre mesure pour améliorer sa performance, mais dans son état actuel, ce n'est pas le genre de pattern à appliquer sur une longue chaîne.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  3. #3
    Membre à l'essai
    Homme Profil pro
    Lycéen
    Inscrit en
    Octobre 2021
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Lycéen
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2021
    Messages : 27
    Points : 11
    Points
    11
    Par défaut
    Bonjour,

    Merci de la réponse.

    J'ai pas encore trouvé la solution à ce que je recherche à faire.

    Voici mon exemple concret.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    my $v1 = "un garde de la porte";
    my $v2 = "de la p p";
    On peut remarquer que le text commun est :
    "de la p"
    Je voudrai donc pouvoir récupérer le text commun,
    ainsi que le text différent après le text commun.

    soit:

    text commun :
    "de la p"
    text dif:
    " p"
    merci encore de votre aide

  4. #4
    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
    Donc les mots peuvent être coupés. Restent les trois autres questions que je t'ai posées, merci d'y répondre car sinon je ne peux rien faire pour toi.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  5. #5
    Membre à l'essai
    Homme Profil pro
    Lycéen
    Inscrit en
    Octobre 2021
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Lycéen
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2021
    Messages : 27
    Points : 11
    Points
    11
    Par défaut
    Bonjour,

    alors pour les 3 questions restantes.

    Si les 2 lignes on plusieurs parties en commun.
    On prend juste la première partie,
    et on renvoie tout le texte se trouvant à droite de cette première partie commune.

    Pour la deuxième questions je ne suis pas sur de comprendre,
    mais il peux avoir effectivement aucune partie commune, dans ce cas la elle sera vide.

    Troisième question :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    my $v1 = "un garde de la porte";
    my $v2 = "de la p p";
    Effectivement la partie commune commencera forcément toujours par:
    "de la p p" dans cette exemple.

    Les variables $v1 et $v2 sont dans une boucle, et le text change à chaque fois.

    Mais je dois toujours chercher si la chaine de $v2 se trouve quelque part dans $v1,
    puis renvoyer le texte à droite du premier texte commun trouvé.

    merci de votre aide

  6. #6
    Membre à l'essai
    Homme Profil pro
    Lycéen
    Inscrit en
    Octobre 2021
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Lycéen
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2021
    Messages : 27
    Points : 11
    Points
    11
    Par défaut
    J'ai oublié pour la troisième question,


    Mais je dois toujours chercher si la chaine de $v2 se trouve quelque part dans $v1,
    puis renvoyer le texte à droite de $v2 du premier texte commun trouvé.
    Dans mon exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    my $v1 = "un garde de la porte";
    my $v2 = "de la p p";

    Le texte commun :
    "de la p"
    le texte différent à droite du texte commun de $v2 :
    " p"

  7. #7
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 499 184
    Points
    499 184
    Par défaut
    Bonjour,

    Tu souhaites juste les mots en commun, sans tenir compte de l'ordre ?

  8. #8
    Membre à l'essai
    Homme Profil pro
    Lycéen
    Inscrit en
    Octobre 2021
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Lycéen
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2021
    Messages : 27
    Points : 11
    Points
    11
    Par défaut
    Bonjour, Si il faut dans l'ordre. merci

  9. #9
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 499 184
    Points
    499 184
    Par défaut
    Il faut que tu fournisse plusieurs exemples.
    L4analyse de données ne se fait pas avec juste quelques mots.

    un garde de la porte et de moi
    de la p p
    doit donner quel résultat ?
    de la
    ? Il faut réexpliquer ce que tu souhaites.

  10. #10
    Membre à l'essai
    Homme Profil pro
    Lycéen
    Inscrit en
    Octobre 2021
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Lycéen
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2021
    Messages : 27
    Points : 11
    Points
    11
    Par défaut
    J'ai trouvé une solution pour obtenir ce que je veux, mais bon niveau algo pas sur que sa soit terrible terrible. peut-être qu'il y a une meilleur solution pour obtenir la même chose.

    Voici mon code :

    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
    my $v1 = "un garde de la porte";
    my $v2 = "de la po tata titi toto";
    (my $c = "$v1\n$v2" ) =~ /^.*?\b(\w.*)(\b.*)\n\1(.*)/;
    my $same_text = $1;
    my $dif1 = $2;
    my $dif2 = $3;
    my @verif = split("",$dif1);
    my @verif2 = split("",$dif2);
    my @result;
    my $count = 0;
    foreach my $k (@verif)
    {
        last if($k ne $verif2[$count]);
        if($k eq $verif2[$count])
        {
            push(@result,$k);
        }
        $count++;
    }
    my $same_text = $same_text.join("",@result);
    print $same_text."\n";
    $v2 =~ s/$same_text//;
    print $v2."\n";

  11. #11
    Membre à l'essai
    Homme Profil pro
    Lycéen
    Inscrit en
    Octobre 2021
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Lycéen
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2021
    Messages : 27
    Points : 11
    Points
    11
    Par défaut
    Je me suis un peu trop avancé. J'ai un exemple là où mon code ne fonctionne pas.
    surement parce que la regexp envoi le texte commun à condition que le mot soit entier.

    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
    my $v1 = "un garde de la porte";
    my $v2 = "gard pat";
    (my $c = "$v1\n$v2" ) =~ /^.*?\b(\w.*)(\b.*)\n\1(.*)/;
    my $same_text = $1;
    my $dif1 = $2;
    my $dif2 = $3;
    my @verif = split("",$dif1);
    my @verif2 = split("",$dif2);
    my @result;
    my $count = 0;
    foreach my $k (@verif)
    {
        last if($k ne $verif2[$count]);
        if($k eq $verif2[$count])
        {
            push(@result,$k);
        }
        $count++;
    }
    my $same_text = $same_text.join("",@result);
    print $same_text."\n";
    $v2 =~ s/$same_text//;
    print $v2."\n";

  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
    Mais je dois toujours chercher si la chaine de $v2 se trouve quelquepart dans $v1,
    puis renvoyer le texte à droite de $v2 du premier texte commun trouvé.
    Dans mon exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    my $v1 = "un garde de la porte";
    my $v2 = "de la p p";
    Le texte commun :
    "de la p"
    le texte différent à droite du texte commun de $v2 :
    " p"
    Sauf que le premier texte commun ce n'est pas "de la p", c'est "de " qui se trouve après "gar" (Ce qui donnerait "la p p" comme texte restant et non pas " p").
    Ce serait bien que ta description corresponde à ce que tu montres en exemple. D'où l'intérêt de couvrir les différents cas de figures avec autant d'exemples, si tu as du mal à mettre en mots ce que tu recherches.

    Une proposition:
    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
    use strict;
    use warnings;
     
    my $v1 = 'un garde de la porte';
    my $v2 = 'de la p p';
     
    my $str = "$v2\n$v1";
     
    print "tel que tu le décris:\n";
    if ( $str =~ /^(?:(.)(?=.*\n((?(2)\2|.*?))(\3?+\1)))+(.*)/ ) {
        print "\tpartie commune: '$3'\n\tdifférence: '$4'\n\n\n";
    }
     
    print "tel que tu le montres dans l'exemple:\n";
    if ( $str =~ /^(.*)(.*)\n.*?\1/ ) {
        print "\tpartie commune: '$1'\n\tdifférence: '$2'\n";
    }
    Suivant celle qui convient je te fournirai une explication détaillée.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  13. #13
    Membre à l'essai
    Homme Profil pro
    Lycéen
    Inscrit en
    Octobre 2021
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Lycéen
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2021
    Messages : 27
    Points : 11
    Points
    11
    Par défaut
    Oui effectivement désolé, j'ai bien du mal à mètre des mots sur ce que je veux obtenir exactement.

    En faite quand je pense texte commun,
    je pensais à un seule bloque.
    Tant que le texte est reconnut pour moi c'est un bloc.
    C'est pour ça que je disais "de la p"

    Mais ce que je souhaite obtenir, c'est la deuxième solution du script

    tel que tu le montres dans l'exemple:
    partie commune: 'de la p'
    différence: ' p'

    merci

  14. #14
    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
    Ok pour la deuxième pattern, mais teste la bien sur plusieurs chaînes pour voir si c'est le comportement que tu veux. C'est pas parce que ça marche comme tu veux pour cette exemple là que ce sera le cas pour les autres exemples.

    Je ne comprends pas ce que tu appelles un bloc.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  15. #15
    Membre à l'essai
    Homme Profil pro
    Lycéen
    Inscrit en
    Octobre 2021
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Lycéen
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2021
    Messages : 27
    Points : 11
    Points
    11
    Par défaut
    tout à l'aire de fonctionner à la perfection, merci encore, car j'étais vraiment bloqué.
    Je vais étudier cette regexp, parce que j'avoue ne pas la comprendre.

  16. #16
    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
    Les quantificateurs * + ? {m,n} sont gourmands par nature, c'est à dire qu'ils prennent le plus de caractères possibles. Il est possible de les rendre non-gourmands pour qu'ils prennent le moins de caractères possibles comme ceci: *? +? ?? {m,n}?.

    On regarde la première partie ^(.*)(.*). Le groupe 1 capture la partie commune, le groupe 2 la partie différente.
    Voyons un peu le déroulement des opérations.

    Les deux quantificateurs * sont gourmands, c'est le premier rencontré (le plus à gauche) qui prendra tous les caractères possibles, le 2e se contente de ceux qui restent, c'est à dire aucun au premier essai. Mais si la suite de la pattern échoue, le 1er quantificateur rendra son dernier caractère (que prendra alors le 2e quantificateur) pour faire un nouvel essai. Si le reste de la pattern échoue encore, le 1er quantificateur rendra encore un caractère et ainsi de suite, jusqu'à ce que la suite de la pattern réussisse.

    Disons que v2 est "abcdefghij" et v1 est "XYZ_abcdef".

       groupe 1    |   groupe 2    | reste de la pattern
    ---------------+---------------+-----------------------       
    1  abcdefghij  |               | echec
    ---------------+---------------+-----------------------
    2  abcdefghi   |   j           | echec
    ---------------+---------------+-----------------------       
    3  abcdefgh    |   ij          | echec
    ---------------+---------------+-----------------------
    4  abcdefg     |   hij         | echec
    ---------------+---------------+-----------------------       
    5  abcdef      |   ghij        | réussite
    ---------------+---------------+-----------------------
    Ce mécanisme qui consiste à rendre des caractères pour essayer une autre possibilité s'appelle le backtracking (le retour sur ses traces). Il se déclenche lorsque la suite de la pattern échoue et s'interrompt dés qu'elle réussit (ou que toutes les possibilités ont été testées sans succés).

    C'est la particularité des quantificateurs gourmands.

    Les quantificateurs non-gourmands se comportent de manière inverse: ils prennent le moins de caractères possible et si la suite de la pattern échoue, ils prennent un caractère en plus et ainsi de suite jusqu'à ce que la suite de la pattern réussisse.

    Voyons ce qui se passe aux étapes 4 et 5 pour la suite de la pattern:

       groupe 1  |     .*?      |   \1
    -------------+--------------+--------------
    4  abcdefg   |              |  echec
                 +--------------+--------------
                 | X            |  echec
                 +--------------+--------------
                 | XY           |  echec
                 +--------------+--------------
                 | XYZ          |  echec
                 +--------------+--------------
                 | XYZ_         |  echec
                 +--------------+--------------
                 | XYZ_a        |  echec
                 +--------------+--------------
                 | XYZ_ab       |  echec
                 +--------------+--------------
                 | XYZ_abc      |  echec
                 +--------------+--------------
                 | XYZ_abcd     |  echec
                 +--------------+--------------
                 | XYZ_abcde    |  echec
                 +--------------+--------------
                 | XYZ_abcdef   |  echec
    -------------+--------------+--------------
    5  abcdef    |              |  echec
                 +--------------+--------------
                 | X            |  echec
                 +--------------+--------------
                 | XY           |  echec
                 +--------------+--------------
                 | XYZ          |  echec
                 +--------------+--------------
                 | XYZ_         |  réussite
    -------------+--------------+--------------
    Donc quelque soit le contenu du premier groupe (la partie commune), puisque le quantificateur est non-gourmand dans cette partie \n.*?\1, le moteur de regex essayera de trouver \1 dés le début de la ligne, puis si ça ne marche pas il essayera aprés le premier caractère, puis le deuxième, puis le troisième jusqu'à ce qu'il réussisse.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  17. #17
    Membre à l'essai
    Homme Profil pro
    Lycéen
    Inscrit en
    Octobre 2021
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Lycéen
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2021
    Messages : 27
    Points : 11
    Points
    11
    Par défaut
    Bonjour, merci bien de ces explications, je vais plancher la dessus pour essayer de comprendre tout ça.

Discussions similaires

  1. Demande d'aide pour une requête
    Par arkzor dans le forum Requêtes
    Réponses: 3
    Dernier message: 28/12/2004, 02h40
  2. Création requete besoin d'aide pour une date
    Par royrremi dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 14/07/2004, 22h03
  3. Besoin d'aide pour une Requête SQL ...
    Par Kokito dans le forum Requêtes
    Réponses: 2
    Dernier message: 07/07/2004, 11h56
  4. Aide pour une requete ... "COUNT(*)"
    Par mechantebestiole dans le forum Langage SQL
    Réponses: 13
    Dernier message: 25/05/2004, 16h27
  5. besoin d'aide pour une requête
    Par Damien69 dans le forum Langage SQL
    Réponses: 11
    Dernier message: 31/03/2004, 15h38

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