OVH Cloud OVH Cloud

regexp qui suit les regles de l'art de maintenabilite

5 réponses
Avatar
Patrice Karatchentzeff
Salut,

En lisant _De l'art de programmer en Perl_, on se dit que cela ne
coûte pas très cher d'appliquer les règles proposées (d'autant que
j'en respectais déjà une bonne partie).

Et pourtant, en « traduisant » une regexp, je cale :

Voici ma regexp originale :


if (/(Vol\. [0-9]{1,2}), (n° [0-9]{1}), ([0-9]{4})/) {
($volume, $numero, $annee) = ($1, $2, $3)
}

Voici comment je la traduis :

if (m{\A # ... du début
(Vol\.\s[0-9]{1,2}), # cherche "Vol. " suivi de 1 ou 2 chiffres
(n°\s[0-9]{1}), # cherche "n°" suivi d'un chiffre
([0-9]{4}) # cherche une chaîne de 4 chiffres (année)
\z # ... à la fin
}xms
) {
($volume, $numero, $annee) = ($1, $2, $3);

(les commentaires sont en français volontairement).

Si je tente de sortir mes trois variables, cela fonctionne dans le
premier cas, pas dans le second.

La chaîne type à détecter est de la forme :

Vol. 1, n° 3, 1976

Quelqu'un a une idée de ce que je fais mal ?

Merci

PK


--
      |\      _,,,---,,_       Patrice KARATCHENTZEFF
ZZZzz /,`.-'`'    -.  ;-;;,_   mailto:p.karatchentzeff@free.fr
     |,4-  ) )-,_. ,\ (  `'-'  http://p.karatchentzeff.free.fr
    '---''(_/--'  `-'\_)       

5 réponses

Avatar
Patrice Karatchentzeff
Patrice Karatchentzeff writes:

[...]

Voici ma regexp originale :


if (/(Vol. [0-9]{1,2}), (n° [0-9]{1}), ([0-9]{4})/) {
($volume, $numero, $annee) = ($1, $2, $3)
}

Voici comment je la traduis :

if (m{A # ... du début
(Vol.s[0-9]{1,2}), # cherche "Vol. " suivi de 1 ou 2 chiffres
(n°s[0-9]{1}), # cherche "n°" suivi d'un chiffre
([0-9]{4}) # cherche une chaîne de 4 chiffres (année)
z # ... à la fin
}xms
) {
($volume, $numero, $annee) = ($1, $2, $3);

(les commentaires sont en français volontairement).

Si je tente de sortir mes trois variables, cela fonctionne dans le
premier cas, pas dans le second.

La chaîne type à détecter est de la forme :

Vol. 1, n° 3, 1976

Quelqu'un a une idée de ce que je fais mal ?


oui, moi, j'ai oublié de compter les blancs intermédiaires (à cause du
pragma x).

La bonne solution est donc

if (m{
(Vol.sd{1,2}), # capture "Vol. " suivi de 1 ou 2 chiffres
s+(n°sd{1}), # capture "n° " suivi d'un chiffre
s+(d{4}) # capture une chaîne de 4 chiffres (année)
}xms
) {
($volume, $numero, $annee) = ($1, $2, $3);

(en plus, j'ai optimisé un peu).

Par contre, je n'ai dû comprendre l'usage de A et z qui mettent le
souk dans mon expression...

PK

--
      |      _,,,---,,_       Patrice KARATCHENTZEFF
ZZZzz /,`.-'`'    -.  ;-;;,_   mailto:
     |,4-  ) )-,_. , (  `'-'  http://p.karatchentzeff.free.fr
    '---''(_/--'  `-'_)       

Avatar
Paul Gaborit
À (at) Fri, 16 Jun 2006 15:40:00 +0200,
Patrice Karatchentzeff écrivait (wrote):
La bonne solution est donc

if (m{
(Vol.sd{1,2}), # capture "Vol. " suivi de 1 ou 2 chiffres
s+(n°sd{1}), # capture "n° " suivi d'un chiffre
s+(d{4}) # capture une chaîne de 4 chiffres (année)
}xms
) {
($volume, $numero, $annee) = ($1, $2, $3);

(en plus, j'ai optimisé un peu).


Quitte à mettre des commentaires autant tout commenter. J'ai aussi
remplacer les 's' par ' ' pour n'accepter que les espaces et non les
tabulations ou les passages à la ligne (c'est juste un suggestion).

if (m{
(Vol. d{1,2}) # capture "Vol. " suivi de 1 ou 2 chiffres
, + # suivi d'une virgule et d'espace(s)
(n° d{1}) # capture "n° " suivi d'un chiffre
, + # suivi d'une virgule et d'espace(s)
(d{4}) # capture une chaîne de 4 chiffres (année)
}xms
) {
($volume, $numero, $annee) = ($1, $2, $3);


Par contre, je n'ai dû comprendre l'usage de A et z qui mettent le
souk dans mon expression...


A est une assertion de longueur nulle (elle ne consomme aucun
caractère) qui oblige la regexp à s'ancrer obligatoirement au début de
la chaîne dans laquelle on cherche.

z est une assertion de longueur nulle qui s'ancre obligatoirement à
la fin de la chaîne dans laquelle on cherche (Z fait la même chose
mais en acceptant tout de même un caractère de passage à la ligne
au-delà).

Dans votre cas, cela signifierait que $_ contient uniquement les
éléments recherchés (le texte 'Vol...').

Par ailleurs, ici, les modificateurs /s et /m ne vous servent
strictement à rien puisque votre regexp ne contient ni '.' ni '^' ou
'$'.

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>

Avatar
Patrice Karatchentzeff
Paul Gaborit writes:

[...]

Quitte à mettre des commentaires autant tout commenter. J'ai aussi
remplacer les 's' par ' ' pour n'accepter que les espaces et non les
tabulations ou les passages à la ligne (c'est juste un suggestion).

if (m{
(Vol. d{1,2}) # capture "Vol. " suivi de 1 ou 2 chiffres
, + # suivi d'une virgule et d'espace(s)
(n° d{1}) # capture "n° " suivi d'un chiffre
, + # suivi d'une virgule et d'espace(s)
(d{4}) # capture une chaîne de 4 chiffres (année)
}xms
) {
($volume, $numero, $annee) = ($1, $2, $3);


Merci pour le réarrangement : j'adopte. C'est plus lisible donc plus
maintenable. Par contre, je garde les s car je ne suis pas sûr du
fichier amont.

[...]

Par ailleurs, ici, les modificateurs /s et /m ne vous servent
strictement à rien puisque votre regexp ne contient ni '.' ni '^' ou
'$'.


Comme ce n'est pas moi qui vais ensuite maintenir et modifier le code,
autant les mettre comme cela il n'y aura pas de surprise (la personne
au bout est un unixien non perlien).

Merci en tout cas,

PK

--
      |      _,,,---,,_       Patrice KARATCHENTZEFF
ZZZzz /,`.-'`'    -.  ;-;;,_   mailto:
     |,4-  ) )-,_. , (  `'-'  http://p.karatchentzeff.free.fr
    '---''(_/--'  `-'_)       

Avatar
tuser
Paul Gaborit wrote:
Par ailleurs, ici, les modificateurs /s et /m ne vous servent
strictement à rien puisque votre regexp ne contient ni '.' ni '^' ou
'$'.


Oui, mais je suis d'accord avec Damian Conway, qui (dans son livre
"Perl Best Practices") propose de prendre l'habitude de mettre /msx
dans chaque regexp, même si ça ne sert à rien.

Avatar
Paul Gaborit
À (at) 20 Jun 2006 18:52:17 -0700,
"tuser" écrivait (wrote):
Oui, mais je suis d'accord avec Damian Conway, qui (dans son livre
"Perl Best Practices") propose de prendre l'habitude de mettre /msx
dans chaque regexp, même si ça ne sert à rien.


Damian a toujours raison... ;-)

Mais ce qui compte vraiment, à mon sens, c'est de savoir pourquoi et
quand on peut mettre ou ne pas mettre /s ou /m. Que ce soit par
habitude, jamais, une fois de temps à autre ou systématiquement
importe peu !

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>