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 :

Caractère "=" dans une RegExp


Sujet :

Langage Perl

  1. #1
    Membre régulier
    Inscrit en
    Avril 2007
    Messages
    161
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 161
    Points : 101
    Points
    101
    Par défaut Caractère "=" dans une RegExp
    Bonjour,

    Dans un code en Perl, je réalise un traitement sur des requêtes SQL.

    Un exemple simple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select col2 from table1 where col1 like '$1'
    $1 est juste une variable, qu'on va venir remplacer grâce au traitement réalisé dans la RegExp.

    Ma RegExp se présente ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
            my $sep = "\$";
            my $request = shift;#je récupère ici la requête dont je parle au-dessus
     
            while ($request =~ /$sep/) {
                    if ($request =~ /(.*)$sep(\d+)(.*)/){
     
                            print "$1";#select col2 from table1 where col1 like '
                            print "$3";#'
     
                            my $value = traitement($2);
                            $request = $1.$value.$3;
                     }
           }
    Tout se passe bien pour ce traitement.

    MAIS, si je transforme la requête avec "=" au lieu de "LIKE", ça ne marche plus.

    Pouvez-vous me donner un coup de pouce, pour que ma RegExp marche à coup sûr dans les 2 cas ("=" et "LIKE")?

    Merci pour votre aide.

  2. #2
    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
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while ($request =~ /$sep/) {
    et non
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while (request =~ /$sep/) {
    Tu peux rajouter ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    my $request = shift;#je récupère ici la requête dont je parle au-dessus
    $request = quotemeta($request);

  3. #3
    Membre régulier
    Inscrit en
    Avril 2007
    Messages
    161
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 161
    Points : 101
    Points
    101
    Par défaut
    Pour le dollar devant "request", c'est une faute de frappe lors du copié collé. J'avais pas fait attention.

    Et pour le quotemeta, je l'ai effectivement utilisé, mais je crois bien que ça mettait des antislash devant les espaces, et que ça ne tournait pas rond ensuite dans la RegExp.

    Je n'ai pas mon code avec moi, je vais profiter du WE, et je tiens au courant du débogage lundi matin depuis le taf.

  4. #4
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

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

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Bonjour,

    Voici mes remarques :
    • le quotemeta n'est pas indispensable, puisqu'il est surtout utile lorsqu'on utilise une chaine de caractère comme motif. Or là, il s'agit de la chaine à analyser.
    • l'usage d'une variable scalaire pour mettre le séparateur $ ne se justifie pas à mes yeux, et par ailleurs, avec les essais que j'ai réalisés sur une version 5.10, le résultat est incorrect : le $ n'est pas matché. Pour être correctement écrit, il faudrait :
      • soit insérer \$ directement dans la regexp
      • soit définir $sep ainsi : $sep = qr/\$/
    • la transformation d'un élément de motif peut être réalisée directement dans l'expression régulière, à l'aide du modificateur /e (pour execute).

    Voici le code proposé (testé avec like et =) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
            my $sep = qr/\$/;
            my $request = shift;#je récupère ici la requête dont je parle au-dessus
     
            while ($request =~ /$sep/) {
                    $request =~ s/$sep(\d+)/traitement($1)/e;
           }
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  5. #5
    Membre régulier
    Inscrit en
    Avril 2007
    Messages
    161
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 161
    Points : 101
    Points
    101
    Par défaut
    Pour djibril :

    J'ai essayé de passer ma requête dans le quotemeta avant le traitement dans la RegExp.

    Ca me donne l'expression suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select\ col2\ from\ table1_bwinf9601\ where\ col1\ like\ \'\$1\'
    Apparemment, je ne rentre même pas dans le IF.

    Philou, je vais essayer de prospecter dans la solution que tu proposes.

    Merci à vous deux, je donne des infos de mon avancement.

  6. #6
    Membre régulier
    Inscrit en
    Avril 2007
    Messages
    161
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 161
    Points : 101
    Points
    101
    Par défaut
    Alors concernant le séparateur utilisé "$", j'ai pris ce caractère en exemple, mais ce peut être n'importe quoi.

    Donc je laisse l'utilisateur le choisir, et je le passe dans un quotemeta, tout seul, avant de balancer la requête dans le traitement de la RegExp.

    Philou, j'ai repris ton idée :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    sub traitementRequest {
     
            my $request = shift;
            print "$request\n";#select col2 from table1 where col1 like '$1'
            my $sep = qr/\$/;
     
            while ($request =~ /$sep/) {
                     $request =~ s/$sep(\d+)/traitement($1)/e;
            }
     
            printError("traitementRequest","request : <$request>");
     
    }
    Ca marche très bien lorsque ma requête est en "LIKE", mais toujours pas quand j'utilise un "=" ...

    Je suis perplexe, j'ai vérifié ma récupération de la requête, tout à l'air correct.

  7. #7
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

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

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Mmmm bizarre, avec mes essais, ça fonctionne.

    Peux-tu poster ici le résultat sur la console de cette expression perl insérée dans le while :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print STDOUT "[$request]\n";
    Pour ton séparateur entré au clavier, il faut effectivement le traiter avec quotemeta, mais également avec chomp pour supprimé la fin de ligne.
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  8. #8
    Membre régulier
    Inscrit en
    Avril 2007
    Messages
    161
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 161
    Points : 101
    Points
    101
    Par défaut
    Citation Envoyé par Philou67430 Voir le message
    Mmmm bizarre, avec mes essais, ça fonctionne.

    Peux-tu poster ici le résultat sur la console de cette expression perl insérée dans le while :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print STDOUT "[$request]\n";
    Pour ton séparateur entré au clavier, il faut effectivement le traiter avec quotemeta, mais également avec chomp pour supprimé la fin de ligne.
    Quand j'utilise un "LIKE" dans la requête :

    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 traitementRequest {
     
            my $request = shift;
            print "$request\n";#select col2 from table1 where col1 like '$1'
            my $sep = qr/\$/;
     
            while ($request =~ /$sep/) {
                     print STDOUT "[$request]\n";[select col2 from table1_bwinf9601 where col1 like '$1']
                     $request =~ s/$sep(\d+)/traitement($1)/e;
            }
     
            printError("traitementRequest","request : <$request>");
     
    }

    Quand j'utilise un "=" dans la requête ....
    Apparemment, il ne se passe rien, je ne rentre même pas dans ma fonction traitementRequest... Je n'avais pas fait attention avant ...

    Je pige pas, le shift que je fais pour récupérer ma requête dans un .cfg fonctionne quand j'utilise "like", je ne vois aucune raison qu'il ne la récupère pas quand c'est un "=" !!

  9. #9
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

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

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Tu peux montrer le code incriminé ?
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  10. #10
    Membre régulier
    Inscrit en
    Avril 2007
    Messages
    161
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 161
    Points : 101
    Points
    101
    Par défaut
    Apparemment, mon code, qui fait partie d'un code beaucoup plus important déjà existant, bute sur le "=", à cause d'une partie de code que je ne connais pas très bien ...

    En gros, si mon code était indépendant du reste, le "=" fonctionnerait sûrement.

    Un collègue qui a travaillé sur le code existant va me filer un coup de main.

    Je vous tiens au courant de l'avancée.

    Merci pour votre aide précieuse, la RegExp telle qu'elle est à présent me semble beaucoup plus optimisée que ce qu'elle était auparavant.

  11. #11
    Membre régulier
    Inscrit en
    Avril 2007
    Messages
    161
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 161
    Points : 101
    Points
    101
    Par défaut
    Bonjour,

    Je reviens vers vous, car j'ai isolé la partie du code que je ne connaissais pas, qui semble poser problème.

    En fait, j'appelle des fonctions de mon code depuis un fichier de configuration .cfg.

    Dans ce fichier, on peut trouver ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select=sep($), traitement(select col2 from table1 where col1 like '$1')
    Le choix du séparateur se fait selon le désir de l'utilisateur, qui peut mettre ce qu'il veut à la place du "$" (le "$" sert juste pour l'exemple).

    Dans le traitement, l'utilisateur peut mettre la requête SQL qu'il souhaite, parmi SELECT, INSERT, UPDATE, DELETE, sachant que le traitement permet d'aller remplacer les variables telles que "$1", "$2", etc grâce à la routine dont j'ai parlé plus haut.

    Mais il se trouve que la partie :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    traitement(select col2 from table1 where col1 like '$1')
    est récupérée une fonction du code dont je n'avais pas connaissance, ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if ($f =~/(.*)[\(](.*)[\)]/) {
                    $f_ID=$1;#traitement
                    $arg = $2;#select col2 from table1 where col1 like '$1'
            }
    Pour la requête en exemple, ça marche mais dès lors qu'on utilise un "=", comme dans :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select col2 from table1 where col1 = '$1'
    Ou des parenthèses dans la requête :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    insert into table1 (col1,col2) values ('$1','$2')
    La RegExp ci-dessus, qui récupère l'ensemble de la requête, ne suffit pas, n'est pas correcte.

    Pouvez-vous m'aider à faire en sorte que la RegExp récupère n'importe quelle requête (avec "=", "(", et ")') ??

    Merci pour votre aide.

  12. #12
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

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

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    J'ai un gros doute sur le contenu de $f avant le if.
    Pourrais-tu l'afficher afin ainsi :
    et donner le résultat.

    Sinon, pour tenir compte des parenthèses dans une requête, une regexp de ce genre doit être correcte :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if ($f =~/([^\(]*)[\(](.*)[\)]$/) {
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  13. #13
    Membre régulier
    Inscrit en
    Avril 2007
    Messages
    161
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 161
    Points : 101
    Points
    101
    Par défaut
    Effectivement, y'a un souci sur le f !

    J'ai ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    f : [compute(insert into table1_bwinf9601 (col1\]
    puis :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    f : [col2) values ('$1'\]
    puis :

    Donc, à priori, il y a en amont du code, quelque chose qui fait que la virgule est un espèce de séparateur.

  14. #14
    Membre régulier
    Inscrit en
    Avril 2007
    Messages
    161
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 161
    Points : 101
    Points
    101
    Par défaut
    Bonjour,

    Ca y est, j'ai eu du temps pour trouver l'endroit qui fait coincer mon histoire de "=", au lieu de "like" !!!!

    En fait, quand j'ai ceci dans mon fichier de conf :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select=sep($), traitement(select col2 from table1 where col1 like '$1')
    Dans le code existant, un traitement de ce type est effectué :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if($l =~ /^\s*(.*)\s*=\s*(.*)\s*$/) {
    Pour récupérer d'un côté le "select", et de l'autre ce qui se trouve après le "=".

    Du coup, quand je mets un égal dans une requête, sur le reste de la ligne, comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select=sep($), traitement(select col2 from table1 where col1 = '$1')
    , et bien c'est ce 2ème "=" qui est retenu, et donc le code plante !

    Avez-vous une idée pour modifier la RegExp, de façon à ce que seul le 1er égal soit pris en compte, et que le traitement fonctionne ?


    Merci beaucoup !

  15. #15
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

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

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Oui, il s'agit d'utiliser les "ungreedily quantifiers" de expressions régulière.
    Extrait du manuel perlre :
    By default, a quantified subpattern is "greedy", that is, it will match as many times as possible (given a
    particular starting location) while still allowing the rest of the pattern to match. If you want it to match
    the minimum number of times possible, follow the quantifier with a "?". Note that the meanings don't change,
    just the "greediness":

    *? Match 0 or more times, not greedily
    +? Match 1 or more times, not greedily
    ?? Match 0 or 1 time, not greedily
    {n}? Match exactly n times, not greedily
    {n,}? Match at least n times, not greedily
    {n,m}? Match at least n but not more than m times, not greedily
    En gros, en ajouter un ? après *, +, ? ou {...}, la recherche de motif se fait "au plus court" au lieu de se faire "au plus long".

    Dans ton cas, je modifierais la regexp ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if($l =~ /^\s*(.*?)\s*=\s*(.*)\s*$/) {
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  16. #16
    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
    Si ton fichier de conf est de type .ini, je te recommande le module Config::Std, el est très très simple d'utilisation.

    Tout ce qui sera dans ton fichier de conf sera mis dans un hash de façon très propre.

    Plus besoin de se préoccuper des = ou autre sections.

  17. #17
    Membre régulier
    Inscrit en
    Avril 2007
    Messages
    161
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 161
    Points : 101
    Points
    101
    Par défaut
    Excellent ....

    La prochaine fois, je penserai "RTFM", plutôt que de demander ça

    Merci Philou, ça marche, il me prend bien en compte le 1er "=", et plus le second.

    djibril, mon fichier de conf est en .cfg, néanmoins, je vais me pencher sur ce dont tu me parles, ça me servira forcément à l'avenir.



    Je crois que mon problème est
    Merci pour vos contributions respectives.

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

Discussions similaires

  1. [RegExp] Repérer le caractère '\' dans une RegExp
    Par Dark_TeToN dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 09/02/2011, 17h06
  2. Réponses: 2
    Dernier message: 13/05/2009, 10h11
  3. [C#] insertion de caractère en exposant dans une string
    Par papouAlain dans le forum Windows Forms
    Réponses: 9
    Dernier message: 11/07/2006, 15h45
  4. pb:inserer des caractère en arabe dans une bd sql server
    Par l_faiza dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 24/12/2005, 14h02
  5. caractère spéciaux à mettre dans une variable
    Par BernardT dans le forum Langage
    Réponses: 7
    Dernier message: 12/12/2005, 11h24

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