Un script perl consiste en une suite de déclarations. Toutes les variables utilisateur non initialisées sont considérées comme nulles (undefined, la valeur 0 ou la chaîne "", suivant la fonction que vous appliquez).
Les commentaires sont introduits par le caractère #, et s'étendent jusqu'à la fin de la ligne. Il existe également un système de documentation plus évoluée, intégré au langage, connu sous le nom de POD (Plain Old Documentation), qui est traité dans le chapitre 7.
La première ligne du script doit contenir le chemin d'accès à l'interpréteur, soit (expression à modifier suivant la localisation de votre interpréteur) :
#! /usr/local/bin/perl
Chaque commande doit être terminée par un point-virgule ;. Elle peut être éventuellement suivie d'un modifier3.1 juste avant le ;. Les modifiers possibles sont :
if EXPR |
unless EXPR |
while EXPR |
until EXPR |
Par exemple :
print "Test reussi\n" if ($var == 1);
Une séquence de commandes simples constitue un bloc. Un bloc peut
être délimité par le fichier qui le contient, mais
généralement il est délimité par des accolades {}
.
Les structures de contrôle sont :
if (EXPR) BLOCK |
if (EXPR) BLOCK else BLOCK |
if (EXPR) BLOCK elsif (EXPR) BLOCK ... else BLOCK |
[LABEL] while (EXPR) BLOCK |
[LABEL] for (EXPR; EXPR; EXPR) BLOCK |
[LABEL] foreach VAR (ARRAY) BLOCK [LABEL] BLOCK continue BLOCK |
Attention : contrairement au C, les accolades sont obligatoires même si les blocs ne sont composés que d'une seule commande. Ceci supprime par exemple les ambiguïtés résultant de l'imbrication de plusieurs if. Il est cependant possible d'utiliser la syntaxe vue plus haut ; les exemples suivants sont équivalents :
if (!open(FICHIER, $fichier)) { die "Impossible d'ouvrir fichier: $!"; } die "Impossible d'ouvrir $fichier: $!" if (!open(FICHIER, $fichier)); open(FICHIER, $fichier) or die "Impossible d'ouvrir $fichier: $!";
La dernière syntaxe est la plus utilisée dans ce cas précis, elle fait
partie des idiomes de perl. N'oubliez jamais de tester la valeur de
retour d'une fonction susceptible de ne pas se terminer correctement,
et de toujours afficher un message d'erreur le plus précis
possible (ici, l'utilisation de la variable spéciale $!
permet d'afficher le message standard d'erreur UNIX indiquant la cause du
problème). Ce conseil ne s'applique évidemment pas qu'à perl.
La commande while exécute le bloc tant que l'expression est vraie. Le LABEL est optionnel. S'il est présent, il consiste en un identificateur, généralement en majuscules, suivi de :. Il identifie la boucle pour les commandes next (équivalent C : continue), last (équivalent C : break) et redo. Il permet ainsi de sortir simplement de plusieurs boucles imbriquées.
BOUCLE: while ($var == 0) { while ($var2 == 0) { ...; last BOUCLE if ($var3 == 1); } }
La commande for a la même syntaxe que son homonyme en C :
for ($i = 1; $i < 10; $i++) { ...; }
La commande foreach3.2 va affecter successivement à la variable VAR les éléments du tableau ARRAY. La variable VAR est implicitement locale à la boucle et retrouve sa valeur initiale - si elle existait - à la sortie de la boucle.
Si ARRAY est un tableau réel (et non une liste retournée par exemple par une fonction), il est possible de modifier chaque élément de ce tableau en affectant la variable VAR à l'intérieur de la boucle.
foreach $arg (@ARGV) { print "Argument : ", $arg, "\n"; # L'action suivante va mettre à zéro les éléments de @ARGV # C'est juste pour l'exemple, ne cherchez pas d'utilité à cette action. $arg = ""; }
Il n'y a pas de commande switch prédéfinie, car il existe plusieurs moyens d'en écrire l'équivalent :
SWITCH: { if (EXPR1) { ...; last SWITCH; } if (EXPR2) { ...; last SWITCH; } if (EXPR3) { ...; last SWITCH; } ...; }
ou encore une suite de if/elsif.
Ils reprennent en grande partie la syntaxe du C, également en ce qui concerne les règles de précédence. On se référera à la section perlop du manuel de perl5 [3] pour obtenir la liste complète des opérateurs ainsi que leur précédence.
Les opérateurs de perl ne sont pas difficiles à apprendre pour quiconque connait un peu de C, perl s'en inspirant largement.
On peut citer quelques opérateurs :
!, ~, <, >, ||, or, &&, and
La différence entre or et ||, de même qu'entre
and et &&
se situe au niveau de la priorité :
and et or sont les éléments de plus faible priorité du
langage.
La distinction la plus grande à faire par rapport au C est l'existence d'opérateurs particuliers s'appliquant aux chaînes de caractères. Le tableau 3.1 donne les équivalences entre les opérateurs s'appliquant aux nombres et ceux s'appliquant aux chaînes.
L'opérateur de comparaison (<=>
pour les nombre et cmp
pour les chaînes) renvoie -1, 0 ou 1 selon que le premier argument est
inférieur, égal ou supérieur au second.
Une chose à noter sur les opérateurs || et or : ils n'évaluent que ce qui est nécessaire (c'est-à-dire qu'ils s'arrêtent à la première valeur évaluée à TRUE), et renvoient la dernière valeur évaluée. On peut donc écrire :
$fichier = $ARGV[0] || "defaut.txt";
De même, les opérateurs &&
et and
s'arrêtent à la première valeur évaluée à FALSE :
windows_is_running() && die "Please, execute me on a *REAL* OS...";
Reprenant une des caractéristiques des shells, perl permet d'effectuer simplement différents tests sur les fichiers, sans qu'il soit nécessaire d'invoquer directement la fonction stat.
Chacun de ces opérateurs s'applique soit à un nom de fichier (une chaîne de caractères), soit à un descripteur de fichier (filehandle).
Une liste complète de ces opérateurs de tests est disponible dans la section perlfunc du manuel [3]. Le tableau 3.2 donne les principaux.
|
La plupart de ces opérateurs renvoient un résultat booléen. Les deux derniers renvoient cependant des informations plus précises (l'âge ou la taille du fichier).
$fichier = "/vmunix"; $age = -M $fichier;
Les fonctions sont déclarées par le mot-clé sub, suivi par le nom de la fonction, puis le bloc d'instructions correspondant, entre accolades
Le script étant pré-compilé avant d'être interprété, la définition de la fonction peut être effectuée indifféremment avant ou après son appel. Il peut être nécessaire de les déclarer avant (ou de faire une forward declaration à la C) si on utilise le pragma use strict;
Les arguments sont passés dans le tableau @_
. On peut définir
des variables locales à la fonction grâce aux mots-clés local()
ou my().
Le mot-clé return existe, mais est optionnel. S'il n'est pas présent, la fonction retourne la dernière valeur évaluée.
Voici un exemple :
sub factorielle { my $n = shift(@_); # ou bien encore # my $n = shift; # puisque @_ est dans ce cas pris par defaut. $n == 1 ? 1 : ( $n * &factorielle($n - 1) ); # équivalent à (notez le return implicite) # if ($n == 1) # { # 1; # } # else # { # $n * &factorielle($n - 1); # } }
my doit être utilisé de préférence à local, car my donne à la variable une étendue lexicale (lexical scoping), i.e. la variable ne sera pas visible des routines appelées ensuite. Ce n'est pas clair ? Un exemple aidera sûrement :
# On declare quelques fonctions... sub f_local { local($foo) = "Foo"; &print_foo(); } sub f_my { my($foo) = "Bar"; &print_foo(); } # Affichage de la valeur de la variable $foo sub print_foo { print $foo, "\n"; } # Début du script. print "Appel avec local sans initialisation globale : "; &f_local; print "Appel avec my sans initialisation globale : "; &f_my; # Initialisation de la variable de manière globale $foo = "Toto"; print "Appel avec local avec initialisation globale : "; &f_local; print "Appel avec my avec initialisation globale : "; &f_my; # Ce qui donne comme résultat a l'exécution : Appel avec local sans initialisation globale : Foo Appel avec my sans initialisation globale : Appel avec local avec initialisation globale : Foo Appel avec my avec initialisation globale : Toto
Ça va mieux ? Si la réponse est non, prenez une aspirine, faites-moi confiance et facilitez-vous la vie en utilisant systématiquement my.
Les noms de fonctions sont précédés du signe &
. Ce signe
est optionnel lorsqu'on fait appel à une fonction. Il est par contre
nécessaire lorsqu'on veut passer une fonction comme paramètre par
exemple.
Les parenthèses lors de l'appel ne sont pas obligatoires, même s'il n'y a aucun argument. On peut donc appeler une fonction de plusieurs manières :
&fonction(2, 4); fonction(2, 4); # Attention à la suite (man perlsub pour plus de détails): fonction2(); # fonction2 est appellée avec une liste vide en argument. &fonction2(); # Idem. &fonction2; # fonction2 est appellée avec la même liste d'arguments # que la fonction d'où l'appel est fait. Attention...
Il existe deux fonctions particulières, héritées de la syntaxe de awk, qui permettent d'avoir une plus grande maîtrise sur le déroulement du script. Ce sont les fonctions BEGIN et END.
Une fonction BEGIN est exécutée aussitôt que possible, i.e. au moment où elle est complètement définie, avant même que le reste du script ne soit analysé. S'il y a plusieurs définitions de BEGIN, elles seront exécutées dans l'ordre de leur déclaration.
Cette fonction est utilisée en particulier pour modifier le chemin de recherche des fichiers à inclure (voir le chapitre 13 sur les variables spéciales) :
BEGIN { push(@INC, "/home/aubert/lib/perl"); } # que l'on écrit plutôt à partir de la version 5.001m # use lib '/home/aubert/lib/perl';
La fonction END est exécutée le plus tard possible, généralement juste avant la sortie de l'interpréteur. Elle permet donc de faire un peu de ménage à la fin d'un programme.
perl offre un moyen de protéger les variables d'un éventuel conflit de nom grâce au mécanisme des paquetages (ou encore espaces de nommage).
Un paquetage est déclaré par le mot-clé package, suivi du nom du paquetage, et s'étend jusqu'à la fin du bloc (ou du fichier, les paquetages étant généralement définis chacun dans leur propre fichier) ou à la prochaine déclaration de paquetage..
On accède ensuite depuis l'extérieur aux variables et aux
fonctions du paquetage en les précédant du nom du paquetage suivi
de ::
. Il est possible de subdiviser les paquetages en
sous-paquetages, ad nauseam.
Le paquetage principal est appelé main.
Voici un exemple :
package Arb; $a = 1; package main; $a = 2; print $a, "\n"; # renverra 2 print $Arb::a, "\n"; # renverra 1
Les modules sont une extension du concept de paquetage : ce sont des paquetages définis dans un fichier de même nom que le module, et qui sont destinés à être réutilisés.
On inclut un module grâce à la ligne suivante :
use Module;
ce qui va en fait être interprété comme
BEGIN { require "Module.pm"; import Module; }
use effectue un import en plus du require, ce qui a pour effet d'importer les définitions des fonctions dans l'espace du paquetage courant. Voici l'explication :
require Cwd; # make Cwd:: accessible $here = Cwd::getcwd(); use Cwd; # import names from Cwd:: $here = getcwd(); require Cwd; # make Cwd:: accessible $here = getcwd(); # oops! no main::getcwd()
Une liste complète est régulièrement postée dans les news et archivée sur les sites CPAN (voir l'introduction). Un certain nombre est livré dans la distribution standard de perl, le reste se trouve également sur les sites CPAN.
Les plus importants sont ceux qui permettent de gérer différents formats de bases de données (NDBM_File, GDBM_File, ...), CGI qui fournit une interface très agréable à utiliser lors de l'écriture de scripts CGI,GetCwd qui permet de ne pas avoir à faire un appel à /bin/pwd pour obtenir le répertoire courant, Fcntl qui permet d'accéder aux constantes définies dans fcntl.h, FileHandle qui fournit des méthodes pour accéder aux filehandles, Find qui traverse une arborescence, GetOptions, POSIX qui permet d'accéder aux fonctions POSIX, Tk qui permet de construire des applications graphiques,...