1) preg_match_all() n'a pas d'équivalent direct en Perl, ce que je tendrais à considérer comme une bonne chose, vu qu'il est extrèmement rare de vraiment vouloir exactement le résultat donné par preg_match_all(), je vois deux cas d'utilisation :
Soit tu as une seule parenthèse capturante dans la regex et tu veux en fait une liste d'un type d'élément, dans ce cas /g en contexte de liste te donne la même chose en Perl :
my @prices = m/\$(\d+\.\d*)/g;
(preg_match_all renvoie un tableau à deux dimensions ici, alors que tu veux probablement une simple liste...)
Soit tu en as plusieurs, et dans ce cas soit tu vas faire un post-traitement une seule fois et dans ce cas, autant faire ce traitement tout de suite :
1 2 3 4 5 6 7 8 9
| while( m{((<([\w]+)[^>]*>)(.*)(</\3>))}g ) {
my ($matched, $otag, $text, $ctag) = ($1, $2, $4, $5);
print <<"EOR";
matched : $matched
opening tag : $otag
content : $text
closing tag : $ctag
EOR
} |
En procédant ainsi, tu as réduit la quantité de code inutile, et tu as gagné un gros avantage en mémoire RAM consommée...
soit tu vas devoir réutiliser les données plusieurs fois, et faire des traitements complexes et globaux (tris, ...), dans ce cas, il est (très) peu probable que le tableau obtenu avec preg_match_all() ait réellement exactement la structure que tu veux (par exemple tu te contrefous dans la plupart des cas du match complet, seuls les parties t'intéressent, et tu préférerais qu'elles soient organisées, rangées autrement), en Perl tu construiras directement la structure dans ta boucle au lieu de modifier le tableau créé par preg_match_all() :
1 2 3 4 5
| my @tags;
while( m{<([\w]+)([^>]*)>(.*)</\1>}g ) {
my ($tag, $attrs, $text) = ($1, $2, $3);
push @tags, { tagname => $tag, attributs => $attrs, content => $text };
} |
En bref preg_match_all() est une fonction qui essaie de faire trop de choses à la fois et fournit des structures par défauts peu judicieuse à mon avis. Les alternatives en Perl sont aussi simples à utiliser et plus claires à mon goût.
2) Les regexps en Perl peuvent s'appliquer à n'importe quelle chaîne de caractère, qu'elle comporte des retours à la ligne ou pas. Cependant le . ne matche pas les \n par défaut, et ^ et $ correspondent au début et à la fin de la chaîne, plutôt qu'au début et à la fin d'une ligne quelconque de la chaîne. Les modificateurs /m et /s changent ces comportements par défauts. Une astuce importante à garder en tête lorsque l'on fait du matching sur plusieurs lignes c'est qu'il est nettement préférable d'utiliser \s plutôt qu'un simple espace blanc, car \s matche tout type d'espace, y compris les passages à la ligne contrairement à un simple espace, ce qui est fréquemment la sémantique que l'on souhaite.
--
Jedaï
PS : J'ai utilisé dans mes exemples la regexp utilisée dans l'exemple de la doc PHP pour preg_match_all(), ce n'est pas une bonne regexp et je n'en recommande pas l'utilisation pour un problème réel.
Partager