Les MANs Linux en français...
PERLTRAP
Section: User Contributed Perl Documentation (1)Updated: 2002-04-17
Index Retour au Menu Principal
NOM
perltrap - Les pièges de Perl pour l'imprudentDESCRIPTION
Le plus grand des pièges est d'oublier d'utiliser l'option -w ; voir perlrun. Le deuxième plus grand piège est de ne pas rendre la totalité de votre programme exécutable sous "use strict". Le troisième plus grand piège est de ne pas lire la liste des changements effectués dans cette version de Perl ; voir perldelta.Les Pièges de Awk
Les utilisateurs avertis de awk devraient se soucier particulièrement de ce qui suit :- *
-
Le module English, chargé par
use English;
vous permet de vous référer aux variables spéciales (comme $/) par des noms (comme $RS), comme si elles étaient en awk ; voir perlvar pour plus de détails.
- *
- Le point-virgule est requis après toute instruction simple en Perl (sauf à la fin d'un bloc). La fin de ligne n'est pas un délimiteur d'instruction.
- *
- Les accolades sont requises pour les "if"s et les "while"s.
- *
- Les variables commencent par ``$'', ``@'' ou ``%'' en Perl.
- *
- Les tableaux sont indexés à partir de 0. De la même manière, les positions renvoyées par substr() et index() dans les chaînes sont comptées à partir de 0.
- *
- Vous devez décider si votre tableau a pour indices des nombres ou des chaînes.
- *
- Les hachages ne sont pas créés par une simple référence.
- *
- Vous devez décider si une comparaison porte sur des chaînes ou des nombres.
- *
- La lecture d'une entrée ne la découpe pas pour vous. Vous devez la transformer en un tableau vous-même. Et l'opérateur split() a des arguments différents qu'en awk.
- *
- La ligne courante en entrée est normalement dans $_, pas dans $0. Elle n'a en général pas encore perdu sa fin de ligne ($0 est le nom du programme exécuté). Voir perlvar.
- *
- $digit ne se réfère pas à des champs --- il se réfère aux sous-chaînes détectées par le dernier motif de correspondance.
- *
- L'instruction print() n'ajoute pas de séparateurs de champs et d'enregistrements à moins que vous ne fixiez $, et "$\". Vous pouvez fixer $OFS et $ORS si vous utilisez le module English.
- *
- Vous devez ouvrir vos fichiers avant d'y écrire.
- *
- L'opérateur d'intervalle est ``..'', et pas la virgule. L'opérateur virgule fonctionne comme en C.
- *
- L'opérateur de correspondance est ``=~'', pas ``~'' (``~'' est l'opérateur de complément à 1, comme en C).
- *
- L'opérateur d'exponentiation est ``**'', pas ``^''. ``^'' est l'opérateur XOR, comme en C (vous savez, on pourrait finir par avoir la sensation que awk est intrinsèquement incompatible avec C).
- *
- L'opérateur de concaténation est ``.'', pas la chaîne vide (utiliser la chaîne vide rendrait "/pat/ /pat/" impossible à analyser lexicalement, car le troisième signe de division serait interprété comme un opérateur de division --- le détecteur de mots-clés est en fait légèrement sensible au contexte pour les opérateurs tels que ``/'', ``?'', et ``>''. Et en fait, ``.'' lui-même peut être le début d'un nombre).
- *
- Les mots-clés "next", "exit", et "continue" fonctionnement différemment.
- *
-
Les variables suivantes fonctionnent différemment :
Awk Perl ARGC $#ARGV ou @ARGV scalaire ARGV[0] $0 FILENAME $ARGV FNR $. - quelque chose FS (ce que vous voulez) NF $#Fld, ou quelque chose comme ça NR $. OFMT $# OFS $, ORS $\ RLENGTH length($&) RS $/ RSTART length($`) SUBSEP $;
- *
- Vous ne pouvez pas mettre un motif dans $RS, seulement une chaîne.
- *
- En cas de doute, faites passer la construction awk dans a2p et voyez ce que cela donne.
Les Pièges de C
Les programmes C cérébraux devraient prendre note de ce qui suit :- *
- Les accolades sont requises pour les "if"s et les "while"s.
- *
- Vous devez utiliser "elsif" à la place de "else if".
- *
- Les mots-clés "break" et "continue" de C deviennent respectivement "last" et "next" en Perl. Contrairement au C, ceux-ci ne fonctionnent pas à l'intérieur d'une structure "do { } while".
- *
- Il n'y a pas d'instruction switch (mais il est aisé d'en construire une à la volée).
- *
- Les variables commencent par ``$'', ``@'' ou ``%'' en Perl.
- *
- "printf()" n'implémente pas le format ``*'' interpolant les largeurs de champs, mais il est trivial d'utiliser l'interpolation de chaînes entre guillemets pour obtenir le même résultat.
- *
- Les commentaires commencent par ``#'', pas par ``/*''.
- *
- Vous ne pouvez pas prendre l'adresse de quelque chose, bien qu'un opérateur analogue en Perl est la barre oblique inverse, qui crée une double référence (hein ? NDT).
- *
- "ARGV" doit être en majuscules. $ARGV[0] est l'"argv[1]" du C, et "argv[0]" atterrit dans $0.
- *
- Les appels systèmes tels que link(), unlink(), rename(), etc. renvoient autre chose que zéro en cas de succès.
- *
- Les handlers de signaux manipulent des noms de signaux, pas des nombres. Utilisez "kill -l" pour déterminer leurs noms sur votre système.
Les Pièges de Sed
Les programmeurs sed expérimentés devraient prendre note de ce qui suit :- *
- Les références arrières dans les substitutions utilisent ``$'' à la place de ``\''.
- *
- Les métacaractères d'expressions rationnelles ``('', ``)'', et ``|'' ne sont pas précédés de barres obliques inverses.
- *
- L'opérateur d'intervalle est "...", à la place de la virgule.
Les Pièges du Shell
les programmeurs shell dégourdis devraient prendre note de ce qui suit :- *
- L'opérateur accent grave effectue une interpolation de variable sans se soucier de la présence ou non d'apostrophes dans la commande.
- *
- L'opérateur accent grave ne fait pas de traduction de la valeur de retour, contrairement au csh.
- *
- Les shells (en particulier csh) effectuent plusieurs niveaux de substitution sur chaque ligne de commande. Perl ne fait de substitution que dans certaines structures comme les guillemets, les accents graves, les crochets et les motifs de recherche.
- *
- Les shells interprètent les scripts petits bouts par petits bouts. Perl compile tout le programme avant de l'exécuter (sauf les blocs "BEGIN", qu'il exécute lors de la compilation).
- *
- Les arguments sont disponibles via @ARGV, et pas $1, $2, etc.
- *
- L'environnement n'est pas automatiquement mis à disposition sous forme de variables scalaires distinctes.
Les Pièges de Perl
Les programmeurs Perl pratiquants devraient prendre note de ce qui suit :- *
- Souvenez-vous que de nombreuses opérations se comportent différemment selon qu'elles sont appelées dans un contexte de liste ou dans un contexte scalaire. Voir perldata pour plus de détails.
- *
- Évitez autant que possible les barewords, en particulier ceux en minuscules. Vous ne pouvez pas dire rien qu'en le regardant si un bareword est une fonction ou une chaîne. En utilisant les apostrophes pour les chaînes et des parenthèses pour les appels de fonctions, vous permettrez qu'on ne les confonde jamais.
- *
- Vous ne pouvez pas distinguer, par une simple inspection, les fonctions intégrées qui sont des opérateurs unaires (comme chop() et chdir()) de celles qui sont des opérateurs de liste (comme print() et unlink()). (Les sous-programmes définis par l'utilisateur ne peuvent être que des opérateurs de liste, jamais des opérateurs unaires). Voir perlop.
- *
- Les gens ont du mal à se souvenir que certaines fonctions utilisent par défaut $_, ou @ARGV, ou autre chose, tandis que d'autres ne le font pas alors qu'on pourrait s'y attendre.
- *
-
La structure <FH> n'est pas le nom du handle de fichier, c'est un
opérateur lisant une ligne sur ce handle. Les données lues sont
affectées à $_ seulement si la lecture du fichier est la seule
condition d'une boucle while :
while (<FH>) { } while (defined($_ = <FH>)) { }.. <FH>; # données rejetées !
- *
-
Souvenez-vous de ne pas utiliser "=" lorsque vous avez besoin de
"=~" ; ces deux structures sont très différentes :
$x = /foo/; $x =~ /foo/;
- *
- La structure "do {}" n'est pas une vraie boucle sur laquelle vous pouvez utiliser un contrôle de boucle (? NDT).
- *
- Utilisez "my()" pour les variables locales chaque fois que vous pouvez vous en satisfaire (mais voyez perlform pour les cas où vous ne le pouvez pas). L'utilisation de "local()" donne vraiment une valeur locale à une variable globale, ce qui vous met à la merci d'effets secondaires de portée dynamique imprévus.
- *
- Si vous localisez une variable exportée dans un module, sa valeur exportée value ne changera pas. Le nom local devient un alias pour une nouvelle valeur, mais le nom externe est toujours un alias de l'original.
Les Pièges entre Perl4 et Perl5
Les programmeurs Perl4 pratiquants devraient prendre note des pièges suivants, spécifiques au passage entre Perl4 et Perl5.Ils sont crûment commandés par la liste suivante :
- Pièges liés aux Corrections de Bugs, aux Désapprobations et aux Abandons
- Tout ce qui a été corrigé en tant que bug de perl4, supprimé ou désapprouvé en tant que caractéristique de perl4, avec l'intention d'encourager l'usage d'une autre caractéristique de perl5.
- Pièges de l'Analyse Syntaxique
- Pièges qui semblent provenir du nouvel analyseur.
- Pièges numériques
- Pièges liés aux opérateurs numériques ou mathématiques.
- Pièges des Types Généraux de données
- Pièges impliquant les types de données standards de perl.
- Pièges du Contexte - contexte scalaire et de liste
- Pièges liés au contexte dans les instructions et déclarations scalaires ou de liste.
- Pièges de la Précédence
- Pièges liés à la précédence lors de l'analyse, de l'évaluation et de l'exécution du code.
- Pièges des Expressions Rationnelles Générales lors de l'utilisation de s///, etc.
- Pièges liés à l'utilisation de la reconnaissance de motifs.
- Pièges des Sous-Programmes, des Signaux, des Tris
- Pièges liés à l'utilisation des signaux et des handlers de signaux, aux sous-programmes généraux, et aux tris, ainsi qu'aux sous-progammes de tri.
- Pièges de l'OS
- Pièges spécifiques au système d'exploitation.
- Pièges du DBM
- Pièges spécifiques à l'utilisation de "dbmopen()", et aux implémentations particulières de dbm.
- Pièges non Classés
- Tout le reste.
Si vous trouvez un exemple de piège de conversion qui ne soit pas listé ici, soumettez-le à Bill Middleton <wjm@best.com> en vue de son inclusion. Notez aussi qu'au moins certains de ceux qui suivent peuvent être capturés par le pragma "use warnings" ou par l'option -w.
Pièges liés aux Corrections de Bugs, aux Désapprobations et aux Abandons
Tout ce qui a été abandonné, désapprouvé ou corrigé comme étant un bug depuis perl4.- * Abandon
-
Les symboles commençant par ``_'' ne sont plus forcément dans le
paquetage main, sauf pour $_ lui-même (ainsi que @_, etc.).
package test; $_legacy = 1;
package main; print "\$_legacy is ",$_legacy,"\n";
# perl4 affiche : $_legacy is 1 # perl5 affiche : $_legacy is
- * Désapprobation
-
Le double deux-points est désormais un séparateur de paquetage valide
dans un nom de variable. Ainsi ceux-ci se comportent différemment en
perl4 et en perl5, car le paquetage n'existe pas.
$a=1;$b=2;$c=3;$var=4; print "$a::$b::$c "; print "$var::abc::xyz\n";
# perl4 affiche : 1::2::3 4::abc::xyz # perl5 affiche : 3
Étant donné que "::" est maintenant le délimiteur de paquetage préféré, on peut se demander si ceci doit être considéré comme un bug ou non (l'ancien délimiteur de paquetage, ' , est utilisé ici).
$x = 10 ; print "x=${'x}\n" ;
# perl4 affiche : x=10 # perl5 affiche : Can't find string terminator "'" anywhere before EOF
Vous pouvez éviter ce problème, en restant compatible avec perl4, si vous incluez toujours explicitement le nom du paquetage :
$x = 10 ; print "x=${main'x}\n" ;
Voyez aussi les pièges de précédence, pour l'analyse de $:.
- * Correction de Bug
-
Les deuxièmes et troisièmes arguments de "splice()" sont désormais
évalués dans un contexte scalaire (comme l'indique le Camel) plutôt
que dans un contexte de liste.
sub sub1{return(0,2) } # retourne une liste de 2 éléments sub sub2{ return(1,2,3)} # retourne une liste de 3 éléments @a1 = ("a","b","c","d","e"); @a2 = splice(@a1,&sub1,&sub2); print join(' ',@a2),"\n";
# perl4 affiche : a b # perl5 affiche : c d e
- * Abandon
-
Vous ne pouvez pas faire un "goto" dans un bloc optimisé. Mince.
goto marker1;
for(1){ marker1: print "Here I is!\n"; }
# perl4 affiche : Here I is! # perl5 effectue un vidage mémoire (SEGV)
- * Abandon
-
Il n'est plus légal syntaxiquement d'utiliser l'espace comme nom de
variable, ou comme délimiteur pour tout type de structure entre
apostrophes. Mince et remince.
$a = ("foo bar"); $b = q baz ; print "a is $a, b is $b\n";
# perl4 affiche : a is foo bar, b is baz # erreur de perl5 : Bareword found where operator expected
- * Abandon
-
La syntaxe archaïque while/if BLOC BLOC n'est plus supportée.
if { 1 } { print "True!"; } else { print "False!"; }
# perl4 affiche : True! # erreur de perl5 : syntax error at test.pl line 1, near "if {"
- * Correction de Bug
-
L'opérateur "**" se lie désormais plus étroitement que le moins
unaire. Cela devait fonctionner ainsi selon la documentation, mais ce
n'était pas le cas.
print -4**2,"\n";
# perl4 affiche : 16 # perl5 affiche : -16
- * Abandon
-
La signification de "foreach{}" a légèrement changé lorsqu'il
traverse une liste qui n'est pas un tableau. C'était utilisé pour
affecter la liste à un tableau temporaire, mais ce n'est plus le cas
(pour des raisons d'efficacité). Cela veut dire que vous devrez
désormais itérer sur les vraies valeurs, pas sur des copies de ces
valeurs. Les modifications de la variable de boucle peuvent changer
les valeurs originelles.
@list = ('ab','abc','bcd','def'); foreach $var (grep(/ab/,@list)){ $var = 1; } print (join(':',@list));
# perl4 affiche : ab:abc:bcd:def # perl5 affiche : 1:1:bcd:def
Pour garder la sémantique de Perl4, vous devrez affecter explicitement votre liste à un tableau temporaire puis itérer dessus. Vous pourriez par exemple devoir changer
foreach $var (grep(/ab/,@list)){
en
foreach $var (@tmp = grep(/ab/,@list)){
Sinon changer $var modifiera les valeurs de @list (Cela arrive le plus souvent lorsque vous utilisez $_ comme variable de boucle, et appelez dans celle-ci des sous-programmes qui ne localisent pas correctement $_).
- * Abandon
-
"split" sans argument se comporte désormais comme "split ' '" (qui
ne retourne pas de champ nul initial si $_ commence par une espace),
il se comportait habituellement comme "split /\s+/" (qui le fait).
$_ = ' hi mom'; print join(':', split);
# perl4 affiche : :hi:mom # perl5 affiche : hi:mom
- * Correction de Bug
-
Perl 4 ignorait tout texte attaché à une option -e, et prenait
toujours le petit bout de code dans l'argument suivant. Qui plus est,
il acceptait silencieusement une option -e non suivie d'un
argument. Ces deux comportements ont été supprimés.
perl -e'print "attached to -e"' 'print "separate arg"'
# perl4 affiche : separate arg # perl5 affiche : attached to -e
perl -e
# perl4 affiche : # perl5 meurt : No code specified for -e.
- * Abandon
-
En Perl 4, la valeur de retour de "push" n'était pas documentée, mais
c'était en fait la dernière valeur poussée sur la liste cible. En Perl
5, la valeur de retour de "push" est documentée, mais elle a changé,
c'est désormais le nombre d'éléments de la liste résultante.
@x = ('existing'); print push(@x, 'first new', 'second new');
# perl4 affiche : second new # perl5 affiche : 3
- * Désapprobation
- Certains messages d'erreur sont différents.
- * Abandon
- Certains bugs peuvent avoir été retirés par inadvertence. :-)
Piège de l'Analyse Syntaxique
Pièges entre Perl4 et Perl5 ayant un rapport avec l'analyse syntaxique.- * Analyse Syntaxique
-
Notez l'espace entre . et =
$string . = "more string"; print $string;
# perl4 affiche: more string # perl5 affiche : syntax error at - line 1, near ". ="
- * Analyse Syntaxique
-
L'analyse est meilleure en perl 5
sub foo {} &foo print("hello, world\n");
# perl4 affiche : hello, world # perl5 affiche : syntax error
- * Analyse Syntaxique
-
Règle ``si ça a l'air d'une fonction, c'est une fonction''.
print ($foo == 1) ? "is one\n" : "is zero\n";
# perl4 affiche : is zero # perl5 avertit : "Useless use of a constant in void context" if using -w
- * Analyse Syntaxique
-
L'interpolation de chaîne de la structure $#array diffère lorsque
des accolades sont utilisées autour du nom.
@ = (1..3); print "${#a}";
# perl4 affiche : 2 # perl5 échoue sur une erreur de syntaxe
@ = (1..3); print "$#{a}";
# perl4 affiche : {a} # perl5 affiche : 2
Pièges Numériques
Pièges entre Perl4 et Perl5 ayant un rapport avec les opérateurs numériques, les opérandes, ou leurs sorties.- * Numérique
-
Sortie formattée et chiffres significatifs
print 7.373504 - 0, "\n"; printf "%20.18f\n", 7.373504 - 0;
# Perl4 affiche : 7.375039999999996141 7.37503999999999614
# Perl5 affiche : 7.373504 7.37503999999999614
- * Numérique
-
Cet élément spécifique a été supprimé. Il démontrait comment
l'opérateur d'auto-incrémentation ne voyait pas qu'un nombre avait
dépassé la limite supérieure des entiers signés. Cela a été réglé dans
la version 5.003_04. Mais soyez toujours prudent lorsque vous utilisez
de grands entiers. En cas de doute :
use Math::BigInt;
- * Numérique
-
L'affectation de valeurs de retour de tests d'égalité numérique ne
fonctionne pas en perl5 lorsque le test échoue (et renvoit 0). Les
tests logique retourne maintenant un null, au lieu de 0
$p = ($test == 1); print $p,"\n";
# perl4 affiche : 0 # perl5 affiche :
Voir aussi ``Pièges des Expressions Rationnelles Générales lors de l'utilisation de s///, etc.'' pour un autre exemple de cette nouvelle caractéristique...
- * Opérateurs de chaîne bit par bit
-
Lorsque des opérateurs bit par bit qui peuvent travailler sur des
nombres ou sur des chaînes ("& | ^ ~") n'ont que des chaînes pour
arguments, perl4 traite les opérandes comme des chaînes de bits dans
la mesure où le programme contenait un appel à la fonction
"vec()". perl5 traite les opérandes chaînes comme des chaînes de bits
(Voir ``Opérateurs bit à bit sur les chaînes'' in perlop pour plus de
détails).
$fred = "10"; $barney = "12"; $betty = $fred & $barney; print "$betty\n"; # Décommentez la ligne suivante pour changer le comportement de perl4 # ($dummy) = vec("dummy", 0, 0);
# Perl4 affiche : 8
# Perl5 affiche : 10
# Si vec() est utilisé quelque part dans le programme, les deux # affichent : 10
Pièges des Types de Données Généraux
Pièges entre Perl4 et Perl5 impliquant la plupart des types de données, et leur usage dans certaines expressions et/ou contextes.- * (Tableaux)
-
Les indices de tableau négatifs sont maintenant comptés depuis la fin
du tableau.
@a = (1, 2, 3, 4, 5); print "The third element of the array is $a[3] also expressed as $a[-2] \n";
# perl4 affiche : The third element of the array is 4 also expressed as # perl5 affiche : The third element of the array is 4 also expressed as 4
- * (Tableaux)
-
Abaisser la valeur de $#array supprime désormais des éléments du
tableau, et rend impossible leur récupération.
@a = (a,b,c,d,e); print "Before: ",join('',@a); $#a =1; print ", After: ",join('',@a); $#a =3; print ", Recovered: ",join('',@a),"\n";
# perl4 affiche : Before: abcde, After: ab, Recovered: abcd # perl5 affiche : Before: abcde, After: ab, Recovered: ab
- * (Hachages)
-
Les hachages sont définis avant leur utilisation
local($s,@a,%h); die "scalar \$s defined" if defined($s); die "array \@a defined" if defined(@a); die "hash \%h defined" if defined(%h);
# perl4 affiche : # perl5 meurt : hash %h defined
Perl génère désormais un avertissement lorsqu'il voit defined(@a) et defined(%h).
- * (Globs)
-
L'affectation globale de variable à variable échouera si la variable
affectée est localisée après l'affectation
@a = ("This is Perl 4"); *b = *a; local(@a); print @b,"\n";
# perl4 affiche : This is Perl 4 # perl5 affiche :
- * (Globs)
- L'affectation de "undef" à un glob n'a pas d'effet en Perl 5. En Perl 4, elle indéfinit le scalaire associé (mais peut avoir d'autres effets de bord, y compris des SEGVs).
- * (Chaîne Scalaire)
-
Changements dans la négation unaire (de chaînes)
Ce changement affecte à la fois la valeur de retour et ce qu'elle fait
à l'incrément automagique.
$x = "aaa"; print ++$x," : "; print -$x," : "; print ++$x,"\n";
# perl4 affiche : aab : -0 : 1 # perl5 affiche : aab : -aab : aac
- * (Constantes)
-
perl 4 vous laisse modifier les constantes :
$foo = "x"; &mod($foo); for ($x = 0; $x < 3; $x++) { &mod("a"); } sub mod { print "before: $_[0]"; $_[0] = "m"; print " after: $_[0]\n"; }
# perl4: # before: x after: m # before: a after: m # before: m after: m # before: m after: m
# Perl5: # before: x after: m # Modification of a read-only value attempted at foo.pl line 12. # before: a
- * (Scalaires)
-
Le comportement est légèrement différent pour :
print "$x", defined $x
# perl 4: 1 # perl 5: <no output, $x is not called into existence>
- * (Suicide de Variable)
-
Le suicide de variable est plus cohérent sous Perl 5. Perl5 montre le même
comportement pour les hachages et les scalaires, que perl4 montre
uniquement pour les scalaires.
$aGlobal{ "aKey" } = "global value"; print "MAIN:", $aGlobal{"aKey"}, "\n"; $GlobalLevel = 0; &test( *aGlobal );
sub test { local( *theArgument ) = @_; local( %aNewLocal ); # perl 4 != 5.001l,m $aNewLocal{"aKey"} = "this should never appear"; print "SUB: ", $theArgument{"aKey"}, "\n"; $aNewLocal{"aKey"} = "level $GlobalLevel"; # what should print $GlobalLevel++; if( $GlobalLevel<4 ) { &test( *aNewLocal ); } }
# Perl4: # MAIN:global value # SUB: global value # SUB: level 0 # SUB: level 1 # SUB: level 2
# Perl5: # MAIN:global value # SUB: global value # SUB: this should never appear # SUB: this should never appear # SUB: this should never appear
Pièges du Contexte - contextes scalaires et de liste
- * (contexte de liste)
-
Les éléments des listes d'arguments pour les formats sont désormais
évalués dans un contexte de liste. Cela signifie que vous pouvez
maintenant interpoler les valeurs de liste.
@fmt = ("foo","bar","baz"); format STDOUT= @<<<<< @||||| @>>>>> @fmt; . write;
# erreur de perl4 : Please use commas to separate fields in file # perl5 affiche : foo bar baz
- * (contexte scalaire)
-
La fonction "caller()" retourne maintenant la valeur faux dans un
contexte scalaire s'il n'y a pas d'appelant. Cela laisse les fichiers
de bibliothèque déterminer s'ils sont en train d'être demandés.
caller() ? (print "You rang?\n") : (print "Got a 0\n");
# erreur de perl4 : There is no caller # perl5 affiche : Got a 0
- * (contexte scalaire)
-
L'opérateur virgule dans un contexte scalaire est désormais garanti
comme donnant un contexte scalaire à ses arguments.
@y= ('a','b','c'); $x = (1, 2, @y); print "x = $x\n";
# Perl4 affiche : x = c # pense contexte de liste, # interpole la liste # Perl5 affiche : x = 3 # sait que le scalaire utilise la # longueur de la liste
- * (liste, fonction intégrée)
-
Couardise de "sprintf()" (argument tableau converti en nombre
scalaire d'éléments du tableau) Ce test pourrait être ajouté à
t/op/sprintf.t
@z = ('%s%s', 'foo', 'bar'); $x = sprintf(@z); if ($x eq 'foobar') {print "ok 2\n";} else {print "not ok 2 '$x'\n";}
# perl4 affiche : ok 2 # perl5 affiche : not ok 2
"printf()" fonctionne toutefois bien :
printf STDOUT (@z); print "\n";
# perl4 affiche : foobar # perl5 affiche : foobar
Probablement un bug.
Pièges de la Précédence
Pièges entre Perl4 et Perl5 impliquant l'ordre de précédence.Perl 4 a presque les mêmes règles de précédence que Perl 5 pour les opérateurs qu'ils ont en commun. Toutefois, Perl 4 semble avoir contenu des incohérences ayant rendu son comportement différent de celui qui était documenté.
- * Précédence
-
LHS vs. RHS pour tout opérateur d'affectation. LHS est d'abord évalué
en perl4, mais en second en perl5 ; ceci peut modifier les relations
entre les effets de bord dans les sous-expressions.
@arr = ( 'left', 'right' ); $a{shift @arr} = shift @arr; print join( ' ', keys %a );
# perl4 affiche : left # perl5 affiche : right
- * Précédence
-
Voici des expressions devenues des erreurs sémantiques à cause de la
précédence :
@list = (1,2,3,4,5); %map = ("a",1,"b",2,"c",3,"d",4); $n = shift @list + 2; # premier élément de la liste plus 2 print "n is $n, "; $m = keys %map + 2; # nombre d'éléments du hachage plus 2 print "m is $m\n";
# perl4 affiche : n is 3, m is 6 # erreur de perl5 et échec de la compilation
- * Précédence
-
La précédence des opérateurs d'affectation est désormais la même que
celle de l'affectation. Perl 4 leur donnait par erreur la précédence
de l'opérateur associé. Vous devez donc maintenant les mettre entre
parenthèses dans les expressions telles que
/foo/ ? ($a += 2) : ($a -= 2);
Autrement
/foo/ ? $a += 2 : $a -= 2
serait analysé de façon erronée sous la forme
(/foo/ ? $a += 2 : $a) -= 2;
D'autre part,
$a += /foo/ ? 1 : 2;
fonctionne désormais comme un programmeur C pourrait s'y attendre.
- * Précédence
-
open FOO || die;
est désormais incorrect. Vous devez mettre le handle de fichier entre parenthèses. Sinon, perl5 laisse sa précédence par défaut à l'instruction :
open(FOO || die);
# perl4 ouvre ou meurt # erreur de perl5 : Precedence problem: open FOO should be open(FOO)
- * Précédence
-
perl4 donne la précédence à la variable spéciale $:, tandis que
perl5 traite $:: comme étant le "paquetage" principale
$a = "x"; print "$::a";
# perl 4 affiche : -:a # perl 5 affiche : x
- * Précédence
-
perl4 a une précédence bugguée pour les opérateurs de test de fichiers
vis-à-vis des opérateurs d'affectation. Ainsi, bien que la table de
précédence de perl4 laisse à penser que "-e $foo .= "q"" devrait être
analysé comme "((-e $foo) .= "q")", il l'analyse en fait comme "(-e
($foo .= "q"))". En perl5, la précédence est telle que documentée.
-e $foo .= "q"
# perl4 affiche : no output # perl5 affiche : Can't modify -e in concatenation
- * Précédence
-
En perl4, keys(), each() et values() étaient des opérateurs spéciaux
de haute précédence qui agissaient sur un simple hachage, mais en
perl5, ce sont des opérateurs unaires nommés normaux. Tels que
documentés, ces opérateurs ont une précédence plus basse que les
opérateurs arithmétiques et de concaténation "+ - .", mais les
variantes de perl4 de ces opérateurs se lient en fait plus étroitement
que "+ - .". Ainsi, pour :
%foo = 1..10; print keys %foo - 1
# perl4 affiche : 4 # perl5 affiche : Type of arg 1 to keys must be hash (not subtraction)
Le comportement de perl4 était probablement plus utile, mais moins cohérent.
Pièges des Expressions Rationnelles Générales lors de l'utilisation de s///, etc.
Tous types de pièges concernant les expressions rationnelles.- * Expression Rationnelle
-
"s'$lhs'$rhs'" n'effectue désormais d'interpolation ni d'un côté ni
de l'autre. $lhs était habituellement interpolé, mais pas $rhs (et ne
détecte toujours pas un '$' littéral dans la chaîne)
$a=1;$b=2; $string = '1 2 $a $b'; $string =~ s'$a'$b'; print $string,"\n";
# perl4 affiche : $b 2 $a $b # perl5 affiche : 1 2 $a $b
- * Expression Rationnelle
-
"m//g" attache maintenant son état à la chaîne fouillée plutôt que
l'expression rationnelle (une fois que la portée d'un bloc est
quittée pour le sous-programme, l'état de la chaîne fouillée est
perdu)
$_ = "ababab"; while(m/ab/g){ &doit("blah"); } sub doit{local($_) = shift; print "Got $_ "}
# perl4 affiche : blah blah blah # perl5 affiche : boucle infinie de blah...
- * Expression Rationnelle
-
Couramment, si vous utilisez le qualificateur "m//o" sur une
expression rationnelle dans un sous-programme anonyme, toutes les
fermetures générées dans ce sous-programme anonyme utiliseront
l'expression rationnelle telle qu'elle a été compilée lors de sa toute
première utilisation dans une telle fermeture. Par exemple, si vous
dites
sub build_match { my($left,$right) = @_; return sub { $_[0] =~ /$left stuff $right/o; }; }
build_match() retournera toujours un sous-programme qui correspondra au contenu de $left et de $right tels qu'ils étaient la première fois que build_match() a été appelé, et pas tels qu'ils sont dans l'appel en cours.
C'est probablement un bug, et cela pourrait changer dans les futures versions de Perl.
- * Expression Rationnelle
-
Si aucune parenthèse n'est utilisée dans une correspondance, Perl4
fixe $+ à toute la corerspondance, tout comme $&. Perl5 ne le
fait pas.
"abcdef" =~ /b.*e/; print "\$+ = $+\n";
# perl4 affiche : bcde # perl5 affiche :
- * Expression Rationnelle
-
La substitution retourne désormais la chaîne vide si elle échoue
$string = "test"; $value = ($string =~ s/foo//); print $value, "\n";
# perl4 affiche : 0 # perl5 affiche :
Voir aussi ``Pièges Numériques'' pour un autre exemple de cette nouvelle caractéristique.
- * Expression Rationnelle
-
"s`lhs`rhs`" (en utilisant des accents graves) est maintenant une
substitution normale, sans expansion des accents graves
$string = ""; $string =~ s`^`hostname`; print $string, "\n";
# perl4 affiche : <the local hostname> # perl5 affiche : hostname
- * Expression Rationnelle
-
Analyse plus stricte des variables utilisées dans les expressions
rationnelles
s/^([^$grpc]*$grpc[$opt$plus$rep]?)//o;
# perl4: compile sans erreur # perl5: compile avec Scalar found where operator expected ..., near "$opt$plus"
un composant ajouté de cet exemple, apparemment depuis le même script, est la véritable valeur de la chaîne fouillée après la substitution (NDT ?). "[$opt]" est une classe de caractère en perl4 et un indice de tableau en perl5
$grpc = 'a'; $opt = 'r'; $_ = 'bar'; s/^([^$grpc]*$grpc[$opt]?)/foo/; print ;
# perl4 affiche : foo # perl5 affiche : foobar
- * Expression Rationelle
-
Sous perl5, "m?x?" ne correspond qu'une fois, comme "?x?". Sous
perl4, cela correspondait plusieurs fois, comme "/x/" ou "m!x!".
$test = "once"; sub match { $test =~ m?once?; } &match(); if( &match() ) { # m?x? correspond plusieurs fois print "perl4\n"; } else { # m?x? correspond une seule fois print "perl5\n"; }
# perl4 affiche : perl4 # perl5 affiche : perl5
Pièges des Sous-Programmes, des Signaux et des Tris
Le groupe général de pièges entre Perl4 et Perl5 ayant un rapport avec les Signaux, les Tris, et leurs sous-programmes associés, ainsi que les pièges généraux liés aux sous-programmes. Cela inclut certains pièges spécifiques au système d'exploitation.- * (Signaux)
-
Les barewords qui avaient l'air de chaînes pour Perl auront l'air
d'appels de sous-programmes si un sous-programme ayant ce nom est
défini avant que le compilateur les voie.
sub SeeYa { warn"Hasta la vista, baby!" } $SIG{'TERM'} = SeeYa; print "SIGTERM is now $SIG{'TERM'}\n";
# perl4 affiche : SIGTERM is main'SeeYa # perl5 affiche : SIGTERM is now main::1
Utilisez -w pour capturer celui-ci
- * (Sous-Programme de Tri)
-
reverse n'est plus autorisé comme nom d'un sous-programme de tri.
sub reverse{ print "yup "; $a <=> $b } print sort reverse a,b,c;
# perl4 affiche : yup yup yup yup abc # perl5 affiche : abc
- * warn() ne vous laisse pas spécifier un handle de fichier.
-
Bien qu'il ait _toujours_ imprimé sur STDERR, warn() vous laissait
spécifier un handle de fichier en perl4. Avec perl5, ce n'est plus le
cas.
warn STDERR "Foo!";
# perl4 affiche : Foo! # perl5 affiche : String found where operator expected
Pièges du Système d'Exploitation
- * (SysV)
-
Sous HPUX, et certains autres systèmes d'exploitation de la famille
SysV, on devait réinitialiser tout handle de signal à l'intérieur de
la fonction de gestion du signal, chaque fois qu'un signal était
traité avec perl4. Avec perl5, la réinitialisation est désormais faite
correctement. Tout code reposant sur un handler n'étant _pas_
réinitialisé devra être réécrit.
Depuis la version 5.002, Perl utilise sigaction() sous SysV.
sub gotit { print "Got @_... "; } $SIG{'INT'} = 'gotit';
$| = 1; $pid = fork; if ($pid) { kill('INT', $pid); sleep(1); kill('INT', $pid); } else { while (1) {sleep(10);} }
# perl4 (HPUX) affiche : Got INT... # perl5 (HPUX) affiche : Got INT... Got INT...
- * (SysV)
-
Sous les systèmes d'exploitation de la famille SysV, "seek()" sur un
fichier ouvert en mode d'ajout ">>" fait désormais ce qu'il
doit selon la page de manuel de fopen(). C'est-à-dire que lorsqu'un
fichier est ouvert en mode d'ajout, il est impossible d'écraser les
informations déjà présentes dans le fichier.
open(TEST,">>seek.test"); $start = tell TEST ; foreach(1 .. 9){ print TEST "$_ "; } $end = tell TEST ; seek(TEST,$start,0); print TEST "18 characters here";
# perl4 (solaris) seek.test dit : 18 characters here # perl5 (solaris) seek.test dit : 1 2 3 4 5 6 7 8 9 18 characters here
Pièges de l'Interpolation
Pièges entre Perl4 et Perl5 ayant un rapport avec la façon dont les choses sont interpolées dans certaines expressions, instructions, dans certains contexts, ou quoi que ce soit d'autre.- * Interpolation
-
@ interpole désormais toujours un tableau en chaînes entre guillemets.
print "To: someone@somewhere.com\n";
# perl4 affiche : To:someone@somewhere.com # erreur de perl5 : In string, @somewhere now must be written as \@somewhere
- * Interpolation
-
Les chaînes entre guillemets ne peuvent plus se terminer par un $ ou
un @ non protégé.
$foo = "foo$"; $bar = "bar@"; print "foo is $foo, bar is $bar\n";
# perl4 affiche : foo is foo$, bar is bar@ # erreur de perl5 : Final $ should be \$ or $name
Note : perl5 NE génère PAS une erreur pour le @ terminant $bar
- * Interpolation
-
Perl évalue maintenant parfois des expressions arbitraires entre
accolades qui apparaissent entre des guillemets (habituellement
lorsque l'accolade ouvrante est précédée par "$" ou "@").
@www = "buz"; $foo = "foo"; $bar = "bar"; sub foo { return "bar" }; print "|@{w.w.w}|${main'foo}|";
# perl4 affiche : |@{w.w.w}|foo| # perl5 affiche : |buz|bar|
Notez que vous pouvez utiliser "use strict;" pour vous mettre à l'abri de tels pièges sous perl5.
- * Interpolation
-
La structure ``this is $$x'' interpolait le pid à cet endroit, mais elle
essaye maintenant apparemment de déréfencer $x. $$ tout seul
fonctionne toutefois toujours bien.
print "this is $$x\n";
# perl4 affiche : this is XXXx (XXX is the current pid) # perl5 affiche : this is
- * Interpolation
-
La création de hachage à la volée avec "eval "EXPR"" exige maintenant
soit que les deux "$" soient protégés dans la spécification du nom du
hachage, soit que les deux accolades soient protégées. Si les
accolades sont protégées, le résultat sera compatible entre perl4 et
perl5. C'est une pratique très commune qui devrait être modifiée de
façon à utiliser si possible la forme bloc d'"eval{}".
$hashname = "foobar"; $key = "baz"; $value = 1234; eval "\$$hashname{'$key'} = q|$value|"; (defined($foobar{'baz'})) ? (print "Yup") : (print "Nope");
# perl4 affiche : Yup # perl5 affiche : Nope
Changer
eval "\$$hashname{'$key'} = q|$value|";
en
eval "\$\$hashname{'$key'} = q|$value|";
donne le résultat suivant :
# perl4 affiche : Nope # perl5 affiche : Yup
ou, changer pour
eval "\$$hashname\{'$key'\} = q|$value|";
donne le résultat suivant :
# perl4 affiche : Yup # perl5 affiche : Yup # et est compatible avec les deux versions
- * Interpolation
-
Programmes perl4 se reposant inconsciemment sur les bugs de versions
précédentes de perl.
perl -e '$bar=q/not/; print "This is $foo{$bar} perl5"'
# perl4 affiche : This is not perl5 # perl5 affiche : This is perl5
- * Interpolation
-
Vous devez aussi faire attention avec les références de tableau.
print "$foo{"
perl 4 affiche : { perl 5 affiche : syntax error
- * Interpolation
-
De façon similaire, prenez garde à :
$foo = "array"; print "\$$foo{bar}\n";
# perl4 affiche : $array{bar} # perl5 affiche : $
Perl 5 cherche $array{bar} qui n'existe pas, mais perl 4 est content de simplement substituer $foo par ``array''. Faites attention à cela en particulier dans les "eval"'s.
- * Interpolation
-
chaîne "qq()" passée à "eval"
eval qq( foreach \$y (keys %\$x\) { \$count++; } );
# perl4 exécute cela sans problème # perl5 affiche : Can't find string terminator ")"
Pièges DBM
Pièges généraux de DBM.- * DBM
-
Les bases de données existantes créées sous perl4 (ou tout autre outil
dbm/ndbm) peuvent faire échouer le même script une fois exécuté sous
perl5. L'exécutable de perl5 doit avoir été lié avec le même dbm/ndbm
par défaut pour que "dbmopen()" fonctionne correctement sans lien
via "tie" vers une implémentation de dbm sous forme d'extension.
dbmopen (%dbm, "file", undef); print "ok\n";
# perl4 affiche : ok # perl5 affiche : ok (IFF linked with -ldbm or -lndbm)
- * DBM
-
Les bases de données existantes créées sous perl4 (ou tout autre outil
dbm/ndbm) peuvent faire échouer le même script une fois exécuté sous
perl5. L'erreur générée lorsque la limite de la taille clé/valeur est
dépassée provoquera la sortie immédiate de perl5.
dbmopen(DB, "testdb",0600) || die "couldn't open db! $!"; $DB{'trap'} = "x" x 1024; # valeur trop grande pour la plupart # des dbm/ndbm print "YUP\n";
# perl4 affiche : dbm store returned -1, errno 28, key "trap" at - line 3. YUP
# perl5 affiche : dbm store returned -1, errno 28, key "trap" at - line 3.
Pièges non Classés
Tout le reste.- * Piège require/do utilisant la valeur de retour
- Si le fichier doit.pl contient :
sub foo { $rc = do "./do.pl"; return 8; } print &foo, "\n";
Et le fichier do.pl contient l'unique ligne suivante :
return 3;
Exécuter doit.pl donne le résultat suivant :
# perl 4 affiche : 3 (abandonne tôt le sous-programme) # perl 5 affiche : 8
Le comportement est le même si vous remplacez "do" par "require".
- * split sur une chaîne vide avec une LIMIT spécifiée
- Si le fichier doit.pl contient :
-
$string = ''; @list = split(/foo/, $string, 2)
Perl4 retourne une liste à un élément contenant la chaîne vide mais Perl5 retourne une liste vide.
Comme toujours, si certains de ces pièges sont déclarés un jour officiellement comme étant des bugs, ils seront corrigés et retirés.
VERSION FRANÇAISE
Cette traduction française correspond à la version anglaise distribuée avec perl 5.6.0. Pour en savoir plus concernant ces traductions, consultez http://www.enstimac.fr/Perl/ .TRADUCTION
Roland Trique <roland.trique@uhb.fr>RELECTURE
Personne pour l'instant.
Index
- NOM
- DESCRIPTION
- Les Pièges de Awk
- Les Pièges de C
- Les Pièges de Sed
- Les Pièges du Shell
- Les Pièges de Perl
- Les Pièges entre Perl4 et Perl5
- Pièges liés aux Corrections de Bugs, aux Désapprobations et aux Abandons
- Piège de l'Analyse Syntaxique
- Pièges Numériques
- Pièges des Types de Données Généraux
- Pièges du Contexte - contextes scalaires et de liste
- Pièges de la Précédence
- Pièges des Expressions Rationnelles Générales lors de l'utilisation de s///, etc.
- Pièges des Sous-Programmes, des Signaux et des Tris
- Pièges du Système d'Exploitation
- Pièges de l'Interpolation
- Pièges DBM
- Pièges non Classés
- VERSION FRANÇAISE
- TRADUCTION
- RELECTURE
Time: 19:00:17 GMT, December 19, 2004