[Perl] Où $1 est-il capturé?
Sebastien Moretti
sebastien.moretti at unil.ch
Ven 1 Avr 12:04:18 CEST 2016
Merci pour ces éclaircissements.
Un risque dont je ne me méfiais pas (encore) sur du vieux code.
>>> C'est pour cette raison qu'il faut vérifier que la regex a bien été
>>> reconnue avant d'utiliser $1.
>>
>> Tu prêches un converti!
>>
>>> Exécute le code qui suit pour illustration. Le premier bloc est
>>> incorrect car $1 conserve sa valeur tant qu'une nouvelle correspondance
>>> n'est pas réussie (auquel cas $1 est mis à jour).
>>
>> Je pensais quand même qu'il y avait une limite, un scope, à ça.
>> Mais non semble-t-il.
>> Potentiellement très dangereux.
>>
> $1 est une variable *globale* et "use strict" accepte cette variable
> globale (ainsi que toutes les variables spéciales comme $! ou $/).
> Ce n'est pas la peine de chercher plus loin.
>
> Adopter de bonnes pratiques comme "use strict" et la déclaration
> systématique de variables avec "my" est une bonne chose, mais il
> ne faut pas oublier qu'il y a quelque chose à côté.
> Les variables globales sont peut-être très dangereuses, mais parfois
> elles se révèlent très utiles. Cf l'anecdote récemment diffusée :
> http://thedailywtf.com/articles/a-meaty-problem
> (c'est du Java et de l'anglais, désolé).
>
> Pour capturer des sous-chaînes, j'utilise la syntaxe :
>
> my $line = " Zone: 2.50h East of Greenwich"
> my ($delta, $hemi) = $line =~ /^\s*Zone:
> \s+(\d+(?:\.\d+)?)h # delta hours
> \s+(East|West) # hemisphere
> \s+of\s+Greenwich/x;
>
> Et si ça foire (par exemple, écrire "Greenwich" dans la chaîne et
> "Greenwwich" dans l'expression régulière, exemple vécu hier soir)
> j'obtiens un message "use of undefined value ...". Mais l'avantage
> est que les captures se font dans des variables *lexicales*
> et que l'on sait rapidement s'il y a un échec.
>
> Il y a aussi les captures nommées directement à l'intérieur
> de l'expression régulière :
>
> $line =~ /^\s*Zone:
> \s+(?<delta>\d+(?:\.\d+)?)h # delta hours
> \s+(?<hemi>East|West) # hemisphere
> \s+of\s+Greenwich/x;
>
> (Le code n'est pas testé, je n'ai pas encore complètement intégré
> les nouvelles fonctionnalités de Perl 5.10.)
>
> Dans ton cas, il s'agit d'un s/// et non pas d'un m//. Je ne sais
> pas si les deux méthodes conviennent au s///.
>
> En espérant t'avoir été utile,
>
> Jean
--
Sébastien Moretti
Plus d'informations sur la liste de diffusion Perl