Vous êtes sur la page 1sur 129

Guide Perl

d ebuter et progresser en Perl

Sylvain Lhullier
http://formation-perl.fr/

Version 1.2.11 ao ut 2013

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

Table des mati` eres


Licence Introduction 1 Premier pas 1.1 Ex ecuter un programme en Perl . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Les types de donn ees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 La notion de contexte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Les 2.1 2.2 2.3 2.4 2.5 2.6 scalaires Les d elimiteurs de cha nes de caract` eres . . . D eclaration et utilisation des variables . . . . La valeur undef . . . . . . . . . . . . . . . . . Op erateurs, fonctions et contexte num eriques Op erateurs, fonctions et contexte de cha nes . Les op erateurs de test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 9 11 11 12 13 15 15 16 16 17 17 18 21 21 23 24 27 27 28 29 30 30 31 31 32 33 34 34 35 35 36

3 Structures de contr ole 3.1 Les instructions de test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 Les boucles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3 Un exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Listes et tableaux 4.1 Valeurs de listes . . . . . . . . . . . . . . . . . . . . . . 4.2 Manipulation de tableaux . . . . . . . . . . . . . . . . 4.3 Aectations . . . . . . . . . . . . . . . . . . . . . . . . 4.4 Multi-d eclaration . . . . . . . . . . . . . . . . . . . . . 4.5 Retour sur laplatissement des listes . . . . . . . . . . 4.6 Absorption dune liste par un tableau . . . . . . . . . 4.7 La structure de boucle foreach . . . . . . . . . . . . . 4.8 Fonctions de manipulation de tableaux . . . . . . . . . 4.9 Lop erateur qw . . . . . . . . . . . . . . . . . . . . . . 4.10 Joindre les el ements dans une cha ne avec join . . . . 4.11 D ecouper une cha ne de caract` eres en liste avec split 4.12 Trier une liste avec sort . . . . . . . . . . . . . . . . . 4.13 S electionner des el ements avec grep . . . . . . . . . . 4.14 Appliquer un traitement ` a tous les el ements avec map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

5 Ecrire une fonction 5.1 D eclaration . . . . . . . . . . . . . . . . 5.2 Appel . . . . . . . . . . . . . . . . . . . 5.3 Visibilit e des variables . . . . . . . . . . 5.4 Une liste pour valeur de retour . . . . . 5.5 Premier exemple de fonction . . . . . . . 5.6 Autre exemple : une fonction r ecursive . 5.7 Dernier exemple : le crible dEratosth` ene 6 Tables de hachage 6.1 D eclaration et initialisation . . . . 6.2 Acc eder ` a un el ement . . . . . . . 6.3 Parcours . . . . . . . . . . . . . . . 6.4 Autovivication . . . . . . . . . . . 6.5 Existence et suppression dune clef 6.6 Tables de hachage et listes . . . . . 6.7 Exemples . . . . . . . . . . . . . . 6.8 Tranches de tableau . . . . . . . . 6.9 Tranches de table de hachage . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

37 37 38 38 39 39 40 40 43 43 44 45 46 46 47 49 51 51 53 53 54 54 55 56 57 58 58 61 61 62 62 63 64 64 65 65 65 66 66 67 68 68 70 71

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7 Manipulation de chiers 7.1 Op erateurs sur les noms de chier . . . . . . . . . . . 7.2 La fonction glob . . . . . . . . . . . . . . . . . . . . . 7.3 Premiers exemples . . . . . . . . . . . . . . . . . . . . 7.4 Ouverture de chier . . . . . . . . . . . . . . . . . . . 7.5 Lecture, ecriture et fermeture de chier . . . . . . . . 7.6 Deuxi` eme exemple . . . . . . . . . . . . . . . . . . . . 7.7 Ex ecution de commandes avec open . . . . . . . . . . 7.8 Ecrire une table de hachage sur disque avec les chiers 8 Expressions r eguli` eres 8.1 Fonctionnalit es . . . . . 8.2 Bind . . . . . . . . . . . 8.3 Caract` eres . . . . . . . . 8.4 Ensembles . . . . . . . . 8.5 Quanticateurs . . . . . 8.6 Ensembles (suite) . . . . 8.7 Regroupement . . . . . 8.8 Alternatives . . . . . . . 8.9 Assertions . . . . . . . . 8.10 R ef erences arri` eres . . . 8.11 Variables d enies . . . . 8.12 Valeurs de retour de m// 8.13 Exemples de probl` emes 8.14 Solutions des probl` emes 8.15 Choisir son s eparateur . 8.16 Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . DBM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

c Sylvain Lhullier

Guide Perl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

http://formation-perl.fr/

8.17 8.18 8.19 8.20

Quanticateurs non-gourmands . . . . . . . Substitution de variables dans les motifs . . Op erateur tr . . . . . . . . . . . . . . . . . Un dernier mot sur les expression r eguli` eres

. . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . .

72 73 73 74 75 75 76 77 79 80 82 82 84 86 88 89 91 92 92 93 93 94 95 96 96 97 98 98 99 100 100 101 102 103 103 105 107 107 108 108 109 110 112 112

9 R ef erences 9.1 R ef erences sur scalaire . . . . . . . . . . . . 9.2 Utilisation des r ef erences sur scalaire . . . . 9.3 R ef erences sur tableau . . . . . . . . . . . . 9.4 R ef erences sur table de hachage . . . . . . . 9.5 R eexions ` a propos des r ef erences . . . . . . 9.6 R ef erences anonymes vers scalaire . . . . . . 9.7 R ef erences anonymes vers tableau . . . . . . 9.8 R ef erences anonymes vers table de hachage 9.9 R ef erences anonymes diverses . . . . . . . . 9.10 Lop erateur ref . . . . . . . . . . . . . . . . 9.11 R ef erences circulaires . . . . . . . . . . . . . 9.12 R ef erences sur chiers . . . . . . . . . . . . 9.13 R ef erences sur fonctions . . . . . . . . . . . 9.14 Un dernier mot sur les r ef erences . . . . . . 10 Les modules 10.1 Utilisation dun premier module . . . 10.2 Dautres modules . . . . . . . . . . . 10.3 O` u trouver les modules ? . . . . . . . 10.4 Ecrire un premier module . . . . . . 10.5 Et les variables ? . . . . . . . . . . . 10.6 De la derni` ere ligne dun module . . 10.7 R epertoires . . . . . . . . . . . . . . 10.8 Blocs BEGIN et END . . . . . . . . . . 10.9 Introduction ` a lexport de symboles . 10.10Export par d efaut de symboles . . . 10.11Export individuel de symboles . . . . 10.12Export par tags de symboles . . . . 10.13Exemple complet dexports . . . . . 10.14Fonctions inaccessibles . . . . . . . . 10.15Documentation des modules . . . . . 10.16Un dernier mot sur les modules . . . 11 Programmation objet 11.1 Vous avez dit objet ? . . 11.2 Pr eparatifs . . . . . . . 11.3 Ecrire un constructeur . 11.4 Appeler le constructeur 11.5 Manipulations de lobjet 11.6 Plusieurs constructeurs . 11.7 Ecrire une m ethode . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

http://formation-perl.fr/

Guide Perl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

c Sylvain Lhullier

11.8 Reparlons des champs . . . . . 11.9 Composition . . . . . . . . . . 11.10Destruction dun objet . . . . . 11.11H eritage . . . . . . . . . . . . . 11.12Classes dun objet . . . . . . . 11.13Champs et m ethodes statiques 11.14Exemple complet . . . . . . . . Conclusion Lauteur

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

113 114 117 117 120 120 122 127 129

Licence
c 2002-2013 Sylvain Lhullier Version 1.2.11 - ao ut 2013 Vous trouverez la derni` ere version de ce document ` a cette adresse : http://formation-perl.fr/guide-perl.html Ce document est y disponible en version HTML, PDF et ePUB. Permission est accord ee de copier et distribuer ce document sans modication et ` a condition de fournir un lien vers la page http ://formation-perl.fr/guide-perl.html

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

Introduction
Ce guide Perl sert de support ` a la formation Perl. Cest une introduction au langage initialement ecrite pour Linux Magazine France et parus dans les num eros de juillet 2002 ` a f evrier 2003 puis r e- edit e au printemps 2004 dans les Dossiers Linux 2. Depuis, ce document est r eguli` erement mis ` a jour. Ce langage tr` es riche et puissant est une bo te ` a outils fort utile dans de nombreuses situations : administration syst` eme, manipulation de textes (mail, logs, linguistique, g en etique), programmation r eseau (CGI, mod_perl, etc), bases de donn ees, interfaces graphiques etc. Ses nombreuses biblioth` eques le rendent vite irrempla cable aux yeux de ceux qui en acqui` erent la ma trise. La prise en main du langage est facilit ee par de nombreux rapprochements possibles avec le C, le shell ou awk. Sa conformit e POSIX en fait un alli e indispensable ` a ladministrateur syst` eme. Ce document a la d elicate ambition de sadresser ` a la fois au programmeur d ebutant et ` a celui qui conna trait bien le C ou le shell. Que le premier me pardonne de faire des comparaisons avec dautres langages et de taire peut- etre certains points qui me semblent evidents. Que le second mexcuse de passer ` a son go ut trop de temps ` a expliquer des notions qui lui semblent simples ; les choses se corseront au fur et ` a mesure de la lecture ... Le d ebut du document aborde des notions importantes en Perl et n ecessaires pour bien comprendre la suite. Vous serez sans doute un peu d e cu de ne pas faire des choses extr emement puissantes imm ediatement, mais patience : qui veut aller loin m enage sa monture. Pour vous mettre en app etit, voici un petit exemple de la concision de Perl et de sa puissance : my @r = qw(Un programme Perl est 5 fois plus rapide a ecrire); map { tr/A-Z/a-z/; s/\d//g; } @r; foreach (sort grep !/^$/, @r) { print "$_\n"; } Ce programme cr e e une liste de mots (la phrase de la premi` ere ligne), transforme les majuscules de ces mots en minuscules, supprime les chires appartenant aux mots, supprime les mots vides et ache la liste des mots ainsi transform es dans lordre lexical. Et dites-vous que vous aurez en main toutes les notions n ecessaires avant la n de la lecture du document ... Perl est un langage de haut niveau, qui a la pr etention de combiner les avantages de plusieurs autres langages. Premi` ere facilit e, il g` ere lui m eme la m emoire (ramasse-miettes, pas de limite de buers, pas dallocation ` a faire etc). De plus, les tableaux, les listes et les tables de hachage sont natifs, ils sont int egr es ` a la grammaire m eme du langage. R ecursivit e, modularit e, programmation objet, acc` es au syst` eme et au r eseau, interface avec le C, avec (g)Tk, avec Apache sont aussi au menu. Et souvenez-vous que lune des devises de Perl est : there is more than one way to do it (il y a plus dune fa con de le faire).

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

10

Chapitre 1

Premier pas
1.1 Ex ecuter un programme en Perl

Il existe principalement deux types de langages : les langages compil es et les langages interpr et es. Pour les premiers (on retrouve par exemple dans cette cat egorie le C et le C++), il existe deux phases distinctes : la compilation des sources par un compilateur (gcc par exemple) puis lex ecution du programme ainsi obtenu par le syst` eme. Pour les seconds (les shells par exemple), il ny a pas de phase de compilation, un interpr eteur va lire le code et directement agir en fonction de celui-ci. Perl est un langage ` a la fois interpr et e et compil e. Il ny a pas de phase interm ediaire de compilation car linterpr eteur (qui se nomme perl en minuscules, alors que le langage prend une majuscule) compile le code sans que le programmeur ne sen rende compte, puis lex ecute. Linterpr eteur se charge donc ` a la fois de la compilation et de lex ecution. Il existe trois fa cons distinctes de faire tourner un programme Perl : Mettre du code en ligne de commande. On peut ecrire ceci dans un shell : perl -w -e print("Salut Larry\n"); Le programme perl est lanc e avec du code Perl comme argument, directement sur la ligne de commande (option -e). En anglais, on appelle cela un one-liner (pas de traduction etablie en fran cais, peut- etre monoligne, uniligne, soliligne ...). Le code sera alors ex ecut e: la fonction print ache son argument. Salut Larry Ce nest pas la fa con la plus courante d ecrire du Perl, mais cest une mani` ere facile et rapide de faire un petit calcul ou de faire appel ` a une fonction Perl. Loption -w, que lon retrouvera tout le temps, est positionn ee dans le but que linterpr eteur ache des messages davertissement (warnings) ` a di erents propos : il indique les variables utilis ees une seule fois ou utilis ees avant d etre initialis ees, il signale les red enitions de fonctions, etc. Pour marquer les esprits, on pourrait faire un parall` ele avec loption -Wall de gcc pour ceux qui connaissent. Je vous conseille donc de toujours utiliser cette option. La seconde mani` ere de faire est de cr eer un chier salut.pl contenant : print("Salut Larry\n"); Puis de lancer la commande suivante depuis un shell : perl -w salut.pl Le programme perl est lanc e avec le nom du chier en argument. Il va alors lire le contenu de ce chier et linterpr eter comme du code Perl.

11

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

La troisi` eme fa con de faire est de cr eer un chier salut2.pl contenant : #!/usr/bin/perl -w print("Salut Larry\n"); La premi` ere ligne est le shebang, bien connu des habitu es des scripts en shell. Cette ligne (qui doit toujours etre la premi` ere du chier) indique au syst` eme dexploitation le chemin de lex ecutable ` a lancer pour interpr eter ce chier. Le premier caract` ere doit etre un di` ese, ce qui a pour eet que cette ligne est consid er ee comme un commentaire Perl par linterpr eteur. Ensuite un point dexclamation. Puis le chemin absolu vers lex ecutable perl (` a adapter selon votre installation, voir ce que r epond type perl ou which perl). Enn les options que lon souhaite passer ` a linterpr eteur. Il faut maintenant rendre ce chier ex ecutable et le lancer : chmod +x salut2.pl ./salut2.pl Gr ace ` a la ligne de shebang, le syst` eme le reconna t donc comme un programme n ecessitant un interpr eteur pour etre ex ecut e. Cet interpr eteur est lanc e avec pour param` etres les options fournies dans le shebang ainsi que le nom du chier. Cette derni` ere fa con de faire est sans doute la plus courante d` es que lon ecrit un programme qui sera utilis e plusieurs fois. Avant de continuer, quelques commentaires sur la syntaxe Perl. Except e dans les cha nes de caract` eres, la pr esence ou labsence despaces, de sauts de ligne ou de tabulations ne change pas le comportement du programme, lindentation est libre. Comme on vient de le voir, une instruction Perl est termin ee par un point-virgule. Les fonctions peuvent prendre leurs arguments entre parenth` eses (comme en C) ; il faut aussi savoir que lon peut se passer de ces parenth` eses. On aurait pu ecrire : print "Salut Larry\n"; Les deux syntaxes sont tout ` a fait valides. Dans les cas simples (appel dune fonction avec un ou deux param` etres), on pourra omettre les parenth` eses. Dans le cas de combinaisons plus complexes (plusieurs fonctions appel ees en param` etre dautres fonctions, listes en argument...), je vous conseille de les mettre pour lever toute ambigu t e possible. Un commentaire commence par un di` ese (#) et se termine en n de ligne (comme en shell). On constitue un bloc dinstructions en les regroupant dans des accolades {} comme en C. Des exemples suivront.

1.2

Les types de donn ees

Perl est un langage faiblement typ e, ce qui signie quune donn ee naura pas sp ecialement de type : les nombres, les cha nes de caract` eres, les bool eens etc seront tous des scalaires et ne seront di erenci es que par leur valeur et par le contexte de leur utilisation. Il existe principalement trois structures de donn ees : les scalaires, les tableaux et les tables de hachage. Chaque structure de donn ees est li ee ` a un caract` ere sp ecial (lire la suite). Un scalaire est une donn ee atomique. Par exemple, ce pourrait etre une cha ne de caract` eres (suite de caract` eres) ou un nombre (entier ou ottant). On verra plus tard que les r ef erences (cest-` a-dire les pointeurs de Perl) sont des scalaires, m eme sils sont un peu sp eciaux. Les variables scalaires sont pr ec ed ees dun dollar ($) : $x est donc une variable scalaire.

12

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

Les tableaux permettent de stocker plusieurs scalaires en les indi cant. De la m eme fa con quen C, on pourra demander le i` eme el ement dun tableau, i etant un entier. Lacc` es ` a un el ement sera en temps constant, il ne d ependra pas de son indice dans le tableau. Les variables de type tableau sont pr ec ed ees dun arobase (@) : @t est donc une variable de type tableau. Lorsque lon utilise la syntaxe @t, on d esigne la totalit e du tableau ; si nous voulons parler du i` eme el ement, nous allons manipuler un scalaire, il faudra donc pr exer par un dollar : $t[4] est l el ement dindice 4 dans le tableau @t, les crochets [] d elimitant lindice (nul besoin de mettre larobase, Perl sait gr ace aux crochets quil sagit dun el ement de tableau). Une table de hachage en Perl est une structure de donn ees permettant dassocier une cha ne de caract` eres ` a un scalaire ; on parle de clefs et de valeurs : une valeur est associ ee ` a une clef. Naturellement, dans une m eme table de hachage les clefs sont uniques ; les valeurs, par contre, peuvent etre tout ` a fait quelconques. Les variables de type table de hachage sont pr ec ed ees dun caract` ere pourcent (%) : %h est donc une variable de type table de hachage. De la m eme fa con que pour les tableaux, %h repr esente la totalit e de la table de hachage ; acc eder ` a un el ement se fera avec un dollar : $h{uneclef} est l el ement de clef uneclef de la table de hachage %h, les accolades {} d elimitant la clef. Fonctionnellement, on pourrait voir une table de hachage comme un tableau dont les indices peuvent etre non-num eriques. Nous reviendrons sur ces types de donn ees tout au long du document.

1.3

La notion de contexte

Chaque op eration en Perl est evalu ee dans un contexte sp ecique. La fa con dont lop eration se comportera peut d ependre de ce contexte. Il peut jouer un r ole important sur le type des op erandes dune expression et/ou sur le type de sa valeur. Il existe deux contextes principaux : le contexte scalaire et le contexte de liste. Par exemple, une aectation dune expression ` a une variable de type scalaire evaluera cette expression dans un contexte scalaire ; de la m eme fa con, une aectation ` a une variable de type liste evaluera le membre droit en contexte de liste. Autre exemple que je d etaillerai un peu plus loin, les op erateurs de test imposent un contexte pr ecis a ` leurs op erandes. Certains op erateurs et fonctions savent dans quel contexte ils sont appel es et renvoient un scalaire ou une liste selon ce contexte dappel. La fonction grep en est un bon exemple (nous verrons cela lorsque nous parlerons des listes). On peut forcer le contexte dune expression au contexte scalaire en utilisant lop erateur scalar(). Il existe plusieurs contextes scalaires : le contexte de cha nes de caract` eres, le contexte num erique et le contexte tol erant. Par exemple une addition impose un contexte num erique ` a ses deux op erandes ; cela signie que les op erandes sont transform es en nombres quels que soient leur type et leur valeur (reste ensuite au programmeur ` a savoir ce que vaut une liste ou une cha ne quelconque en contexte scalaire...). Le contexte de cha nes est un contexte o` u, comme son nom lindique, les scalaires seront consid er es comme des cha nes de caract` eres. Le contexte tol erant nest ni de cha nes ni num erique, il est simplement scalaire. Il existe aussi un contexte vide (void context in english) qui correspond au fait que la valeur dune expression est ignor ee. Cest par exemple le contexte utilis e lorsque lon appelle une fonction sans r ecup erer sa valeur de retour, comme lappel ` a la fonction print dans la section pr ec edente. Ce contexte napporte pas grand chose au programmeur, mais permet ` a linterpr eteur Perl appel e avec loption -w de pr evenir en cas dusage dune expression sans eet de bord en contexte vide (cest-` a-dire une expression qui ne fait rien et dont on ne se sert pas). Par exemple,

13

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

la ligne dinstructions suivante : "Bonjour"; provoque le message suivant : Useless use of a constant in void context at prog.pl line 5. Vous aurez loccasion de manipuler les contextes tout au long de cette introduction au langage. M eme si cela nest pas forc ement explicite ` a chaque instant, le contexte est souvent important.

14

Chapitre 2

Les scalaires
Les scalaires sont le type de donn ees atomique de Perl, dit autrement un scalaire est une donn ee atome. Cela signie que la granularit e de donn ees ne va pas au-del` a. Comme dit pr ec edemment, une variable scalaire peut contenir une cha ne de caract` eres (String en Java et autres) ou un nombre (entier ou nombre ` a virgule ottante : int ou float en C, C++ etc) ; je ne rentrerai pas dans lexplication de ce ou. Voici des exemples de scalaires corrects : 12 "texte" texte -3.14 3e9 Contrairement au C o` u le caract` ere \0 de code ASCII 0 (z ero) est le marqueur de n de cha ne, en Perl les cha nes de caract` eres peuvent sans souci contenir ce caract` ere : "a\0f" est une cha ne comportant 3 caract` eres. On naura donc aucun mal ` a traiter des chiers binaires en Perl.

2.1

Les d elimiteurs de cha nes de caract` eres

Les cha nes de caract` eres ont, comme en shell, principalement deux d elimiteurs possibles : les doubles quotes (") et les simples quotes (). Elles nont pas le m eme r ole : Dans une cha ne d elimit ee par des doubles quotes, le contenu est interpr et e: "Bonjour\n" est une cha ne suivie dune n de ligne. De la m eme mani` ere "\t" est une tabulation (il existe dautres caract` eres sp eciaux). Dans "Bonjour $prenom" la variable $prenom est substitu ee par son contenu ; cest-` a-dire que ce scalaire contiendra la cha ne Bonjour, suivie dune espace, suivie du contenu de la variable $prenom. Sil faut accoler un texte imm ediatement apr` es une variable, on utilisera les accolades pour d elimiter le nom de la variable ; par exemple dans "il ${prefixe}donn$suffixe", cest bien la variable $prefixe qui sera utilis ee, puis la cha ne donn et enn la variable $suffixe. On notera que ces accolades nont rien ` a voir avec celles des tables de hachage. Certains caract` eres doivent etre prot eg es avec un anti-slash (\) si on veut les faire appara tre tels quels dans la cha ne de caract` eres ; ce sont les quatre suivants : " $ @ \. La cha ne "\$v" ne contient donc pas la valeur dune suppos ee variable $v mais contient le caract` ere dollar et le caract` ere v. Dans une cha ne d elimit ee par des simples quotes, aucune interpr etation du contenu na lieu : Bonjour\n est une cha ne comportant les caract` eres B o n j o u r \ et n, cest-` a-dire 9 caract` eres (notez que \n comporte 2 caract` eres).

15

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

La cha ne Bonjour $prenom ne comporte pas le contenu dune hypoth etique variable $prenom mais le caract` ere dollar suivi de la cha ne prenom. Puisque les variables ne sont pas substitu ees, les caract` eres ` a prot eger sont moins nombreux. Le caract` ere a besoin d etre pr ec ed e dun anti-slash pour appara tre tels-quels dans une cha ne d elimit ee par de simples quotes. Il en est de m eme pour le caract` ere \ si celui-ci est suivi dun autre caract` ere \ Les nombres nont quant ` a eux pas besoin de d elimiteurs pour etre manipul es : $x = 10.2 aecte le nombre 10,2 ` a la variable $x.

2.2

D eclaration et utilisation des variables

En Perl, il nest pas obligatoire de d eclarer les variables. Par d efaut, lusage dune variable la cr ee ; si cest un scalaire, elle aura la valeur undef (lire plus loin) ; sil sagit dune liste ou une table de hachage, elle sera vide. Pour d evidentes raisons de relecture et pour eviter des erreurs b etes, je vous conseille de toujours d eclarer vos variables avant de les utiliser (sauf peut- etre dans le cas de scripts de quelques lignes). Pour d eclarer une variable, il nous faut utiliser my : my $x; my $y = 10; my $z = "hello"; Nous venons ici de d eclarer trois variables scalaires. Ces variables seront visibles (accessibles) dans toute la suite du bloc ainsi que dans les sous-blocs (comme en C) ; comme on sy attend, elles ne le seront par contre pas dans les fonctions appel ees depuis ces blocs. Le placement des d eclarations est libre dans le bloc (comme en C++), il nest pas n ecessaire de les mettre en d ebut de bloc. Voici quelques exemples dutilisation de variables (on suppose quelles sont d ej` a d eclar ees) : $x = $y + 3; $prenom = "Jules"; $phrase = "Bonjour $prenom"; print("$phrase\n"); Cette derni` ere ligne achera ` a l ecran Bonjour Jules suivi dun caract` ere de nouvelle ligne. Les habitu es du shell noteront bien quune variable est toujours pr ec ed ee de son dollar m eme si elle est ` a gauche dun egal daectation.

2.3

La valeur undef

Cest une valeur particuli` ere signiant non-d eni. Cest aussi la valeur par d efaut des variables scalaires non initialis ees : my $x; est equivalent ` a my $x=undef; On peut aecter cette valeur ` a une variable apr` es son initialisation : $x=undef; ou undef($x); Si lon veut tester quune variable scalaire vaut ou non undef, il faut utiliser la fonction defined : if(defined($x))... Ce test est vrai si $x est d enie, cest-` a-dire si elle ne vaut pas undef. Une erreur classique est d ecrire : *incorrect* if($x!=undef) *incorrect* Ne surtout pas tenter de comparer une variable ` a undef, car cela ne fait pas ce quon attend.

16

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

La valeur undef est une valeur fausse pour les tests. Le test if( $x ) ... est faux si $x est non-d enie. Mais comme on le verra plus tard, il est egalement faux si $x vaut 0 (z ero) ou bien la cha ne vide. Donc un test if( $x ) ... est potentiellement dangereux. Pour tester si une variable est d enie, une seule bonne fa con : if(defined($x))...

2.4

Op erateurs, fonctions et contexte num eriques

Sur les nombres, les op erateurs classiques sont disponibles : + - / * % ; ce dernier op erateur % est le modulo, cest-` a-dire le reste de la division enti` ere du premier op erande par le second. Notez que la division eectu ee par lop erateur / nest pas une division enti` ere mais une division r eelle, cela m eme si ses op erandes sont entiers (2/3 vaut 0.6666...) ; si vous voulez eectuer une division enti` ere, il vous faut tronquer le r esultat de la division pr ec edente avec int() : lexpression int($x/$y) vaut le quotient de la division enti` ere de $x par $y (pour des nombres positifs). Des raccourcis existent : += -= *= /= %=. Ces op erateurs sont ` a la fois une op eration arithm etique et une aectation : $x+=3 est equivalent ` a $x=$x+3 mais en plus synth etique : on ajoute 3 ` a $x. Linstruction $y*=5 multiplie $y par 5. Il existe aussi des auto-incr ementeurs et des auto-d ecr ementeurs : ++ et -- qui peuvent etre plac es avant ou apr` es une variable : ils ajoutent ou d eduisent 1 ` a cette variable. $x++ ` a le m eme eet que $x+=1 ou que $x=$x+1. Lop erateur ** correspond ` a la puissance : 2**10 vaut 1024. Les fonctions suivantes manipulent les nombres : sin($x) cos($x) renvoient le sinus et le cosinus de $x. exp($x) log($x) renvoient e puissance $x et le logarithme en base e de $x. abs($x) renvoie la valeur absolue de $x. sqrt($x) renvoie la racine carr ee de $x. Voici quelques r` egles de conversion en contexte num erique. Les cha nes de caract` eres repr esentant exactement un nombre sont converties sans probl` eme ; "30" + "12" vaut 42. Dans tous les autres cas ( enum er es dans ce qui suit), loption -w provoquera un message davertissement. Les scalaires commen cant par un nombre sont converties en ce nombre : "34.2blabla" vaudra 34,2. Les autres valeurs scalaires (y compris undef) sont converties en 0. Conclusion : utilisez toujours loption -w !

2.5

Op erateurs, fonctions et contexte de cha nes

Les cha nes de caract` eres ont aussi leurs op erateurs. Le point (.) permet de concat ener deux cha nes : linstruction $x="bon"."jour" a pour eet daecter la cha ne bonjour ` a $x (pas de gestion de la m emoire ` a eectuer). Cet op erateur est, entre autres cas, utile lorsque certaines parties de la cha ne sont les valeurs de retour de fonctions ; en eet, il sut souvent dutiliser les substitutions eectu ees dans les cha nes d elimit ees par des doubles quotes pour concat ener deux cha nes. Lop erateur x est la multiplication pour les cha nes de caract` eres : "bon"x3 vaut "bonbonbon". Fort sympathique ... Les raccourcis suivants peuvent etre utilis es : .= x= Lexpression $x.=$y est equivalente ` a $x=$x.$y et concat` ene donc $y ` a la n de $x. Voici un certain nombre de fonctions utiles qui manipulent les cha nes de caract` eres :

17

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

length($x) renvoie la longueur de la cha ne $x. Par exemple length("bonjour\n") vaut 8 et length(bonjour\n) vaut 9. chop($x) supprime le dernier caract` ere de la cha ne $x (la variable $x est modi ee). Ce caract` ere est renvoy e par la fonction : $c = chop($l); chomp($x) supprime le dernier caract` ere de $x sil sagit dune n de ligne (la variable $x est modi ee). Cette fonction peut prendre plusieurs arguments, chacun subira un sort similaire. Ne pas ecrire *incorrect* $x=chomp($x) *incorrect* car chomp renvoie le nombre de caract` eres supprim es. Cette fonction nous sera tr` es utile lorsque nous lirons des chiers ligne ` a ligne. reverse($x) en contexte scalaire, renvoie la cha ne compos ee des caract` eres de $x dans lordre inverse. Par exemple $v = reverse("bonjour\n") aecte "\nruojnob" ` a $v. On rencontrera aussi cette fonction chez les listes (son comportement d epend du contexte). substr($x,oset,length) vaut la sous-cha ne de position oset et de longueur length. Les positions commencent ` a0: substr("bonjour",1,2) vaut on. La longueur peut etre omise, dans ce cas toute la partie droite de la cha ne est s electionn ee. Cette fonction peut etre une lvalue, cest-` a-dire quon peut lui aecter une valeur (lvalue pour left-value : ` a la gauche du signe egal de laectation) : my $v = "salut toi"; substr($v,5,1) = "ation ` a "; $v vaut alors "salutation ` a toi". Cest l` a que lon se rend compte que Perl g` ere vraiment la m emoire tout seul ! index($cha^ ne,$sousCha^ ne,$position) renvoie la position de la premi` ere occurrence de $sousCha^ ne dans $cha^ ne. Le troisi` eme param` etre, sil est fourni, indique la position du d ebut de la recherche ; sinon la recherche part du d ebut de la cha ne (position 0). rindex($cha^ ne,$sousCha^ ne,$position) eectue la m eme recherche que la fonction index mais en partant de la n de la cha ne (la recherche est eectu ee de droite ` a gauche). En contexte de cha ne de caract` eres, undef vaut la cha ne vide ; loption -w provoquera un message davertissement. Dans ce contexte, un nombre vaut la cha ne de sa repr esentation d ecimale.

2.6

Les op erateurs de test

Les bool eens (type de donn ees ayant pour seules valeurs vrai et faux) nexistent pas en tant que tels en Perl, on utilise les scalaires pour eectuer les tests (comme C le fait avec les entiers). Il me faut donc pr eciser quelles sont les valeurs scalaires vraies et quelles sont les fausses. Les valeurs fausses sont : 0, cest-` a-dire lentier valant z ero, "0" ou 0, cest-` a-dire la cha ne de caract` eres ne comportant que le caract` ere z ero (pas le caract` ere \0 de code ASCII z ero, mais 0 de code 48), la cha ne vide :"" ou (ce qui est la m eme chose), undef. Toutes les autres valeurs sont vraies, par exemple : 1, -4.2, "blabla", etc. La plus originale est "00" qui vaut lentier 0 dans les op erations num eriques, mais qui est vraie ... Il existe deux cat egories dop erateurs de test : ceux pour lesquels on impose un contexte

18

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

num erique aux op erandes et ceux pour lesquels on impose un contexte de cha ne de caract` eres. Par exemple == teste l egalit e de deux nombres (contexte num erique) et eq teste l egalit e de deux cha nes (contexte de cha ne). ("02"=="2") est vrai alors que ("02" eq "2") est faux. La di erence est encore plus agrante pour les op erateurs dinf eriorit e et de sup eriorit e ; < teste lordre entre nombres, lt teste lordre ASCII entre cha nes ; donc (9<12) est vrai alors que (9 lt 12) est faux car 9 est apr` es 1 dans la table ASCII. Confondre ou m elanger ces deux types dop erateurs est une erreur tr` es courante que font les d ebutants, ainsi que les initi es qui ne font pas attention ... Sachez que loption -w permet souvent de rep erer ces situations. Voici un tableau d ecrivant les op erateurs de tests : contexte impos e egalit e di erence inf eriorit e sup eriorit e inf ou egal sup ou egal comparaison num erique == != < > <= >= <=> de cha nes eq ne lt gt le ge cmp

Les op erateurs bool eens classiques sont pr esents : expr1&&expr2 est vrai si expr1 et expr2 sont vraies (si expr1 est faux expr2 nest pas evalu ee), expr1expr2 est vrai si expr1 ou expr2 est vraie (si expr1 est vrai expr2 nest pas evalu ee), !expr est vrai si expr est fausse. Il existe aussi les op erateurs and or et not. Ceux-ci ont la m eme table de v erit e que les pr ec edents, mais sont dune priorit e plus faible. Les deux op erateurs cit es ` a la derni` ere ligne du tableau ne sont pas des op erateurs de test mais des op erateurs de comparaison ; ils sont pr esents dans ce tableau en raison des similitudes quils ont avec les op erateurs de test en ce qui concerne le contexte impos e aux op erandes. Ces op erateurs renvoient un nombre qui d epend de lordre entre leurs deux param` etres. Lexpression ($x<=>$y) est : positive si $x est un nombre plus grand que $y, n egative si $x est un nombre plus petit que $y, nulle si $x et $y sont des nombres egaux. Cet op erateur <=> est surnomm e spaceship (vaisseau spatial en fran cais) en raison de sa forme ;-) ... Pour lop erateur cmp, la comparaison se fait sur lordre des cha nes selon la table ASCII. Ces op erateurs seront fort utiles lorsque nous parlerons de la fonction sort qui eectue le tri des listes.

19

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

20

Chapitre 3

Structures de contr ole


Ici nous allons apprendre ` a contr oler le ux des instructions en Perl. En eet un programme nest pas quune simple suite dinstructions se d eroulant lin eairement une fois et une seule. Il faut savoir que Perl (tout comme le C) permet dindenter notre code comme bon nous semble, les exemples qui suivent comportent donc des choix personnels dindentation qui peuvent diverger des v otres.

3.1

Les instructions de test

Ces instructions permettent de conditionner lex ecution dinstructions ` a la valeur de v erit e dune expression. Linstruction la plus usit ee est le if (si en fran cais) qui a besoin dune expression et dun bloc dinstructions. Cette expression sera evalu ee en contexte scalaire et servira de condition ; si elle est v eri ee, le bloc dinstructions sera ex ecut e. if( $x != 1 ) { print "$x\n"; } Ce code Perl a pour eet dacher la variable $x si elle ne vaut pas 1. Plusieurs instructions peuvent etre plac ees dans le bloc, elles seront alors toutes ex ecut ees si la condition est vraie. Notez que les accolades ({}) sont obligatoires pour d elimiter le bloc (contrairement au C). Il est possible dex ecuter dautres instructions dans le cas o` u la condition est fausse. On utilise pour cela lop erateur else (sinon en fran cais) qui, lui aussi, est suivi dun bloc dinstructions : if( $x == $y ) { print "\$x et \$y sont egaux\n"; } else { print "\$x et \$y sont diff erents\n"; } Le fait que les accolades sont obligatoires a pour cons equence que le programme suivant est incorrect : if( condition1 ) { instructions1

21

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

} else # Attention ce code est incorrect if { instructions2 } Il faut en eet entourer le second if par des accolades comme ceci : if( condition1 ) { instructions1 } else { if( condition2 ) { instructions2 } } Si le programmeur se sent des envies de devenir sylviculteur en plantant des for ets difs, il faudrait donc quil utilise de multiples couples daccolades. Pour ne pas rencontrer les m emes probl` emes que le Lisp en rencontre pour les parenth` eses ;-), Perl met ` a notre disposition linstruction elsif qui permet de cumuler le comportement dun else et dun if tout en faisant l economie dun couple daccolades : if( condition1 ) { instructions1 } elsif( condition2 ) { instructions2 } else { instructions3 } Linstruction switch de C na pas d equivalent direct en Perl ; il faut pour cela planter une for et difs, comme dans lexemple pr ec edent. Mais Perl nen reste pas l` a. Il existe une syntaxe tr` es utilis ee pour eectuer une unique instruction si une condition est v eri ee : instruction if( condition ); On parle ici de modicateur dinstruction. Pour cette syntaxe, les parenth` eses sont optionnelles autour de la condition, mais je vous conseille de les mettre syst ematiquement pour une meilleure lisibilit e. Le code suivant ache la variable $s si elle est d enie : print "$s\n" if( defined($s) ); On notera que cette syntaxe ne permet pas lusage dun else. Linstruction unless a exactement le m eme r ole que le if, ` a la di erence que les instructions seront eectu ees si la condition est fausse (il est aussi moins d epaysant den faire des for ets). unless( expression ) est equivalent ` a if( !(expression) ) dans toutes les constructions pr ec edemment cit ees.

22

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

3.2

Les boucles

Les boucles permettent dex ecuter plusieurs fois les m emes instructions sans avoir ` a ecrire plusieurs fois les m emes lignes de code. Bien souvent nous avons besoin de modier une variable a chaque ` etape ; dans ce cas nous utiliserons linstruction for (pour en fran cais) dont voici la syntaxe : for( initialisation; condition; incr ement ) { instructions; } La boucle for prend trois expressions entre parenth` eses : la premi` ere expression permet dinitialiser la variable de boucle, la deuxi` eme est une condition de continuation et la derni` ere permet de modier la valeur de la variable de boucle. Quand la boucle d emarre, la variable est initialis ee (expression 1) et le test est eectu e (expression 2). Si cette condition est v eri ee, le bloc dinstructions est ex ecut e. Quand le bloc se termine, la variable est modi ee (expression 3) et le test est de nouveau eectu e (expression 2). Si la condition est v eri ee, le bloc dinstructions est r e-ex ecut e avec la nouvelle valeur pour la variable de boucle. Tant que le test reste vrai, le bloc dinstructions et lexpression de modication de la variable ` larr sont ex ecut es. A et de la boucle, les instructions qui suivent la boucle sont ex ecut ees. Lexemple suivant ache tous les entiers pairs de 0 ` a 20 inclus : for( my $i=0; $i<=20; $i+=2 ) { print "$i\n"; } La boucle sarr ete lorsque $i vaut 22. Cette variable est d eclar ee dans le bloc dinitialisation et nexiste donc que dans la boucle. Notez quil est tout ` a fait possible dutiliser une variable pr eexistante comme variable de boucle (et donc de ne pas faire de my dans la partie initialisation) ; dans ce cas, apr` es ex ecution de la boucle, la variable vaut la derni` ere valeur qui lui a et e aect ee au cours de la boucle. Une autre boucle existe : la boucle while (tant que en fran cais) dont voici la syntaxe : while( condition ) { instructions; } Les instructions sont eectu ees tant que la condition est vraie. La partie initialisation doit avoir et e eectu ee avant la boucle ; la partie modication de la variable doit avoir lieu dans le bloc dinstructions. Lexemple suivant ache lui aussi les entiers pairs de 0 ` a 20 : my $i = 0; while( $i <= 20 ) { print "$i\n"; $i+=2; }

23

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

La seule di erence entre les deux exemples est le fait que, dans le cas du while, la variable $i existe apr` es la boucle. Comme pour le if, certaines facilit es sont oertes pour le while. Tout dabord, la syntaxe suivante est correcte : instruction while( condition ); Elle permet dex ecuter plusieurs fois une instruction et une seule tant quune condition est v eri ee. Ensuite, il existe une instruction until (jusqu` a en fran cais) qui a la m eme syntaxe que le while mais qui demande une condition darr et (comme unless pour if) : until(condition) est equivalent ` a while(!(condition)) Lors de lex ecution dune boucle, il est fr equent de rencontrer des cas particuliers que lon souhaiterait sauter ou pour lesquels on aimerait mettre n a ` la boucle. Les instructions next, last et redo vont nous servir ` a cela dans les boucles for, while ou until. Linstruction next (suivant en fran cais) provoque la n de lex ecution du bloc, le programme evalue directement lincr ement (dans le cas dune boucle for) puis le test est eectu e. Linstruction last (dernier en fran cais) provoque la n de la boucle, ni lincr ement ni le test ne sont eectu es. Linstruction redo (refaire en fran cais) provoque le red emarrage du bloc dinstructions sans que la condition ni lincr ementation ne soient eectu ees. Lexemple suivant est une autre fa con dimprimer ` a l ecran les entiers pairs de 0 ` a 20 : my $i = -1; while( 1 ) { # 1 est vrai $i++; last if( $i > 20 ); next if( $i%2 != 0 ); print "$i\n"; } Dans le cas o` u lon souhaite ex ecuter le bloc dinstructions une fois avant deectuer le test, on peut utiliser la syntaxe suivante : do { instruction; } while( condition ); Pour des raisons trop longues ` a exposer ici, il ne faut pas utiliser les instructions next, last et redo dans le cas de la boucle do while. Nous verrons dans la suite quil existe une autre structure de boucle : foreach. Elle permet dit erer sur les el ements dune liste (notion que nous aborderons ` a cette occasion). Vous verrez alors quen Perl on utilise beaucoup le foreach et assez peu le for(;;).

3.3

Un exemple

Voici un petit exemple de programme Perl ; il nest pas tr` es utile dans la vie de tous les jours, mais il utilise beaucoup des notions abord ees jusquici. Si vous parvenez ` a comprendre tout ce quil fait, vous naurez pas perdu votre temps ` a le lire !

24

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:

#!/usr/bin/perl -w use strict; my $v ="##########"; for( my $i=9; $i>0; $i-- ) { print("$i impair\n") if( $i % 2 ); print( "-"x$i . "\n") unless( $i % 3 ); substr( $v, $i, 0 ) = $i; } print("$v\n");

Voici le d etail du r ole des lignes : 1 : Le shebang Perl avec loption -w (achage de messages davertissement) 2 : Cette instruction rend le langage moins permissif, je vous conseille de toujours la placer au d ebut de vos programmes. 3 : Nous d eclarons et initialisons une variable scalaire. 4 : Une boucle for. D eclaration et initialisation ` a 9 de la variable de boucle $i. Nous continuerons tant quelle est strictement positive ; ` a chaque etape nous la d ecr ementerons : elle variera donc de 9 ` a 1. 5 et 6 : achage dune cha ne dans le cas o` u $i est impair. 7 et 8 : achage dune cha ne dans le cas o` u $i est multiple de 3. Cette cha ne comporte $i caract` eres moins (-). 9 : insertion de $i dans la cha ne $v en position $i (une longueur de 0 provoque une insertion et non un remplacement). 10 : accolade d elimitant le bloc de la boucle. 11 : Achage de la variable $v Lachage suivant est donc eectu e: 9 impair --------7 impair -----5 impair 3 impair --1 impair #1#2#3#4#5#6#7#8#9# Avez-vous tout compris ?

25

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

26

Chapitre 4

Listes et tableaux
Les scalaires et les expressions de base nont maintenant plus aucun secret pour vous. Des notions plus complexes et des fonctions plus puissantes sont alors ` a notre port ee. Cest le cas des listes, des tableaux et de limpressionnant arsenal de fonctions Perl permettant de les manipuler ; vous verrez tout ce quil est possible de faire en Perl avec ces deux concepts a priori anodins. Une liste est une suite (donc ordonn ee) de valeurs scalaires. Nous verrons comment cr eer une liste, la manipuler, la parcourir etc. Une variable de type tableau peut contenir plusieurs valeurs scalaires. Cette notion est pr esente dans de nombreux langages de programmation et ne posera sans doute probl` eme ` a personne. Les passerelles entre listes et tableaux sont nombreuses et tr` es intuitives en Perl. Cest pour cela que nous nentrerons pas ici dans les d etails de la distinction entre liste et tableau. Dans ce document, jutiliserai chacun des deux termes ` a bon escient sans forcement indiquer explicitement pourquoi jutilise lun plut ot que lautre, mais les notions pourront appara tre naturelles au lecteur sans quil ne soit n ecessaire de pr eciser les choses formellement.

4.1

Valeurs de listes

En Perl, une liste peut etre repr esent ee par les valeurs quelle doit contenir encadr ees par un couple de parenth` eses. Par exemple (2,5,-3) est une liste de 3 scalaires : 2, 5 et -3. Autre exemple (2,age,"Bonjour $prenom") est aussi une liste ; en eet les listes contenant des scalaires, rien ne nous emp eche den constituer une comportant des nombres et des cha nes de caract` eres m el es. La liste vide se repr esente sous la forme suivante : () Lop erateur dintervalle .. permet de cr eer une liste comportant des valeurs successives entre deux bornes. La liste (1..10) comporte tous les entiers de 1 ` a 10 ; on aurait pu aussi ecrire (1,2,3,4,5,6,7,8,9,10), mais cette derni` ere notation est bien plus lourde. Il faut savoir que les valeurs des bornes ne doivent pas obligatoirement etre des nombres : par exemple, la liste (a..z) comporte toutes les lettres de lalphabet, en minuscule et dans lordre. Il est aussi possible de sp ecier les bornes ` a laide de variables : ($debut..$fin) On comprendra quil nest pas toujours possible de r esoudre ce type de liste (par exemple si $debut vaut 1 et $fin vaut a), dans ce cas la liste est vide. Dernier exemple, la liste (1..10, "age", "a".."z") comporte 37 el ements (10+1+26). La liste (1,2,("nom",12),"aaa",-1) nest pas une liste ` a5 el ements dont le troisi` eme serait une autre liste, cest en fait une liste ` a6 el ements. On aurait pu ecrire (1,2,"nom",12,"aaa",-1)

27

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

et on aurait obtenu la m eme liste. On appelle cela laplatissement (ou la lin earisation) des listes. Pour constituer une liste de listes, il faudra faire usage de r ef erences (notion que nous aborderons plus tard). Lop erateur de r ep etition (x), que lon a d ej` a appliqu e aux cha nes de caract` eres pr ec edemment, sapplique aussi aux listes : (2,10) x 3 est une liste ` a6 el ements valant (2,10,2,10,2,10).

4.2

Manipulation de tableaux

Pour simplier les choses, un tableau est une variable qui peut avoir une liste pour valeur. Une telle variable se d eclare de la sorte : my @t; On a alors un tableau vide, cest-` a-dire sans el ement. De mani` ere plus explicite, voici comment d eclarer un tableau vide : my @t = (); Pour lui donner une valeur lors de sa d eclaration, il faut faire ainsi : my @t = (3,chaine,"bonjour $prenom"); On a alors d eclar e ce tableau en linitialisant au moyen dune liste. On peut acc eder directement ` a un el ement dun tableau gr ace ` a son indice : $t[indice] repr esente l el ement dindice indice du tableau @t. Notez bien que la globalit e du tableau se repr esente au moyen dune arobase @t alors quun el ement particulier est d esign e` a laide dun dollar $t[indice], cette derni` ere expression etant bien une variable de type scalaire (le dollar est r eserv e aux scalaires en Perl). Les indices des tableaux en Perl commencent ` a 0 (comme en C), ce qui signie que le premier el ement du tableau @t est $t[0] et le deuxi` eme $t[1] etc. Voici un petit exemple dutilisation de tableau : my @t = (3,5); # d eclaration et initialisation $t[1] = 4; # affectation dun el ement print "$t[0]\n"; # affichage dun el ement Il est int eressant de savoir quil est possible dacc eder au dernier el ement dun tableau en utilisant lindice -1 : $t[-1] est le dernier el ement de @t. De la m eme fa con, $t[-2] est lavantdernier, etc. Il est possible de conna tre lindice du dernier el ement dun tableau @t gr ace ` a la variable $#t On a donc $t[$#t] equivalent ` a $t[-1] (ce dernier etant bien plus lisible). Il peut etre utile de savoir que lexpression scalar(@t) (cest-` a-dire lutilisation dun tableau en contexte scalaire) donne le nombre d el ements du tableau @t (ce qui vaut 1 de plus que $#t) ; $x=@t donnerait la m eme chose. Il faut savoir que vous ne g en ererez pas derreur (d ebordement ou autre) si vous tentez dacc eder ` a un el ement au-del` a du dernier. La valeur de cet el ement sera simplement undef et le programme continuera. Depuis la version 5.6 de Perl, linstruction exists (que lon retrouvera pour les tables de hachage) permet de tester lexistence dun el ement dun tableau : if( exists( $t[100] ) ) { ... }

28

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

Ce test sera vrai si l el ement dindice 100 du tableau @t existe. Ce qui est di erent du test suivant : if( defined( $t[100] ) ) { ... } Car on teste ici si lexpression $t[100] vaut undef ou non, ce qui peut etre vrai dans deux cas : soit l el ement existe et vaut undef, soit l el ement nexiste pas ... Voici une autre illustration du fait que vous navez pas ` a vous soucier de probl` emes dallocation m emoire : my @t = (3,23.4,"as"); $t[1000] = 8; Ce programme est correct et fonctionne parfaitement : laectation ` a lindice 1000 agrandit le tableau dautant ... Les el ements dindice compris entre 3 et 999 valent undef et scalar(@t) vaut 1001. Cest si facile nalement ! Un tableau quil est utile de conna tre est @ARGV. Cette variable sp eciale est toujours d enie (m eme dans les fonctions) et ne n ecessite pas de d eclaration. Elle contient les arguments de la ligne de commande du programme. Les trois fa cons de lancer un programme en Perl sont susceptibles dutiliser @ARGV : perl -w -e ... code perl ... arg1 arg2 arg3 perl -w script.pl arg1 arg2 arg3 ./script.pl arg1 arg2 arg3 Ces trois programmes sont lanc es avec les trois m emes arguments. Sachez que, contrairement au langage C, le nom du programme nest pas contenu dans @ARGV qui ne comporte donc que les arguments au sens strict. La variable sp eciale $0 (comme en shell) contient le nom du programme (nul besoin de d eclarer cette variable pour lutiliser).

4.3

Aectations

Il est possible daecter un tableau ` a un autre tableau en une seule instruction : @t = @s; Cette instruction copie le tableau @s dans le tableau @t. Le tableau @t perd ses anciennes valeurs, prend celles de @s et sa taille devient celle de @s : on obtient bien deux tableaux tout a fait identiques (et distincts, la modication de lun nentra ` nant nullement la modication de lautre). Voici dautres instructions daectation m elant tableaux et listes : ($a,$b) = (1,2); Cette instruction aecte une valeur ` a chacune des variables de la liste de gauche : $a re coit 1 et $b re coit 2. ($a,$b) = (1,2,3); Les m emes aectations sont eectu ees ici, la valeur 3 n etant daucune utilit e.

29

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

($a,$b) = (1); Laectation ` a $a de la valeur 1 est eectu ee et $b est mis ` a undef (son ancienne valeur est perdue). ($a,$b) = @t; Les variables cit ees ` a gauche re coivent les premi` eres valeurs du tableau @t : $a en re coit le premier el ement ou undef si @t est vide ; $b re coit le deuxi` eme el ement ou undef si @t il ne contient quun el ement. @t = (1,2); Cette instruction r einitialise le tableau @t (dont les anciennes valeurs sont toutes perdues, y compris celles dindice di erent de 0 et 1) en lui aectant les valeurs de droite : on obtient donc un tableau ` a deux el ements. ($a,$b) = Fonction(); Nous verrons un peu plus loin comment ecrire une fonction, et comment lui faire renvoyer une liste : ici laectation se fait dans les m emes conditions que pour les trois premiers cas. ($a,$b) = ($b,$a); Cette instruction est la plus savoureuse : on peut echanger deux variables Perl sans avoir ` a en utiliser une troisi` eme ... (Ai-je d ej` a dit que Perl soccupe lui-m eme de la m emoire ?)

4.4

Multi-d eclaration

Pour d eclarer plusieurs variables avec un seul my, le d ebutant aurait tendance ` a ecrire la chose suivante (il ny a pas de honte !) : my $a,$b; # Incorrect !

Ceci est incorrect. Pour pouvoir faire cela, il nous faut utiliser une liste : my ($a,$b); Les variables $a et $b sont cr e ees et valent undef. Pour leur aecter des valeurs, il faut l` a aussi utiliser une liste (ou un tableau) : my ($a,$b) = (1,2); my ($c,$d) = @t; Les m emes r` egles que pour laectation de listes sappliquent ici.

4.5

Retour sur laplatissement des listes

On retrouve la notion daplatissement des listes avec les tableaux : @t = (1,2,"age"); @t2 = (10,@t,20); Le tableau @t2 ne comporte pas trois el ements dont celui du milieu serait lui-m eme un tableau, mais contient les cinq el ements, r esultat de laplatissement du tableau @t dans la liste de droite lors de laectation de @t2. Cette aectation a eu le m eme r esultat quaurait eu la suivante : @t2 = (10,1,2,"age",20);

30

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

4.6

Absorption dune liste par un tableau

La syntaxe suivante est int eressante ` a conna tre : ($a,@t) = @s; Le membre gauche de laectation est constitu e dune liste comportant une variable scalaire et un tableau. Il ny a pas ` a proprement parler daplatissement de liste car il sagit ici dune l-value (membre gauche dune aectation), mais la variable $a re coit le premier el ement du tableau @s et le tableau @t absorbe tous les autres (@s n etant bien-s ur pas modi e). En fait dans cette syntaxe, le premier tableau rencontr e dans la liste de gauche re coit tous les el ements restant de la liste de droite. D eventuelles autres variables qui le suivraient (cas idiot, mais bon...) seraient mises ` a undef sil sagit de scalaires et ` a vide sil sagit de tableaux. Par exemple, laectation suivante : @s = (10,1,2,"age",20); ($a, @t, @u, $b) = @s; equivaut ` a: @s $a @t @u $b = = = = = (10,1,2,"age",20); 10; (1,2,"age",20); (); undef;

Simple et intuitif.

4.7

La structure de boucle foreach

Cette instruction permet de parcourir une liste. Son impl ementation optimis ee dans linterpr eteur Perl rend son usage bien plus ecace quun parcours qui utiliserait une variable indicielle incr ement ee ` a chaque tour dune boucle for. Sa syntaxe est la suivante : foreach variable ( liste ) { instructions } ` chaque tour de boucle, la variable aura pour valeur un A el ement de la liste, la liste etant parcourue dans lordre. Aucune modication ni suppression dans la liste nest eectu ee par d efaut dans ce type de boucle. Il vous est possible de modier la variable de boucle (ce qui aura pour eet de modier l el ement en question), mais, par d efaut, le parcours nest pas destructif. Par exemple : foreach $v (1,43,"toto") { print "$v\n"; } Ce petit programme ache chaque el ement de la liste sur une ligne. Ces autres exemples sont valides eux-aussi : foreach $v (@t) { .... } foreach $v (32,@t,"age",@t2) { .... }

31

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

Dans le premier cas, les el ements du tableau @t sont parcourus. Le second exemple illustre les ph enom` enes daplatissement des listes qui se retrouvent ici aussi. Il est possible de d eclarer la variable de boucle dans le foreach de la mani` ere suivante : foreach my $v (@t) { print "$v\n"; } Il est aussi possible de ne pas utiliser explicitement de variable de boucle ; dans ce cas cest la variable sp eciale $_ qui sera automatiquement utilis ee : foreach (@t) { print "$_\n"; } Comme pour les autres boucles, linstruction next passe ` a la valeur suivante sans ex ecuter les instructions qui la suivent dans le bloc. Linstruction last met n ` a la boucle. Voici un petit exemple dutilisation de foreach achant des tables de multiplication : #!/usr/bin/perl -w use strict; die("Usage: $0 <n> <n>\n") if( !defined( $ARGV[1] ) ); foreach my $i (1..$ARGV[0]) { foreach my $j (1..$ARGV[1]) { printf( "%4d", $i*$j ); } print "\n"; } Et le voici ` a luvre : ./mult.pl Usage: ./mult.pl <n> <n> ./mult.pl 5 3 1 2 3 2 4 6 3 6 9 4 8 12 5 10 15 Passons ` a la suite.

4.8

Fonctions de manipulation de tableaux

Il existe de nombreuses fonctions permettant de manipuler les tableaux. Pour chacun des exemples qui vont suivre, je suppose que nous avons un tableau @t d eclar e de la sorte :

32

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

my @t = (1,2,3,4); Ajout et suppression ` a gauche La fonction unshift prend en arguments un tableau et une liste de valeurs scalaires ; ces valeurs sont ajout ees au d ebut du tableau : unshift(@t,5,6); @t vaut alors la liste (5,6,1,2,3,4). La fonction shift prend un tableau en argument ; elle supprime son premier el ement (les autres sont alors d ecal es) et renvoie cet el ement : $v = shift(@t); $v vaut alors 1 et @t la liste (2,3,4). Ajout et suppression ` a droite La fonction push prend en argument un tableau et une liste de valeurs scalaires ; ces valeurs sont ajout ees ` a la n du tableau : push(@t,5,6); @t vaut alors la liste (1,2,3,4,5,6). La fonction pop prend un tableau en argument ; elle supprime son dernier el ement et renvoie cet el ement : $v = pop(@t); $v vaut alors 4 et @t la liste (1,2,3). Inversion En contexte de liste, la fonction reverse prend en argument une liste et renvoie la liste invers ee, cest-` a-dire celle dont les el ements sont pris dans le sens oppos e: @s = reverse(@t); @s vaut alors la liste (4,3,2,1) et @t nest pas modi ee. Avec de telles fonctions, il est alors envisageable de manipuler des objets algorithmiques tels que les piles et les les. Une pile est un lieu de stockage ayant pour particularit e que le dernier el ement ` ay etre entr e sera le premier ` a en sortir (last in-rst out) comme pour une pile dassiettes sur une etag` ere de placard. On peut utiliser pour cela un tableau, avec les fonctions push pour ajouter un el ement et pop pour en prendre un. De fa con analogue, une le est un endroit o` u le premier entr e est le premier ` a sortir (rst in-rst out) comme pour une le ` a une caisse de magasin. On peut par exemple utiliser les fonctions push pour ajouter un el ement et shift pour en prendre un. Dautres manipulations plus complexes du contenu dun tableau sont possibles avec la fonction splice, mais je vous renvoie ` a la documentation pour les d etails.

4.9

Lop erateur qw

Lop erateur qw nous permet de cr eer facilement une liste de cha nes de caract` eres. En eet, il peut sembler p enible de constituer une longue liste de tels el ements en raison du fait quil faut d elimiter chacun dentre eux au moyen de simples ou de doubles quotes : @t = ( Ceci, est, quelque, peu, p enible, ` a, ecrire, ,, non, ? ); Avec qw, ceci devient tout ` a coup plus lisible :

33

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

@t = qw(Cela est bien plus facile ` a faire non ?); La cha ne de caract` eres sera d ecoup ee selon les espaces, les tabulations et les retours ` a la ligne. Les d elimiteurs les plus souvent utilis es sont les parenth` eses (comme dans lexemple pr ec edent) ainsi que les slashs : @t = qw/Ou alors comme cela .../; Cette fonction est bien pratique mais peut etre source derreurs, voyez lexemple suivant : @t = qw/ attention aux erreurs b^ etes /; Les simples quotes () semblent indiquer que le programmeur souhaite constituer un seul el ement comportant les mots aux et erreurs ; ce nest pas ce qui est fait ici. En eet, ni les simples quotes ni les doubles quotes ne constituent un moyen de regrouper des mots pour lop erateur qw. La liste ainsi cr e ee comporte donc 4 el ements ; on aurait pu ecrire : ("attention","aux","erreurs","b^ etes").

4.10

Joindre les el ements dans une cha ne avec join

La fonction join prend en param` etre un scalaire et une liste ; elle renvoie une cha ne de caract` eres comportant les el ements de la liste, concat en es et s epar es par ce premier param` etre scalaire. Les arguments pass es ne sont pas modi es. scalaire = join( s eparateur, liste ); Voici quelques exemples : $s = join(" ",1,2,3); La variable $s vaut alors la cha ne "1 2 3". $s = join(,,$x,$y,$y); Les valeurs des trois variables sont jointes en les alternant avec des virgules. Le r esultat est aect e` a $s. $s = join(" : ",@t); La variable vaut alors la concat enation des valeurs du tableau @t avec " : " pour s eparateur.

4.11

D ecouper une cha ne de caract` eres en liste avec split

La fonction split prend en param` etres un s eparateur et une cha ne de caract` eres ; elle renvoie la liste des el ements de la cha ne de caract` eres d elimit es par le s eparateur. Le s eparateur est une expression r eguli` ere, notion que nous aborderons dans la suite, mais dont le minimum de connaissances sut ` a cette fonction ; admettez ici quune telle expression est ` a placer entre slashs (/). Les arguments pass es ne sont pas modi es. liste = split( /s eparateur/, cha ne ); Voici quelques exemples : @t = split(/-/,"4-12-455"); Le tableau comporte alors les el ements 4, 12 et 455. ($x,$y) = split(/==/,$v); Les deux variables auront pour valeur les deux premi` eres cha nes de caract` eres qui soient s epar ees par deux signes d egalit e. print join(:,split(/ /,salut ici)); Ache salut:ici (il existe des m ethodes plus ecaces et plus lisibles de faire cela...).

34

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

4.12

Trier une liste avec sort

La fonction sort prend en param` etres un bloc dinstructions optionnel et une liste ; elle renvoie une liste tri ee conform ement au crit` ere de tri constitu e par le bloc dinstructions. La liste pass ee en argument nest pas modi ee. liste2 = sort( liste1 ); liste2 = sort( { comparaison } liste1 ); (attention ` a ne pas mettre de virgule entre le bloc dinstructions et la liste) Tout au long du tri, le bloc dinstructions sera evalu e pour comparer deux valeurs de la liste ; ces deux valeurs sont localement aect ees aux variables sp eciales $a et $b qui ne sont d enies que dans le bloc et sur lesquelles il faut donc eectuer la comparaison. Il faut faire particuli` erement attention au fait que sil existe des variables $a et $b dans le programme elles seront localement masqu ees par ces variables sp eciales (source courante derreurs). Le bloc doit etre compos e dune expression dont la valeur est : n egative, si $a doit etre avant $b dans la liste r esultat, positive, si $b doit etre avant $a, nulle, sils sont equivalents. Cest l` a quentrent en jeu les op erateurs de comparaison cmp et <=> : ils permettent de comparer respectivement les cha nes de caract` eres selon lordre lexical et les nombres selon lordre num erique. Si la fonction sort est appel ee sans bloc dinstructions, la liste est tri ee selon lordre lexical. Voici quelques exemples : @s = sort( {$a cmp $b} @t ); La liste @s a pour valeur la liste @t tri ee selon lordre lexical. @s = sort( @t ); Le fonctionnement est identique ` a lexemple pr ec edent. @s = sort( {$a <=> $b} @t ); Le crit` ere de tri est ici num erique. @s = sort( {length($b) <=> length($a) or $a cmp $b} @t ); Une expression compos ee peut bien s ur servir de crit` ere : le tri est ici dabord num erique inverse sur la longueur puis lexical. Cela permet deectuer un second tri pour les el ements egaux selon le crit` ere du premier tri. @s = sort( { fonction($a,$b) } @t ); Vous pouvez ecrire votre propre fonction de tri (` a deux arguments) ; elle doit renvoyer un nombre dont la valeur d epend de lordre voulu (voir juste avant).

4.13

S electionner des el ements avec grep

La fonction grep prend en param` etres un crit` ere de s election et une liste ; elle renvoie la liste des el ements correspondant au crit` ere. La liste pass ee en argument nest pas modi ee. Le crit` ere de s election peut etre soit une expression r eguli` ere (cas sur lequel nous reviendrons plus tard), soit un bloc dinstructions (cas sur lequel nous allons nous etendre) : liste2 = grep { s election } liste1; (attention : pas de parenth` eses ni de virgule) Les el ements renvoy es sont ceux pour lesquels l evaluation du bloc dinstructions a pour valeur vrai. Durant cette evaluation, chacune des valeurs sera localement aect ee ` a la variable sp eciale $_ sur laquelle les tests devront donc etre eectu es. Voici quelques exemples : @t = grep { $_<0 } $x,$y,$z; Aecte ` a @t les el ements n egatifs de la liste.

35

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

@s = grep { $_!=8 and $_!=4 } @t; Met dans @s les el ements de @t di erents de 4 et de 8. @s = grep { fonction($_) } @t; Vous pouvez ecrire votre propre fonction de s election ; elle doit renvoyer vrai ou faux selon que l el ement est ` a garder ou non. En contexte scalaire, la fonction grep renvoie le nombre d el ements qui correspondent au crit` ere : $n = grep { .... } @t; La syntaxe de grep comportant une expression r eguli` ere est la suivante : liste2 = grep( /regexp/, liste1 ); En quelques mots, les el ements renvoy es seront ceux qui correspondront ` a lexpression r eguli` ere. Par exemple @s = grep( /^aa/, @t ); aecte ` a @s les el ements de @t qui commencent par deux lettres a. Plus dexplications sur les expressions r eguli` eres seront donn ees dans la suite. Jai arm e que la liste dorigine n etait pas modi ee, mais il vous est possible de le faire. Si, durant la s election, vous aectez une valeur ` a $_, la liste sera modi ee. Mais cela est sans doute une mauvaise id ee de modier la liste pass ee en param` etre dun grep car la fonction map est faite pour cela.

4.14

Appliquer un traitement ` a tous les el ements avec map

La fonction map prend en param` etres un bloc dinstructions et une liste ; elle applique le bloc ` chacun des a el ements de la liste (modication possible de la liste) et renvoie la liste constitu ee des valeurs successives de lexpression evalu ee. liste2 = map( { expression } liste1 ); (attention ` a ne pas mettre de virgule entre le bloc dinstructions et la liste) La variable sp eciale $_ vaut localement (dans le bloc dinstructions) chaque el ement de la liste. La valeur de la derni` ere expression du bloc sera plac ee dans la liste r esultat. Voici quelques exemples : @s = map( { -$_ } @t ); Le tableau @s aura pour valeurs les oppos es des valeurs de @t. @p = map( { $_."s" } @t ); Tous les mots de @t sont mis au pluriel dans @p. @s = map( { substr($_,0,2) } @t ); Le tableau @s aura pour valeurs les deux premiers caract` eres des valeurs de @t. @s = map( { fonction($_) } @t ); Vous pouvez ecrire votre propre fonction ; les valeurs quelle renverra seront plac ees dans @s. Dans les exemples qui pr ec` edent, la liste dorigine nest pas modi ee (sauf dans le dernier exemple o` u elle peut l etre dans la fonction). Voici un exemple de modication de liste : map( { $_*=4 } @t ); Tous les el ements de @t sont multipli es par quatre.

36

Chapitre 5

Ecrire une fonction


Une fonction est un ensemble dinstructions regroup ees de mani` ere ` a etre utilis ees plusieurs fois sans avoir ` a dupliquer du code.

5.1

D eclaration

Le mot-clef sub permet de d enir des fonctions en Perl. Les arguments dune fonction sont des valeurs scalaires, ` a lexclusion de toutes autres (on verra comment faire en sorte de passer un tableau en argument) ; ces param` etres sont accessibles via la variable sp eciale @_ (qui est donc un tableau). Modier une valeur de @_ modiera les variables dappel, il est donc dusage den faire une copie avant manipulation. sub maJolieFonction { my ($x,$y,$t) = @_; ... instructions ... return $z; } Ces quelques lignes d enissent une nouvelle fonction dont le nom est maJolieFonction. Cette fonction copie dans trois variables locales les trois premi` eres valeurs du tableau @_, cesta-dire ses trois premiers param` ` etres (les r` egles classiques daectation entre listes et tableaux sappliquent ici). Je vous conseille de toujours commencer vos fonctions par une ligne copiant les valeurs de @_ et de ne plus utiliser @_ dans la suite de la fonction (sauf cas sp ecial). Si votre fonction attend un seul param` etre, la syntaxe peut etre la suivante : my ($x) = @_; mais ne peut pas etre : my $x = @_; #incorrect Cette ligne est incorrecte car, dans ce cas, la variable $x aurait pour valeur le nombre de param` etres (aectation dun tableau ` a un scalaire). La syntaxe suivante peut aussi etre utile : my ($x,@t) = @_;

37

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

la variable $x re coit le premier param` etre et le tableau @t re coit tous les param` etres restants. Enn, une autre ecriture que vous verrez souvent dans les programmes Perl est la suivante : my $x = shift; celle-ci sappuie sur le fait que dans une sous-routine, la fonction shift travaille par d efaut sur @_. Linstruction return met n ` a lex ecution de la fonction et on peut lui fournir une expression qui sera alors la valeur de retour de la fonction.

5.2

Appel

La fonction ainsi d enie peut etre appel ee au moyen de la syntaxe suivante : maJolieFonction(10,20,30); Dans ce cas, l eventuelle valeur de retour est ignor ee. Pour r ecup erer cette valeur : $v = maJolieFonction(10,20,30); Il est possible domettre les parenth` eses lors de lappel a ` une fonction : maJolieFonction 10,20,30; # ` A e viter

mais cela peut cr eer des ambigu t es et je vous d econseille donc cette syntaxe. Sil est possible en Perl dimposer le nombre darguments pour une fonction (nous nen parlerons pas ici), cela nest pas fait par d efaut. Rien ne nous emp eche en eet dappeler la fonction maJolieFonction pr ec edemment d enie avec deux ou quatre arguments, alors quelle semble en attendre trois ; si on lappelle avec deux arguments, la variable $t vaudra undef ; par contre si on lappelle avec plus de trois arguments, les valeurs suivantes seront ignor ees. Mais cette particularit e du langage est parfois bien pratique, notamment pour ecrire des fonctions ` a nombre variable darguments.

5.3

Visibilit e des variables

Les variables d eclar ees au moyen de my dans une fonction ne seront visibles qu` a lint erieur m eme de la fonction, dans le code qui suit la d eclaration. Dans une fonction, il est possible dacc eder aux variables d enies ` a la racine du programme (cest-` a-dire en dehors de toute fonction) : il sagit donc de variables globales. Si une variable locale a le m eme nom quune variable globale, cette derni` ere est masqu ee par la variable locale : my $a = 3; my $b = 8; my $c = 12; sub maJolieFonction { my $a = 5; print "$a\n"; # affiche 5

38

c Sylvain Lhullier

Guide Perl # affiche 8 # modification de la variable globale # affiche 15

http://formation-perl.fr/

print "$b\n"; $c = 15; print "$c\n"; } maJolieFonction(); print "$a\n"; print "$b\n"; print "$c\n";

# affiche 3 # affiche 8 # affiche 15

De mani` ere plus g en erale, les variables d eclar ees au moyen de my sont visibles jusqu` a la n du plus petit bloc qui les englobe. En particulier, dans une fonction... sub maJolieFonction2 my $d = -3; if( ... ) { my $d = 4; my $e = 8; print "$d\n"; print "$e\n"; } print "$d\n"; print "$e\n"; } {

# affiche 4 # affiche 8 # affiche -3 # $e nexiste pas ici

5.4

Une liste pour valeur de retour

Il est tout ` a fait possible de faire renvoyer plusieurs scalaires par une fonction, il sut juste dutiliser une liste. Voici des exemples de syntaxe de liste renvoy ee par des fonctions : return ($x,$z); return @t; Dans le second cas, le tableau est converti en liste. Et voici comment il est possible de r ecup erer ces valeurs : @s = fonction(...); ($j,$k) = fonction(...); Ces deux mani` eres de proc eder peuvent parfaitement etre utilis ees chacune dans les deux cas de return pr e-cit es (ce sont toujours les m emes r` egles daectation qui sappliquent).

5.5

Premier exemple de fonction

Voici un exemple complet de programme en Perl avec une fonction :

39

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:

#!/usr/bin/perl -w use strict; my $t = "Bonjour Larry"; print "$t\n"; sub f { my ($x,$z) = @_; my $m = $x*$z; printf("%d\n", $m); return ($x+$z,$m); } my @t = f(3,5); print "$t $t[0] $t[1]\n";

# variable globale # avec ou sans parenth` eses # deux arguments attendus

# retourne une liste

Un bon programme Perl commence toujours par les premi` ere et deuxi` eme lignes. Si la variable scalaire $t, elle, est globale, en revanche les variables $x, $z et $m sont locales ` a la fonction. En ligne 11, le tableau @t re coit pour valeur la liste renvoy ee par la fonction. Notez bien quil ny a aucun conit entre les variables $t et @t ; en eet, linstruction de la derni` ere ligne proc` ede dabord ` a lachage de la variable scalaire $t puis du premier et deuxi` eme el ements du tableau @t (les crochets permettent de savoir quil sagit d el ements dun tableau).

5.6

Autre exemple : une fonction r ecursive

Voici un exemple de fonction. Elle est r ecursive (cest-` a-dire quelle fait appel ` a elle-m eme) : nous allons calculer la factorielle dun nombre. Par d enition, F(0)=F(1)=1 et F(n)=nF(n-1) pour tout n sup erieur ` a1: sub Fact { my ($n) = @_; return 1 if( $n == 1 || $n == 0 ); return $n * Fact($n-1); } print Fact(5)."\n"; # affiche 120 Aussi lisible que dans tout autre langage.

5.7

Dernier exemple : le crible dEratosth` ene

Nous allons ici illustrer lusage des listes et des tableaux par un exemple math ematique : le crible dEratosth` ene. Cet algorithme permet de calculer tous les nombres premiers inf erieurs ` a un nombre donn e n. Son principe est le suivant : nous construisons tout dabord la liste de tous les entiers de 2 ` a n. Ensuite, ` a chaque it eration, nous supprimons de la liste tous les multiples du premier nombre de la liste et signalons ce premier nombre comme etant premier. Au premier tour de boucle, je supprime tous les nombres pairs et dis que 2 est premier. Au suivant, je supprime tous les multiples de 3 et arme que 3 est premier. Au tour suivant, cest le 5 qui est au d ebut de la liste

40

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

(4 etant multiple de 2, il a d ej` a et e supprim e), jenl` eve de la liste les multiples de 5 et annonce la primalit e de 5 etc ... Lalgorithme se termine lorsque la liste est vide, jai alors d etermin e tous les nombres premiers inf erieurs ` a n. Voici la fonction r ealisant cet algorithme en Perl : sub Crible { my ($n) = @_; # Liste initiale : my @nombres = (2..$n); # Liste des nombres premiers trouv es : my @premiers = (); # Tant quil y a des el ements (un tableau # en contexte bool een vaut faux sil est vide) : while( @nombres ) { # On extrait le premier nombre my $prem = shift @nombres; # On indique quil est premier push @premiers, $prem; # On supprime ses multiples @nombres = grep { ( $_ % $prem )!=0 } @nombres; } # On renvoie la liste des nombres premiers return @premiers; } Quiconque a d ej` a r ealis e cet algorithme en C ou C++ comprendra la joie que cette concision procure ...

41

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

42

Chapitre 6

Tables de hachage
Les tables de hachage de Perl ne se retrouvent pas dans beaucoup dautres langages ; pour les avoir souvent utilis ees en Perl, il est dur de repasser a ` des langages qui nen sont pas pourvus. Une table de hachage (hash table en anglais) est un type de donn ee en Perl permettant dassocier une valeur ` a une clef. On peut dire dun tableau (notion abord ee pr ec edemment) quil associe une valeur scalaire ` a un entier : ` a la position i (pour i entier), une certaine valeur scalaire est pr esente. Une table de hachage va nous permettre daller au-del` a : on pourra faire correspondre une valeur scalaire (comme pour un tableau) ` a toute cha ne de caract` eres (plut ot qu` a un entier). Je peux, par exemple, avoir envie de g erer en Perl un index t el ephonique simple : chacun de mes amis a un num ero de t el ephone, je veux pouvoir retrouver leur num ero ` a partir de leur pr enom. Je vais donc associer le num ero au pr enom : "Paul" -> "01.23.45.67.89" "Virginie" -> "06.06.06.06.06" "Pierre" -> "heu ..." Les pr enoms seront les clefs, cest-` a-dire le point dentr ee dans la table de hachage (comme les indices num eraux le sont pour les tableaux). Les num eros de t el ephone seront les valeurs associ ees ` a ces clefs. Il sagit bien dune association cha ne de caract` eres vers scalaire. Vous lavez sans doute compris, dans une table de hachage, une clef nest pr esente quune seule fois et ne peut donc avoir quune seule valeur (comme l el ement dun indice donn e dun tableau). Par contre, une valeur peut etre associ ee ` a plusieurs clefs.

6.1

D eclaration et initialisation

Une variable de type table de hachage se d eclare de la sorte : my %h; On a alors une table de hachage vide (aucune clef). Il est possible de signaler explicitement que lon d eclare une table de hachage vide : my %h = ();

43

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

Pour donner des valeurs initiales ` a notre table de hachage, on peut utiliser la syntaxe suivante : my %h = ( "Paul" => "01.23.45.67.89", "Virginie" => "06.06.06.06.06", "Pierre" => "heu ..." ); Cette derni` ere table de hachage est d eclar ee et initialis ee avec les clefs Paul, Virginie et Pierre ayant respectivement pour valeurs 01.23.45.67.89, 06.06.06.06.06 et heu ...

6.2

Acc eder ` a un el ement

Dans une table de hachage %h, on peut acc eder ` a la valeur dune clef au moyen de la syntaxe suivante : $h{clef} ; par exemple $h{Paul} vaut 01.23.45.67.89. Si la clef comporte dautres caract` eres que des lettres, des chires et le soulign e (underscore en anglais _), il faut la d elimiter au moyen de simples ou de doubles quotes : $h{"Marie-Pierre"} ou $h{Marie-Pierre} En fait, cette syntaxe force un contexte de cha ne de caract` eres entre les accolades, ce qui fait quun mot simple (bareword en anglais) sera converti silencieusement en cha ne de caract` eres (m eme en positionnant loption -w). De fa con similaire aux tableaux avec larobase (@t), la totalit e dune table de hachage se repr esente au moyen du signe pourcentage (%h), alors quune valeur particuli` ere est d esign ee ` a laide dun dollar $h{clef}, cette derni` ere expression etant bien une variable de type scalaire. Voici quelques exemples de manipulation d el ements de la table de hachage %h : $h{Jacques} = "02.02.02.02.02"; print "T el : $h{Jacques}\n"; $h{Jean-Paul} = "03.03.03.03.03"; if( $h{"Jean-Paul"} ne "Heu ..." ) { ... } La clef utilis ee pour cette syntaxe peut tout ` a fait etre contenue dans une variable scalaire (qui sera evalu ee en contexte de cha ne de caract` eres) : my $k = "Jacques"; $h{$k} = "02.02.02.02.02"; Elle peut m eme etre une expression plus complexe : sub f { return "Jac"; } $h{f().ques} = "02.02.02.02.02";

44

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

6.3

Parcours

Il existe trois fonctions permettant de parcourir une table de hachage. Dans les exemples fournis, nous consid ererons que la table %h a et e d eclar ee ainsi :

my %h = ( "Paul" => "01.23.45.67.89", "Virginie" => "06.06.06.06.06", "Pierre" => "heu ..." ); keys : obtenir une liste des clefs Cette fonction prend en param` etre une table de hachage et renvoie une liste comportant toutes les clefs de la table. Lordre des clefs est quelconque, seule lexhaustivit e des clefs est garantie. my @t = keys(%h); Le tableau @t peut par exemple valoir la liste ("Virginie", "Pierre", "Paul"). Cette fonction va nous permettre de parcourir toute la table de hachage en eectuant une boucle sur la liste des clefs : foreach my $k (keys(%h)) { print "Clef=$k Valeur=$h{$k}\n"; } La variable de boucle $k prendra pour valeurs successives lensemble des clefs de la table, lexpression $h{$k} est la valeur associ ee ` a la clef $k. Ce petit programme achera donc tous les couples clef/valeur de la table %h. values : obtenir une liste des valeurs De la m eme fa con que keys renvoie une liste des clefs dune table de hachage, la fonction values fournit une liste des valeurs ; pour cette fonction non plus lordre nest pas garanti et seule lexhaustivit e lest. Lexemple suivant foreach my $v (values(%h)) { print "Valeur=$v\n"; } achera tous les num eros de t el ephone (cest-` a-dire les valeurs) de la table %h. Il nest bien s ur pas possible de retrouver la clef des valeurs que lon manipule ainsi. Il peut etre int eressant de savoir que lordre des clefs renvoy ees par keys et celui des valeurs par values sera le m eme ` a condition de ne pas modier la table de hachage entre temps. each : it eration sur les couples (clef,valeur) Cette fonction renvoie un ` a un tous les couples (clef,valeur) dune table de hachage. Elle a un comportement un peu sp ecial du fait quil faut lappeler autant de fois quil y a de couples : cest une fonction avec etat, cest-` a-dire quelle ne renvoie pas toujours la m eme chose dun appel ` a lautre : en eet, elle renvoie le couple suivant ! De ce fait, je vous conseille de toujours lutiliser dans la syntaxe qui suit : while( my ($k,$v) = each(%h) ) { print "Clef=$k Valeur=$v\n"; } Libre ` a vous de parcourir vos tables de hachage avec la fonction qui vous convient le mieux.

45

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

6.4

Autovivication

Sous ce terme barbare se cache une id ee simple : si vous tentez de modier un el ement dune table de hachage qui nexiste pas, il sera cr e e. Sil est utilis e dans un contexte num erique, il prendra pour valeur initiale z ero. Sil est utilis e dans un contexte de cha ne de caract` eres, il prendra pour valeur la cha ne vide (depuis Perl 5.6). Par exemple, consid erons une table de hachage qui ne comporte pas la clef hello ; lexpression suivante $h{hello} .= "apr` es"; associe ` a la clef hello la valeur cha ne vide puis lui concat` ene la cha ne "apr` es". De la m eme fa con, lexpression $h{bye}++; cr ee un el ement de valeur 1. Cette propri et e dautovivication est bien pratique dans le cas o` u lon ne conna t pas les clefs avant de devoir y acc eder. Par exemple nous allons pouvoir compter le nombre doccurrences des mots dans un texte de mani` ere tr` es simple. Supposons que les mots du texte soient d ej` a dans un tableau (par exemple en utilisant la fonction qw ; elle ne r` egle pas les probl` emes des ponctuations, des majuscules et des lettres accentu ees, mais elle sura ` a notre exemple). Nous allons utiliser chaque mot comme une clef de la table et nous allons ajouter 1 ` a la valeur de cette clef : my @texte = qw( bonjour vous bonjour ); my %comptage = (); foreach my $mot ( @texte ) { $comptage{$mot}++; } while( my ($k,$v) = each(%comptage) ) { print "Le mot $k est pr esent $v fois\n"; } Ce qui donne lachage suivant : Le mot vous est pr esent 1 fois Le mot bonjour est pr esent 2 fois Dans la suite nous verrons comment d ecouper un texte en mots au moyen des expressions r eguli` eres.

6.5

Existence et suppression dune clef

` la lecture de ce qui pr A ec` ede, il peut sembler impossible de savoir si un el ement dune table de hachage existe ou non. Rassurez-vous, les auteurs de Perl ont tout pr evu :-) Lop erateur exists renvoie vrai si l el ement de table de hachage quon lui donne en param` etre existe ; sinon il renvoie faux. Par exemple :

46

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

if( exists( $h{hello} ) ) { print "La clef hello existe\n"; } Il est important de noter quun test eectu e au moyen de lop erateur defined aurait et e possible, mais dangereux. En eet, lexpression defined( $h{hello} ) est fausse dans deux cas tr` es di erents : soit si l el ement nexiste pas, soit si l el ement existe et vaut undef ; elle sera vraie si l el ement existe et ne vaut pas undef. Il est donc impossible de distinguer le cas dun el ement absent et celui dun el ement ind eni (valant undef) avec defined. Cette distinction entre absent et ind eni peut para tre articielle dans ce cas (elle peut tout de m eme etre importante dans certaines situations !), mais dans le cas de la suppression dune clef, il en est tout autrement. Pour supprimer une clef dans une table de hachage, il faut utiliser lop erateur delete. Linstruction delete( $h{hello} ); supprime la clef hello de la table %h si elle existe (si elle nexiste pas, elle ne fait rien). De la m eme fa con que exists est la bonne m ethode pour tester lexistence dun el ement, delete est la bonne m ethode pour en supprimer un. Le d ebutant pourrait etre tent e d ecrire : $h{hello} = undef; # attention!

Ce qui est fort di erent car, dans ce cas, la clef hello aura une valeur ind enie, mais existera toujours ! On la retrouvera, par exemple, dans les parcours eectu es au moyen des op erateurs keys, values ou each ; ce qui nest sans doute pas le but recherch e. Pour r esumer, on peut dire que pour tester lexistence dune clef, il faut utiliser exists et que pour en supprimer une, il faut utiliser delete. En marge de ces deux fonctions, voici une mani` ere de savoir si une table de hachage est vide ou non (on qualie de vide une table de hachage qui ne comporte aucune clef). Cette syntaxe utilise la table de hachage en contexte de cha ne de caract` eres, par exemple de cette fa con : if( %h eq 0 ) { print "%h est vide\n"; } La valeur dun hachage en contexte scalaire na pas dautre utilisation que celle-ci. En eet, scalar(%A) renvoie une valeur du type 4/8 qui indique le nombre de places (buckets en anglais) utilis ees par rapport au nombre total disponibles dans le hachage. Une table vide est un cas particulier, elle renverra 0.

6.6

Tables de hachage et listes

On peut facilement passer dune liste (ou tableau) ` a une table de hachage et inversement. Voyez, par exemple, le petit programme suivant : my @t = ("Paul", "01.23.45.67.89", "Virginie", "06.06.06.06.06", "Pierre", "heu ..."); my %h = @t;

47

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

La premi` ere instruction cr ee un tableau @t initialis e ` a une liste ` a 6 el ements. La seconde cr ee une table de hachage %h initialis ee au moyen du pr ec edent tableau. Les valeurs du tableau sont prises deux ` a deux : la premi` ere de chaque couple sera la clef dans la table de hachage, la seconde la valeur. Si le nombre d el ements de la liste est impair, la derni` ere clef cr e ee aura undef pour valeur. Si une clef venait ` a etre pr esente plusieurs fois dans la liste, cest la derni` ere valeur qui sera prise en compte dans la table de hachage. On aurait aussi pu ecrire : my %h = ("Paul", "01.23.45.67.89", "Virginie", "06.06.06.06.06", "Pierre", "heu ..."); Il est ` a noter que cette syntaxe rappelle etrangement lun des premiers exemples de cr eation de table de hachage qui utilisait => pour s eparer clefs et valeurs. Cette similarit e est en fait une quasi- equivalence, car lop erateur => peut etre utilis e` a la place de la virgule pour cr eer des listes ; il na et e ajout e au langage Perl que pour faciliter la lecture des aectations de tables de hachage, car il force un contexte de cha ne ` a sa gauche, ce qui permet justement d ecrire %a = ( toto => titi ); La conversion dans lautre sens est aussi possible. L evaluation dune table de hachage dans un contexte de liste renvoie une liste des clefs et des valeurs, se suivant respectivement deux ` a deux, dans un ordre quelconque entre couples. La table de hachage %h de lexemple pr ec edent peut etre aect ee ` a un tableau : my @t2 = %h; Le tableau @t2 sera initialis e, par exemple, avec la liste suivante : ("Pierre", "heu ...", "Paul", "01.23.45.67.89", "Virginie", "06.06.06.06.06") ; chaque clef pr ec` ede sa valeur, mais lordre des couples (clef,valeur) est quelconque (un peu comme pour la fonction each). Une table de hachage se convertit en liste sans encombre d` es quelle est en contexte de liste. Je vous laisse deviner ce que fait le code suivant : foreach my $x (%h) { print "$x\n"; } La fonction reverse, qui nous a permis dinverser les listes, peut etre employ ee pour inverser une table de hachage : %h = reverse(%h); Les valeurs deviennent les clefs et inversement. Si plusieurs valeurs identiques sont pr esentes le comportement est impr evisible car, certes, lors de la transformation de liste en table de hachage la derni` ere valeur compte, mais lors de la transformation de table de hachage en liste lordre est quelconque ... Lassociation individu - num ero de t el ephone est id eale pour illustrer cela : my %h = ("Paul", "01.23.45.67.89", "Virginie", "06.06.06.06.06", "Pierre", "heu ..."); my %quidonc = reverse %h;

48

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

On pourra alors retrouver la personne ` a partir de son num ero de t el ephone. Si, par contre, Paul et Virginie avaient eu le m eme num ero, on naurait pas pu pr edire quelle serait la personne renvoy ee.

6.7

Exemples

Voici quelques exemples dutilisation des tables de hachage. Le premier concerne la variable sp eciale %ENV qui contient les variables denvironnement du programme. $ENV{PATH} contient le path, $ENV{HOME} vaut le nom du r epertoire personnel de lutilisateur qui ex ecute le programme, etc. Deuxi` eme exemple, les tables de hachage peuvent servir ` a constituer des tableaux ` a plusieurs dimensions ; on pourrait en eet imaginer avoir des clefs qui seraient la concat enation des coordonn ees dans les n dimensions : dim1 :dim2 :dim3 :... my %h = (); foreach my $i (0..4) { foreach my $j (-3..10) { foreach my $k (130..148) { $h{"$i:$j:$k"} = Calcul($i,$j,$k); } } } Nous verrons dans la suite quil est possible de b atir de r eels tableaux ` a plusieurs dimensions en utilisant des r ef erences. Lexemple suivant concerne les ensembles ; nous allons utiliser les tables de hachage pour calculer lunion et lintersection de deux ensembles. # Voici mes deux ensembles # Je mets les el ements dans des tableaux my @ensA = (1, 3, 5, 6, 7, 8); my @ensB = (2, 3, 5, 7, 9); # Voici mon union et mon intersection, # les el ements des ensembles en seront les clefs my %union = (); my %inter = (); # Je mets tous les el ements de A dans lunion : foreach my $e (@ensA) { $union{$e} = 1; } # Pour tous les el ements de B : foreach my $e (@ensB) { # Sil est d ej` a dans lunion, cest quil est # dans A : je le mets donc dans lintersection : $inter{$e} = 1 if ( exists( $union{$e} ) );

49

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

# Je le mets dans lunion $union{$e} = 1; } # # # # Tous sont Tous sont les des les des l e ements clefs de el ements clefs de pr esents la table pr esents la table dans A ou B union. dans A et B inter.

# Je reconstitue des tableaux ` a partir # des tables de hachage (en les triant # pour laffichage) my @union = sort( {$a<=>$b} keys(%union) ); my @inter = sort( {$a<=>$b} keys(%inter) ); print("@union\n"); # affiche : 1 2 3 5 6 7 8 9 print("@inter\n"); # affiche : 3 5 7

Pour le m eme probl` eme, voici une solution nutilisant quune seule table de hachage, je vous laisse le soin den appr ecier le principe :

my @ensA = (1, 3, 5, 6, 7, 8); my @ensB = (2, 3, 5, 7, 9); my %hash = (); # Quune seule table ...

foreach my $e (@ensA) { $hash{$e}++; } foreach my $e (@ensB) { $hash{$e}++; } my @union = sort( {$a<=>$b} keys(%hash) ); my @inter = sort( {$a<=>$b} ( grep { $hash{$_}==2 } keys(%hash) ) ); print("@union\n"); # affiche : 1 2 3 5 6 7 8 9 print("@inter\n"); # affiche : 3 5 7

La compr ehension de cet exemple demande davoir assimil e plusieurs notions importantes vues jusquici.

50

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

6.8

Tranches de tableau

Maintenant que nous connaissons tous les types de donn ees de Perl, notamment les tableaux et les tables de hachage, nous allons maintenant voir comment on peut manipuler plusieurs el ements dun tableau ou dune table de hachage ` a la fois. Cela sappelle une tranche (slice en anglais). Une tranche de tableau est un sous-ensemble des el ements du tableau. Imaginons par exemple un tableau @t duquel nous souhaiterions manipuler les el ements dindice 4 et 10 ; pour cela nous allons prendre la tranche correspondante de ce tableau : @t[4,10] est une liste ` a deux el ements qui est equivalente ` a ($t[4],$t[10]) Quelques explications sur la syntaxe. Tout dabord, lexpression commence par une arobase, car il sagit dune liste d el ements ; le dollar est r eserv e aux scalaires, par exemple $t[4] est un scalaire. Ensuite, comme dhabitude pour les tableaux, les crochets permettent de sp ecier les indices. Enn, lensemble des indices est indiqu e par une liste dentiers : @t[2,10,4,3] @t[3..5] @t[fonction()] ... Une telle tranche est utilisable comme valeur (passage de param` etres, etc) et comme l-value (expression ` a gauche du signe egal daectation) : @t[4,10] = (4321,"age"); cette instruction aecte 4321 ` a lindice 4 du tableau @t et la cha ne age ` a lindice 10. On aurait pu ecrire ($t[4],$t[10]) = (4321,"age"); Une autre utilisation des tranches de tableau appara t avec les fonctions qui renvoient une liste. Par exemple la fonction stat prend en param` etre un nom de chier et renvoie toute sorte dinformations sur le chier : taille, dates, propri etaire etc. Il est courant d ecrire : ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat($filename); La fonction renvoie une liste qui est aect ee aux variables de la liste de gauche. Les tranches peuvent intervenir si seules quelques informations vous int eressent et que vous ne voulez pas d eclarer de variables inutiles. Par exemple, si seules les dates de modication (indice 9) et de cr eation (indice 10) vous int eressent, vous pouvez ecrire : ($mtime,$ctime) = ( stat($filename) )[9,10]; Lappel ` a la fonction est plac e entre parenth` eses et on ne prend que les el ements dindice 9 et 10 de sa valeur de retour. On a alors une liste ` a deux el ements, celle-ci est aect ee ` a la liste a gauche du signe ` egal et donc ces deux el ements sont aect es aux deux variables.

6.9

Tranches de table de hachage

De la m eme fa con quil existe des tranches pour les tableaux et les listes, il en existe pour les tables de hachage. La s election seectue bien s ur sur les clefs. Par exemple, si %h est une table de hachage, alors @h{clef1,clef2} est une liste equivalente ` a ($h{clef1},$h{clef2})

51

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

Il est ensuite possible dutiliser cette liste comme bon vous semble (aectation, passage en param` etre, etc). Une utilisation (assez complexe) des tranches serait indiqu ee lorsque lon veut construire automatiquement une liste de valeurs uniques ` a partir dun tableau dont on nest pas s ur que ses valeurs soient uniques : # Un tableau avec des valeurs dupliqu ees : my @t = qw(hello toto hello vous); # D eclaration dune table de hachage : my %h; # On prend la tranche de %h dont les clefs # sont les valeurs du tableau @t # et on leur associe la valeur undef @h{@t} = (); # Les clefs de %h sont donc constitu ees des # valeurs de @t, et on est s^ ur de ne les # retrouver quune seule fois : @t = keys %h; Le tableau @t comporte alors une fois et une seule chacun de ses el ements.

52

Chapitre 7

Manipulation de chiers
Pour le moment nous avons ecrit des programmes dont les interactions avec leur environnement etaient faibles. Nous allons voir dans cette partie comment manipuler des chiers en Perl. Les chiers se retrouvent dans tous les langages, mais la mani` ere tr` es simple et tr` es puissante de les manipuler fait des chiers une facilit e de Perl.

7.1

Op erateurs sur les noms de chier

Perl dispose dop erateurs prenant en param` etre un nom de chier ; ce nom de chier doit etre un scalaire (une variable ou une constante). Leur valeur de retour est souvent bool eenne et quelquefois num erique. Les coutumiers du shell retrouveront de nombreuses options de la commande test. -e teste si son param` etre est un chemin valable dans le syst` eme de chier (r epertoire, chier, etc). On pourrait lutiliser ainsi : if( -e "/usr/tmp/fichier" ) { print "Le fichier existe\n"; } -f teste si son param` etre est un chier normal. -d teste si son param` etre est un r epertoire. -l teste si son param` etre est un lien symbolique. Ceci nexclut pas que -f ou -d renvoie vrai. -r teste si le programme a le droit de lire le chier/r epertoire/etc pass e en param` etre. -w teste si le programme a le droit d ecrire. -x teste si le programme a le droit dex ecuter le chier ou dacc eder (ou ax eder :-)) au r epertoire. -o teste si le chier appartient ` a lutilisateur qui ex ecute le programme. -z teste si le chier est vide. -s teste si le chier est non vide ; en fait cet op erateur renvoie la taille du chier. -M renvoie l age en jour du chier (depuis le d ebut de lex ecution du programme). Il existe tout plein dautres op erateurs sur les chiers ; pour en conna tre la liste compl` ete, je vous invite ` a lancer la commande perldoc -f -X Voici quelques exemples dutilisation de ces op erateurs : my $file = "/usr/doc/perl";

53

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

if( -f $file && -w $file ) { .... } my $taille = -s $file; my $age = -M $file; Simple et ecace.

7.2

La fonction glob

La fonction glob prend en argument une expression et renvoie une liste de noms de chiers. Cette liste correspond ` a l evaluation de lexpression selon les wildcards du shell. Par exemple, glob( *.o ) renvoie la liste des chiers du r epertoire courant ayant lextension .o Notez bien quil ne sagit pas dune expression r eguli` ere (pour ceux qui connaissent ; pour les autres, nous en parlerons plus tard), mais bien dune expression telle quon la donnerait ` a un shell : ls [A-Z]*.h liste tous les chiers commen cant par une majuscule ayant lextension .h Il existe une syntaxe plus concise et au comportement identique ` a cette fonction : lexpression peut etre mise entre chevrons. Les deux lignes suivantes eectuent la m eme op eration : @l = glob(/usr/include/*.h); @l = </usr/include/*.h>; Apr` es lex ecution dune de ces deux lignes, le tableau @l contient la liste des noms absolus des chiers dinclude pour le C du r epertoire /usr/include

7.3

Premiers exemples

Voici un premier exemple de manipulation de noms de chiers : #!/usr/bin/perl -w use strict; foreach my $name ( <*> ) { print "$name\n" if( -l $name ); } Il ache les liens symboliques du r epertoire courant. Voici un second exemple : #!/usr/bin/perl -w use strict; foreach my $name ( <.*>, <*> ) { next if( ! -d $name ); next if( ! -w $name ); print "$name : ". ( -s $name ) ."\n"; } Ce programme ache le nom et la taille des sous-r epertoires du r epertoire courant sur lesquels jai les droits d ecriture (y-compris ceux commen cant par un point, donc . et ..).

54

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

7.4

Ouverture de chier

Pour lire ou ecrire dans un chier, il est n ecessaire de louvrir pr ealablement. La fonction eectuant cette op eration en Perl se nomme open et sa syntaxe est la suivante : open( HANDLE, expression ) Le param` etre HANDLE sera lidentiant du chier apr` es ouverture (on pourrait parler de descripteur de chier). Cest ce descripteur qui devra etre fourni aux fonctions de lecture et d ecriture pour manipuler le chier. Pour ne pas rentrer trop dans les d etails, un descripteur de chier se repr esente dans le code Perl par une simple cha ne de caract` eres (sans quotes pour la d elimiter, ni de $ pour la d ebuter) ; la convention veut quon le mette toujours en majuscules. Le param` etre expression est un scalaire (cha ne de caract` eres) comportant le nom du chier a ouvrir pr ` ec ed e de z ero, un ou deux caract` eres indiquant le mode douverture : Caract` ere(s) aucun < > >> +> +< Mode douverture lecture lecture ecriture ( ecrasement) ecriture (ajout) lecture et ecriture ( ecrasement) lecture et ecriture (ajout)

Les habitu es du shell retrouveront certaines notations connues. Par exemple open(FIC1,"<index.html") ouvre le chier index.html en lecture et open(FIC2,">index.htm louvre en ecriture- ecrasement (cest-` a-dire que le chier sera vid e avant que le curseur ne soit plac e au d ebut du chier). Cette fonction open renvoie une valeur bool eenne vrai ou faux indiquant le bon d eroulement ou non de lop eration. Il est tr` es important de tester les valeurs de retour des fonctions manipulant les chiers (cela est vrai quel que soit le langage), car on ne peut jamais etre s ur de rien. Voici deux exemples de tests de la valeur de retour dopen : if( ! open(FIC,">>data.txt") ) { exit(1); } Dans ce premier exemple, on tente douvrir en ajout un chier data.txt ; en cas dimpossibilit e, on appelle la fonction exit qui met n au programme (la valeur 1 signale une erreur ; la valeur 0 signalant la n normale du programme, les autres valeurs sont utilis ees pour signaler au shell appelant une erreur). Vous noterez que lutilisateur qui ex ecute le programme nest pas inform e de la cause de l echec ; le programme se termine, tout au plus sait-il quil y a eu un probl` eme avec louverture de ce chier, mais il nen conna t pas la cause. Lexemple suivant va nous permettre de lui acher un joli message derreur : open(FIC2,"</tmp/$a") or die("open: $!"); Nous cherchons ici ` a ouvrir en lecture le chier dont le nom serait la concat enation de la cha ne /tmp/ et du contenu de la variable $a. La fonction die met n au programme comme exit le ferait, mais ache en plus le param` etre quon lui passe. En loccurrence, le param` etre fourni est la cha ne de caract` eres comportant le nom de la fonction qui cause l echec (on aurait pu ajouter le nom du chier) ainsi que la variable $!. En contexte de cha ne de caract` eres,

55

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

cette variable magique $! contient le message errno de la derni` ere erreur survenue, par exemple No such file or directory ou Permission denied etc. Lutilisateur est donc inform e de la cause de la n du programme. La syntaxe open() or die(); ainsi que sa signication proviennent de l evaluation paresseuse du or. En eet, dans lexpression (a or b) si a est vrai, il nest pas n ecessaire d evaluer b pour conna tre la valeur de lexpression. Cest ce quil se passe ici : si open() renvoie vrai, il nest pas n ecessaire d evaluer die(). Les descripteurs de chier sont dune esp` ece etrange en Perl, le d ebutant sabstiendra de chercher ` a trop comprendre les m ecanismes sous-jacents. Ce que lon pourrait dire, cest quil nest pas n ecessaire de d eclarer un descripteur de chier, la fonction open valant d eclaration.

7.5

Lecture, ecriture et fermeture de chier

Une fois un chier ouvert, il nous est possible d ecrire et/ou de lire dedans (selon le mode douverture) et de le fermer. La lecture des chiers texte seectue typiquement au moyen de lop erateur chevrons, cette lecture se faisant ligne par ligne. $l = <FIC>; Cette instruction lit la prochaine ligne disponible du chier FIC. Vous noterez bien que lop erateur chevrons (diamond operator en anglais) est ici en contexte scalaire. En contexte de liste, il renvoie la liste de toutes les lignes restant dans le chier : @t = <FIC>; Cette instruction absorbe toutes les lignes du chier dans une liste qui est plac ee dans le tableau @t. Pour it erer sur les lignes dun chier, il est courant de faire ainsi : while( defined( $l = <FIC> ) ) { chomp $l; print "$. : $l\n"; } La boucle while donne pour valeur ` a la variable $l une ` a une toutes les lignes du chier. La fonction chomp supprime le dernier caract` ere sil sagit dun retour ` a la ligne. La variable sp eciale $. vaut le num ero de la ligne courante du dernier chier lu (ici FIC). Si vous utilisez la variable sp eciale omnipr esente $_, la construction while( defined( $_ = <FIC> ) ) peut m eme sabr eger en : while( <FIC> ) Pour ecrire dans un chier, nous allons utiliser les fonctions print et printf que nous avons d ej` a vues. Elles prennent en premier argument le descripteur de chier :

56

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

print( FIC "toto\n" ); printf( FIC "%03d", $i ); Il faut noter quil ny a pas de virgule apr` es le descripteur de chier (il ne faut pas en mettre !). Les parenth` eses sont comme toujours optionnelles autour des arguments, mais permettent de lever certaines ambigu t es. La fonction printf fonctionne comme printf ou fprintf du C et ne sera donc pas d etaill ee ici (voir man~3~printf). Pour fermer un descripteur de chier (et donc vider les buers associ es), il faut faire appel a la fonction close : ` close( FIC ); ` noter que si vous r A eutilisez un descripteur de chier dans un open sans faire de close au pr ealable, Perl ne rousp etera pas et fermera consciencieusement le premier chier avant douvrir le deuxi` eme. Il existe plusieurs chiers ouverts automatiquement par Perl d` es le lancement du programme : STDIN : lentr ee standard (souvent le clavier). STDOUT : la sortie standard (souvent le terminal). Par d efaut print et printf ecrivent sur ce ux. STDERR : la sortie derreur standard (souvent le terminal). Par d efaut warn et die ecrivent sur ce ux. ARGV : ce descripteur est un peu sp ecial, mais souvent bien pratique. Les lignes lues sont celles des chiers de la ligne de commande (donc les arguments pass es au programme sont consid er es comme des noms de chier) ; si le programme est lanc e sans argument, lentr ee standard est lue. NB : vous pouvez ecrire soit <ARGV> soit <> La variable sp eciale $ARGV contient le nom du chier en cours de lecture. Discutons un peu de la manipulation de chiers binaires. Les exemples de lecture de chiers donn es jusquici ne conviennent pas a ` de tels chiers mais plut ot ` a des chiers contenant du texte. Vous pouvez, pour cela, utiliser la fonction getc qui renvoie le prochain caract` ere disponible : $c = getc(FIC); Vous pouvez aussi faire usage de la fonction read qui lit un nombre d etermin e de caract` eres : $tailleLue = read(~FIC,~$tampon,~$taille` ALire ); Les ` la n du chier, ou sil y a un probl` donn ees seront plac ees dans la variable $tampon. A eme, le tampon nest pas compl` etement rempli. Cest pour cela que lon r ecup` ere la valeur de retour de read. Pour ecrire des donn ees non textuelles dans un chier, vous pouvez tout ` a fait utiliser les fonctions print et printf car les cha nes de caract` eres de Perl peuvent contenir le caract` ere de code ASCII z ero. On notera que la fonction write existe, mais nest pas linverse de read. Sil vous est n ecessaire dutiliser les fonctions dentr ee/sortie bas niveau, voici leurs noms en Perl : sysopen, sysread, syswrite et close.

7.6

Deuxi` eme exemple

Voici le prolongement de lexemple donn e pour les tables de hachage. Nous nallons plus consid erer que les mots sont contenus dans un tableau, mais nous allons les extraire dun chier. #!/usr/bin/perl -w use strict;

57

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

open(FILE,"<$filename.txt") or die"open: $!"; my($line,@words,$word,%total); while( defined( $line = <FILE> ) ) { @words = split( /\W+/, $line ); foreach $word (@words) { $word =~ tr/A-Z/a-z/; $total{$word}++; } } close(FILE); foreach $word (sort keys %total) { print "$word a et e rencontr e $total{$word} fois.\n"; } On eectue une boucle while sur les lignes du chier. Chaque ligne est alors d ecoup ee en mots par la fonction split (\W+ correspond aux suites de caract` eres non-alphanum eriques, nous verrons cela dans la suite lorsque nous etudierons les expressions r eguli` eres). Chaque mot est mis en minuscules au moyen de lop erateur tr (que nous expliquerons avec les expressions r eguli` eres).

7.7

Ex ecution de commandes avec open

Il est facile en Perl de lancer une commande shell et de r ecup erer sa sortie standard ou de fournir son entr ee standard. Pour lire la sortie standard dun programme, il sut dutiliser la syntaxe suivante : open(HANDLE,"commande par exemple : open(FIC1,"ls|") open(FIC2,"df -HT $device|") Les lignes lues via le descripteur de chier ainsi cr e e seront celles que la commande aurait ach ees ` a l ecran si on lavait lanc ee depuis un terminal. La syntaxe open(HANDLE,"commande") permet de lancer une commande. Les lignes ecrites dans le descripteur de chier constitueront son entr ee standard, par exemple : open(FIC3,"|gzip > $a.gz") open(FIC4,"|mail robert\@bidochon.org") Quoi de plus simple ?

7.8

Ecrire une table de hachage sur disque avec les chiers DBM

Le format DBM est un format de chier de hachage (clef/valeur) standardis e. Il existe en dehors de Perl. En Perl, il nous est possible de manipuler directement une table de hachage en la liant avec un tel chier : les valeurs de la table de hachage et du chier sont synchronis ees. Pour y acc eder nous utiliserons les fonctions dbmopen et dbmclose

58

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

Nous allons directement passer ` a un exemple. Il comporte deux phases : dans la premi` ere nous allons cr eer un chier DBM comportant un couple clef/valeur, dans la seconde nous utiliserons ce chier pour retrouver ce couple. Premier script : my %h; dbmopen(%h,"data",0644) or die($!); $h{prenom} = Larry; dbmclose(%h) or die($!); Un ensemble de chiers data* est alors cr e e. Ces chiers sont ensuite exploitables de la sorte : my %h; dbmopen(%h,"data",0644) or die($!); print "$h{prenom}\n"; dbmclose(%h) or die($!); Lors de cet appel ` a dbmopen la table %h retrouve la valeur quelle avait lors du dbmclose du premier script.

59

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

60

Chapitre 8

Expressions r eguli` eres


Nous abordons ici un sujet tr` es riche en d eveloppements : les expressions r eguli` eres. Perl en tire une partie de sa grande puissance pour lanalyse et le traitement des donn ees textuelles. La lecture de cette partie du document peut aussi int eresser toute personne utilisant grep, sed, Python, PHP, C, C++ et m eme Java. Atout important de Perl par rapport ` a dautres langages, les expressions r eguli` eres permettent de manipuler le texte de fa con tr` es puissante et tr` es concise. Lacquisition de leur ma trise peut sav erer dicile au d ebut, mais en vaut tr` es largement la chandelle, aussi bien pour programmer en Perl que pour utiliser les outils classiques du shell ou les autres langages pr ec edemment cit es. Au niveau vocabulaire, on utilise en anglais le terme regular expression (souvent abr eg e en regexp voire regex), ce qui a donn e en fran cais une traduction correcte expressions rationnelles et une traduction mot ` a mot expressions r eguli` eres. La seconde est entr ee dans les murs et sera donc utilis ee ici. On retrouve les expressions r eguli` eres dans certaines fonctions Perl que vous connaissez d ej` a, comme par exemple split ou grep ; mais elles existent aussi par le biais dop erateurs sp eciques.

8.1

Fonctionnalit es

Il existe deux types principaux de fonctionnalit es dans les expressions r eguli` eres : la correspondance (pattern matching en anglais : pattern=motif, matching=correspondance) et la substitution. La correspondance est le fait de tester (v erier) si une cha ne de caract` eres comporte un certain motif. Par exemple, on pourrait se poser les questions suivantes et y r epondre par un match : la variable $v commence-t-elle par un chire ? Comporte-t-elle au moins deux lettres majuscules ? Contient-elle une sous-cha ne r ep et ee deux fois dau moins 5 caract` eres ? Etc. Sa syntaxe est la suivante : m/motif/ Le m indique que nous voulons faire un match, les slashes (/) servent ` a d elimiter le motif recherch e (on verra plus loin comment utiliser dautres s eparateurs). Cette fonctionnalit e nous permettra aussi dextraire des sous-cha nes dune variable donn ee sans la modier. Par exemple, si je veux r ecup erer le premier nombre que comporte $v, jutiliserai aussi la correspondance. La substitution permet de faire subir des transformations a ` la valeur dune variable. Par exemple : remplacer dans la variable $v toutes les sous-cha nes toto par titi. Supprimer de $v tous les mots entre guillemets. Etc.

61

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

Sa syntaxe est la suivante : s/motif/cha ne/ Le s indique que nous voulons faire une substitution, les slashes (/) servent ` a d elimiter le motif recherch e ainsi que la cha ne de remplacement.

8.2

Bind

Pour lier une variable ` a une telle expression, il faut utiliser lop erateur =~ (dit bind en anglais). $v =~ m/sentier/ v erie si la variable $v comporte le mot sentier. On dit alors que la variable est li ee ` a lexpression r eguli` ere. Cette expression vaut vrai ou faux ; nous lutiliserons donc tr` es souvent dans une structure de contr ole de type if : if( $v =~ m/sentier/ ) { instructions } Dans les cas o` u le test est vrai, cest-` a-dire si la variable contient le motif (ici si $v contient sentier), les instructions seront ex ecut ees. Par cette op eration de bind, nous venons de lier une expression r eguli` ere ` a une variable. Par d efaut, une telle expression sapplique ` a la variable $_ (comme beaucoup de fonctions Perl). De la m eme fa con, $v =~ s/voiture/pieds/; remplace la premi` ere occurrence de voiture dans la variable $v par pieds (on verra plus loin comment remplacer toutes les occurrences). Le reste de $v nest pas modi e. Le point-virgule indique la n de linstruction. Pour la correspondance, il existe aussi lop erateur !~ qui equivaut ` a =~ suivi dune n egation de lexpression. if( $w !~ m/pieds/ ) { ... } est plus concis et est equivalent ` a if( ! ( $w =~ m/pieds/ ) ) { ... } Les instructions sont ex ecut ees si $w ne contient pas la cha ne pieds.

8.3

Caract` eres

Dans cette sous-partie et dans les suivantes, nous allons voir quels sont les motifs utilisables dans les expressions r eguli` eres. Dans le cas g en eral, un caract` ere vaut pour lui-m eme ; comprenez que lorsque lon utilise lexpression r eguli` ere m/a/ on v erie si la variable (ici non cit ee) contient le caract` ere a. Cela semble evident, mais il est bon de le dire. En eet, pour certains caract` eres sp eciaux, cela nest pas le cas. Ces caract` eres ont un r ole particulier dans les expressions r eguli` eres (nous allons voir cela dans la suite). Si vous avez besoin

62

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

de rechercher ces caract` eres, il faut donc les d esp ecier au moyen dun anti-slash (\). Voici la liste de ces caract` eres : \ | ( ) [ ] { } ^ $ * + ? . Il faut ajouter ` a cette liste le caract` ere choisi comme s eparateur. Pour le moment, seul le slash (/) est utilis e dans ce document, mais nous verrons plus tard quil est possible den changer. Par exemple $x =~ m/to\.to/ est vrai si la variable $x comporte les caract` eres t o . t o contigus. Les caract` eres sp eciaux habituels peuvent etre utilis es ; en voici quelques exemples : Motif \n \r \t \f \e Seuls les plus utiles sont pr esent es ici. Caract` ere saut de ligne retour chariot tabulation saut de page echappement

8.4

Ensembles

Le caract` ere . (point) correspond a ` un caract` ere quel quil soit (sauf \n (ce comportement peut etre chang e : nous verrons cela plus loin)). Cela signie qu` a lemplacement de ce point dans le motif pourra (devra) correspondre un caract` ere quelconque dans la variable. Par exemple, le motif m/t.t./ reconna tra toute variable comportant une lettre t suivie dun caract` ere quelconque, puis une autre lettre t, puis un autre caract` ere quelconque ; par exemple toute variable comportant une des cha nes suivantes correspondra au motif : tata, t%tK, tot9 ... Vous comprenez pourquoi il faut d esp ecier le caract` ere point avec un anti-slash si vous voulez chercher un point litt eral : sans cela un point matche avec nimporte quel caract` ere. Le motif [caract` eres] matche un caract` ere parmi ceux pr esents entre crochets. Par exemple [qwerty] peut reconna tre une de ces six lettres. Le motif m/t[oa]t[ie]/ reconna tra toute variable comportant une des quatre cha nes suivantes : toti, tati, tote ou tate. On comprendra ais ement que si un caract` ere est pr esent plusieurs fois dans cette liste, cela a le m eme eet que sil etait pr esent une seule fois : [aeiouyie] est equivalent ` a [aeiouy]. Il est possible de d enir des intervalles de caract` eres dans ces ensembles. Par exemple a-z equivaut aux 26 lettres minuscules de lalphabet. Par exemple [2a-zR] entrera en correspondance avec toute lettre minuscule ou bien avec le 2 ou bien avec le R majuscule. On peut aussi utiliser les ensembles A-Z ou 0-9 ; par extension tout intervalle est envisageable, par exemple R-Z ou toute autre combinaison tant que le num ero ASCII du premier caract` ere est inf erieur ` a celui du second. Autre exemple, le motif [ -~] correspond ` a un caract` ere ASCII imprimable et de num ero inf erieur ` a 127. Un intervalle peut prendre place au milieu dun motif quelconque : m/tot[a-zA0-9]V/ matche totaV, totbV ... totzV, totAV, tot0V ... tot9V. Si le caract` ere tiret (-) doit etre pr esent dans lensemble, il faut le mettre en premi` ere ou en derni` ere position an de lever toute ambigu t e possible avec un intervalle. Par exemple [a-z4-] matche soit une minuscule, soit un 4, soit un tiret. Le caract` ere ^ (accent circonexe) a un r ole particulier sil est plac e en d ebut dintervalle ; il prend le compl ementaire de lensemble, il faut le lire tout caract` ere sauf .... Par exemple [^ao] matche tout caract` ere sauf le a et le o. Le motif [^0-9] matche tout caract` ere non num erique.

63

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

Nous verrons un peu plus loin quil existe des raccourcis pour les ensembles les plus courants.

8.5

Quanticateurs

Les quanticateurs sappliquent au motif atomique (cest-` a-dire le plus petit possible) le pr ec edant dans lexpression r eguli` ere. Ils permettent de sp ecier un nombre de fois o` u ce motif peut/doit etre pr esent. Par exemple l etoile * indique que le motif peut etre pr esent z ero fois ou plus : m/a*/ se met en correspondance avec le mot vide, avec a, aa, aaa, aaaa ... Quand je dis quun quanticateur sapplique au motif atomique le plus petit possible, je veux dire par l` a que dans lexpression r eguli` ere m/za*/ l etoile sapplique uniquement ` a la lettre a et non au mot za. Nous verrons plus loin comment faire cela. Il est par ailleurs important de noter quun tel quanticateur est par d efaut gourmand, cest-` a-dire quil se met en correspondance avec le plus de caract` eres possible dans la variable li ee. Cela a son importance dans le cas dune substitution : si la variable $v contient la cha ne vbaaal, et si on eectue linstruction suivante : $v =~ s/ba*/hello/; la cha ne match ee par la premi` ere expression ba* sera baaa (le quanticateur matche le plus de caract` eres possible) et la substitution aura pour eet de donner pour valeur vhellol ` a la variable $v. Voici un tableau des quanticateurs : le motif pr esent 0 fois ou plus 1 fois ou plus 0 ou 1 fois n fois exactement au moins n fois au plus n fois entre m et n fois exemple m/a*/ m/a+/ m/a?/ m/a{4}/ m/a{2,}/ m/a{,3}/ m/a{2,5}/ mots match es mot vide, a, aa, aaa ... a, aa, aaa ... mot vide ou a aaaa aa, aaa, aaaa ... mot vide, a, aa ou aaa aa, aaa, aaaa ou aaaaa

* + ? {n} {n,} {,n} {n,m}

On remarquera que * est un raccourci pour {0,} ainsi que + pour {1,}, de m eme que ? pour {0,1}. Dans les exemples pr ec edents, tous les quanticateurs sont appliqu es ` a un caract` ere. On peut les appliquer ` a tout motif, par exemple ` a un ensemble : m/[0-9-]{4,8}/ recherche une cha ne comportant entre 4 et 8 caract` eres num eriques ou tirets contigus.

8.6

Ensembles (suite)

Nous allons ici enum erer un certain nombre de raccourcis pour des ensembles courants : \d : un chire, equivalent ` a [0-9] (d comme digit, chire en anglais) \D : un non-num erique, equivalent ` a [^0-9] \w : un alphanum erique, equivalent ` a [0-9a-zA-Z_] (w comme word, cest un caract` ere dun mot) \W : un non-alphanum erique, equivalent ` a [^0-9a-zA-Z_] \s : un espacement, equivalent ` a [ \n\t\r\f] (s comme space) \S : un non-espacement, equivalent ` a [^ \n\t\r\f]

64

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

On remarquera quun ensemble et son compl ementaire sont not es par la m eme lettre, lune est minuscule, lautre majuscule. Par exemple, lexpression r eguli` ere suivante : m/[+-]?\d+\.\d+/ permet de reconna tre un nombre d ecimal, sign e ou non : un caract` ere + ou - optionnel, au moins un chire, un point et enn au moins un chire.

8.7

Regroupement

Si dans notre exemple pr ec edent, nous souhaitons rendre optionnelle la partie d ecimale, on pourrait ecrire : m/[+-]?\d+\.?\d*/ rendant ainsi non-obligatoire la pr esence du point et celle des chires apr` es la virgule. Le probl` eme de cette expression est que la pr esence du point et de ces chires sont d ecorr el ees : lexpression r eguli` ere reconna tra un nombre o` u lune de ces deux parties serait pr esente et lautre absente. Or ce que lon veut, cest que le point et les chires qui le suivent soient rendus solidaires dans labsence ou la pr esence. Pour cela nous allons utiliser des parenth` eses pour eectuer un regroupement entre plusieurs motifs (ici le point et les chires) pour leur appliquer conjointement le m eme quanticateur. Lexpression r eguli` ere m/[+-]?\d+(\.\d+)?/ reconna t donc les nombres tels que nous les souhaitons. Pour marquer la m emoire de mes etudiants, jaime ` a leur dire que m/meuh{3}/ permet de meugler longtemps et que m/(meuh){3}/ de meugler plusieurs fois !

8.8

Alternatives

Il est possible davoir le choix entre des alternatives ; il faut pour cela utiliser le signe pipe (|) : lexpression m/Fred|Paul|Julie/ reconna t les mots comportant soit Fred, soit Paul, soit Julie. De la m eme fa con, lexpression m/Fred|Paul|Julie Martin/ reconna t les cha nes comportant soit Fred, soit Paul, soit Julie Martin mais rien noblige Fred ` a sappeler Fred Martin ni Paul ` a sappeler Paul Martin, comme on aurait sans doute aim e que cela se fasse (dans ces deux derniers cas, seul le pr enom est reconnu, pas le nom). Pour cela, vous lavez compris, un regroupement est n ecessaire. Lexpression r eguli` ere m/(Fred|Paul|Julie) Martin/ reconna t les trois fr` eres et sur de la famille Martin.

8.9

Assertions

Une assertion marque une position dans lexpression, elle ne correspond ` a aucun caract` ere (aucune consommation de caract` eres nest eectu ee). Par exemple, laccent circonexe (^) correspond au d ebut de la cha ne. Lexpression $v =~ m/^a/ est vraie si la variable $v commence par la lettre a. Le signe ^ a donc plusieurs r oles. Sil est au d ebut dun ensemble entre crochets, il permet den prendre le compl ementaire ; sil est au d ebut de lexpression r eguli` ere, il marque le d ebut de la cha ne. On veillera ` a ne pas les confondre. Le dollar ($) correspond ` a la n de la cha ne. Lexpression $v =~ m/c$/ est vraie si la variable $v se termine par la lettre c.

65

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

Ces deux assertions sont les plus courantes. Il en existe dautres dont \b qui marque un d ebut ou une n de mot ; cest-` a-dire entre \w et \W (ou entre \w et une n ou d ebut de cha ne). Par exemple m/\btoto\b/ matche toto, toto autreMot, unMot toto autreMot, etc. mais pas unMot totoMotColl e car le deuxi` eme \b ne peut pas etre vrai entre la lettre o et la lettre M.

8.10

R ef erences arri` eres

Le regroupement au moyen des parenth` eses est dit m emorisant. Cela signie que lexpression match ee par ce regroupement est gard ee en m emoire par le moteur dexpressions r eguli` eres et quelle pourra servir ` a nouveau dans la suite de lexpression. Lexemple typique consiste ` a se demander si une variable contient le m eme mot r ep et e deux fois. Lexpression m/\w+.*\w+/ ne saurait nous satisfaire ; en eet elle matche toute valeur comportant deux mots pouvant etre di erents. La solution est dutiliser les notations \1, \2 etc qui font r ef erence aux sous-cha nes match ees par (respectivement) la premi` ere, la deuxi` eme, etc. expression entre parenth` eses (il nest pas possible dacc eder ` a une expression au-del` a de \9, mais cela nous donne d ej` a une expression tr` es lourde ` a g erer). Par exemple, la r eponse ` a notre probl` eme de deux occurrences dun m eme mot est la suivante : m/(\w+).*\1/ Le \w+ matchera un mot, les parenth` eses m emoriseront la valeur alors trouv ee, le .* permet comme avant quil y ait un nombre ind eni de caract` eres quelconques entre les deux occurrences, enn \1 fait r ef erence ` a la valeur trouv ee par le \w+ pr ec edent. Autre exemple basique, m/(.+), (.+), \2 et \1/ matchera une cha ne de caract` eres comportant un certain premier motif suivi dune virgule et dune espace, puis un certain second motif egalement suivi dune virgule et dune espace, puis ce second motif doit etre r ep et e suivi dune espace, du mot et puis dune autre espace et enn du premier motif. Ces motifs m emoris es sont aussi accessibles depuis le second membre dune substitution au moyen des notations $1, $2 etc. Par exemple, linstruction suivante $v =~ s/([0-9]+)/"$1"/ place des guillemets de part et dautre du premier nombre de la variable $v : sdq 32sq deviendra sdq "32"sq. Vous allez me dire : mais cela signie que d` es que lon fait un regroupement, le moteur dexpressions r eguli` eres m emorise la valeur et si lon nutilise pas certains regroupements et que dautres sont au-del` a de 9, on ne peut donc pas sen servir ... Je vais alors vous dire : il existe un regroupement non-m emorisant ! La notation (?:motifs) permet de regrouper les motifs (pour leur appliquer le m eme quanticateur par exemple) sans pour autant quune m emorisation nait lieu. Par exemple m/(.*) (?:et )+(.*) avec \1 \2/ matchera par exemple les valeurs suivantes : Paul et Julie avec Paul Julie et lala et et lili avec lala lili

8.11

Variables d enies

Ces variables sp eciales $1, $2 etc. sont aussi accessibles apr` es lexpression r eguli` ere (jusqu` a la n du bloc courant ou une autre expression r eguli` ere). Elles correspondent bien s ur aux sous-cha nes match ees entre parenth` eses. Nous pouvons nous en servir pour extraire certaines sous-cha nes et les utiliser ensuite.

66

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

Il existe aussi trois autres variables, dont je vous d econseille lusage, mais qui peuvent etre int eressantes : $& vaut toute la sous-cha ne matchant, $ vaut toute la sous-cha ne qui pr ec` ede la sous-cha ne matchant, $ vaut toute la sous-cha ne qui suit la sous-cha ne matchant. Je vous d econseille en eet lusage de ces trois variables sp eciales car leur pr esence dans un script active pour tout le script des m ecanismes particuliers dans le moteur dexpressions r eguli` eres, qui ont pour eet secondaire den ralentir fortement la vitesse dex ecution. Si vous avez besoin de ces variables dans un petit script qui ne sert qu` a cela, pas de probl` eme pour les utiliser, mais evitez leur usage dans un projet de plusieurs milliers de lignes ou dans un script CGI appel e 10 fois par seconde. Voici un exemple : my $v = "za aa et tfe"; if( $v =~ /(a+) et ([a-z])/ ) { print "$1\n"; # aa print "$2\n"; # t print "$&\n"; # aa et t print "$\n"; # za print "$\n"; # fe } Il est bon de savoir que cela est possible sans obligatoirement se souvenir du nom de toutes les variables.

8.12

Valeurs de retour de m//

Je vous ai dit jusquici que lop erateur de correspondance m// retournait vrai ou faux ; cela est exact en contexte scalaire. Cest par exemple le cas lorsquon ecrit : if( $w =~ m/motif/ ) { ... } On parle alors de correspondance. Mais en contexte de liste, cet op erateur retourne la liste des el ements match es entre parenth` eses (les fameux $1, $2 etc, et cela sans limite ` a 9). Par exemple : ($x,$y) = ( $v =~ m/^(A+).*(B+)$/ ); place dans $x les caract` eres A du d ebut de la cha ne $v et dans $y la suite de caract` eres B terminant la cha ne. On parle ici dextraction. Il se peut tout ` a fait que cette op eration echoue (en cas dabsence des lettres aux endroits attendus par exemple). Cet usage peut etre combin e avec lutilisation dun test. On peut en eet ecrire : if( ($x,$y) = ( $v =~ m/^(A+).*(B+)$/ ) ) { ... } auquel cas, on nex ecute les instructions du if que si $v comporte au moins un A en son d ebut et un B ` a sa n. Dans ce cas, les variables $x et $y re coivent les valeurs entre parenth` eses. On a alors combin e correspondance et extraction.

67

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

8.13

Exemples de probl` emes

Dans cette partie, je vais vous pr esenter di erents petits exercices pratiques sur les expressions r eguli` eres. Les solutions se trouvent un peu plus loin. Essayez de ne pas vous pr ecipiter pour les lire, prenez le temps de chercher dans ce qui pr ec` ede ce quil vous faut pour r esoudre les probl` emes. Que font les instructions suivantes ? if( $v =~ m/\w+ \d* ?:/ ) { ... } if( $v =~ m/^"([a-z]{4,})",/ ) { print "$1\n"; } if( $v =~ m/([a-z]+)[a-z]*\1/ ) { print "$1\n"; } ($n,$m) = ( $v =~ m/(\w+)=(\d+)/ ); if( ($n,$m) = ( $v =~ m/(\w+)=(\d+)/ ) ) { print "$n $m\n"; } $v =~ s/^ServerRoot/DocumentRoot/; $v =~ s/^C="([^"]*)"/D=$1/; $v =~ s/ +/ /; Ecrivez les instructions r ealisant les actions suivantes : V erier que $v comporte velo. V erier que $v nit par une lettre majuscule. V erier que $v comporte deux fois de suite un m eme nombre (s epar ees par un signe dop eration math ematique). Extraire de $v chacun des deux premiers caract` eres. Extraire de $v les deux premiers mots. Extraire de $v le dernier caract` ere non-num erique. Remplacer dans $v rouge par bleu. Supprimer de $v les espaces en n de cha ne. Supprimer les guillemets autour du nombre entier de $v. Je rel` eve les copies dans 30 minutes ;-)))

8.14

Solutions des probl` emes

Voici les solutions de la premi` ere partie des probl` emes : if( $v =~ m/\w+ \d* ?:/ ) { ... } On v erie que $v comporte un mot dune lettre ou plus (\w+) suivi dune espace, puis eventuellement dun nombre (\d*), puis dune espace optionnelle ( ?) et enn du signe deux-points. Si cest le cas, les instructions du if sont ex ecut ees.

68

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

if( $v =~ m/^"([a-z]{4,})",/ ) { print "$1\n"; } On v erie que $v commence par un guillemet, suivi dau moins quatre lettres minuscules (que lon m emorise), dun autre guillemet puis dune virgule. Si la variable est du bon format, ces quatre lettres (ou plus) sont ach ees. if( $v =~ m/([a-z]+)[a-z]*\1/ ) { print "$1\n"; } On recherche quelque chose de la forme : une suite de caract` eres en minuscules (au moins 1) puis une deuxi` eme suite de caract` eres en minuscules ( eventuellement aucun) et enn la m eme suite de caract` eres que la premi` ere suite. On cherche donc un mot (suite de lettres) dont un certain nombre de lettres se r ep` etent. Si la variable $v comporte un tel mot, on achera ces lettres r ep et ees. ($n,$m) = ( $v =~ m/(\w+)=(\d+)/ ); On recherche une suite alphanum erique, un signe egal puis un nombre. Il sagit dune aectation. La variable et le nombre sont respectivement aect es aux variables $n et $m. if( ($n,$m) = ( $v =~ m/(\w+)=(\d+)/ ) ) { print "$n $m\n"; } Si la variable $v est du format pr ec edemment cit e, on ache la variable et le nombre de laectation. $v =~ s/^ServerRoot/DocumentRoot/; On remplace ServerRoot par DocumentRoot sil est en d ebut de cha ne. $v =~ s/^C="([^"]*)"/D=$1/; On recherche en d ebut de cha ne une sous-cha ne C="motif" dont motif ne comporte pas de ". Tout cela est remplac e par D=motif o` u motif est inchang e. $v =~ s/ +/ /; Remplace dans $v la premi` ere suite despaces par une seule espace. Voici les solutions de la seconde partie des probl` emes : V erier que $v comporte velo. Pas trop dur : il sagit dun simple match. if( $v =~ m/velo/ ) { ... } V erier que $v nit par une lettre majuscule. Match ici aussi. Le dollar nous permet de nous accrocher en n de cha ne : if( $v =~ m/[A-Z]$/ ) { ... } V erier que $v comporte deux fois de suite un m eme nombre (s epar ees par un signe dop eration math ematique). Encore un match. Nous cherchons un nombre \d+ que nous m emorisons (parenth` eses). Un signe doit suivre (il faut d esp ecier le signe de la division car il est aussi le s eparateur de lexpression r eguli` ere). Finalement le m eme nombre quavant doit etre pr esent (\1) :

69

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

if( $v =~ m/(\d+)[+*\/-]\1/ ) { ... } Extraire de $v chacun des deux premiers caract` eres. Nous allons utiliser un match pour faire de lextraction : on se place en d ebut de cha ne avec ^, on prend un caract` ere avec . que lon m emorise, puis de la m eme fa con pour le deuxi` eme. Vous noterez que, dans ce cas, lusage de la fonction substr est possible (et indiqu e ...) ($prem,$deux) = ( $v =~ m/^(.)(.)/ ); Extraire de $v les deux premiers mots. La m ethode est la m eme que pour lexemple pr ec edent. Le seul point un peu d elicat ` a voir, cest quentre deux mots (\w+), il doit forcement y avoir des caract` eres non-mot (\W+) : ($prem,$deux) = ( $v =~ m/^\W*(\w+)\W+(\w+)/ ); Extraire de $v le dernier caract` ere non-num erique. De la m eme fa con, apr` es le dernier caract` ere non-num erique, il ny a que des num eriques (z ero ou plus), le dollar pour se placer ` a la n de la cha ne : ($c) = ( $v =~ m/(\D)\d*$/ ); Remplacer dans $v rouge par bleu. Facile (seule la premi` ere occurrence est remplac ee) : $v =~ s/rouge/bleu/; Supprimer de $v les espaces en n de cha ne. On va remplacer tous ces espaces par rien : $v =~ s/ +$//; Supprimer les guillemets autour du nombre entier de $v. On va faire une substitution, en m emorisant ce fameux nombre : $v =~ s/"(\d+)"/$1/; Les fonctionnalit es les plus importantes ont et e abord ees vous voil` a par es pour la suite des op erations. Voici dautres fonctionnalit es plus pouss ees et donc plus int eressantes. Les quanticateurs non-gourmands et surtout les options sont des points importants.

8.15

Choisir son s eparateur

Il est tout ` a fait possible de choisir un autre caract` ere que le slash (/) comme s eparateur. Il se peut par exemple que nous ayons ` a manipuler des URL ; dans ce cas, le caract` ere slash fait partie des motifs que lon est susceptible de rechercher ; il est de ce fait fort fastidieux de devoir d esp ecier chaque slash utilis e, comme par exemple dans lexpression suivante (ici une version simpli ee de lexpression r eguli` ere qui reconna t les URL) : if( $v =~ m/http:\/\/\w+\/(\w+\/)*\w+\.html/ ) Il serait plus lisible de prendre un autre s eparateur, le signe egal par exemple :

70

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

if( $v =~ m=http://\w+/(\w+/)*\w+\.html= ) La plupart des caract` eres est utilisable comme s eparateur. Si vous utilisez le slash comme s eparateur, la lettre m nest pas obligatoire pour faire un match : $v =~ /velo/ est equivalent ` a $v =~ m/velo/ Libre ` a vous de choisir le bon s eparateur, sachant que dans la grande majorit e des cas le slash est utilis e.

8.16

Options

Apr` es le dernier s eparateur des op erateurs de correspondance (m ou rien) ou de substitution (s) il est possible dindiquer une ou plusieurs options. Les syntaxes sont donc : m/motif/options et s/motif1/motif2/options Les options permettent de modier le comportement du moteur dexpressions r eguli` eres. Voici la liste de quelques options parmi les plus utiles : Loption i rend le motif insensible ` a la casse (minuscules/majuscules) : lexpression r eguli` ere m/toto/i recherche le mot toto indi eremment en majuscules ou en minuscules. On aurait pu ecrire m/[tT][oO][tT][oO]/ Loption g permet deectuer toutes les substitutions dans la variable. Par d efaut, lop erateur s/// eectue la transformation de la premi` ere occurrence du motif recherch e et ne va pas plus loin. Si cette option est sp eci ee, le moteur dexpressions r eguli` eres avancera dans la variable tant quil pourra y faire des substitutions. Par exemple, lexpression $v =~ s/ +/ /g; remplace chaque groupe de plusieurs espaces par une seule (contrairement ` a un des exercices pr ec edents o` u lexpression r eguli` ere ne rempla cait que la premi` ere occurrence du motif trouv e). Voyez par exemple le code suivant : $t = $s = "sd et sd"; $t =~ s/sd/toto/; # => "toto et sd" $s =~ s/sd/toto/g; # => "toto et toto" Loption g est aussi utilisable en correspondance. Elle permet ` a cet op erateur de fonctionner avec etat, cest-` a-dire de poursuivre sa recherche en partant du dernier motif trouv e. On lutilise typiquement dans une boucle ; voyez cet exemple : my $v = "aatobbtbvvtczz"; while( $v =~ m/t./g ) { print "$&\n"; } Lachage eectu e est le suivant : to tb tc Dans une substitution, loption e evalue le membre de droite comme une expression Perl, et remplace le motif trouv e par la valeur de cette expression. Par exemple : $s =~ s/(\d+)/fonction($1)/e; remplace le premier nombre trouv e dans la variable $s par la valeur de retour de la fonction appliqu ee ` a ce nombre.

71

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

Autre exemple, avec des options combin ees celui-l` a: $s =~ s/0x([0-9a-f]+)/hex($1)/gei; transforme tous les nombres hexad ecimaux en nombres d ecimaux dans la variable $s. Loption o a pour eet quune seule compilation de lexpression r eguli` ere a lieu. En temps normal, ` a chaque fois que linterpr eteur Perl passe sur une expression r eguli` ere, il la compile (pour ceux qui connaissent, il construit lautomate) ; avec cette option, la compilation a lieu une seule fois lors de la premi` ere ex ecution. Le principal avantage est un temps dex ecution plus court pour le programme, si cette expression est utilis ee plusieurs fois. Les inconv enients sont une place m emoire occup ee (inutilement si lexpression r eguli` ere ne sert que peu de fois) et que, si le motif peut changer (voir la suite concernant les variables dans les motifs), ce changement ne sera pas pris en compte. Il existe deux options (exclusives lune de lautre) qui permettent de changer certains comportements sur les d ebuts et ns de cha nes. Pour les exemples qui suivent, je pose $s = "mot\nlu"; : Par d efaut : mode interm ediaire. Les caract` eres ^ $ se positionnent en d ebut/n de cha ne. Par exemple ($s=~m/mot$/) est faux. Le caract` ere . ne matche pas \n. Par exemple ($s=~m/t.lu$/) est faux. Avec loption s : on travaille en ligne unique. Les caract` eres ^ $ se positionnent en d ebut/n de cha ne. Par exemple ($s=~m/mot$/s) est faux. Le caract` ere . peut matcher \n. Par exemple ($s=~m/t.lu$/s) est vrai. Avec loption m : on travaille en ligne multiple. Les caract` eres ^ $ se positionnent en d ebut/n de ligne. Par exemple ($s=~m/mot$/m) est vrai. Le caract` ere . ne matche pas \n. Par exemple ($s=~m/t.lu$/m) est faux.

8.17

Quanticateurs non-gourmands

Posons-nous le probl` eme suivant. Nous avons une cha ne de la forme "s r g e y" de laquelle nous souhaitons extraire les cha nes qui sont entre guillemets. La premi` ere id ee est d ecrire quelque chose comme : /.*/ ce qui nest pas satisfaisant, car dans notre exemple la cha ne r g e serait match ee. En eet, je vous avais dit que les quanticateurs consomment le plus de caract` eres possible, nous voici dans une illustration du ph enom` ene. On parle de quanticateurs gourmands, gloutons, avides ou greedy en anglais. Il existe des quanticateurs dont le comportement est, au contraire, de consommer le moins de caract` eres possible. On parle alors de quanticateurs non-gourmands, economes ou frugaux. Leur notation est la m eme que celle des quanticateurs que vous connaissez mais suivie dun point dinterrogation : Gourmand * + ? {n,m} Non gourmand *? +? ?? {n,m}?

Pour revenir ` a notre exemple, on peut ecrire /.*?/ et la correspondance sera eectu ee telle que nous la souhaitions.

72

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

Vous allez me dire, car vous avez tout compris aux expressions r eguli` eres ;-) , quil est possible de faire cela sans utiliser ces quanticateurs non-gourmands. Dans notre exemple, on peut tout ` a fait ecrire : /[^]*/ ce qui permet de ne pas accepter de guillemets entre les guillemets. Je r epondrais que je suis daccord avec vous. Mais voici un autre exemple o` u les quanticateurs non-gourmands nous sauvent la mise. Si cette fois la cha ne a pour valeur "s STARTrSTOP g STARTe fSz zSTOP y" et que nous souhaitons extraire les sous-cha nes plac ees en les marqueurs START et STOP, il nous est fort ais e d ecrire : /START.*?STOP/

8.18

Substitution de variables dans les motifs

Il est tout ` a fait possible de mettre une variable dans un motif dune expression r eguli` ere. Cette variable sera substitu ee par son contenu. Par exemple : $s = "velo"; if( $v =~ m/$s$/ ) { ... } La variable sera substitu ee et la recherche seectuera sur le mot velo en n de cha ne ; le premier dollar concerne la variable $s, le second marque la n de cha ne. Perl sait automatiquement si un $ correspond ` a une variable ou ` a la sp ecication n de cha ne. Il est ainsi possible de rechercher la valeur dune variable dans une autre. La m eme chose est possible avec la substitution, aussi bien pour le premier membre que pour le second. Notez cependant que si la variable substitu ee contient des caract` eres sp eciaux au sens des expressions r eguli` eres, ils seront vus comme tels. Si dans notre exemple, la variable $s avait pour valeur la cha ne ve(lo, le moteur dexpression r eguli` ere nous signalerait une erreur due ` a la parenth` ese ouvrante qui nest pas referm ee, exactement comme si nous avions ecrit : if( $v =~ m/ve(lo$/ ) { ... } # incorrect

Cela peut aussi poser des probl` emes de s ecurit e si le programmeur ne sait pas ce que peut contenir la variable substitu ee (par exemple si sa valeur provient de lutilisateur). Il existe pour cela une fonction quotemeta qui prend en param` etre une cha ne de caract` eres et renvoie cette m eme cha ne en ayant d esp eci e les caract` eres sp eciaux. $s = "fds(ds"; $s2 = quotemeta($s); print "$s2\n"; # affiche if( $v =~ m/$s2/ ) { ... }

fds\(ds

Pensez ` a toujours utiliser cette fonction lorsque vous voulez placer une variable dans un motif ; cela r esout bien des probl` emes.

8.19

Op erateur tr

Cet op erateur ne concerne pas vraiment les expressions r eguli` eres, mais il en est proche. Mettez de c ot e ce que vous venez dapprendre sur celles-ci pour lire la suite.

73

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

tr est un op erateur de translation lettre ` a lettre (on parle de translitt eration). Voici sa syntaxe : tr/cha ne1/cha ne2/ ou encore y/cha ne1/cha ne2/ Les deux cha nes doivent etre de la m eme longueur car cet op erateur va remplacer la premi` ere lettre de la premi` ere cha ne par la premi` ere lettre de la seconde cha ne, la deuxi` eme lettre de la premi` ere cha ne par la deuxi` eme lettre de la seconde cha ne, etc. Cette transformation a lieu sur la variable li ee ou sur $_ par d efaut. Voici un petit exemple : $s = "azerty"; $s =~ tr/abcde/01234/; print "$s\n"; # affiche 0z4rty Dans la variable $s, tous les a seront transform es en 0, tous les b en 1, etc, tous les e en 4 etc. Il est possible dutiliser des intervalles : $s =~ tr/a-z/A-Z/; met par exemple le contenu de la variable en majuscules. Cest lun des seuls usages courants de lop erateur tr.

8.20

Un dernier mot sur les expression r eguli` eres

Les expressions r eguli` eres sont un outil tr` es puissant. Les ma triser ouvre des portes au programmeur. Certes, il est souvent dicile de rentrer dans le jeu, mais cet eort est r ecompens e par de nouvelles possibilit es inimaginables avant. Les expressions r eguli` eres de Perl sont si puissantes et bien pens ees que de nombreux langages les impl ementent, en se vantant d etre perl5-regexes compliant ! On peut, par exemple, citer la librairie pcre du langage C, dont le nom provient des initiales de Perl-compatible regular expressions ... Sachez aussi que toutes les fonctionnalit es des expressions r eguli` eres nont pas et e trait ees ici. Les plus courantes ou importantes le sont, mais il en existe dautres encore ... Sachez de plus que les expressions r eguli` eres, cest bien, mais il faut savoir quand les utiliser et quand ne pas les utiliser.

74

Chapitre 9

R ef erences
Les r ef erences permettent de b atir des structures complexes et compos ees : tableau de tableaux ou de tables de hachage et inversement, table de hachage de tableaux ou de tables de hachage ... Le terme de r ef erence en Perl correspond ` a peu pr` es ` a celui de pointeur en C et C++ et ` a celui de r ef erence en Java. Les habitu es du C ou C++ noteront que les calculs sur r ef erences sont interdits en Perl, ce qui permet d eviter toutes sortes de probl` emes dus ` a des acc` es m emoire erron es (plus de Segmentation fault). Chaque variable, quelle soit scalaire, tableau ou table de hachage, est pr esente ` a une position donn ee dans la m emoire. Une r ef erence vers une variable est (sch ematiquement) ladresse m emoire de cette variable. Une telle r ef erence peut elle-m eme etre stock ee dans une variable scalaire.

9.1

R ef erences sur scalaire

Lop erateur qui permet de prendre la r ef erence dune variable est lanti-slash (\) : \$v est la r ef erence de la variable $v my $refv = \$v; Ici la variable $refv (on aurait pu choisir un tout autre nom pour cette variable) est une r ef erence vers la variable $v. Une variable de type r ef erence, quel que soit celui de la variable quelle r ef erence (scalaire, tableau ou table de hachage), est un scalaire. On peut repr esenter la relation entre ces deux variables de la fa con suivante :

$refscalaire $v 43.5
La variable $refv contient ladresse de la variable $v (ainsi que linformation consistant ` a savoir que $v est une variable scalaire). On dit que $refv pointe vers $v, car on va pouvoir manipuler $v (lacher, la modier etc) en utilisant $refv ; on repr esente ce lien par une ` eche de $refv vers $v.

75

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

Il nous est alors possible de manipuler $v au travers de $refv. La notation $$refv (donc avec deux dollars) est equivalente ` a $v tant que $refv pointe vers $v. Autrement dit, la notation $$refv equivaut ` a la variable scalaire point ee par la r ef erence $refv. Dit de mani` ere plus prosa que, on va acc eder ` a la variable quil y a au bout de la r ef erence (au bout de la ` eche du sch ema). On dit alors que lon d er ef erence la variable $refv. Pour faire un parall` ele avec le langage C, il sagit de l equivalent de l etoile (*) appliqu ee ` a un pointeur. Revenons sur notre exemple. Nous d eclarons une variable scalaire $v que nous initialisons. Nous d eclarons ensuite une autre variable scalaire $refv ` a laquelle on aecte ladresse de $v ; $refv est donc une r ef erence sur $v : my $v = -43.5; my $refv = \$v; On ache la valeur de la r ef erence : print "$refv\n"; # affiche SCALAR(0x80ff4f0)

On voit bien alors que la r ef erence pointe vers une variable de type scalaire (SCALAR) dont ladresse m emoire est ach ee en hexad ecimal. Achons maintenant la variable point ee par $refv (cest-` a-dire $v ici) : print "$$refv\n"; # affiche -43.5

Lachage eectu e est -43.5 (cest-` a-dire la valeur de $v). Cette notation $$refv est equivalente ` a $v puisque $refv est une r ef erence sur $v. Cette equivalence vaut aussi bien lorsque lon a besoin de la valeur de $v (achage etc) que lorsque lon veut aecter une nouvelle valeur ` a $v : $$refv = 56; # affecte 56 a ` $v

On aecte 56 ` a $$refv, cest-` a-dire ` a $v. Si on ache cette variable, on voit bien quelle contient cette nouvelle valeur : print "$$refv\n"; print "$v\n"; # affiche 56 # affiche 56

Rien de bien sorcier.

9.2

Utilisation des r ef erences sur scalaire

` quoi peut bien servir une r A ef erence sur un scalaire ? Par exemple ` a le modier dans une fonction : sub f { my ($ref) = @_; $$ref = 0; }

76

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

Cette fonction prend en argument une r ef erence et aecte 0 a ` la variable scalaire point ee par cette r ef erence. On pourrait lutiliser ainsi : f( $refv ); Ce qui aurait pour eet de mettre la variable $v ` a la valeur 0. On pourrait aussi ecrire directement : f( \$v ); Voici un autre exemple simple dutilisation des r ef erences : sub f2 { my $w = 43; return \$w; } Cette fonction f2 d eclare une variable locale $w et renvoie une r ef erence vers cette variable. Contrairement ` a ce quil se passe en C, ceci est tout ` a fait l egal et sans risque en Perl. Voici comment utiliser cette fonction : my $reff = f2(); La variable scalaire $reff devient donc une r ef erence vers une variable scalaire valant 43. Cette variable scalaire valant 43 est lancienne variable $w de la fonction f2. La variable $reff pointe donc vers une variable qui na plus de nom : dans f2 elle sappelait $w, mais en dehors de lappel ` a cette fonction qui la cr e ee, elle na plus de nom.

$reff 0
En temps normal, une variable locale ` a une fonction est d etruite lorsque lon sort de la fonction. Mais tant quil existe une r ef erence vers la variable, elle est conserv ee en m emoire. Cest le garbage-collector (ramasse-miette ou glaneur de cellules) qui la lib erera lorsque plus aucune r ef erence sur la variable nexistera. Il faut noter que lors dun prochain appel ` a la fonction f2, une autre variable $w sera cr e ee ind ependante de la premi` ere ; il ny aura donc pas deet de bord sur la premi` ere r ef erence renvoy ee. Nous sommes ici en pr esence dune fonction qui peut faire oce de g en erateur de r ef erences sur scalaire ;-)

9.3

R ef erences sur tableau

Il est possible de cr eer une r ef erence sur un tableau. Lop erateur qui permet cela est le m eme que pour les scalaires ; il sagit de lanti-slash (\) appliqu e` a une variable de type tableau :

77

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

my @t = (23, "ab", -54.4); my $reft = \@t; La variable scalaire $reft est donc une r ef erence vers le tableau @t :

$reft @t 0 23 1 ab 2 54.4

Pour d er ef erencer une telle r ef erence, il convient dutiliser une arobase (@) : @$reft est equivalent ` a @t. On peut ainsi utiliser la valeur de @t en utilisant $reft : my @t2 = @$reft; foreach my $e (@$reft) { .... } On peut aussi modier @t de la sorte : @$reft = (654.7, -9, "bonjour"); Si, pour acc eder au i` eme el ement de @t, il etait possible d ecrire $t[i], il est maintenant possible d ecrire $$reft[i]. On peut alors dire, de mani` ere sch ematique et pour xer les choses, que la notation $reft est equivalente au nom t de la variable dans toutes les syntaxes utilisant ce tableau (partout o` u lon peut ecrire t, on peut ecrire $reft ` a la place, tant que $reft pointe sur @t). Voici, en eet, un r ecapitulatif des equivalences de notations : Tableau t @t $t[i] $t[i] R ef erence $reft @$reft $$reft[i] $reft->[i]

Cette derni` ere notation $reft->[i] est equivalente ` a $$reft[i] et correspond donc au i` eme el ement du tableau r ef erenc e par $reft. Cest la notation la plus souvent utilis ee pour cela ; elle rappelle la m eme notation ` eche (->) du langage C. Lexpression $reft->[1] = "coucou"; aecte donc ` a l el ement dindice 1 du tableau point e par $reft une nouvelle valeur. Munis des r ef erences, il va maintenant nous etre possible de cr eer des tableaux de tableaux. Cela etait pour le moment impossible en raison de laplatissement des listes. Une r ef erence etant un scalaire, il va nous etre possible de stocker une r ef erence comme valeur dans un tableau : my @t1 = ( 16, -33 ); my @t2 = ( "el", 0.3, 4 ); my @t = ( 6, \@t1, \@t2, "s" );

78

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

Le tableau @t comporte donc un premier el ement valant 6, un deuxi` eme etant une r ef erence vers un tableau ` a deux el ements, un troisi` eme une r ef erence vers un tableau ` a trois el ements et enn un el ement valant la cha ne "s". Ce qui peut se repr esenter sous la forme suivante :

@t 0 6 1 2 3 s

el

0.3

16

33

Vous noterez bien que la syntaxe suivante correspond ` a la cr eation dun tableau ` a sept el ements (aplatissement des listes) : my @t2 = ( 6, ( 16, -33 ), ( "el", 0.3, 4 ), "s" ); Nous verrons dans la suite dautres syntaxes pour construire des tableaux de tableaux.

9.4

R ef erences sur table de hachage

De la m eme fa con que pour les scalaires et pour les tableaux, la cr eation dune r ef erence vers une table de hachage utilise lop erateur anti-slash (\) : my %h = ( Paul => 21, Julie => 19 ); my $refh = \%h; La variable scalaire $refh est donc une r ef erence vers la table de hachage %h :

$refh %h Julie Paul => => 19 21

Pour d er ef erencer une r ef erence vers une table de hachage, il faut utiliser le caract` ere pourcentage (%) ; %$refh est equivalent ` a %h :

79

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

my %h2 = %$refh; foreach my $k (keys %$refh) { ... } Les deux notations suivantes permettent dacc eder ` a la valeur associ ee ` a la clef Paul : $$refh{Paul} et $refh->{Paul} sachant que la seconde est la plus utilis ee pour des raisons identiques aux cas des tableaux. $refh->{Jacques} = 33; Voici un r ecapitulatif des equivalences : Hash h %h $h{Paul} $h{Paul} R ef erence $refh %$refh $$refh{Paul} $refh->{Paul}

Voici une fa con dacher tous les couples clef/valeur de la table de hachage r ef erenc ee par $refh : foreach my $k (keys %$refh) { print "$k $refh->{$k}\n"; } Cette notation ` eche rend lexpression plut ot lisible.

9.5

R eexions ` a propos des r ef erences

On a vu que pour d er ef erencer une r ef erence vers un scalaire on utilise le caract` ere dollar ($), vers un tableau le caract` ere arobase (@) et vers une table de hachage le caract` ere pourcentage (%). Mais que se passerait-il sil nous venait ` a lid ee de ne pas choisir le bon caract` ere de d er ef erencement, par exemple dutiliser le dollar pour une r ef erence sur tableau ou bien le pourcentage pour une r ef erence sur scalaire ? Narriverons-nous pas ` a des incoh erences comme en C ? La r eponse est non, car linterpr eteur veille au grain. Il refusera de consid erer comme un tableau une variable scalaire par exemple. En cas dincompatibilit e de type, un de ces trois messages sera ach e lors de lex ecution et le programme prendra n : Not a SCALAR reference at script.pl line 23. Not an ARRAY reference at script.pl line 23. Not a HASH reference at script.pl line 23. Comme une r ef erence peut pointer vers nimporte quel type de structure (scalaire, tableau, table de hachage), cette v erication ne peut avoir lieu quau moment de lex ecution. De plus, les habitu es du langage C seront invit es ` a se mettre une bonne fois pour toutes dans la t ete :-) quil ny a pas darithm etique possible sur les r ef erences en Perl. Ajouter 1 ` a une r ef erence ne correspond pas ` a pointer vers l el ement dindice 1 dun tableau, mais ` a faire perdre le caract` ere r ef erence ` a la variable (elle devient un scalaire comme un autre) :

80

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

my $v my $r print $r++; print

= 45; = \$v; "$r\n"; # affiche SCALAR(0x80fd4c4) "$r\n"; # affiche 135255237

On voit bien ici que la variable $r perd son caract` ere sp ecique de r ef erence ; elle a toujours pour valeur ladresse de la variable (ici incr ement ee de 1 : 80fd4c4 est la repr esentation hexad ecimale du nombre 135255236), mais nest plus une r ef erence, il sera donc impossible de la d er ef erencer. Notez aussi quune r ef erence peut changer de valeur, cest-` a-dire de variable point ee et donc de type de variable point ee : my $v = 45; my @t = ("ee",-2); my $r = \$v; $$r = -32; # modification de $v $r = \@t; $r->[0] = 28; # modification de $t[0] Derni` ere chose importante, si vous passez une r ef erence ` a une fonction, vous devez bien voir que la copie de la seule r ef erence est eectu ee, la structure point ee par la r ef erence ne lest pas ; vous pourrez donc la modier dans la fonction : sub f3 { my ($reftab) = @_; $reftab->[2] = 32.3; } my @t = ( 49, "hello", -2 ); my $r = \@t; f3( $r ); f3( \@t ); # equivalent # @t est modifi e On peut sch ematiser ce quil se passe de la mani` ere suivante :

Visiblit du programme principal $r @t 0 49 1 hello 2 2 32.3

$reftab

Visibilit de la fonction f3

81

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

Les deux r ef erences pointent donc vers la m eme zone m emoire.

9.6

R ef erences anonymes vers scalaire

Une r ef erence anonyme est une r ef erence vers une variable qui na pas de nom. Nous avons d ej` a vu comment faire cela pour un scalaire avec une fonction (fonction f2 un peu avant), mais cela nest pas la fa con de faire la plus simple. La syntaxe pour cr eer directement une r ef erence anonyme vers un scalaire est la suivante : \valeur-constante my $ref1 = \34; my $ref2 = \"er"; print "$$ref1 $$ref2\n";

$ref1 34 $ref2 er

Une telle valeur est une constante, il est impossible de modier la valeur point ee par la r ef erence (di erence avec le m ecanisme de la fonction f2) : $$ref1 = "hello"; # Modification of a read-only value attempted at script.pl line 24. Ce nest pas dans le cas des scalaires que les r ef erences anonymes sont les plus utilis ees ; elles le sont bien plus avec les tableaux et les tables de hachage.

9.7

R ef erences anonymes vers tableau

Pour cr eer une r ef erence anonyme vers un tableau, il faut utiliser la notation suivante : [ el ement1, el ement2, el ement3, etc] est une r ef erence vers un tableau comportant les el ements en question. my $r = [ 34.4, "ac", -71 ]; my @t = ( 34.4, "ac", -71 ); La variable $r est une r ef erence vers un tableau comportant trois el ements alors que la variable @t est un tableau ` a trois el ements (cette derni` ere notation nous est d ej` a famili` ere) :

82

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

$r 0 34.4 1 ac 2 71

@t 0 34.4 1 ac 2 71

On acc` ede aux el ements de cette r ef erence anonyme comme pour une r ef erence normale : print "$r->[0]\n"; $r->[2] = 901; foreach my $e (@$r) { ... } Attention ` a ne pas ecrire \(2,"er",$v) si vous voulez cr eer une r ef erence vers un tableau, car cette syntaxe fait toute autre chose : elle est en fait equivalente ` a (\2,\"er",\$v), donc ` a une liste de r ef erences, ce qui est fort di erent. La structure pr ec edemment d ecrite par my @t1 = ( 16, -33 ); my @t2 = ( "el", 0.3, 4 ); my @t = ( 6, \@t1, \@t2, "s" ); peut donc s ecrire de la mani` ere suivante : my @t = ( 6, [ 16, -33 ], [ "el", 0.3, 4 ], "s" ); Ce qui peut se repr esenter toujours sous la forme suivante :

@t 0

el

0.3

16

33

On peut pousser le vice jusqu` a utiliser une r ef erence pour le premier tableau :

83

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

my $r = [ 6, [ 16, -33 ], [ "el", 0.3, 4 ], "s" ];

$r

el

0.3

16

33

Comment acc eder aux el ements des di erentes profondeurs dune telle construction ? Il sut de suivre les r ef erences ... print "$r->[0]\n"; # affiche 6 # $r->[1] est une r ef erence vers tableau print "$r->[1]->[0]\n"; # affiche 16 print "$r->[1]->[1]\n"; # affiche -33 # $r->[2] est une r ef erence vers tableau print "$r->[2]->[0]\n"; # affiche el print "$r->[2]->[1]\n"; # affiche 0.3 print "$r->[2]->[2]\n"; # affiche 4 print "$r->[3]\n"; # affiche s Ce nest pas si complexe quil ny para t pour peu que nous ayons un bon sch ema sous la main ... Vous noterez que nous faisons usage de lop erateur ` eche (->) plut ot que de la syntaxe double-dollar ($$). De plus, si $r->[1] est une r ef erence vers tableau, @{$r->[1]} est le tableau en question. On peut donc ecrire : foreach my $e ( @{$r->[1]} ) { ... } # Parcourt 16 et -33

Il faut noter quen cas de d er ef erencements successifs, seule la premi` ere ` eche est n ecessaire : $r->[2][1] est equivalent ` a $r->[2]->[1].

9.8

R ef erences anonymes vers table de hachage

De la m eme fa con il est possible de cr eer une r ef erence anonyme vers une table de hachage. La notation {clef1=>valeur1, clef2=>valeur2, etc} est une r ef erence vers une table de hachage comportant les couples clef/valeur en question.

84

c Sylvain Lhullier

Guide Perl => => => => 21, "e" }; 21, "e" );

http://formation-perl.fr/

my $r = { Paul Julie my %h = ( Paul Julie

La variable $r est une r ef erence vers une table de hachage alors que la variable %h est une table de hachage (notation famili` ere) :

$r Julie Paul => => e 21

%h Julie Paul => => e 21

De la m eme fa con quavec des tableaux, nous allons mettre sur pied des tables de hachage de tables de hachage : my %h1 = ( rue tel my %h2 = ( rue tel my $r = { Paul Julie => => => => => => Pasteur, 06461341 ); Jaures, 03729103 ); \%h1, \%h2 };

Ou plus directement : my $r = { Paul => { rue tel Julie => { rue tel };

=> Pasteur, => 06461341 }, => Jaures, => 03729103 }

85

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

$r

Julie Paul

=> =>

rue tel

=>

Jaures

=> 03729103

tel rue

=> 06461341 => Pasteur

Voici comment acc eder ` a tous les el ements dune telle construction : # $r->{Paul} est une r ef erence vers une table de hachage print "$r->{Paul}->{tel}\n"; # affiche 06461341 print "$r->{Paul}{tel}\n"; # equivalent print "$r->{Paul}{rue}\n"; # affiche Pasteur # $r->{Julie} est une r ef erence vers une table de hachage print "$r->{Julie}{tel}\n"; # affiche 03729103 print "$r->{Julie}{rue}\n"; # affiche Jaures Il sut de suivre sur le sch ema, do` u limportance de faire un bon sch ema.

9.9

R ef erences anonymes diverses

Il est bient-s ur tout ` a fait possible de m elanger les r ef erences vers les tableaux et vers les tables de hachage : my $r = [ [a,4], b, [1,z], {P=>[-2,"er",0],A=>7},

86

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

8 ]; Voici le sch ema correspondant ` a cette structure (essayer de vous en convaincre !) :

$r

A P

=> =>

er

Voici comment acc eder ` a un el ement dune telle structure : print "$r->[3]->{P}->[1]\n"; # affiche "er" print "$r->[3]{P}[1]\n"; # equivalent Les crochets correspondent ` a une prise dindice dun tableau ; les accolades ` a la clef dune table de hachage. Je peux parcourir le premier tableau du deuxi` eme niveau (celui qui comporte a et 4) de la mani` ere suivante : my $reft = $r->[0]; foreach my $v (@$reft) { print "$v\n"; } Je cr ee une variable $reft qui est une r ef erence vers ce tableau, je peux ensuite parcourir @$reft qui repr esente le tableau en question. Il est possible d ecrire cela sans cr eer de variable temporaire, la syntaxe est la suivante : @{r ef erence} Ces accolades nont rien a ` voir avec les tables de hachage elles permettent juste de d elimiter la r ef erence ` a laquelle on applique larobase. Voici ce que cela donne :

87

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

foreach my $v (@{$r->[0]}) { print "$v\n"; } On fait de la m eme fa con pour un table de hachage, les accolades d elimitent la r ef erence ` a laquelle on applique le pourcentage : foreach my $k (keys %{$r->[3]}) { print "$k $r->[3]{$k}\n"; } Commencez-vous ` a voir lint eret de faire des sch emas ?

9.10

Lop erateur ref

La question qui pourrait maintenant venir ` a lesprit est la suivante : comment pourrait-on ecrire une boucle sur les el ements du tableau r ef erenc e par $r et surtout comment savoir de quel type ils sont pour pouvoir les utiliser ? Pour r epondre ` a cette question, voici un nouvel op erateur : ref(). Il permet de conna tre le type dune r ef erence. Cette fonction renvoie : "SCALAR" si son argument est une r ef erence sur scalaire, "ARRAY" si son argument est une r ef erence sur tableau, "HASH" si son argument est une r ef erence sur table de hachage, faux si son argument nest pas une r ef erence (cest un scalaire classique). On peut alors ecrire le code suivant : foreach my $p (@$r) { if( ref($p) eq "ARRAY" ) { print "( "; foreach my $v (@$p) { print "$v "; } print ")\n"; } elsif( ref($p) eq "HASH" ) { foreach my $k (keys(%$p)) { print "$k : $p->{$k}\n"; } } elsif( !ref($p) ) { print "$p\n"; } } Lachage suivant est eectu e: ( a 4 ) b ( 1 z )

88

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

P : ARRAY(0x8100c20) A : 7 8 Dans cet exemple, un seul premier niveau de r ef erences est explor e. Pour aller au-del` a, cesta-dire, acher le tableau associ ` e ` a la clef P, il faudrait concevoir un ensemble de fonctions sappelant les unes les autres en fonction du type des r ef erences rencontr ees. Ne vous fatiguez pas ` a les ecrire, il existe d ej` a une telle fonctionnalit e en Perl : use Data::Dumper; print Dumper($r); La premi` ere ligne ajoute des fonctions ` a Perl (cest un peu le #include du langage C) et ne doit donc etre pr esente quune seule fois dans le programme (plut ot au d ebut). La seconde consiste en lachage de la valeur de retour de la fonction Dumper : cette fonction renvoie une (longue) cha ne de caract` eres repr esentant toute la structure r ef erenc ee par $r : $VAR1 = [ [ a, 4 ], b, [ 1, z ], { P => [ -2, er, 0 ], A => 7 }, 8 ]; Vous noterez que lachage eectu e est directement int egrable dans un code Perl.

9.11

R ef erences circulaires

La notion de r ef erence circulaire na rien de compliqu e ; cest juste le fait que plusieurs tableaux et/ou tables de hachage et/ou scalaires peuvent se r ef erencer entre elles. Par exemple :

89

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

$r

71

* Od R5 => => As4 Hello Ptt => => 34.7

On voit bien alors quun cycle de r ef erences existe entre ces r ef erences. Voici comment ecrire cela en Perl : my $r = [ 71, { "Hello" => -34.7, "Ptt" => { "R5" => "As4" } } ]; $r->[1]{Ptt}{Od} = $r; On comprend bien quil nest pas possible de cr eer une telle structure en une seule instruction. Comment se comporte Data::Dumper dans une telle situation ? Ne va-t-il pas boucler ` a linni ? Eh bien non : il se comporte bien : print Dumper($r); $VAR1 = [ 71, { Ptt => { R5 => As4, Od => $VAR1 }, Hello => -34.7 } ];

90

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

Data::Dumper se rend compte quil passe sur une r ef erence quil a d ej` a parcourue et lache comme telle ($VAR1). Pourquoi vous parler de r ef erences circulaires ? Premi` erement parce quil faut savoir quil est possible den faire (cela peut etre utile de cr eer des listes cha n ees circulaires etc). Mais surtout parce quelles posent des probl` emes au garbage-collector dans sa t ache de lib eration de ` la m emoire. A la suite de lexemple pr ec edent, je pourrais ecrire : $r = undef; En temps normal, tout ce que $r r ef eren cait serait lib er e. Mais ici, ce nest pas le cas. En eet, chacun des tableaux et des tables de hachage ont encore au moins une r ef erence vers eux, le garbage-collector ne se rend pas compte, quen fait, les trois objets peuvent etre lib er es. Nous sommes donc en pr esence de zones m emoires inaccessibles (aucune variable ne nous permet dy acc eder) et non lib erables : cette m emoire est perdue pour le programme ! Elle sera bien s ur lib er ee quand le programme prendra n, mais sil sagit dun d emon qui tourne en permanence, cette fuite m emoire nest pas forc ement ` a n egliger. La solution pour eviter cela est de casser la circularit e avant de modier la valeur de la variable $r : $r->[1] = undef; Je viens de casser le lien indiqu e par un ast erisque, il ny a plus de boucle dans les r ef erences. Maintenant et seulement maintenant, je puis sans risque ecrire : $r = undef; Et la m emoire sera lib er ee ...

9.12

R ef erences sur chiers

Une ouverture de chier cr ee une variable dont il est possible de prendre ladresse. Voici la syntaxe pour cela : open(FILE,">toto") or die("$!"); my $reff = \*FILE; La variable scalaire $reff est une r ef erence vers le descripteur de chier FILE. Il nous est aussi possible de cr eer une r ef erence vers un des trois chiers pr e-existant : my $refo = \*STDOUT; Voici des exemples dutilisation de ces r ef erences : open(FILE,">toto") or die("$!"); my $reff = \*FILE; print $reff "ok\n"; sub affiche { my ($ref) = @_;

91

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

print $ref "ok\n"; } affiche( $reff ); affiche( \*FILE ); # equivalent close( $reff ); Cette derni` ere ligne est equivalente ` a close(FILE); On peut sans restrictions stocker une r ef erence vers chier dans une table de hachage ou dans un tableau.

9.13

R ef erences sur fonctions

Comme dans le langage C, une fonction a elle-aussi une adresse m emoire. Cette adresse correspond ` a lendroit de la m emoire o` u le code de la fonction est stock e. On peut obtenir une r ef erence vers une fonction de la mani` ere suivante : sub affcoucou { my ($p) = @_; print "Coucou $p\n"; } my $ref = \&affcoucou; La variable scalaire $ref est une r ef erence vers la fonction affcoucou. Elle peut sutiliser des fa cons suivantes : &$ref("Larry"); # appel $ref->("Larry"); # equivalent sub f { my ($f,$p) = @_; $f->( $p ); } f( $ref, "Larry" ); f( \&affcoucou, "Larry" ); # equivalent Notez bien quil est tout ` a fait possible de stocker une telle r ef erence dans un tableau ou dans une table de hachage ...

9.14

Un dernier mot sur les r ef erences

De telles structures nous donnent envie de faire de la programmation objet (champs et m ethodes pourraient etre stock es dans une table de hachage). Nallons pas trop vite car Perl a et e pr evu pour la programmation objet et propose les fonctionnalit es n ecessaires (h eritage ...) en se basant sur les modules.

92

Chapitre 10

Les modules
Nous allons aborder ici lusage et l ecriture de modules, cest-` a-dire de biblioth` eques ou encore librairies. Perl tire sa puissance de la richesse des modules existants ; peu dautres langages (voire aucun) ne peuvent pr etendre etre aussi riches que Perl. Par exemple, quasiment tous les protocoles r eseau auxquels vous pouvez penser sont accessibles en Perl en utilisant un module existant. En quelques mots, un module est un ensemble de fonctions regroup ees dans un chier. Ces fonctions y sont regroup ees car elles touchent toutes ` a un m eme domaine, ` a un m eme ensemble de fonctionnalit es autour dune m eme utilisation, dun m eme protocole ... La premi` ere chose que je vous invite ` a faire, cest ` a lancer la commande perl -V : elle ache toutes sortes dinformations, dont le contenu de la variable @INC. Cette variable de type tableau contient la liste des r epertoires o` u seront recherch es les modules. Le nom INC rappelle etrangement (et cest voulu) la notion dinclude en C. Lordre des r epertoires de cette variable est important car si un module vient ` a etre pr esent dans deux r epertoires, seule loccurrence pr esente dans le premier r epertoire de la liste comptera (mais ce cas proviendrait plut ot dune erreur de nommage ou dinstallation).

10.1

Utilisation dun premier module

Il existe de nombreux modules d ej` a install es sur votre syst` eme ; une distribution de Perl inclut les modules les plus utilis es. Ainsi, le module nomm e Math::Trig ; permet dacc eder ` a des fonctions math ematiques de trigonom etrie autres que les seuls cosinus et sinus pr ed enis dans Perl sous les noms de cos et sin. Je vous invite ` a taper la commande perldoc Math::Trig dans un terminal ; vous visualiserez ainsi la documentation de ce module. Cette commande perldoc fonctionne un peu comme la commande man ; vous verrez d etaill ees les fonctionnalit es auxquelles vous avez acc` es avec un module donn e. Vous taperez q pour quitter. On voit ici que nous avons acc` es a ` des fonctions comme tan, acos ou asin ainsi qu` a des fonctions de conversion entre unit es dangles ou bien ` a la valeur de pi. De petits exemples simples dutilisations vous sont aussi fournis. La premi` ere ligne de code ` a ecrire pour utiliser un module est la suivante : use NomDuModule;

93

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

Dans bien des cas, cette instruction ajoute des fonctions et des variables ` a lespace de nommage (nous reviendrons sur ce point dans la suite). Pour notre exemple, la ligne est : use Math::Trig; Cette ligne devra etre plac ee dans chaque script qui fait usage du module et etre ex ecut ee avant tout usage de fonctions ou de variables du module. Typiquement toutes les lignes use sont regroup ees au d ebut du script. Vous remarquerez que la ligne use strict; que je vous ai conseill e de placer dans chaque script, nest en fait que le chargement dun module ; ce module ayant pour r ole de rendre la syntaxe Perl plus coercitive. Le nom des modules de ce type est en minuscule. Ils sont appel es modules pragmatiques. Ils ont pour objet de modier ou d etendre la s emantique de Perl. Ainsi diagnostics permet davoir des messages derreurs plus complets (vous pouvez charger sur CPAN la version 1.2-alpha1 qui vous permet davoir ces messages avec des explications en fran cais). Revenons ` a notre module Math::Trig. Voici un exemple de code Perl lutilisant (jen plagie ici la documentation) : use Math::Trig; $x = tan(0.9); $y = acos(3.7); $z = asin(2.4); $pi_sur_deux = pi/2; $rad = deg2rad(120); Je laisse au lecteur le soin de deviner (ou plut ot comprendre) ce que font ces instructions. Une fois charg e, un module nest pas d echargeable.

10.2

Dautres modules

Voici lexemple dun autre module : File::Copy ; il permet certaines manipulations de chiers lourdes ` a mettre en uvre avec de simples appels syst` eme. Il est par exemple possible de copier un chier vers un autre (chiers disque ou ux de donn ees), ou den d eplacer un dune partition vers une autre (impossible avec lappel syst` eme rename). Comme lindique perldoc File::Copy : use File::Copy; copy("file1","file2"); copy("Copy.pm",\*STDOUT); move("/dev1/fileA","/dev2/fileB"); Voici un autre exemple de module en action. Il sagit du module Net:FTP qui nous permet dacc eder tr` es simplement aux fonctionnalit es dun client FTP. Voici, par exemple, comment se connecter sur un serveur (en mode passif, car jai un rewall), changer de r epertoire et t el echarger un chier : #!/usr/bin/perl -w use strict;

94

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

use Net::FTP; my $ftp = Net::FTP->new("ftp.cpan.org", Debug => 0, Passive =>1 ) or die("$!"); $ftp->login("anonymous",-anonymous@); $ftp->cwd("/pub/CPAN/"); $ftp->get("ls-lR.gz"); $ftp->quit(); On remarquera au passage la notation objet (new, ->) ; beaucoup de modules lutilisent. M eme si nous ne verrons la programmation objet que dans une prochaine partie, il est ais e de comprendre comment utiliser de tels modules (de toute fa con la documentation des modules comporte des exemples). Quoi de plus simple nalement pour faire du FTP client ? Comment faisais-je avant pour mettre ` a jour mon site web des seules pages que jai modi ees depuis la derni` ere fois ? ? ?

10.3

O` u trouver les modules ?

Cest tr` es bien tout cela, mais comment trouver le module qui r epond ` a mon probl` eme ? Pour cela je dois vous pr esenter larchive de tous les modules Perl, jai nomm e CPAN (Comprehensive Perl Archive Network). Cette archive recense tous les modules dius es pour Perl. Je vous invite ` a visiter le site http://www.cpan.org/ vous y trouverez de tout ` a propos de Perl. Vous pouvez t el echarger les sources de linterpr eteur (Perl source code), des versions compil ees (Perl binary distributions) disponibles pour de tr` es nombreuses plates-formes, ainsi que de la documentation sur les modules et de quoi les t el echarger. Le lien int eressant est : CPAN modules, distributions, and authors (search.cpan.org). Une page vous est propos ee avec de nombreuses sections listant des modules regroup es par th` eme, ainsi quun champ de saisie servant ` a la recherche de mots clefs dans les modules. Je vous invite ` a entrer SMTP et ` a voir la vari et e des modules qui gravitent autour de ce protocole ; le module le plus int eressant est s urement Net::SMTP (plus le nom dun module est court et semble canonique, plus il y a de chance quil soit int eressant). Di erents liens permettent de visualiser la documentation (le perldoc correspondant) ainsi que de t el echarger le module le cas ech eant. Linstallation de modules CPAN nest pas au menu de ce document, je ne vais pas mappesantir sur la question ; juste deux mots pour vous dire que les commandes perl~Makefile.PL, make, make~test et make~install sont la clef du succ` es. Les modules CPAN sont pr esents sous forme de package dans toute bonne distribution Linux. Par exemple sous Debian, il sagit des paquets libxxx-yyy-perl (o` u xxx-yyy correspond au nom du module Xxx::Yyy mis en minuscules). M eme si vous ninstallez pas de module, CPAN nen reste pas moins la source majeure dinformations sur les modules de votre syst` eme. Vous vous rendez par exemple compte que le module Net::SMTP r epond ` a vos besoins, vous v eriez alors que ce module est pr esent sur votre syst` eme en tapant perl -e use Net::SMTP et vous navez plus qu` a lutiliser. La documentation sera accessible par perldoc Net::SMTP Juste pour sourire deux minutes, je vous invite ` a rechercher dans CPAN un module nomm e Sex ecrit un premier avril et den lire la documentation (ainsi que le code) ...

95

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

10.4

Ecrire un premier module

Apr` es avoir manipul e des modules existants et avoir parl e de CPAN, nous allons maintenant apprendre ` a ecrire nos propres modules. Pour ecrire un module, nous devons cr eer un chier ind ependant du ou des scripts qui lutilisent. Lextension de ce chier est imp erativement .pm : par exemple Utils.pm Ce chier doit etre plac e dans un des r epertoires list es dans la variable @INC ; pour commencer vous pourriez le placer dans votre r epertoire de travail ` a c ot e du script qui lutilisera, car le r epertoire . est pr esent dans ce tableau @INC. Ce chier doit contenir une premi` ere ligne indiquant le nom du module ; pour cela, vous devez ecrire : package Utils; Il est important de voir que le nom du package doit etre le m eme que celui du chier (` a lextension pr` es). Le chier peut ensuite contenir des d enitions de fonctions. Voici un exemple simple dun tout petit module complet : # --- fichier Utils.pm --package Utils; use strict; sub bonjour { my ($prenom) = @_; print "Bonjour $prenom\n"; } 1; Il est important de ne pas oublier la derni` ere ligne, celle qui contient 1; ; nous reviendrons plus tard sur son r ole. Pour pouvoir utiliser ce module dans un script, il est n ecessaire dinvoquer linstruction use suivie du nom du module. Voici un exemple de lutilisation du module pr ec edent : #!/usr/bin/perl -w # --- fichier script.pl --use strict; use Utils; # chargement du module Utils::bonjour( "Paul" ); La derni` ere ligne correspond ` a lappel de la fonction bonjour du module Utils. La syntaxe est la suivante : le nom du module est suivi de deux signes deux-points puis du nom de la fonction.

10.5

Et les variables ?

Il est possible de d eclarer des variables propres au module. Ces variables seront : soit accessibles exclusivement aux fonctions pr esentes dans le module (on pourrait parler de variables priv ees, correspondant aux variables static d eclar ees en dehors des fonctions en C),

96

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

soit aussi accessibles ` a lext erieur du module (on pourrait parler de variables publiques ou variables globales). Une variable accessible exclusivement aux fonctions du module se d eclare avec my (que lon conna t d ej` a). Une variable aussi accessible depuis lext erieur du module se d eclare avec our (my pour dire ` a moi, our pour dire ` a nous). Avant la version 5.6 de Perl, on utilisait un autre m ecanisme dont je ne parlerai pas ici, assurez-vous davoir une version r ecente de Perl (cf perl -v). Ces variables doivent etre d eclar ees en dehors de toute fonction ; les variables d eclar ees dans les fonctions sont comme toujours locales au bloc dans lequel elles sont d eclar ees. # --- fichier Utils.pm --package Utils; use strict; # variable accessible our $x = toto; # variable inaccessible my $y = toto; # fonction sub bonjour { # Variable locale my ($prenom) = @_; print "Bonjour $prenom\n"; print "$x $y\n"; } 1; Que la variable soit d eclar ee avec my ou avec our, il est tout ` a fait possible dy acc eder ` linverse, depuis lext depuis une fonction du module (ici bonjour). A erieur du module, cest-` adire depuis le script, seule la variable $x est accessible. #!/usr/bin/perl -w # --- fichier script.pl --use strict; use Utils; Utils::bonjour( "Paul" ); # Ok : print "$Utils::x\n"; # Erreur : print "$Utils::y\n"; De m eme que pour les fonctions, les noms de variable sont pr ex es par le nom du module puis deux signes deux-points. Ici, le nom complet de la variable est donc Utils::x quil faut faire pr ec eder dun signe dollar, ce qui donne : $Utils::x au nal. Il ny a pas derreur de ma part : on n ecrit pas Utils::$x ! :-)

10.6

De la derni` ere ligne dun module

Jusquici, nous avons toujours plac e une ligne 1; ` a la n du chier de notre module. Il faut savoir que cette valeur est la valeur du chargement du module (valeur de linstruction

97

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

use Utils;) et quelle indique si ce chargement sest bien pass e ou non : une valeur fausse indique un probl` eme, une valeur vraie (comme ici 1) indique au contraire que le chargement sest bien d eroul e. Une valeur fausse mettra n au script qui fait appel ` a linstruction use. Il est donc tout ` a fait possible de mettre une autre valeur quune valeur constante ; on peut, par exemple, envisager mettre un test en derni` ere instruction pour v erier si les conditions sont r eunies pour lusage du module. On pourrait imaginer conditionner le chargement du module ` a louverture dun chier, dune connexion r eseau (ou je-ne-sais-quoi encore...). Je ne donnerai pas dexemple ici car le cas est rare de la n ecessit e dun tel usage, mais il faut savoir que cela est possible.

10.7

R epertoires

Voyons maintenant comment cr eer des modules aux noms compos es comme Truc::Utils (nous avons par exemple vu le module Net::FTP). Ces noms compos es permettent de regrouper les modules par type dusages ; par exemple Net correspond ` a tout ce qui concerne le r eseau. Revenons ` a notre exemple Truc::Utils. Ce nom Truc correspond ` a un r epertoire qui doit etre pr esent dans un des r epertoires de la variable @INC (par exemple .) et le chier Utils.pm doit etre pr esent dans ce r epertoire Truc. Voici un exemple de tel module : # --- fichier Truc/Utils.pm --package Truc::Utils; use strict; our $x = toto; sub bonjour { my ($prenom) = @_; print "Bonjour $prenom\n"; } 1; Et voici un script lutilisant : #!/usr/bin/perl -w # --- fichier script.pl --use strict; use Truc::Utils; Truc::Utils::bonjour( "Paul" ); print "$Truc::Utils::x\n"; Rien de sorcier.

10.8

Blocs BEGIN et END

Les amoureux de awk retrouveront ici deux de leurs enfants pr ef er es :-)). Dans un module, il est possible de pr evoir deux blocs dinstructions qui seront ex ecut es soit d` es le chargement du module (bloc BEGIN) soit lors de la n de lusage du module (bloc END).

98

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

package Utils; use strict; sub f { ... } BEGIN { print "Chargement du module\n"; } END { print "Fin dusage du module\n"; } 1; Notez bien quil ne sagit pas de fonctions (pas de mot clef sub), mais bien de blocs lab elis es. Le bloc BEGIN sera ex ecut e lors de linstruction use Utils; avant toute autre instruction du module (y compris les use plac es dans le module). Le bloc END sera ex ecut e lors de la n du programme. Lusage de ces deux blocs peut etre n ecessaire lorsque lutilisation du module est conditionn ee par lobtention dune ou plusieurs ressources comme un chier ou une connexion r eseau. Ces blocs vont nous servir ` a pr eparer le terrain au d ebut et ` a lib erer les ressources ` a la n. Lorsque dans un module sont pr esentes dautres instructions que des d enitions de variables et des d enitions de fonctions, ces instructions sont ex ecut ees au moment du chargement du module. Tout se passe comme si ces instructions guraient dans un BEGIN implicite. Lusage dun bloc BEGIN permet juste au programmeur d ecrire un code un peu plus lisible et propre, dans la mesure o` u toutes ces instructions sont regroup ees sous un nom (BEGIN) qui rappelle explicitement quelles sont ex ecut ees au d ebut. Notez bien que la programmation objet (lire la suite) a quelque peu rendu ces deux blocs obsol` etes voire inutiles.

10.9

Introduction ` a lexport de symboles

Sous ce titre barbare se cache une id ee simple : il peut etre p enible de toujours ecrire le nom complet des fonctions de modules. Je veux dire par l` a que d ecrire Utils::bonjour ` a chaque fois que vous voulez appeler cette fonction est sans doute lourd et est quelque peu p enible ` a la longue. Il existe un moyen pour navoir qu` a ecrire bonjour sans avoir ` a rappeler le nom du module qui contient la fonction. En faisant cela nous allons ajouter la fonction dans lespace de nommage du script. Placer une fonction ou une variable dun module dans lespace de nommage dun script ou dun autre module sappelle faire un export, on parle dexporter le symbole (fonction ou variable). Ce symbole est donc import e par le script. Pour avoir la capacit e dexporter des symboles, notre module futur-exportateur doit comporter les lignes suivantes : package Utils; use Exporter; our @ISA = qw(Exporter);

99

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

Ces deux nouvelles lignes dinstructions doivent etre plac ees juste apr` es linstruction package. La premi` ere est linvocation du module Exporter ; avec la seconde on indique que notre module est un (ISA) Exporter (nous reverrons cette syntaxe et ses implications en programmation objet). Notre module est maintenant capable dexporter des symboles. Il existe quatre types de symboles (fonctions ou variables) : ceux qui sont export es pas d efaut : le script utilisant le module na rien besoin de faire de sp ecial (autre que de faire le use) pour que ces symboles soient export es, ceux qui sont individuellement exportables en fonction de ce que demande le script utilisateur, ceux qui sont exportables en groupe (on parle de tags) selon ce que demande le script utilisateur, ceux qui ne sont pas exportables (cest-` a-dire quil faudra toujours faire pr ec eder leur nom par le nom complet du module). Chacun des trois premiers ensembles est associ e` a une variable d eclar ee avec our.

10.10

Export par d efaut de symboles

Les symboles export es par d efaut doivent etre list es dans la variable @EXPORT ; il sagit donc dun tableau. Il est courant dinitialiser ce tableau avec lop erateur qw que nous avons d ej` a vu et sur lequel je ne reviendrai donc pas : our @EXPORT = qw(&bonjour &hello $var); Cette ligne plac ee dans le module Utils ` a la suite de la ligne our @ISA = qw(Exporter); va permettre dutiliser les fonctions bonjour et hello ainsi que la variable scalaire $var sans pr exe dans le script utilisateur. Notez bien que, si les variables doivent etre cit ees avec leur caract` ere de di erentiation de type (le dollar, larobase ou le pourcentage), il en est de m eme avec les fonctions et le signe et-commercial (&). Sachez juste que ce et-commercial peut etre omis. Voici comment on peut maintenant utiliser le module en question : use Utils; bonjour("Paul"); hello("Peter"); print "$var\n"; Plut ot simple.

10.11

Export individuel de symboles

Un symbole peut etre export e` a la demande de celui qui utilise le module. Cest-` a-dire que ce symbole nest pas export e par d efaut, mais il peut faire lobjet dun export sil est nomm ement cit e lors de linstruction use. Un symbole doit appara tre dans la variable @EXPORT_OK pour etre autoris e` a etre export e:

100

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

our @EXPORT_OK = qw(&gutenTag &ciao $var2); Ces trois symboles sont maintenant exportables dans le script utilisant ce module. Pour cela il convient dajouter une liste de symboles ` a linstruction use : use Utils qw(&ciao $var2); ciao("Paula"); print "$var2\n"; Cette ligne importe donc les symboles demand es et ces derniers sont donc utilisables sans pr exe. Il se trouve quune telle ligne nimporte plus les symboles par d efaut (ceux de la variable @EXPORT) ; ne me demandez pas pourquoi, je trouve cela aussi stupide que vous ... Pour rem edier a cela, il nous faut ajouter ` ` a la liste des imports le tag :DEFAULT : use Utils qw(:DEFAULT &ciao $var2); bonjour("Paul"); hello("Peter"); print "$var\n"; ciao("Paula"); print "$var2\n"; Ce m ecanisme de s election des symboles export es permet a ` lutilisateur du module de ne pas trop polluer son espace de nommage et de choisir les seules fonctions dont il aura besoin.

10.12

Export par tags de symboles

Il est possible de regrouper les symboles dans des tags. Un tag est une liste de symboles. Limport dun tag provoque limport de tous les symboles composant ce tag. La variable qui entre ` chaque tag est associ ici en jeu est %EXPORT_TAGS ; il sagit donc dune table de hachage. A ee une r ef erence vers un tableau contenant la liste des symboles du tag : our %EXPORT_TAGS=(T1=>[qw(&ciao &gutenTag)], T2=>[qw(&ciao $var2)]); Le tag T1 est associ e aux fonctions ciao et gutenTag. Le tag T2 est associ e ` a la fonction ciao et ` a la variable $var2. Le nom des tags est par convention en majuscules. Remarque importante : les symboles pr esents dans les listes associ ees aux tags doivent absolument etre pr esents dans @EXPORT et/ou @EXPORT_OK. Dans le cas contraire, leur export sera impossible. Voici un usage de ce module : use Utils qw(:T2); ciao("Paula"); print "$var2\n"; Le nom du tag est plac e dans la liste des modules pr ec ed e par le signe deux-points. Il est possible de combiner les di erents types dacc` es :

101

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

use Utils qw(:DEFAULT &ciao :T1); bonjour("Paul"); hello("Peter"); print "$var\n"; ciao("Paula"); print "$var2\n"; gutenTag("Hans"); On voit alors que DEFAULT est un tag.

10.13

Exemple complet dexports

Voici un exemple complet dusage des exports dans les modules ; jai essay e de regrouper toutes les congurations. Voici le module Utils dans le chier Utils.pm : package Utils; use strict; use Exporter; our @ISA = qw(Exporter); our @EXPORT = qw(&f1 &f2); our @EXPORT_OK = qw(&f3 &f4 &f5 &f6); our %EXPORT_TAGS = (T1 => [qw(&f5 &f6)], T2 => [qw(&f4 &f6)]); sub f1 { print "f1\n"; } sub f2 { print "f2\n"; } sub f3 { print "f3\n"; } sub f4 { print "f4\n"; } sub f5 { print "f5\n"; } sub f6 { print "f6\n"; } 1; Et voici un script lutilisant (apr` es chaque appel de fonction est signal ee la raison qui fait quil est possible de lappeler sans pr exe) : #!/usr/bin/perl -w use strict; use Utils qw(:DEFAULT :T2 &f3); f1(); # tag DEFAULT f2(); # tag DEFAULT f3(); # individuellement f4(); # tag T2 Utils::f5(); # pas import ee f6(); # tag T2 Notez bien le cas de la fonction f5 qui nest pas import ee, mais qui nen reste pas moins utilisable. Pour plus dinformations et dexemples je vous invite ` a vous r ef erer ` a perldoc Exporter.

102

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

10.14

Fonctions inaccessibles

Vous allez me poser la question suivante : comment faire pour rendre une fonction dun module inaccessible depuis le script ? Et je vous r epondrai : cela nest a priori pas possible (vous allez voir que si nalement). Vous lavez compris, Perl nest pas un langage extr emement coercitif, notamment par rapport a des langages comme Java ou C++. Il ny a donc rien de pr ` evu dans le langage pour rendre certaines fonctions uniquement accessibles depuis lint erieur du module. Est alors apparue la convention suivante : toute fonction ou variable dont le nom commence par un soulign e (ou under-score _) est priv ee et ne doit pas etre utilis ee ` a lext erieur du module. Cette conance en lutilisateur du module est souvent susante et les modules CPAN sont b atis sur ce mod` ele. N eanmoins, si vous etes outr e par ce que je viens d ecrire car vous etes un fanatique de Java ou autres, il existe un moyen d ecrire des fonctions vraiment internes aux modules. Il faut pour cela d eclarer une variable avec my (donc invisible depuis lext erieur du module) et den faire une r ef erence anonyme vers fonction : package Utils; use strict; my $affiche = sub { my ($n,$m) = @_; print "$n, $m\n"; }; La variable $affiche est donc une variable priv ee qui pointe vers une fonction anonyme. Son usage est donc r eserv e aux fonctions d eclar ees dans le module : sub truc { $affiche->(4,5); } Remarquez que, comme le code Perl est toujours accessible en lecture, il est toujours possible ` a lutilisateur du module de prendre le code en copier-coller et den faire une fonction personnelle ... Perl nest pas fait pour les parano aques.

10.15

Documentation des modules

Documenter son travail est important pour une r e-utilisation du code par dautres ou m eme par soi-m eme plus tard ... En Perl la documentation des modules se fait dans le code m eme du module. Une syntaxe particuli` ere, nomm ee POD, permet cela. Les instructions POD commencent toujours par le signe egal (=). La documentation dun module commence typiquement ainsi : =head1 NAME Utils.pm - Useful functions

103

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

=head1 SYNOPSIS use Utils; bonjour("Paul"); =head1 DESCRIPTION Blabla blabla =head2 Exports =over =item :T1 Blabla =item :T2 Blabla =back =cut Les tags =head1 d enissent des en-t etes de premier niveau (des gros titres) et les tags =head2 d enissent des en-t etes de deuxi` eme niveau (des sous-titres). Il est de coutume de mettre les premiers exclusivement en majuscules. Les tags =over, =item et =back permettent de mettre en place une liste. Le reste du texte est libre. Le tag =cut indique la n du POD. Les blocs de POD et les portions de code peuvent alterner : cela est m eme recommand e de documenter une fonction et den faire suivre le code. Pour cela vous devez savoir que lapparition en d ebut de ligne dun tag POD indique la n temporaire du code Perl et le d ebut dun bloc de documentation. La n de ce POD est signal ee ` a laide du tag =cut et le code Perl peut alors reprendre. package Utils; =head1 FUNCTION hello This function prints hello. =cut sub hello { my ($firstName) = @_; print "Hello $firstName\n"; } =head1 FUNCTION bonjour This function prints hello in french.

104

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

=cut sub bonjour { my ($prenom) = @_; print "Bonjour $prenom\n"; } Comment visualiser une telle documentation, allez-vous me demander ? Rien de plus simple : perldoc est notre alli e ! Tapez donc perldoc Utils (ou tout autre nom que vous aurez choisi de donner ` a votre module) et sa documentation appara t au format man comme tout bon module CPAN. Quoi de plus simple ? NAME Utils.pm - Useful functions SYNOPSIS use Utils; bonjour("Paul"); DESCRIPTION Blabla blabla Exports :T1 Blabla :T2 Blabla FUNCTION hello This function prints hello. FUNCTION bonjour This function prints hello in french. Pour plus dinformations et de d etails sur ce format, je vous invite ` a consulter perldoc perlpod o` u de nombreux exemples sont donn es. Vous pouvez aussi jeter un il au code dun module ou deux dont le perldoc vous intrigue ...

10.16

Un dernier mot sur les modules

Jesp` ere que la lecture de cette partie vous a donn e envie de structurer votre code en regroupant vos fonctions dans de telles biblioth` eques. Vous vous rendrez compte de cette n ecessit e lorsque vous aurez un chier de code trop gros ` a g erer ... Mais m eme sans cela, nh esitez pas ` a faire des modules, ne serait-ce que pour une r e-utilisation de fonctionnalit es dans dautres scripts ou pour partager votre code avec des amis, des coll` egues voire avec la communaut e.

105

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

106

Chapitre 11

Programmation objet
La programmation objet est le concept nouveau de ces vingt derni` eres ann ees. C++ est b ati sur le C et apporte lobjet. Java a et e mis au point (entre autres) pour passer outre les nombreux pi` eges et probl` emes de C++. Ruby est un langage interpr et e bas e sur ce concept objet. Perl, qui utilisait un garbage collector bien avant que Java nexiste, ne pouvait pas etre en reste et la communaut e Perl a rapidement propos e les extensions du langage n ecessaires ` a ce type de programmation. On notera que ces extensions sont peu nombreuses car lid ee a et e de r eutiliser au maximum ce qui existait d ej` a en Perl et de lappliquer ` a la programmation objet. Le C++ etant compil e et devant rester compatible avec le C, cela fut un challenge de mettre sur pied ce langage ; cela explique sans doute pourquoi C++ est si complexe et comporte tant de pi` eges. Perl, de par sa nature interpr et ee, na pas pos e de probl` eme pour s etendre ` a lobjet. La programmation par objets ouvre le champ des possibilit es oertes au programmeur ; alli ee ` a un langage puissant et exible comme Perl, elle ore la souplesse, la richesse et la facilit e d ecriture quil manque aux langages uniquement objet. Toutefois, de par sa nature permissive, le langage Perl ne saurait etre aussi strict que des langages exclusivement objet. Le programmeur est invit e` a faire les choses proprement, mais rien ne ly oblige.

11.1

Vous avez dit objet ?

Sans revenir sur la th eorie de la programmation objet, je vais tenter ici dy faire une courte introduction. La programmation orient ee objet est un type de programmation qui se concentre principalement sur les donn ees. La question qui se pose en programmation OO (orient ee objet) est quelles sont les donn ees du probl` eme ? ` a linstar de la programmation proc edurale par exemple, qui pose la question quelles sont les fonctions/actions ` a faire ?. En programmation OO, on parle ainsi dobjets, auxquels on peut aecter des variables/attributs (propri et es) et des fonctions/actions (m ethodes). On parle de classe, qui est une mani` ere de repr esenter des donn ees et comporte des traitements : une classe Chaussure d ecrit, par exemple, les caract eristiques dune chaussure. Elle contient un champ d ecrivant la pointure, la couleur, la mati` ere etc. Une telle classe comporte de plus des traitements sur ces donn ees ; ces traitements sont appel es m ethodes. Grossi` erement une m ethode est une fonction appliqu ee ` a un objet. Une fois d enie une telle classe, il est possible den construire des instances : une instance dune classe est dite etre un objet de cette classe. Dans notre exemple, il sagirait dune chaussure

107

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

dont la pointure, la couleur et la mati` ere sont renseign ees.

11.2

Pr eparatifs

Nous allons maintenant voir comment ecrire une classe en Perl. Vous verrez, cela est tr` es simple et d emystie la programmation objet. En Perl, une classe nest autre quun module et un objet (instance de cette classe) nest autre quune r ef erence associ ee ` a cette classe. Dans le constructeur, nous allons donc cr eer une r ef erence (typiquement vers une table de hachage) et nous allons lassocier au package en question ; lors de cette association, on dit en Perl que lon b enit (bless en anglais) la r ef erence. Les champs de lobjet seront en fait stock es dans cette table de hachage, sous forme de la clef pour le nom du champ et de la valeur pour la valeur du champ. Voyons un exemple : d enissons une classe Vehicule qui comporte deux champs : un nombre de roues et une couleur.

11.3

Ecrire un constructeur

Nous d enissons un package Vehicule dans un chier Vehicule.pm comme nous le faisons pour tout module. 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: # --- fichier Vehicule.pm --package Vehicule; use strict; sub new { my ($class,$nbRoues,$couleur) = @_; my $this = {}; bless($this, $class); $this->{NB_ROUES} = $nbRoues; $this->{COULEUR} = $couleur; return $this; } 1; # ` A ne pas oublier...

La ligne num ero 2 indique le nom du package actuel ; il est conseill e de choisir le m eme nom que pour le chier, simplement pour des raisons dorganisation et de maintenance. La ligne 12 comporte le fameux code de retour du chargement du module. La ligne 3 force une syntaxe plus rigoureuse. En Perl, le nom des modules et donc des classes que le programmeur d enit doit etre compos e de majuscules et de minuscules, avec typiquement une majuscule au d ebut de chaque mot ; les noms de package exclusivement en minuscules sont r eserv es pour les modules pragmatiques de Perl (dits modules pragma comme strict etc), les noms exclusivement en majuscules sont in el egants. :-) Nous d enissons une fonction new (ligne 4) dont le but est de construire un objet Vehicule. Il sagit donc dun constructeur ; un constructeur en Perl est une simple fonction renvoyant un objet. Il est bon de noter que le choix du nom pour cette fonction est totalement libre ; il est courant de lappeler new mais rien ne nous y oblige. On pourrait par exemple choisir le nom de

108

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

la classe (si on est un habitu e de C++ ou de Java), mais on verra par la suite que cela nest pas forc ement une bonne id ee. Cette fonction prend en premier param` etre le nom de la classe ; cela semble superu, mais on verra quil nen est rien. Les param` etres suivants sont laiss es ` a la discr etion du programmeur : bien souvent on passe ici les valeurs de champs pour linitialisation. Cest ce que lon fait ici : le nombre de roues et la couleur sont transmis (ligne 5). Ligne 6, nous cr eons une r ef erence anonyme vers une table de hachage vide {}. Cette r ef erence est stock ee dans une variable scalaire nomm ee $this car il va sagir de notre futur objet. Le nom de cette variable est totalement arbitraire et jai choisi de prendre le nom $this car il rappelle les variables this de C++ et de Java. Mais comprenez bien quil ny a rien dobligatoire dans cette appellation. Il est dailleurs fr equent que le nom de lobjet dans les m ethodes soit plut ot $self en Perl (vous trouverez ce nom dans la plupart des modules objet de CPAN). Ligne 7, nous indiquons que cette r ef erence est li ee au package (` a la classe) $class. Cette variable $class vaudra ici Vehicule. Lop erateur bless associe le package en question ` a la r ef erence. La r ef erence est maintenant li ee au package. Dans les lignes 8 et 9, les champs NB_ROUES et COULEUR sont initialis es. Le champ dun objet nest rien dautre quune entr ee dans la table de hachage qui constitue lobjet. Pour aecter un champ de lobjet que nous sommes en train de construire, il sut de cr eer un couple clef/valeur dans la table de hachage r ef erenc ee par $this. Jai pris lhabitude de mettre le nom des champs en lettres majuscules. Notez que le nombre, le nom et le contenu des champs peuvent donc varier dune instance de la classe ` a une autre instance de cette m eme classe. Libre au programmeur de faire ce quil veut : si le but est de vraiment programmer objet de fa con formelle, il va respecter les habitudes de ce type de programmation qui veut que toutes les instances dune m eme classe aient les m emes champs ; mais sil ne tient pas ` a respecter ces contraintes, il est libre de faire ce quil veut de chacun de ses objets. La ligne 10 consiste en un return de la r ef erence vers la table de hachage ainsi construite.

11.4

Appeler le constructeur

Pour faire usage de cette classe, nous allons devoir disposer dun script ecrit dans un autre chier (par exemple script.pl) : #!/usr/bin/perl -w use strict; Comme pour tout module, nous devons explicitement indiquer que nous allons lutiliser : use Vehicule; Nous pouvons maintenant utiliser le constructeur que nous avons d eni : my $v = Vehicule->new( 2, "bleu" ); my $v2 = Vehicule->new( 4, "rouge" ); Nous venons ici de cr eer deux instances de la classe Vehicule. On dit que ces deux variables $v et $v2 sont des Vehicule. Ces deux objets sont donc ind ependants lun de lautre ; ils sont de la m eme classe Vehicule, mais en constituent des instances autonomes, la modication de lun ne modiant pas lautre. Voici un sch ema de l etat de notre m emoire :

109

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

$v

Vehicule NB_ROUES COULEUR => => 2 bleu

$v2

Vehicule NB_ROUES COULEUR => => 4 rouge

Cette syntaxe Vehicule->new correspond ` a lappel du constructeur new que nous venons d ecrire. La variable $v est initialis ee a ` la valeur de retour de cette fonction. Elle est donc une r ef erence vers une table de hachage dont deux champs sont initialis es et qui a et e b enie (bless) en Vehicule. Idem pour $v2. Il est aussi possible de faire usage de la syntaxe suivante : my $v = new Vehicule( 2, "bleu" ); Cette formulation va sans doute rassurer les habitu es de Java ou de C++, mais peut induire le programmeur en erreur. En eet, cette derni` ere syntaxe semble indiquer que new est un op erateur sp ecique pour appeler un constructeur et est donc un mot r eserv e du langage. Il nen est rien ; comme on le verra un peu plus loin, ce nom est totalement arbitraire.

11.5

Manipulations de lobjet

Revenons ` a notre exemple. En plus de savoir quelle pointe vers une table de hachage, la r ef erence $v sait de quelle classe elle est. En eet, si nous lachons : print "$v\n"; Nous obtenons la chose suivante ` a l ecran : Vehicule=HASH(0x80f606c) Je vous rappelle que dans le cas de lachage dune r ef erence vers une table de hachage non b enie, nous obtenons quelque chose de la forme : HASH(0x80fef74)

110

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

Un objet (` a partir de maintenant nommons ainsi une r ef erence vers une table de hachage b enie) sait donc de quelle classe il est. Cela va lui permettre de choisir le bon package quand on appellera une m ethode sur cet objet (lire la suite). Voyons maintenant ce que donne le module Data::Dumper (dont jai d ej` a parl e) sur une telle r ef erence : use Data::Dumper; print Dumper($v)."\n"; Lachage suivant est eectu e: $VAR1 = bless( { COULEUR => bleu, NB_ROUES => 2 }, Vehicule ); On remarquera que la tradition de Data::Dumper qui consiste en ce que la cha ne renvoy ee est directement int egrable dans un code Perl est respect ee : m eme lop eration de b en ediction (bless) est pr esente. Il faut bien voir que $v est une r ef erence vers un objet. Autrement dit, si on fait une copie de cette variable my $w = $v; nous obtenons deux variables qui pointent vers le m eme objet.

$v

Vehicule NB_ROUES => => 2 bleu

$w COULEUR

$v2

Vehicule NB_ROUES COULEUR => => 4 rouge

La modication de lobjet point e par lun modiera celui point e par lautre car il sagit du m eme objet.

111

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

11.6

Plusieurs constructeurs

Comment ecrire plusieurs constructeurs pour une m eme classe ? Rien de plus simple. Le nom new que jai choisi pour le constructeur na rien dobligatoire, en fait un constructeur est une simple fonction qui renvoie une r ef erence b enie. Seule la syntaxe dappel change par rapport ` a ce que lon a vu pour les modules. Je peux donc ecrire un autre constructeur (donc avec un autre nom) : sub nouveau { my ($class,$couleur) = @_; my $this = {}; bless($this, $class); $this->{COULEUR} = $couleur; return $this; } Ce constructeur de Vehicule prend par exemple un seul param` etre (la couleur) et naecte ` pas de champs NB_ROUES car rien de ne ly oblige. A moi de savoir comment je veux g erer mes v ehicules, ` a savoir comment jautorise quils soient construits. Pour etre propre et coh erent, nous allons tout de m eme consid erer quil est sage daecter une valeur ` a la clef NB_ROUES : sub nouveau { my ($class,$couleur) = @_; my $this = {}; bless($this, $class); $this->{NB_ROUES} = 0; $this->{COULEUR} = $couleur; return $this; } Voici comment on va faire appel ` a ce constructeur : my $v2 = Vehicule->nouveau( "bleu" ); De la m eme fa con que pour le pr ec edent constructeur, il est possible dutiliser la syntaxe suivante : my $v2 = nouveau Vehicule( "bleu" ); Ce qui est, reconnaissons-le, quelque peu d eroutant. Cest pour cela que je vous conseille dutiliser plut ot la premi` ere syntaxe Vehicule->nouveau() ou alors de vous en tenir ` a un constructeur new pour ecrire new Vehicule().

11.7

Ecrire une m ethode

Une m ethode est une fonction qui sapplique ` a une instance de la classe. Cela est vrai dans tous les langages objet, mais bien souvent cela est masqu e ; dans notre cas rien de masqu e, le premier param` etre de la fonction sera lobjet (la r ef erence b enie) :

112

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

sub roule { my ($this,$vitesse) = @_; print "Avec $this->{NB_ROUES} roues, je roule ` a $vitesse.\n"; } Cette fonction d eclar ee dans le chier Vehicule.pm a donc pour premier param` etre lobjet sur lequel elle est appel ee. Vous noterez une fois de plus que rien noblige le programmeur ` a nommer cette variable $this ; la seule contrainte est sa premi` ere place parmi les arguments. Cette m ethode peut d` es maintenant etre appel ee depuis le chier script.pl sur les objets de type Vehicule. Il ny pas de n ecessit e de faire usage du lourd m ecanisme dExporter car nous navons pas besoin de modier lespace de nom des fonctions des scripts appelants. Pour appeler la m ethode, il sut d ecrire dans le chier script.pl : $v->roule( 15 ); La fonction appel ee sera celle qui a pour nom roule d enie dans le package li e` a la r ef erence $v lors de sa b en ediction. Lachage suivant a donc lieu : Avec 2 roues, je roule ` a 15. Ecrivons par exemple une m ethode dachage : sub toString { my ($this) = @_; return "(Vehicule:$this->{NB_ROUES},$this->{COULEUR})"; } Cette m ethode renvoie une cha ne de caract` eres, repr esentation de lobjet. Les habitu es de Java noteront que jai choisi le nom de cette fonction pour leur rappeler des souvenirs, mais quil na rien de sp ecial. Voici comment lutiliser dans le script : print $v->toString()."\n"; Et lachage a lieu : (Vehicule:2,bleu) Libre ` a vous de choisir un plus bel achage.

11.8

Reparlons des champs

Un champ est une donn ee propre ` a une instance de classe. En Perl, ces champs sont stock es comme clef/valeur dans la table de hachage qui constitue lobjet (si on utilise une table de hachage comme objet, ce qui est souvent le cas). Nos v ehicules comportent deux champs : NB_ROUES et COULEUR. Ces champs etant de simples clef/valeur dune table de hachage dont on dispose dune r ef erence dans le script, ils y sont accessibles. Dans le script, nous pouvons ecrire dans le chier script.pl :

113

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

foreach my $k (keys %$v) { print "$k : $v->{$k}\n"; } Cest-` a-dire que je peux acc eder sans restriction ` a lensemble des champs de lobjet. En eet, jai en main une r ef erence vers une table de hachage ; le fait quelle soit b enie ne change rien au fait que je peux la d er ef erencer et acc eder aux diverses valeurs quelle contient. Je peux aussi bien modier ces valeurs ou m eme en ajouter ou en supprimer, car il sagit en eet dune table de hachage comme les autres. Comment prot eger les donn ees dun objet ? allez-vous alors me demander. Et bien, Perl na rien pr evu pour ca. Cela va sans doute faire hurler les puristes de la programmation objet, mais cest comme cela ... Perl vous propose les principaux m ecanismes pour faire de la programmation objet tout en restant coh erent avec le reste du langage, certaines choses ne sont donc pas possibles. Faute de champs priv es en Perl, il existe une convention qui dit que les champs dont la clef commence par un underscore (soulign e _) sont des champs priv es et les scripts qui utilisent les objets ainsi faits sont pri es de respecter cette convention. Cest le cas de beaucoup de modules CPAN. Cette convention est aussi valable pour les m ethodes (une m ethode dont le nom commence par une underscore est une m ethode priv ee). De fa con g en erale, un programmeur Perl est quelquun de bonne education (sinon il programmerait en Java ;-))) et il ne modiera pas une instance dune classe quil na pas ecrite. En eet, pourquoi modier un objet Net::FTP alors quil fait tr` es bien son travail ? De toute fa con, il a forc ement acc` es au code source de cette classe et sil veut la modier, il peut en faire une copie et la modier ! La protection des donn ees est donc plus une n ecessit e sociale (manque de conance en lesp` ece humaine ` a laquelle les d eveloppeurs pr etendent encore faire partie :-))) quune n ecessit e technique. Pas dramatique pour faire de lobjet.

11.9

Composition

Prenons le temps de faire un petit exemple pratique pour illustrer le concept de composition. La composition est le fait quun objet est constitu e dautres objets. Par exemple un garage comporte des v ehicules. Je d ecide quun garage aura une taille limite : il sagira du nombre maximal de v ehicules quil pourra contenir. Un garage devra donc contenir une liste de v ehicules. Nous devons cr eer un chier Garage.pm contenant : package Garage; use strict; # ... ici les m ethodes qui vont suivre 1; Voyons ensuite le constructeur : sub new { my ($class,$places) = @_; my $this = {};

114

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

bless($this, $class); $this->{PLACES} = $places; $this->{VEHICULE} = []; return $this; } Ce constructeur prendra en param` etre le nombre de places disponibles du garage ; cette valeur est enregistr ee dans le champ PLACES. Le champ VEHICULE comportera la liste des v ehicules ; pour cela elle est initialis ee ` a la r ef erence anonyme vers une liste vide. La m ethode ajoute se chargera dajouter les v ehicules dans la limite du nombre de places : sub ajoute { my ($this,$vehicule) = @_; if( @{$this->{VEHICULE}} < $this->{PLACES} ) { push @{$this->{VEHICULE}}, $vehicule; return 1; } return 0; } Cette m ethode prend en param` etre une r ef erence vers un v ehicule. Elle compare la longueur de la liste des v ehicules au nombre total de places (lexpression @{$this->{VEHICULE}} est la liste point ee par la r ef erence $this->{VEHICULE} ; evalu ee en contexte num erique, elle vaut son nombre d el ements). Sil reste de la place, le v ehicule est ajout e (fonction push) et elle renvoie vrai, sinon elle renvoie faux. Voici comment lutiliser dans le script : use Garage; my $g = Garage->new(3); my $v = new Vehicule( 2, "bleu" ); $g->ajoute( $v ) or die("ajoute: plus de place"); $g->ajoute( Vehicule->new( 4, "vert" ) ) or die("ajoute: plus de place"); $g->ajoute( Vehicule->new( 1, "jaune" ) ) or die("ajoute: plus de place"); Ecrivons maintenant une m ethode dachage pour un tel objet : sub toString { my ($this) = @_; my $s = "{Garage:$this->{PLACES},"; foreach my $v ( @{$this->{VEHICULE}} ) { $s .= $v->toString(); } return $s."}"; }

115

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

On appelle sur chaque objet Vehicule la m ethode toString de fa con ` a le faire appara tre dans la cha ne que nous allons renvoyer. Voici comment appeler cette m ethode dans le script : print $g->toString()."\n"; Ce qui donne lachage suivant : {Garage:3,(Vehicule:2,bleu)(Vehicule:4,vert)(Vehicule:1,jaune)} On pourrait ecrire cette m ethode di eremment si on voulait s eparer chaque v ehicule par une virgule : sub toString { my ($this) = @_; my $s = "{Garage:$this->{PLACES},"; $s .= join( ,, map( { $_->toString() } @{$this->{VEHICULE}} ) ); return $s."}"; } Ce qui donne lachage suivant : {Garage:3,(Vehicule:2,bleu),(Vehicule:4,vert),(Vehicule:1,jaune)} Pour ajouter encore une dicult e, je d ecide de trier les v ehicules par nombre de roues croissant : sub toString { my ($this) = @_; my $s = "{Garage:$this->{PLACES},"; $s .= join( ,, map( {$_->toString()} sort( {$a->{NB_ROUES} <=> $b->{NB_ROUES} } @{$this->{VEHICULE}} ) ) ); return $s."}"; } Ce qui donne lachage suivant : {Garage:3,(Vehicule:1,jaune),(Vehicule:2,bleu),(Vehicule:4,vert)} Ces deux derniers exemples vous sont propos es pour que vous vous torturiez un peu les m eninges ;-))

116

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

11.10

Destruction dun objet

Un objet est d etruit d` es quaucune r ef erence ne pointe vers cet objet. La ligne suivante, par exemple, lib` ere la place m emoire occup ee par lobjet Vehicule r ef erenc e par $v2 : $v2 = undef; ` cet instant, Perl se rend compte que lobjet en question nest plus accessible, la m A emoire sera donc automatiquement lib er ee par le m ecanisme du garbage collector. La m eme chose a lieu dans le cas de la disparition dune variable locale : if( ... ) { my $v3 = Vehicule->new(3,jaune); ... ... } La variable $v3 cesse dexister ` a la fermeture de laccolade du if. Lobjet qui a et e cr e e dans le bloc sera donc d etruit (sauf si on a fait en sorte quune autre variable dont la visibilit e d epasse ce bloc pointe aussi vers lobjet). Cette lib eration nest peut- etre pas faite en temps r eel, mais ce nest pas au programmeur de sen occuper. Il existe une m ethode tr` es sp eciale, dont le nom est r eserv e, qui est appel ee lors de la destruction dune instance dun objet. Il sagit de la m ethode DESTROY. Cette m ethode sera appel ee (si elle existe dans la classe) par le garbage collector juste avant la lib eration de la m emoire de lobjet. sub DESTROY { my ($this) = @_; print "` A la casse Vehicule ! "; print "($this->{NB_ROUES} $this->{COULEUR})\n"; } Cette m ethode doit etre d enie dans le package de lobjet en question et re coit en premier argument une r ef erence vers lobjet qui va etre d etruit. Cette m ethode est tr` es utile pour lib erer des ressources (chier, connexion r eseau etc) qui ont et e allou ees lors de la cr eation de lobjet.

11.11

H eritage

Lh eritage est un des apports de la programmation objet. Perl dispose de tout ce quil faut pour le mettre en uvre. Imaginons quen plus de v ehicules, nous avons besoin de manipuler des v elos et des voitures. Ces objets ont en commun davoir un nombre de roues et une couleur. Ils ont des caract eristiques suppl ementaires qui leur sont propres ; les v elos ont un nombre de vitesses et les voitures, un nombre de si` eges. Ces classes Velo et Voiture vont donc h eriter de la classe Vehicule, cest-` adire quelles vont comporter tous les champs et les m ethodes de cette classe.

117

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

On dit alors que la classe Vehicule est la classe m` ere ; les classes Velo et Voiture etant des classes lles. Notez bien que je prends comme exemple deux classes lles et quil nest nullement n ecessaire davoir deux classes lles pour mettre en uvre lh eritage, une seule est susante. Voyons le cas de la classe Velo, cr eons pour cela un chier Velo.pm qui contient : package Velo; use strict; use Vehicule; our @ISA = qw(Vehicule); # ... ici les m ethodes qui vont suivre 1; On signale le lien de liation entre classes au moyen de la variable @ISA positionn ee ` a la valeur dune liste contenant le nom de la classe m` ere. ISA vient de langlais is a, est un : on dit quun v elo est un v ehicule. Il h erite donc des champs et m ethodes de la classe Vehicule. D enissons lui un constructeur : sub new { my ($class,$couleur,$nbVitesses) = @_; my $this = $class->SUPER::new( 2, $couleur ); $this->{NB_VITESSES} = $nbVitesses; return bless($this,$class); } Ce constructeur prend donc deux param` etres. Il appelle le constructeur de la classe m` ere (syntaxe $class->SUPER::new). Il ajoute un champ NB_VITESSE et renvoie une r ef erence b enie en Velo. Notez bien quaucun appel au constructeur de la classe m` ere nest fait par d efaut, il faut le faire explicitement dans tous les cas. Le lecteur aura not e que, comme les champs de la classe m` ere et de la classe lle sont stock es dans la m eme table de hachage, il ny a pas moyen simple de faire de surcharge ou de masquage des champs. Les noms des champs devront etre minutieusement choisis pour ne pas entrer en conit les uns avec les autres. Voyons ` a pr esent comment ecrire une m ethode pour cet objet : sub pedale { my ($this,$ici) = @_; print "Sur mon v elo $this->{COULEUR} "; print "je p edale avec $this->{NB_VITESSES} vitesses"; print " dans $ici.\n"; } Utilisons maintenant tout cela dans notre script : use Velo; my $velo = Velo->new(blanc,18); $velo->pedale(les bois); $velo->roule(10);

118

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

Un v elo dispose de la m ethode roule car il est aussi un v ehicule. Lachage suivant est eectu e: Sur mon v elo blanc je p edale avec 18 vitesses dans les bois. Avec 2 roues, je roule ` a 10. Voyons ` a pr esent comment acher un tel objet. Nous laisserons le soin ` a la classe Vehicule dacher le v elo comme etant un v ehicule et nous neectuerons dans la classe Velo que lafchage de ce que nous avons ajout e` a la classe m` ere : sub toString { my ($this) = @_; my $s = "[Velo:$this->{NB_VITESSES}"; $s .= $this->SUPER::toString(); $s .= "]"; } La syntaxe $this->SUPER::toString() correspond ` a lappel de la m ethode toString de la classe m` ere. Nous pouvons maintenant lappeler dans notre script : print $velo->toString()."\n"; Lachage suivant est eectu e: [Velo:18(Vehicule:2,blanc)] Rien de plus simple ! Seule chose pas extr emement pratique, lappel au destructeur sarr ete au premier destructeur rencontr e. Si dans notre exemple nous d enissions une m ethode DESTROY pour la classe Velo, la m ethode DESTROY de la classe Vehicule ne sera pas appel ee. Cela peut etre g enant si des ressources importantes sont lib er ees dans cette m ethode ; il faut alors lappeler explicitement. Voici un exemple de m ethode DESTROY pour la classe Velo : sub DESTROY { my ($this) = @_; $this->SUPER::DESTROY(); print "Bye bye Velo ! "; print "($this->{NB_VITESSES} $this->{NB_ROUES} ". "$this->{COULEUR})\n"; } La deuxi` eme ligne de la m ethode fait un appel ` a la m ethode de la classe m` ere. Pour faire de lh eritage multiple en Perl, rien de plus simple. Vous aurez peut- etre not e que la variable @ISA est un tableau, elle peut donc contenir plusieurs noms de classe : package Voiture; our @ISA = qw(Vehicule Danger Pollution); La d etermination de la bonne m ethode ` a appeler est eectu ee dynamiquement par une recherche en profondeur dans larbre dh eritage. Je ne m etendrai pas plus sur cette question de lh eritage multiple.

119

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

11.12

Classes dun objet

Dans cette partie nous allons voir comment conna tre la classe dun objet ainsi que tester lappartenance ` a une classe pour un objet. Souvenez-vous de lop erateur ref qui, appliqu e` a une r ef erence, renvoie le type de structure de donn ees vers laquelle elle pointe (scalaire, tableau, table de hachage etc). Appliqu e` a un objet, il renvoie la classe de lobjet : print ref($velo)."\n"; print "Ouf, tout va bien !\n" if( ref($velo) eq "Velo" ); Lachage eectu e est le suivant : Velo Ouf, tout va bien ! Il sagit donc de la classe principale de lobjet. Sachant quun v elo est aussi un v ehicule, il peut etre utile de pouvoir tester lappartenance de lobjet ` a une classe plut ot que de conna tre sa classe principale. Par exemple, si nous manipulons un tableau comportant des objets divers et vari es et si nous souhaitons y retrouver tous les objets de classe Vehicule pour appeler leur m ethode roule, nous ne pouvons pas ecrire if( ref($r) eq "Vehicule" ) { ... } car les v elos ne seront pas s electionn es. En fait la question que nous devons ici nous poser nest pas de savoir si la classe principale de lobjet est Vehicule, mais nous devons nous demander si lobjet est un objet de classe Vehicule (ce qui est vrai pour tout objet de classe Vehicule et ses sous-classes, comme Velo et Voiture). La fonction isa du package UNIVERSAL va nous permettre de faire cela : use UNIVERSAL qw(isa); if( isa( $r, "Vehicule" ) ) { $r->roule( 40 ); } On teste ainsi si la variable $r est un objet de classe Vehicule.

11.13

Champs et m ethodes statiques

Un champ statique est un champ qui est commun ` a tous les objets dune classe, cest-` a-dire quil nest pas li e` a une instance particuli` ere mais ` a une classe. Cest une sorte de variable globale (dont lacc` es peut eventuellement etre contr ol e) qui est situ ee dans une classe. Pour faire cela en Perl, nous utiliserons des variables d eclar ees dans le package de la classe en question. package Vehicule; my $privateVar = 0; our $publicVar = "hello";

120

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

Avec le qualicateur my, nous d eclarons des variables priv ees (car visibles uniquement depuis lint erieur du package). Avec our, sont d eclar ees des variables publiques (accessibles depuis nimporte quel package). Je rappelle que pour acc eder ` a la variable $publicVar du package Vehicule, on doit ecrire $Vehicule::publicVar ; depuis les fonctions et m ethodes de ce package, il est susant d ecrire $publicVar (sauf masquage par une variable locale). On pourrait par exemple compter le nombre de v ehicules cr e es au moyen dune telle variable : package Vehicule; my $nbVehicules = 0; sub new { my ($class,$nbRoues,$couleur) = @_; my $this = {}; bless($this, $class); $this->{NB_ROUES} = $nbRoues; $this->{COULEUR} = $couleur; $nbVehicules++; # un v ehicule de plus return $this; } ` chaque appel au constructeur de cette classe, la variable $nbVehicules sera donc incr A ement ee. Maintenant, comment ecrire une m ethode statique ? Une m ethode statique (ou m ethode de classe) est une m ethode qui nest pas appel ee sur une instance de la classe (donc pas de variable $this) mais pour toute la classe. Ce nest ni plus ni moins quune brave fonction pr esente dans le package. Cette fonction pourra donc uniquement acc eder aux champs statiques de la classe. Nous pourrions, par exemple, ecrire une m ethode statique qui renvoie le nombre de v ehicules cr e es (variable $nbVehicules) : sub getNbVehicules { my ($class) = @_; return $nbVehicules; } On notera que la m ethode prend en premier argument le nom de la classe. Cela a pour cons equence que lappel ` a la m ethode ne se fait pas tout ` a fait comme pour une fonction dun package (comme vu pour les modules), mais de la mani` ere suivante : print Vehicule->getNbVehicules()."\n"; Le nom de la classe est suivi dune ` eche, du nom de la m ethode et des eventuels arguments entre parenth` eses. N ecrivez pas Vehicule::getNbVehicules() car le nom de la classe nest pas transmis et surtout car les m ecanismes dh eritage ne sont pas mis en uvre. Sil est possible d ecrire Velo->getNbVehicules(), il nest pas permis d ecrire Velo::getNbVehicules(). Le lecteur notera que les constructeurs sont des m ethodes statiques. Ils retournent des r ef erences b enies, mais nont rien de particulier par rapport ` a dautres m ethodes de classe. Il est tout ` a fait possible dappeler cette m ethode sur une instance de la classe Vehicule

121

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

print $v->getNbVehicules()."\n"; mais dans ce cas le premier argument re cu nest pas le nom de la classe mais lobjet en question (cest donc une m ethode dinstance et de classe ...). Cela ne change rien pour notre m ethode getNbVehicules car elle nutilise pas son premier argument, mais le cas est g enant pour les constructeurs qui ont ` a b enir une r ef erence. Pour cela, tout constructeur devrait commencer par d eterminer sil a en premier argument le nom de la classe ou une r ef erence. Linstruction qui suit place dans la variable $class la classe actuelle, que cette variable ait pour valeur initiale le nom de la classe ou une instance de la classe : $class = ref($class) || $class; Il convient dor enavant d ecrire le constructeur ainsi : sub new { my ($class,$nbRoues,$couleur) = @_; $class = ref($class) || $class; my $this = {}; bless($this, $class); $this->{NB_ROUES} = $nbRoues; $this->{COULEUR} = $couleur; $nbVehicules++; # un v ehicule de plus return $this; } Il est maintenant possible d ecrire la ligne suivante dans le script : $v2 = $v->new( 1, "noir" ); Le constructeur est appel e sur une instance de la classe plut ot que sur la classe. On pourrait faire de m eme pour toutes les m ethodes statiques (cest m eme plut ot conseill e).

11.14

Exemple complet

Voici le contenu exact des chiers dexemple b atis tout au long de cette partie du document. Fichier Vehicule.pm : package Vehicule; use strict; my $nbVehicules = 0; sub new { my ($class,$nbRoues,$couleur) = @_; $class = ref($class) || $class; my $this = {}; bless($this, $class); $this->{NB_ROUES} = $nbRoues; $this->{COULEUR} = $couleur;

122

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

$nbVehicules++; # un v ehicule de plus return $this; } sub roule { my ($this,$vitesse) = @_; print "Avec $this->{NB_ROUES} roues, je roule ` a $vitesse.\n"; } sub toString { my ($this) = @_; return "(Vehicule:$this->{NB_ROUES},$this->{COULEUR})"; } sub getNbVehicules { my ($class) = @_; $class = ref($class) || $class; return $nbVehicules; } sub DESTROY { my ($this) = @_; print "Bye bye Vehicule ! "; print "($this->{NB_ROUES} $this->{COULEUR})\n"; } 1; # ` A ne pas oublier... Fichier Velo.pm : package Velo; use strict; use Vehicule; our @ISA = qw(Vehicule); sub new { my ($class,$couleur,$nbVitesses) = @_; $class = ref($class) || $class; my $this = $class->SUPER::new( 2, $couleur ); $this->{NB_VITESSES} = $nbVitesses; return bless($this,$class); } sub pedale { my ($this,$ici) = @_; print "Sur mon v elo $this->{COULEUR} "; print "je p edale avec $this->{NB_VITESSES} vitesses"; print " dans $ici.\n"; } sub toString { my ($this) = @_; my $s = "[Velo:$this->{NB_VITESSES}"; $s .= $this->SUPER::toString(); $s .= "]";

123

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

} sub DESTROY { my ($this) = @_; $this->SUPER::DESTROY(); print "Bye bye Velo ! "; print "($this->{NB_VITESSES} $this->{NB_ROUES} ". $this->{COULEUR})\n"; } 1; Fichier Garage.pm : package Garage; use strict; sub new { my ($class,$places) = @_; $class = ref($class) || $class; my $this = {}; bless($this, $class); $this->{PLACES} = $places; $this->{VEHICULE} = []; return $this; } sub ajoute { my ($this,$vehicule) = @_; if( @{$this->{VEHICULE}} < $this->{PLACES} ) { push @{$this->{VEHICULE}}, $vehicule; return 1; } return 0; } sub toString { my ($this) = @_; my $s = "{Garage:$this->{PLACES},"; $s .= join( ,, map( {$_->toString()} sort( {$a->{NB_ROUES} <=> $b->{NB_ROUES} } @{$this->{VEHICULE}} ) ) ); return $s."}"; } 1; Fichier script.pl : #!/usr/bin/perl -w use strict; use Data::Dumper; use UNIVERSAL qw(isa);

124

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

use Vehicule; use Garage; use Velo; my $v = Vehicule->new( 2, "bleu" ); my $v2 = Vehicule->new( 4, "rouge" ); print "$v\n"; print Dumper($v)."\n"; $v->roule(30); $v2 = undef; if( 1 ) { my $v3 = Vehicule->new(3,jaune); } foreach my $k (keys %$v) { print "$k : $v->{$k}\n"; } print $v->toString()."\n"; my $g = Garage->new(3); $g->ajoute( $v ) or die("ajoute: plus de $g->ajoute( Vehicule->new( or die("ajoute: plus de $g->ajoute( Vehicule->new( or die("ajoute: plus de print $g->toString()."\n"; my @tab = ( Velo->new(rose,15), Vehicule->new(3,gris), "hello", Velo->new(vert,21), ); foreach my $r (@tab) { if( isa( $r, "Vehicule" ) ) { $r->roule( 40 ); } } my $velo = Velo->new(blanc,18); $velo->pedale(les bois); $velo->roule(10); print $velo->toString()."\n"; print ref($velo)."\n"; print "Ouf, tout va bien !\n" if( ref($velo) eq "Velo" ); print Vehicule->getNbVehicules()."\n";

place"); 4, "vert" ) ) place"); 1, "jaune" ) ) place");

125

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

print Velo->getNbVehicules()."\n"; print $v->getNbVehicules()."\n"; $v2 = $v->new( 1, "noir" );

126

Conclusion
Nous sommes ici au terme de ce cours introductif ` a la programmation en Perl. Vous avez maintenant en main la plupart des concepts et des notions pour etre autonome en Perl. Noubliez pas que la documentation de Perl est tr` es bien faite et est disponible sur votre ordinateur au moyen de la commande perldoc : perldoc perl vous donne acc` es ` a la liste des th` emes consultables avec perldoc. Par exemple perldoc perldata vous explique les structures de donn ees en Perl. Pour une fonction particuli` ere, utilisez loption -f : perldoc -f chomp Pour un module particulier, utilisez perldoc sans option : perldoc Data::Dumper ` vous de les mettre Vous avez maintenant en main beaucoup de notions importantes de Perl. A en uvre pour vos propres probl` emes. Il nest pas forc ement facile dexprimer son besoin en termes directement exploitables dans un langage particulier, mais en ayant un peu dexp erience de Perl, vous trouverez vite votre mani` ere de r esoudre un probl` eme. Vous allez alors commencer a faire connaissance avec Tim Towtdi (There is more than one way to do it). ;-) `

127

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

128

Lauteur
Sylvain Lhullier http://sylvain.lhullier.org/ Sp ecialiste du langage Perl, Sylvain Lhullier propose des formations professionnelles dans le domaine de la programmation en Perl ` a destination des administrateurs syst` emes comme des d eveloppeurs (http://formation-perl.fr/). Depuis 2000, il enseigne ce langage en universit es et ecole ding enieurs. Il est egalement lauteur de conf erences et dateliers sur la prise en main et lutilisation de Perl. Membre de lassociation de promotion du langage Perl en France Les Mongueurs de Perl (http://mongueurs.net/) depuis 2002, il a et e le coordinateur du groupe de travail Articles qui a pour vocation daider ` a la publication darticles sur Perl et les technologies connexes. Entre 2002 et 2004, il publie, avec laide de ce groupe de travail, une s erie de 7 articles dans Linux Magazine France sur le langage Perl. Lauteur remercie les autres membres de lassociation pour les corrections eectu ees.

129

Vous aimerez peut-être aussi