Casse-tête: évaluation d'expression

Le
Yves Martin
Bonjour,

J'ai hésité à poser la question ici avant de passer un bon moment ave=
c
un collègue pour comprendre le comportement d'un bout de code (mal)
généré. Et comme ce n'est pas banal comme problème, je le poste qua=
nd
même.

Voici le code mal généré - le "if" provient d'une recopie d'expressio=
n
régulière depuis un fichier de configuration dans un "eval":

my $line='2007/11/14 12:00:20 066 ERROR Exception caught';

if ( $line =~ m/^./../.. 05:3 .*ERROR/ ){
print "Match !!";
exit 1;
}

L'erreur provient de l'oubli des escapes sur les "/" dans le fichier de
configuration des expressions régulières.

Mais on s'est demandé pourquoi ce code compilait et était valide (il y =
a
quand même un warning à l'évaluation) et aussi pourquoi la condition =
du
"if" était toujours vrai

Désolé mais il n'y a rien à gagner à ce jeu concours ;)
--
Yves Martin
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
kurtz le pirate
Le #153119
In article Yves Martin
Bonjour,

J'ai hésité à poser la question ici avant de passer un bon moment avec
un collègue pour comprendre le comportement d'un bout de code (mal)
généré. Et comme ce n'est pas banal comme problème, je le poste quand
même.

Voici le code mal généré - le "if" provient d'une recopie d'expression
régulière depuis un fichier de configuration dans un "eval":

my $line='2007/11/14 12:00:20 066 ERROR Exception caught';

if ( $line =~ m/^..../../.. 05:3 .*ERROR/ ){
print "Match !!n";
exit 1;
}

L'erreur provient de l'oubli des escapes sur les "/" dans le fichier de
configuration des expressions régulières.

Mais on s'est demandé pourquoi ce code compilait et était valide (il y a
quand même un warning à l'évaluation) et aussi pourquoi la condition du
"if" était toujours vrai...


oui, un :
use of uninitialized value in pattern match (m//) at ... line 8.

le test donne :
$& -> "2007"
$' -> "/11/14 12:00:20 066 ERROR Exception caught"

je pense (mais je suis très loin d'être un expert) que lors de la
recherche, perl trouve la concordance de ^.... avec 2007 (d'ailleurs la
valeur de $MATCH et bien "2007" et sort car le / suivant est pour lui la
fin de l'expression m// puisqu(il n'est bien sûr pas protégé !

le reste

il faudrait utiliser les Q...E pour "protéger" la chaine.
voir perlfaq perlre


:)
--
klp

Jean-Baptiste Mazon
Le #153118
In article Yves Martin

L'erreur provient de l'oubli des escapes sur les "/" dans le fichier de
configuration des expressions régulières.



Plutôt qu'échapper les `/' on peut aussi changer de délimiteur.
Lisibilité à débattre (dans les deux cas). Les goûts et les
couleurs...

kurtz le pirate
je pense (mais je suis très loin d'être un expert) que lors de la
recherche, perl trouve la concordance de ^.... avec 2007 (d'ailleurs la
valeur de $MATCH et bien "2007" et sort car le / suivant est pour lui la
fin de l'expression m// puisqu(il n'est bien sûr pas protégé !

le reste

Oui et non.
Essaye de définir $_ avant le bloc, et pouf! plus d'erreur ;-)


Jerome Quelin
Le #153117
Yves Martin wrote:
my $line='2007/11/14 12:00:20 066 ERROR Exception caught';

if ( $line =~ m/^..../../.. 05:3 .*ERROR/ ){
print "Match !!n";
exit 1;
}
[...]

Mais on s'est demandé pourquoi ce code compilait et était valide (il y a
quand même un warning à l'évaluation) et aussi pourquoi la condition du
"if" était toujours vrai...


parce que .. est un opérateur valide en perl : c'est l'opérateur flip flop
dans une condition. sauf que le flip-flop n'a aucune valeur pratique dans
un if, c'est utilisé pour des boucles. perldoc perlop pour plus d'infos sur
cet opérateur.

ton expression est donc parsée comme :
if ( $line =~ m/^..../ .. /.. 05:3 .*ERROR/ ){

et comme $line a bien 4 caractères, ça matche et ton bloc conditionnel est
exécuté.

c'est donc un hasard qui fait que tu matchais 2 caractères (..) au milieu.
note que avec 3 points (...) ça aurait marché aussi (autre forme du
flip-flop), mais au delà (4 points ....) cela ne marche plus.

cdlt,
jérôme
--


jl_morel
Le #153116
Dans l'article

J'ai hésité à poser la question ici avant de passer un bon moment ave >c
un collègue pour comprendre le comportement d'un bout de code (mal)
généré. Et comme ce n'est pas banal comme problème, je le poste qua >nd
même.

Voici le code mal généré - le "if" provient d'une recopie d'expressio >n
régulière depuis un fichier de configuration dans un "eval":

my $line='2007/11/14 12:00:20 066 ERROR Exception caught';

if ( $line =~ m/^..../../.. 05:3 .*ERROR/ ){
print "Match !!n";
exit 1;
}

L'erreur provient de l'oubli des escapes sur les "/" dans le fichier de
configuration des expressions régulières.

Mais on s'est demandé pourquoi ce code compilait et était valide (il y >a
quand même un warning à l'évaluation) et aussi pourquoi la condition >du
"if" était toujours vrai...



Pour compléter ce qui a déjà été dit, on peut utiliser le debugger de
regexp intégré à perl. Il suffit d'ajouter
use re 'debug';
au debut du script.
Avec votre bout de code, on voit que perl compile deux regexps :
( pour les détails voir perldebguts :
http://www.bribes.org/perl/docfr/perldebguts.html#LD64431B2 )

Compiling REx `^....'
size 6 Got 52 bytes for offset annotations.
first at 2
1: BOL(2)
2: REG_ANY(3)
3: REG_ANY(4)
4: REG_ANY(5)
5: REG_ANY(6)
6: END(0)
anchored(BOL) minlen 4
Offsets: [6]
1[1] 2[1] 3[1] 4[1] 5[1] 6[0]
Compiling REx `.. 05:3 .*ERROR'
size 11 Got 92 bytes for offset annotations.
first at 1
1: REG_ANY(2)
2: REG_ANY(3)
3: EXACT < 05:3 >(6)
6: STAR(8)
7: REG_ANY(0)
8: EXACT <ERROR>(11)
11: END(0)
anchored ` 05:3 ' at 2 floating `ERROR' at 8..2147483647 (checking anchored)
minlen 13
Offsets: [11]
1[1] 2[1] 3[6] 0[0] 0[0] 10[1] 9[1] 11[5] 0[0] 0[0] 16[0]
Matching REx `^....' against `2007/11/14 12:00:20 066 ERROR Exception caught'
Setting an EVAL scope, savestack=5
0 <> <2007/11/14 1> | 1: BOL
0 <> <2007/11/14 1> | 2: REG_ANY
1 <2> <007/11/14 1> | 3: REG_ANY
2 <20> <07/11/14 1> | 4: REG_ANY
3 <200> <7/11/14 1> | 5: REG_ANY
4 <2007> </11/14 1> | 6: END
Match successful!
Use of uninitialized value in pattern match (m//) at F:tmp_perlREGEXP~4.PL
line 8.
Freeing REx: `"^...."'
Freeing REx: `".. 05:3 .*ERROR"'
Match !!

HTH
--
J-L.M.
http://www.bribes.org/perl

Publicité
Poster une réponse
Anonyme