NOM |
perlsyn - Syntaxe de Perl
Un script Perl est constitué d'une suite de déclarations et d'instructions.
La séquence d'instructions est exécutée une seule fois, contrairement
aux scripts sed et awk, où la séquence est exécutée pour chaque
ligne en entrée. Même si cela signifie que vous devez explicitement
boucler sur les lignes de votre (ou de vos) fichier(s)
d'entrée, cela
veut aussi dire que vous avez bien plus de contrôle sur les fichiers
et les lignes que vous manipulez (en fait, je mens -- il est possible
de faire une boucle implicite avec les options -n ou -p. Ce
n'est juste pas le comportement par défaut comme avec sed et
awk).
Perl est, en majeure partie, un langage à syntaxe libre (La seule
exception en est les déclarations de format, pour des raisons
évidentes). Le texte situé entre un caractère "#"
et la fin de la
ligne est un commentaire, et est ignoré. Si vous essayez d'utiliser
/* */
pour des commentaires dans le style du C, ce sera interprété
soit comme une division, soit comme un pattern matching, en fonction
du contexte, et les commentaires //
du C++ auront juste l'air d'une
expression régulière nulle, alors ne faites pas cela.
Les seules choses que vous devez déclarer en Perl sont les formats de
rapport et les sous-programmes -- et même des sous-programmes
indéfinis peuvent être manipulés via AUTOLOAD. Une variable contient
la valeur indéfinie (undef
) jusqu'à ce qu'on lui affecte une
valeur, qui est n'importe quoi sauf undef
. Lorsqu'il est utilisé
comme un nombre, undef
est traité comme 0
; lorsqu'il est
utilisé comme une chaîne, il est traité comme la chaîne vide, ""
;
et lorsqu'il est utilisé comme une référence qui n'a pas été affectée,
il est traité comme une erreur. Si vous validez les avertissements,
vous serez notifié de l'utilisation d'une valeur non initialisée
chaque fois que vous traiterez undef
comme une chaîne ou un
nombre. En tout cas, habituellement. Les contextes booléens
(``je-m'en-moque'') et les opérateurs tels que ++
, --
, +=
,
-=
et .=
sont toujours exempts de tels avertissements.
Une déclaration peut être mise partout où une instruction peut trouver
place, mais n'a pas d'effet sur l'exécution de la séquence
d'instructions principale - les déclarations prennent toutes effet au
moment de la compilation. Typiquement, toutes les déclarations sont
placées au début ou à la fin du script. Toutefois, si vous utilisez
des variables privées de portée lexicales créées avec my()
, vous
devrez vous assurez que la définition de votre format ou de votre
sous-programme est à l'intérieur du même bloc que le my si vous voulez
pouvoir accéder à ces variables privées.
La déclaration d'un sous-programme permet à un nom de sous-programme
d'être utilisé comme s'il était un opérateur de liste à partir de ce
point dans le programme. Vous pouvez déclarer un sous-programme sans
le définir en disant sub name
, ainsi :
sub myname; $me = myname $0 or die "can't get myname";
Notez que my fonctionne comme un opérateur de liste, pas comme un
opérateur unaire ; faites donc attention d'utiliser or
au lieu de
||
dans ce cas. Toutefois, si vous déclariez le sous-programme avec
sub myname ($)
, alors myname
fonctionnerait comme un opérateur
unaire, donc or
aussi bien que ||
feraient l'affaire.
Les déclarations de sous-programmes peuvent aussi être chargées à
l'aide de l'instruction require
ou bien à la fois chargées et
importées dans votre espace de noms via l'instruction use
. Voir
the perlmod manpage pour plus de détails.
Une séquence d'instructions peut contenir des déclarations de variables de portée lexicale, mais à part pour déclarer un nom de variable, la déclaration fonctionne comme une instruction ordinaire, et est élaborée à l'intérieur de la séquence d'instructions en tant que telle. Cela signifie qu'elle a à la fois un effet à la compilation et lors de l'exécution.
Le seul type d'instruction simple est une expression évaluée pour ses
effets de bord. Chaque instruction simple doit être terminée par un
point-virgule, à moins qu'elle ne soit la dernière instruction d'un
bloc, auquel cas le point-virgule est optionnel (Nous vous
encourageons tout de même à placer ce point-virgule si le bloc prend
plus d'une ligne, car vous pourriez éventuellement ajouter une autre
ligne). Notez qu'il existe des opérateurs comme eval {}
et do
{}
qui ont l'air d'instructions composées, mais qui ne le sont pas
(ce sont juste les TERMES d'une expression), et ont donc besoin d'une
terminaison explicite s'ils sont utilisés comme dernier élément d'une
instruction.
Toute instruction simple peut être suivie de façon optionelle par un UNIQUE modificateur, juste avant le point-virgule de terminaison (ou la fin du bloc). Les modificateurs possibles sont :
if EXPR unless EXPR while EXPR until EXPR foreach EXPR
Les modificateurs if
et unless
ont la sémantique attendue, en
supposant que vous parlez anglais. Le modificateur foreach
est un
itérateur : il place successivement $_
à chaque valeur de EXPR et
exécute l'instruction. Les modificateurs while
et until
ont la
sémantique habituelle ``while
loop'' (la condition est évaluée en
premier), sauf lorsqu'ils sont appliqués à un do
-BLOC (ou à
l'instruction désapprouvée do
-SOUS_PROGRAMME), auquel cas le bloc
s'exécute une fois avant que la condition ne soit évaluée. C'est
ainsi pour que vous puissiez écrire des boucles telles que :
do { $line = <STDIN>; ... } until $line eq ".\n";
Voir do in the perlfunc manpage. Notez aussi que l'instruction de contrôle de
boucle décrite plus tard ne fonctionnera pas dans cette
construction, car les modificateurs n'utilisent pas de labels de
boucle. Désolé. Vous pouvez toujours mettre un autre bloc à
l'intérieur (for next
) ou autour (for last
) pour réaliser ce
genre de choses. Pour next
, il suffit de doubler les accolades :
do {{ next if $x == $y; # do something here }} until $x++ > $z;
Pour last
, vous devez faire quelque chose de plus élaboré :
LOOP: { do { last if $x = $y**2; # do something here } while $x++ <= $z; }
En Perl, une séquence d'instructions qui définit une portée est appelée un bloc. Un bloc est parfois délimité par le fichier qui le contient (dans le cas d'un fichier requis, ou dans celui du programme en entier), et parfois un bloc est délimité par la longueur d'une chaîne (dans le cas d'un eval).
Mais généralement, un bloc est délimité par des accolades. Nous appellerons cette construction syntaxique un BLOC.
Les instructions composées suivantes peuvent être utilisées pour contrôler un flux :
if (EXPR) BLOC if (EXPR) BLOC else BLOC if (EXPR) BLOC elsif (EXPR) BLOC ... else BLOC LABEL while (EXPR) BLOC LABEL while (EXPR) BLOC continue BLOC LABEL for (EXPR; EXPR; EXPR) BLOC LABEL foreach VAR (LIST) BLOC LABEL foreach VAR (LIST) BLOCK continue BLOCK LABEL BLOC continue BLOC
Notez que, contrairement au C et au Pascal, tout ceci est défini en termes de BLOCs, et non d'instructions. Ceci veut dire que les accolades sont requises - aucune instruction ne doit traîner. Si vous désirez écrire des conditionnelles sans accolades, il existe plusieurs autres façons de le faire. Les exemples suivants font tous la même chose :
if (!open(FOO)) { die "Can't open $FOO: $!"; } die "Can't open $FOO: $!" unless open(FOO); open(FOO) or die "Can't open $FOO: $!"; # FOO or bust! open(FOO) ? 'hi mom' : die "Can't open $FOO: $!"; # ce dernier est un peu exotique
L'instruction if
est directe. Puisque les BLOCs sont toujours
entourés d'accolades, il n'y a jamais d'ambiguïté pour savoir à quel
if
correspond un else
. Si vous utilisez unless
à la place de
if
, le sens du test est inversé.
L'instruction while
exécute le bloc tant que l'expression est vraie
(son évaluation ne renvoie pas une chaîne nulle (""
) ou 0
ou
"0")
. Le LABEL est optionnel, et s'il est présent, il est constitué
d'un identifiant suivi de deux points. Le LABEL identifie la boucle
pour les instructions de contrôle de boucle next
, last
, et
redo
. Si le LABEL est omis, l'instruction de contrôle de boucle se
réfère à la boucle incluse dans toutes les autres. Ceci peut amener
une recherche dynamique dans votre pile au moment de l'exécution pour
trouver le LABEL. Un comportement aussi désespéré provoque un
avertissement si vous utilisez le pragma use warnings
ou l'option
-w. Contrairement à une instruction foreach
, une instruction
while
ne localise jamais implicitement une variable.
S'il existe un BLOC continue
, il est toujours exécuté juste avant
que la condition ne soit à nouveau évaluée, de la même manière que la
troisième partie d'une boucle for
en C. Il peut ainsi être utilisé
pour incrémenter une variable de boucle, même lorsque la boucle a été
continuée via l'instruction next
(qui est similaire à l'instruction
continue
en C).
La commande next
a le même rôle que l'instruction continue
en C
; elle démarre la prochaine itération de la boucle :
LINE: while (<STDIN>) { next LINE if /^#/; # elimine les commentaires ... }
La commande last
est identique à l'instruction break
en C (telle
qu'elle est utilisée dans les boucles) ; elle sort immédiatement de la
boucle en question. Le bloc continue
, s'il existe, n'est pas
exécuté :
LINE: while (<STDIN>) { last LINE if /^$/; # sort quand on en a fini avec l'en-tete ... }
La commande redo
redémarre le bloc de la boucle sans réévaluer la
condition. Le bloc continue
, s'il existe, n'est pas
exécuté. Cette commande est normalement utilisée par les programmes
qui veulent se mentir à eux-mêmes au sujet de ce qui vient de leur
être fourni en entrée.
Par exemple, lors du traitement d'un fichier comme /etc/termcap. Si vos lignes en entrée sont susceptibles de se terminer par un antislash pour indiquer leur continuation, vous pouvez vouloir poursuivre et récupérer l'enregistrement suivant.
while (<>) { chomp; if (s/\\$//) { $_ .= <>; redo unless eof(); } # now process $_ }
qui est le raccourci Perl pour la version plus explicite :
LINE: while (defined($line = <ARGV>)) { chomp($line); if ($line =~ s/\\$//) { $line .= <ARGV>; redo LINE unless eof(); # pas eof(ARGV)! } # now process $line }
Notez que s'il y avait un bloc continue
dans le code ci-dessus, il
serait exécuté même pour les lignes rejetées. Ceci est souvent utilisé
pour réinitialiser les compteurs de lignes ou les recherches de motifs
?pat?
.
# inspire par :1,$g/fred/s//WILMA/ while (<>) { ?(fred)? && s//WILMA $1 WILMA/; ?(barney)? && s//BETTY $1 BETTY/; ?(homer)? && s//MARGE $1 MARGE/; } continue { print "$ARGV $.: $_"; close ARGV if eof(); # reinitialise $. reset if eof(); # reinitialise ?pat? }
Si le mot while
est remplacé par le mot until
, le sens du test
est inversé, mais la condition est toujours testée avant la première
itération.
Les instructions de contrôle de boucle ne fonctionnent pas dans un
if
ou dans un unless
, puisque ce ne sont pas des boucles. Vous
pouvez toutefois doubler les accolades pour qu'elles le deviennent.
if (/pattern/) {{ next if /fred/; next if /barney/; # mettre quelque chose ici }}
La forme while/if BLOC BLOC
, disponible en Perl 4, ne l'est
plus. Remplacez toutes les occurrences de if BLOC
par if (do
BLOC)
.
Les boucles for
de Perl dans le style de C fonctionnent exactement
de la même façon que les boucles while
correspondantes ; cela
signifie que ceci :
for ($i = 1; $i < 10; $i++) { ... }
est la même chose que ça :
$i = 1; while ($i < 10) { ... } continue { $i++; }
(Il existe une différence mineure : la première forme implique une
portée lexicale pour les variables déclarées avec my
dans
l'expression d'initialisation).
En plus du bouclage classique dans les indices d'un tableau, for
peut se prêter à de nombreuses autres applications intéressantes. En
voici une qui évite le problème que vous rencontrez si vous testez
explicitement la fin d'un fichier sur un descripteur de fichier
interactif, ce qui donne l'impression que votre programme se gèle.
$on_a_tty = -t STDIN && -t STDOUT; sub prompt { print "yes? " if $on_a_tty } for ( prompt(); <STDIN>; prompt() ) { # faire quelque chose ici }
La boucle foreach
itère sur une liste de valeurs normale et fixe la
variable VAR à chacune de ces valeurs successivement. Si la variable
est précédée du mot-clé my
, alors elle a une portée limitée du
point de vue lexical, et n'est par conséquent visible qu'à l'intérieur
de la boucle. Autrement, la variable est implicitement locale à la
boucle et reprend sa valeur précédente à la sortie de la boucle. Si la
variable était précédemment déclaré par my
, elle utilise cette
variable au lieu de celle qui est globale, mais elle est toujours
locale à la boucle.
Le mot-clé foreach
est en fait un synonyme du mot-clé for
, vous
pouvez donc utiliser foreach
pour sa lisibilité ou for
pour sa
concision (Ou parce que le Bourne shell vous est plus familier que
csh, vous rendant l'utilisation de for
plus naturelle). Si VAR
est omis, $_
est fixée à chaque valeur. Si un élément de LIST est
une lvalue, vous pouvez la modifier en modifiant VAR à l'intérieur de
la boucle. C'est parce que la variable d'index de la boucle foreach
est un alias implicite de chaque élément de la liste sur laquelle vous
bouclez.
Si une partie de LIST est un tableau, foreach
sera très troublé
dans le cas où vous lui ajouteriez ou retireriez des éléments à
l'intérieur de la boucle, par exemple à l'aide de splice
. Ne faites
donc pas cela.
foreach
ne fera probablement pas ce que vous désirez si VAR est une
variable liée ou une autre variable spéciale. Ne faites pas cela non
plus.
Exemples :
for (@ary) { s/foo/bar/ }
for my $elem (@elements) { $elem *= 2; }
for $count (10,9,8,7,6,5,4,3,2,1,'BOOM') { print $count, "\n"; sleep(1); }
for (1..15) { print "Merry Christmas\n"; }
foreach $item (split(/:[\\\n:]*/, $ENV{TERMCAP})) { print "Item: $item\n"; }
Voici comment un programmeur C pourrait coder un algorithme en Perl :
for (my $i = 0; $i < @ary1; $i++) { for (my $j = 0; $j < @ary2; $j++) { if ($ary1[$i] > $ary2[$j]) { last; # ne peut pas sortir totalement :-( } $ary1[$i] += $ary2[$j]; } # voici l'endroit ou ce last m'emmene }
Tandis que voici comment un programmeur Perl plus à l'aise avec l'idiome pourrait le faire :
OUTER: for my $wid (@ary1) { INNER: for my $jet (@ary2) { next OUTER if $wid > $jet; $wid += $jet; } }
Vous voyez à quel point c'est plus facile ? C'est plus propre, plus
sûr, et plus rapide. C'est plus propre parce qu'il y a moins de
bruit. C'est plus sûr car si du code est ajouté entre les deux boucles
par la suite, le nouveau code ne sera pas exécuté accidentellement. Le
next
itère de façon explicite sur l'autre boucle plutôt que de
simplement terminer celle qui est à l'intérieur. Et c'est plus rapide
parce que Perl exécute une instruction foreach
plus rapidement
qu'une boucle for
équivalente.
Un BLOC en lui-même (avec ou sans label) est d'un point de vue
sémantique, équivalent à une boucle qui s'exécute une fois. Vous
pouvez donc y utilisez n'importe quelle instruction de contrôle de
boucle pour en sortir ou le recommencer (Notez que ce n'est PAS
vrai pour les blocs eval{}
, sub{}
, ou do{}
contrairement à la
croyance populaire, qui NE comptent PAS pour des boucles). Le
bloc continue
est optionnel.
La construction de BLOC est particulièrement élégante pour créer des structures case.
SWITCH: { if (/^abc/) { $abc = 1; last SWITCH; } if (/^def/) { $def = 1; last SWITCH; } if (/^xyz/) { $xyz = 1; last SWITCH; } $nothing = 1; }
Il n'y a pas d'instruction switch
officielle en Perl, car il existe
déjà plusieurs façons d'écrire l'équivalent. Vous pourriez écrire à la
place de ce qui précède :
SWITCH: { $abc = 1, last SWITCH if /^abc/; $def = 1, last SWITCH if /^def/; $xyz = 1, last SWITCH if /^xyz/; $nothing = 1; }
(Ce n'est pas aussi étrange que cela en a l'air une fois que vous avez réalisé que vous pouvez utiliser des ``opérateurs'' de contrôle de boucle à l'intérieur d'une expression, c'est juste l'opérateur virgule, normal en C).
ou
SWITCH: { /^abc/ && do { $abc = 1; last SWITCH; }; /^def/ && do { $def = 1; last SWITCH; }; /^xyz/ && do { $xyz = 1; last SWITCH; }; $nothing = 1; }
ou formaté de façon à avoir un peu plus l'air d'une instruction
switch
``convenable'' :
SWITCH: { /^abc/ && do { $abc = 1; last SWITCH; };
/^def/ && do { $def = 1; last SWITCH; };
/^xyz/ && do { $xyz = 1; last SWITCH; }; $nothing = 1; }
ou
SWITCH: { /^abc/ and $abc = 1, last SWITCH; /^def/ and $def = 1, last SWITCH; /^xyz/ and $xyz = 1, last SWITCH; $nothing = 1; }
or même, horreur,
if (/^abc/) { $abc = 1 } elsif (/^def/) { $def = 1 } elsif (/^xyz/) { $xyz = 1 } else { $nothing = 1 }
Un idiome courant pour une instruction switch
est d'utiliser
l'aliasing de foreach
pour effectuer une affectation temporaire de
$_
pour une reconnaissance pratique des cas :
SWITCH: for ($where) { /In Card Names/ && do { push @flags, '-e'; last; }; /Anywhere/ && do { push @flags, '-h'; last; }; /In Rulings/ && do { last; }; die "unknown value for form variable where: `$where'"; }
Une autre approche intéressante de l'instruction switch est de
s'arranger pour qu'un bloc do
renvoie la valeur correcte :
$amode = do { if ($flag & O_RDONLY) { "r" } # XXX : n'est-ce pas 0? elsif ($flag & O_WRONLY) { ($flag & O_APPEND) ? "a" : "w" } elsif ($flag & O_RDWR) { if ($flag & O_CREAT) { "w+" } else { ($flag & O_APPEND) ? "a+" : "r+" } } };
ou
print do { ($flags & O_WRONLY) ? "write-only" : ($flags & O_RDWR) ? "read-write" : "read-only"; };
Ou si vous êtes certain que toutes les clauses &&
sont vraies, vous
pouvez utiliser quelque chose comme ceci, qui ``switche'' sur la valeur
de la variable d'environnement HTTP_USER_AGENT
.
#!/usr/bin/perl # choisir une page du jargon file selon le browser $dir = 'http://www.wins.uva.nl/~mes/jargon'; for ($ENV{HTTP_USER_AGENT}) { $page = /Mac/ && 'm/Macintrash.html' || /Win(dows )?NT/ && 'e/evilandrude.html' || /Win|MSIE|WebTV/ && 'm/MicroslothWindows.html' || /Linux/ && 'l/Linux.html' || /HP-UX/ && 'h/HP-SUX.html' || /SunOS/ && 's/ScumOS.html' || 'a/AppendixB.html'; } print "Location: $dir/$page\015\012\015\012";
Ce type d'instruction switch ne fonctionne que lorsque vous savez que
les clauses &&
seront vraies. Si vous ne le savez pas, l'exemple
précédent utilisant ?:
devrait être utilisé.
Vous pourriez aussi envisager d'écrire un hachage de références de
sous-programmes au lieu de synthétiser une instruction switch
.
Bien que cela ne soit pas destiné aux âmes sensibles, Perl supporte
une instruction goto
. Il en existe trois formes : goto
-LABEL,
goto
-EXPR, et goto
-&NAME. Un LABEL de boucle n'est pas en vérité
une cible valide pour un goto
; c'est juste le nom de la boucle.
La forme goto
-LABEL trouve l'instruction marquée par LABEL et
reprend l'exécution à cet endroit. Elle ne peut pas être utilisée pour
aller dans une structure qui nécessite une initialisation, comme un
sous-programme ou une boucle foreach
. Elle ne peut pas non plus
être utilisée pour aller dans une structure très optimisée. Elle peut
être employée pour aller presque n'importe où ailleurs à l'intérieur
de la portée dynamique, y compris hors des sous-programmes, mais il
est habituellement préférable d'utiliser une autre construction comme
last
ou die
. L'auteur de Perl n'a jamais ressenti le besoin
d'utiliser cette forme de goto
(en Perl, à vrai dire - C est une
toute autre question).
La forme goto
-EXPR attend un nom de label, dont la portée sera
résolue dynamiquement. Ceci permet des goto
s calculés à la mode de
FORTRAN, mais ce n'est pas nécessairement recommandé si vous optimisez
la maintenance du code :
goto(("FOO", "BAR", "GLARCH")[$i]);
La forme goto
-&NAME est hautement magique, et substitue au
sous-programme en cours d'exécution un appel au sous-programme
nommé. C'est utilisé par les sous-programmes AUTOLOAD()
qui veulent
charger une autre routine et prétendre que cette autre routine a été
appelée à leur place (sauf que toute modification de @_
dans le
sous-programme en cours est propagée à l'autre routine). Après le
goto
, même caller()
ne pourra pas dire que cette routine n'a pas
été appelée en premier.
Dans presque tous les cas similaires, une bien, bien meilleure idée est
d'utiliser les mécanismes de contrôle de flux structurés comme
next
, last
, ou redo
au lieu de s'en remettre à un
goto
. Pour certaines applications, la paire eval{}
- die()
pour
le traitement des exceptions peut aussi être une approche prudente.
Perl dispose d'un mécanisme pour mélanger de la documentation avec le code source. Lorsqu'il s'attend au début d'une nouvelle instruction, si le compilateur rencontre une ligne commençant par un signe égal et un mot, comme ceci
=head1 Here There Be Pods!
Alors ce texte et tout ce qui suit jusqu'à et y compris une ligne
commençant par =cut
sera ignoré. Le format du texte en faisant
partie est décrit dans the perlpod manpage.
Ceci vous permet de mélanger librement votre code source et votre documentation, comme dans
=item snazzle($)
La fonction snazzle() se comportera de la facon la plus spectaculaire que vous pouvez imaginer, y compris la pyrotechnie cybernetique.
=cut retour au compilateur, nuff of this pod stuff!
sub snazzle($) { my $thingie = shift; ......... }
Notez que les traducteurs pod ne devraient traiter que les paragraphes débutant par une directive pod (cela rend leur analyse plus simple), tandis que le compilateur sait en réalité chercher des séquences pod même au milieu d'un paragraphe. Cela veut que le matériel secret qui suit sera ignoré à la fois par le compilateur et les traducteurs.
$a=3; =truc secret warn "Neither POD nor CODE!?" =cut back print "got $a\n";
Vous ne devriez probablement pas vous reposer sur le fait que le
warn()
sera ignoré pour toujours. Les traducteurs pod ne sont pas
tous bien élevés de ce point de vue, et le compilateur deviendra
peut-être plus regardant.
On peut aussi utiliser des directives pod pour mettre rapidement une partie de code en commentaire.
À la manière du préprocesseur C, Perl peut traiter des directives de
ligne. Avec cela, on peut contrôler l'idée que Perl se fait des noms
de fichiers et des numéros de ligne dans les messages d'erreur ou dans
les avertissements (en particulier pour les chaînes traitées par
eval()
). La syntaxe de ce mécanisme est la même que pour pour la
plupart des préprocesseurs C : elle reconnaît l'expression régulière
/^#\s*line\s+(\d+)\s*(?:\s"([^"]*)")?/\s*$/
où $1
est le numéro
de la prochaine ligne, et $2
le nom de fichier optionnel (spécifié
entre apostrophes).
Voici quelques exemples que vous devriez pouvoir taper dans votre interpréteur de commandes :
% perl # line 200 "bzzzt" # the `#' on the previous line must be the first char on line die 'foo'; __END__ foo at bzzzt line 201.
% perl # line 200 "bzzzt" eval qq[\n#line 2001 ""\ndie 'foo']; print $@; __END__ foo at - line 2001.
% perl eval qq[\n#line 200 "foo bar"\ndie 'foo']; print $@; __END__ foo at foo bar line 200.
% perl # line 345 "goop" eval "\n#line " . __LINE__ . ' "' . __FILE__ ."\"\ndie 'foo'"; print $@; __END__ foo at goop line 345.
Cette traduction française correspond à la version anglaise distribuée avec perl 5.6.0. Pour en savoir plus concernant ces traductions, consultez http://perl.enstimac.fr/.
Roland Trique <roland.trique@free.fr>
Régis Julié <Regis.Julie@cetelem.fr>, Etienne Gauthier <egauthie@capgemini.fr>
NOM |