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 :

Fonction testant regex contenue dans un fichier renvoyant toujours undef


Sujet :

Langage Perl

  1. #1
    Membre à l'essai
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2013
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Février 2013
    Messages : 24
    Points : 17
    Points
    17
    Par défaut Fonction testant regex contenue dans un fichier renvoyant toujours undef
    Salut tout le monde,

    J'ai rencontré un problème lors de la programmation d'une routine qui dans un fichier va chercher des regex grâce à une macro passée en paramètre.

    Le format du fichier contenant les regex est celui-ci :
    J'ai donc écrit une routine qui va chercher les regex dans le fichier. La fonction retourne dans tous les cas que l'expression passée en argument ne correspond pas à la regex.

    Voici la routine :

    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
    sub find_regex_in_expression($$$) {
            my $macro = $_[0];
            my $expr  = $_[1];
            my $file  = $_[2];
            my $regex_true=0;
            my $regex;
            while(my $line = <$file>) {
                    if ($line =~ $macro) { $regex_true = 1; }
                    elsif ($regex_true == 1) { 
                            $regex = $line; 
                            $regex_true=0; 
                    }
            }
            if (!length($regex)) {
                    fatal('mauvaise macro'); 
            } else {
    		print $regex . "\n";
                    if ($expr !~ m/$regex/) { 
                            return undef;
                    }
                    return 1;
            }
    }
    Et lorsque que je l'éxecute :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $:~/programmation/Perl/regex$ ./main.pl digit 3
    [[:digit:]]
    l'expression ne correspond pas à la regex
    Pour ne pas vous donner la chose sans tous ses détails j'ai aussi un fichier main.pl :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    require 'find_regex_in_expression.pl';
     
    open(my $fh,'regex_file');
     
    if(find_regex_in_expression($ARGV[0],$ARGV[1],$fh)) { print 'l\'expression correspond à la regex'; } 
             else { print 'l\'expression ne correspond pas à la regex'; }
    print "\n";
    Avez-vous des idées sur comment régler ce problème ?

    Merci de votre lecture

  2. #2
    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
    Bonjour,

    peux-tu donner le code de la fonction qui lit les regex dans le fichier?

    Je soupçonne une anomalie à ce niveau.

  3. #3
    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
    Ajoute un "chomp($line)" en ligne 8, avant le traitement de $line.
    Ce sera déjà une bonne chose.
    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

  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
    Bonne chose, en effet, d'ajouter ce chomp.

    Cela dit, perso, je pensais surtout à un chomp manquant dans la fonction lisant les regex à partir du fichier.

  5. #5
    Membre à l'essai
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2013
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Février 2013
    Messages : 24
    Points : 17
    Points
    17
    Par défaut
    La solution de rajouter chomp en ligne 8 a réglé mon souci.

    Entretemps j'ai trouvé une autre solution au problème.

    J'ai opté pour une syntaxe du fichier contenant les regex différente :
    Du coup le code de la fonction s'adapte :
    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
    sub find_regex_in_expression($$$) {
     
    	...
     
    	while(my $line = <$file>) {
    		if ($line =~ "$macro:(.+)") { $regex = $1; }
    	}
    	if (!length($regex)) {
    		fatal('mauvaise macro');
    	} else {
    		if ($expr !~ m/$regex/) {
    			return 0;
    		}
    		return 1;
    	}
    }
    Et voilà, ça fonctionne à merveille.

    Merci à vous deux.

  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
    Hum, j'ai dû mal comprendre ce que faisait ton code dans ce cas, mais si ça marche, tout est bien.

    Euh, juste un point supplémentaire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sub find_regex_in_expression($$$) {
    Les 3 signes $ formant un prototype de fonction (le ($$$)) n'est probablement pas une bonne idée et ne font probablement pas ce que tu crois. Plutôt à éviter, à moins que tu ne saches exactement ce que tu fais et les conséquences que ça a.

    A priori, écris plutôt ta fonction comme suit:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sub find_regex_in_expression {

  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
    Citation Envoyé par Lolo78 Voir le message
    Cela dit, perso, je pensais surtout à un chomp manquant dans la fonction lisant les regex à partir du fichier.
    Pour moi, c'était justement l'objectif de la boucle de la ligne 7 que de lire ce fichier contenant la regexp
    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
    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 bien possible et c'était apparemment le cas, mais comme on n'avait qu'une partie du code, ce n'est pas ce que je croyais avoir compris.

  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
    Une façon de se rendre compte que le code est incorrect, sans le modifier, c'est de placer un breakpoint au début de la fonction, et de contrôler le contenu des paramètres reçus...

    Je suis globalement d'accord que le script mérite un gros "dépoussiérage"...
    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 à l'essai
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2013
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Février 2013
    Messages : 24
    Points : 17
    Points
    17
    Par défaut
    Comme j'ai changé la syntaxe du fichier j'extrais l'expression entre parenthèses avec la variable $1.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if ($line =~ "$macro:(.+)") { $regex = $1 }
    Du coup ça évite de faire un chomp vu que le caractère de saut de ligne n'est pas compris dans $regex.

    J'utilise la limitation d'argument pour faciliter la compréhension du code. Ca me permet d'avoir un prototype plus précis et de savoir comment est-ce que je vais m'organiser. En tant qu'habitué du C j'ai trouvé cette syntaxe utile.

    Qu'est-ce que vous entendez par ''dépoussiérage" ?

  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
    Le problème avec ces prototypes en Perl est qu'ils ne sont justement pas des prototypes au sens C ou Java du terme, mais plutôt des modèles automatiques d'appel de fonction, et qu'ils modifient silencieusement la nature ou le type des arguments passés à la fonction. C'est dans ce sens qu'ils ne font pas ce que tu crois qu'ils font.

    par exemple, si tu définit une fonction comme ceci:

    la fonction attend une référence sur un tableau. Si tu l'appelle ainsi:

    ou même

    la présence du prototype va transformer implicitement le tableau passé en paramètre en une référence vers ce tableau à l'intérieur de la fonction (qui pourra donc modifier le tableau). C'est très pratique dans certains cas, en particulier pour créer des fonctions qui s'appellent comme les fonctions internes de Perl (sans avoir besoin de mettre de parenthèses lors de l'appel), mais à condition de bien comprendre ce qui se passe.

    Pour des déclarations de fonctions ordinaires, il vaut donc mieux écrire quelque chose comme:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    sub find_regex_in_expression {
            my ($macro, $expr, $file_fh) = @_;
            my $regex_true=0;
            my $regex;
    Moyennant un minimum de discipline, il est clair que la fonction attend trois paramètres.

  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
    Citation Envoyé par Yodestarn Voir le message
    Comme j'ai changé la syntaxe du fichier j'extrais l'expression entre parenthèses avec la variable $1.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if ($line =~ "$macro:(.+)") { $regex = $1 }
    Tu peux également l'écrire ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if (my ($regex) = $line =~ "$macro:(.+)")) {
      # traitement si regex a été trouvé
    }
    Par dépoussiérage, j'entendais par là, une programmation perl en perl, et non une programmation C en perl.

    Quelques exemples :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    sub find_regex_in_expression($$$) {
            my $macro = $_[0];
            my $expr  = $_[1];
            my $file  = $_[2];
    s'écrit plus succinctement (sans perdre en lisibilité) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    sub find_regex_in_expression($$$) {
            my ($macro, $expr, $file) = @_;
    Ce code met en oeuvre des expressions dans un contexte de liste... qui est propre à perl (comparativement à C).

    L'usage de la fonction length pour tester le contenu de $regex n'est pas judicieux, car si justement, $regex vaut undef, cet appel soulèvera une exception. Il est préférable soit d'utiliser "defined($regex)" pour uniquement que $regex a été défini (sans vérifier s'il contient une chaine non nulle), soit d'utiliser uniquement $regex (ce qui vérifie à la fois l'existence ET que sa valeur convertie en booléen est vrai, donc pour une chaine, qu'elle n'est pas vide).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
            if (!length($regex)) {
    devient alors
    Rien de bien grave cela dit.
    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 à l'essai
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2013
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Février 2013
    Messages : 24
    Points : 17
    Points
    17
    Par défaut
    Le code retravaillé devient ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    sub find_regex_in_expression {
            (my $macro, my $expr, my $file_fh) = @_;
            while(my $line = <$file_fh>) {
                    if (my ($regex) = $line =~ "$macro:(.+)") {
                            if ($expr !~ $regex) { return 0 }
                            else { return 1 }
                    }
                    else { fatal('mauvaise macro') }
            }
    }
    J'ai donc un code plus court, mieux compréhensible et moins complexe.

    J'ai juste une question: pourquoi mettre $regex entre parenthèses ?

  14. #14
    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 Yodestarn Voir le message
    J'ai juste une question: pourquoi mettre $regex entre parenthèses ?
    Pour que l'évaluation de l'expression régulière se fasse en contexte de liste (et non scalaire) et que tu récupères le motif recherché comme premier élément de la liste (dans $regex).

    En contexte scalaire, tu récupèrerais un 1 dans $regex (un booléen signifiant vrai, ou succès, en l'occurrence).

    Plutôt que :

    (my $macro, my $expr, my $file_fh) = @_;
    Utilise cette forme plus simple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    my ($macro, $expr, $file_fh) = @_;

  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
    Autre point: j'avais lu quelques part, je ne sais plus trop où (doc perl ou perl best practices ?) qu'une regexp devrait toujours être délimitée, même lorsqu'elle est contenue entièrement dans une variable, et même si c'est variable est le resultat de l'opération qr{}.
    Dans ton cas, écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if ($expr !~ /$regex/) { return 0 }
    plutot que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if ($expr !~ $regex) { return 0 }
    (il est possible d'utiliser d'autres délimiteurs, comme m{}).
    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
    Membre à l'essai
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2013
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Février 2013
    Messages : 24
    Points : 17
    Points
    17
    Par défaut
    Merci pour vos conseils et vos précisions. J'en prendrais compte dans mes prochains codes.

Discussions similaires

  1. Réponses: 6
    Dernier message: 07/06/2008, 17h38
  2. appel d'une fonction contenu dans un fichier js
    Par geoman dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 24/08/2007, 07h51
  3. Utiliser des fonctions contenues dans un fichier .bas
    Par usbeck dans le forum Visual C++
    Réponses: 4
    Dernier message: 11/08/2006, 12h03
  4. Réponses: 5
    Dernier message: 16/03/2005, 22h17
  5. Réponses: 4
    Dernier message: 10/02/2005, 16h10

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