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 :

Besoin d'être sûr de ma RegExp


Sujet :

Langage Perl

  1. #1
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 572
    Points : 2 014
    Points
    2 014
    Par défaut Besoin d'être sûr de ma RegExp
    Bonjour,

    pour les besoins d'un script professionnel, je dois lire des lignes issues d'un fichier texte et faire ressortir la condition VRAIE si la chaîne recherchée se trouve dans la-dite ligne.

    Exemple de lignes du fichier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    01.040.29*27.120
    33.100*13*17.100
    45.080*13.160.40*97.220
    ATTENTION : * est un séparateur de données !

    J'ai 2 RegExp selon les cas de figure :

    1) je dois trouver une donnée commençant par 13

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    FAUX -> 01.040.13*27.120
    VRAI -> 33.100*13*17.100
    VRAI -> 45.080*13.160.40*97.220
    Ma RegExp : /\*?13.*/

    2) je dois trouver une donnée commençant par 13.160

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    FAUX -> 01.040.13*27.120
    FAUX -> 33.100*13*17.100
    VRAI -> 45.080*13.160.40*97.220
    Ma RegExp : /\*?13\.160.*/

    Le soucis pour que tout soit nickel, c'est qu'il ne faut surtout pas, si je prend la ligne 1 pour exemple, que mon script me retourne VRAI parce qu'il a topé sur la ligne "01.040.13"

    Et le problème, c'est que ma 1ère RegExp /\*?13.*/ va toper comme VRAI la donnée "01.040.13".

    Si qqun pouvait me donner un p'tit coup d'pouce pour affiner tout ça ?


  2. #2
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    172
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 172
    Points : 208
    Points
    208
    Par défaut
    Salut,

    essaie ça et ça 13 peut être au début de la ligne?
    Dans ton cas on peut dire qu'on utilise * comme ancrage?

    Si tu mets \*? alors l'étoile est optionnelle. Mais comme ? est avide la reconnaissance sera tentée. Et si étoile n'est pas réconnu alors tu risque de reconnaître aussi 13 après le point .


    Prenons ton cas
    /\*?13.*/ va toper comme VRAI la donnée "01.040.13".
    \*? - comme ? est avide alors il va tenter la reconnaissance de * mais il va garder en mémoire l'emplacement avant 13 (donc après le point).
    Comme la reconnaissance de l'étoile ne peux par réussir la regex aura un échec. Mais ce n'est pas un échec totale puisque ? est optionnelle.
    Donc la reconnaissance va continuer avec l'emplacement avant le 13. Comme 1 suit de 3 sont reconnus la regex va annoncer un succés.


    lami20j
    --
    lami20j

  3. #3
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 572
    Points : 2 014
    Points
    2 014
    Par défaut
    Citation Envoyé par lami20j
    13 peut être au début de la ligne?
    Dans ton cas on peut dire qu'on utilise * comme ancrage?
    Oui, 13 peut se trouver en début de ligne

    Pour tout dire, chaque ligne correspond à un enregistrement d'une table d'une BDD. Dans l'exemple, je n'ai mis que le champ qui m'intéressait et il faut savoir que ce champ là est multi-valué, chaque donnée séparée d'une autre par * est comme une valeur parmi d'autres du champ.

    Grosso modo, il faut que, algorithmiquement parlant, je trouve tout enregistrement dont le champ multi-valué contient au moins 1 de ses données commençant par "13" ou "13.160" comme dans mes exemples.

  4. #4
    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
    J'utiliserais sans doute cette regex :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    m/(?: \A | \* )13/x
    --
    Jedaï

  5. #5
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 572
    Points : 2 014
    Points
    2 014
    Par défaut
    Et que dites-vous de celle-ci : Sachant que le début de la valeur recherchée peut se trouver en 1ère position dans le champ ou quelque part après un *, cette RegExp là devrait pouvoir remplir toutes les conditions recherchées d'aprés vous ???

    Et pour rechercher "13.160" : ???

  6. #6
    Membre éclairé
    Avatar de gerald2545
    Profil pro
    Inscrit en
    Février 2003
    Messages
    744
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2003
    Messages : 744
    Points : 773
    Points
    773
    Par défaut
    pas bien compris ta description sur les champs mutlivalués (un exemple concret sous la main peut-être?)
    pourquoi n'insères tu pas chaque ligne dans un tableau
    tu parcours le tableau et pour chaque cellule tu exploses ta string suivant le caractère * dans un autre tableau
    et tu grep 13 ou 13.160 sur le second tableau?

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    427
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 427
    Points : 459
    Points
    459
    Par défaut
    tu peux faire /(?:^|\*)13/ et /(?:^|\*)13\.160/

    (le "?:" n'est la que pour eviter une capture inutile)


    EDIT: en fait c'est ce que Jeday proposait deja
    Recherche staigiaire(s) motivé(s) sur projet perl/reseau a grande echelle. Me contacter par mp.

  8. #8
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 572
    Points : 2 014
    Points
    2 014
    Par défaut
    Grrrrrrrrrrr

    J'avais rédigé un long truc pour te répondre et au moment de valider, PAF (le chien) ! Coupure de courant !!

    Citation Envoyé par gerald2545
    pas bien compris ta description sur les champs mutlivalués (un exemple concret sous la main peut-être?)
    Pour faire simple avant la prochaine coupure de jus , disons que dans une BDD "classique", tu as une table qui gère des enregistrements, que chaque enregistrement contient des champs, lesquels champs contiennent (ou pas, sans importance ici) 1 donnée.

    Le SGBD sur lequel je travaille reprend le même principe SAUF que certains champs peuvent contenir + d'une donnée.

    Imagine que tu veux créer la table PERSONNEL pour y consigner les noms, prénoms et profession du personnel d'une boîte. Tu as besoin d'avoir tous les prénoms d'une personne.

    Ta table pourrait très bien être comme suit :

    champ1 = NOM
    champ2 = PRENOM1
    champ3 = PRENOM2
    champ4 = PRENOM3
    champ5 = PROFESSION

    Ici, ça donnerait plus ceci :

    champ1 = NOM
    champ2 = PRENOMS
    champ3 = PROFESSION

    Citation Envoyé par gerald2545
    pourquoi n'insères tu pas chaque ligne dans un tableau
    tu parcours le tableau et pour chaque cellule tu exploses ta string suivant le caractère * dans un autre tableau
    et tu grep 13 ou 13.160 sur le second tableau?
    Pour l'exemple que je voulais montrer, j'ai été à l'essentiel mais dans la réalité, il y a des milliers d'enregistrements et plusieurs dizaines de conditions recherchées.

    Une des conditions recherchées peut très bien être de rechercher dans le CHAMP27 si le champ contient une valeur commençant par "13", ou "27.120" ou "33.100" ou "97.100" et la condition suivante pourra très bien être de rechercher tout enregistrement dont le CHAMP27 contient une valeur commençant par "17" ou "33.180" MAIS NE COMMENCANT PAS PAR "95.100".

    Eclater le contenu du champ dans une liste, puis de parcourir celle-ci en fonction des critères de sélection ou de non sélection, ça fait un peu trop lourd. D'où mon idée de passer par une RegExp directement en scannant le contenu du champ dans son intégralité. D'autant plus faisable que chaque donnée est séparée des autres par un *.

  9. #9
    Membre éclairé
    Avatar de gerald2545
    Profil pro
    Inscrit en
    Février 2003
    Messages
    744
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2003
    Messages : 744
    Points : 773
    Points
    773
    Par défaut
    OK merci pour les explications.
    Les différentes propositions t'ont permis de répondre à ton problème?
    bon WE

  10. #10
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 572
    Points : 2 014
    Points
    2 014
    Par défaut
    J'ai trouvé une autre soluce : copier l'intégralité du champ dans une variable temporaire, mettre * en début et fin de variable et ensuite, il ne me restera qu'à chercher mes valeurs en les préfixant de \*


  11. #11
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    172
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 172
    Points : 208
    Points
    208
    Par défaut
    Salut,
    Citation Envoyé par Arioch
    J'ai trouvé une autre soluce : copier l'intégralité du champ dans une variable temporaire, mettre * en début et fin de variable et ensuite, il ne me restera qu'à chercher mes valeurs en les préfixant de \*

    Il y a toujours plusieurs façons de le faire (au moins en Perl - TMTOWTDI).
    Je pense que la solution de Jedai est très efficace et doit te satisfaire.

    Tu n'as pas un seul champ à copier, donc l'exécution de ton script sera ralentie. A toi de voir.

    lami20j
    --
    lami20j

  12. #12
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 572
    Points : 2 014
    Points
    2 014
    Par défaut
    Je sais bien, et je ne veux froisser personne mais un code comme n'est pas idéal, en terme de lisibilité, quand tu n'as pas un motif à rechercher mais une dizaine d'un coup



    J'essaie surtout de trouver une syntaxe rapide à modifier si le besoin s'en fait sentir

  13. #13
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    172
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 172
    Points : 208
    Points
    208
    Par défaut
    Re,
    Citation Envoyé par Arioch
    Je sais bien, et je ne veux froisser personne mais un code comme n'est pas idéal, en terme de lisibilité, quand tu n'as pas un motif à rechercher mais une dizaine d'un coup



    J'essaie surtout de trouver une syntaxe rapide à modifier si le besoin s'en fait sentir
    Je suis d'accord pour la lisibilité. Mais Perl nous mets à notre disposition les objets regex grâce à l'opérateur qr//

    Tu ne froisses personne , sûrement tu vas trouver la solution qui te convient mieux. D'ailleurs c'est le but.

    lami20j
    --
    lami20j

  14. #14
    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
    Citation Envoyé par Arioch
    Je sais bien, et je ne veux froisser personne mais un code comme n'est pas idéal, en terme de lisibilité, quand tu n'as pas un motif à rechercher mais une dizaine d'un coup



    J'essaie surtout de trouver une syntaxe rapide à modifier si le besoin s'en fait sentir
    Dans ce cas, j'essaie toujours de fabriquer automatiquement la regex à partir d'une liste ou d'un hash. Tu as ainsi un script très facile à modifier, tout en réduisant le risque d'erreur.

    --
    Jedaï

  15. #15
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 572
    Points : 2 014
    Points
    2 014
    Par défaut
    Jedai, j'avais pensé au hash mais je ne suis pas fichu de bien goupiller le truc pour faire de la RegExp à partir d'une clé recherché partiellement (recherche d'un motif commençant par une clé existant dans le hash)

    Alors, voici ce que j'ai fait. Avec ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    45.080*13.160.40*97.220
    J'ai copié ces 3 valeurs (exemple) en tant que simple chaîne dans un scalaire + qq transformations pour que ça donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    a45_080a13_160_40a97_220a
    Maintenant, toute valeur est "encapsulée" entre 2 "a", ça m'évite de mettre des \ devant les * et les "." changés en "_" pour la même raison. Ca a l'air de fonctionner.

    Merci pour vos propals en tout cas

  16. #16
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    427
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 427
    Points : 459
    Points
    459
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    my @check = qw(
        13
        13.160
    );
     
    my $regexp = join('|', map {"\Q$_"} @check); # ou en utilisant Regexp::List
    $regexp = qr/(?:^|\*)(?:$regexp)/;
    Recherche staigiaire(s) motivé(s) sur projet perl/reseau a grande echelle. Me contacter par mp.

  17. #17
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    172
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 172
    Points : 208
    Points
    208
    Par défaut
    Salut,
    Citation Envoyé par pospos
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    my @check = qw(
        13
        13.160
    );
     
    my $regexp = join('|', map {"\Q$_"} @check); # ou en utilisant Regexp::List
    $regexp = qr/(?:^|\*)(?:$regexp)/;
    Ca ne marche pas comme il veut.
    Puisque dans le 1er cas il veut reconnaître ce qui commence avec 13 (donc aussi 13.160) - donc il va obtenir son 1er résultat voulu

    En revanche le 2ème cas il veut connaître uniquement ce qui commence avec 13.160 (ce qui commence seulement avec 13 est exclu).

    En ce cas ton code va trouver toujours la même chose.

    lami20j
    --
    lami20j

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

Discussions similaires

  1. Générateur de clés de validation (besoin d'être testé)
    Par Demystificator dans le forum Autres Logiciels
    Réponses: 3
    Dernier message: 31/05/2010, 20h21
  2. [Débutant] Besoin d'être guidé dans l'utilisation d'XML
    Par jppaysan dans le forum XML/XSL et SOAP
    Réponses: 2
    Dernier message: 28/04/2006, 11h19
  3. [débutant] besoin d'être éclairci.
    Par Fabouney dans le forum Applets
    Réponses: 1
    Dernier message: 04/10/2005, 05h13

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