Vous êtes sur la page 1sur 171

Introduction ` a la programmation en Perl

ou comment dbuter en Perl e

Sylvain Lhullier Version 1.0.5 21 novembre 2004

Introduction a la programmation en Perl `

c sylvain@lhullier.org

Table des mati`res e


Licence Introduction 7 9

1 Premiers pas 11 1.1 Excuter un programme en Perl . . . . . . . . . . . . . . . . . 11 e 1.2 Les types de donnes . . . . . . . . . . . . . . . . . . . . . . . 13 e 1.3 La notion de contexte . . . . . . . . . . . . . . . . . . . . . . 14 2 Les 2.1 2.2 2.3 2.4 2.5 2.6 scalaires Les dlimiteurs de cha e nes de caract`res . . . e Dclaration et utilisation des variables . . . . e La valeur undef . . . . . . . . . . . . . . . . . Oprateurs, fonctions et contexte numriques e e Oprateurs, fonctions et contexte de cha e nes . Les oprateurs de test . . . . . . . . . . . . . e 17 17 18 19 19 20 22

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

3 Structures de contrle o 25 3.1 Les instructions de test . . . . . . . . . . . . . . . . . . . . . 25 3.2 Les boucles . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 3.3 Un exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 4 Listes et tableaux 4.1 Valeurs de listes . . . . . . . . . . . . . 4.2 Manipulation de tableaux . . . . . . . 4.3 Aectations . . . . . . . . . . . . . . . 4.4 Multi-dclaration . . . . . . . . . . . . e 4.5 Retour sur laplatissement des listes . 4.6 Absorption dune liste par un tableau 4.7 La structure de boucle foreach . . . . 3 33 33 34 36 37 37 38 38

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

Introduction a la programmation en Perl ` 4.8 4.9

c sylvain@lhullier.org

Fonctions de manipulation de tableaux . . . . . . . . . . . . . Loprateur qw . . . . . . . . . . . . . . . . . . . . . . . . . . e

40 41 43 43 44 45 46 46 47 49 49 49 50 51 52 52 55 56 56 57 58 60 61 63

5 Ecrire une fonction 5.1 Dclaration . . . . . . . . . . . . . . . e 5.2 Appel . . . . . . . . . . . . . . . . . . 5.3 Visibilit des variables . . . . . . . . . e 5.4 Une liste pour valeur de retour . . . . 5.5 Premier exemple de fonction . . . . . . 5.6 Autre exemple : une fonction rcursive e

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

6 Autres fonctions sur les listes 6.1 Joindre les lments dans une cha avec join . . . . ee ne 6.2 Dcouper une cha de caract`res en liste avec split e ne e 6.3 Trier une liste avec sort . . . . . . . . . . . . . . . . . 6.4 Slectionner des lments avec grep . . . . . . . . . . e ee 6.5 Appliquer un traitement a tous les lments avec map . ` ee 6.6 Un exemple : le crible dEratosth`ne . . . . . . . . . . e 7 Tables de hachage 7.1 Dclaration et initialisation . . . . e 7.2 Accder a un lment . . . . . . . e ` ee 7.3 Parcours . . . . . . . . . . . . . . . 7.4 Autovivication . . . . . . . . . . . 7.5 Existence et suppression dune clef 7.6 Tables de hachage et listes . . . . . 7.7 Exemples . . . . . . . . . . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

8 Tranches 67 8.1 Tranches de tableau . . . . . . . . . . . . . . . . . . . . . . . 67 8.2 Tranches de table de hachage . . . . . . . . . . . . . . . . . . 68 9 Manipulation des chiers 9.1 Oprateurs sur les noms de chier . . . e 9.2 La fonction glob . . . . . . . . . . . . . 9.3 Premiers exemples . . . . . . . . . . . . 9.4 Ouverture de chier . . . . . . . . . . . 9.5 Lecture, criture et fermeture de chier e 9.6 Deuxi`me exemple . . . . . . . . . . . . e 9.7 Excution de commandes avec open . . e 4 71 71 72 73 73 75 77 78

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

c sylvain@lhullier.org

Introduction a la programmation en Perl ` 79 81 81 82 83 84 85 86 86 87 87 87 89 89 90 91 94 94 96 97 98 98 101 101 103 104 106 107 109 110 113 115 117 119 122 122 123

9.8

Ecrire une table de hachage sur disque avec les chiers DBM

10 Expressions rguli`res e e 10.1 Fonctionnalits . . . . . . . . . . . . . . . . e 10.2 Bind . . . . . . . . . . . . . . . . . . . . . . 10.3 Caract`res . . . . . . . . . . . . . . . . . . . e 10.4 Ensembles . . . . . . . . . . . . . . . . . . . 10.5 Quanticateurs . . . . . . . . . . . . . . . . 10.6 Ensembles (suite) . . . . . . . . . . . . . . . 10.7 Regroupement . . . . . . . . . . . . . . . . 10.8 Alternatives . . . . . . . . . . . . . . . . . . 10.9 Assertions . . . . . . . . . . . . . . . . . . . 10.10Rfrences arri`res . . . . . . . . . . . . . . ee e 10.11Variables dnies . . . . . . . . . . . . . . . e 10.12Valeurs de retour de m// . . . . . . . . . . . 10.13Exemples de probl`mes . . . . . . . . . . . e 10.14Solutions des probl`mes . . . . . . . . . . . e 10.15Choisir son sparateur . . . . . . . . . . . . e 10.16Options . . . . . . . . . . . . . . . . . . . . 10.17Quanticateurs non-gourmands . . . . . . . 10.18Substitution de variables dans les motifs . . 10.19Oprateur tr . . . . . . . . . . . . . . . . . e 10.20Un dernier mot sur les expression rguli`res e e 11 Rfrences ee 11.1 Rfrences sur scalaire . . . . . . . . . . . . ee 11.2 Utilisation des rfrences sur scalaire . . . . ee 11.3 Rfrences sur tableau . . . . . . . . . . . . ee 11.4 Rfrences sur table de hachage . . . . . . . ee 11.5 Rexions a propos des rfrences . . . . . . e ` ee 11.6 Rfrences anonymes vers scalaire . . . . . . ee 11.7 Rfrences anonymes vers tableau . . . . . . ee 11.8 Rfrences anonymes vers table de hachage ee 11.9 Rfrences anonymes diverses . . . . . . . . ee 11.10Loprateur ref . . . . . . . . . . . . . . . . e 11.11Rfrences circulaires . . . . . . . . . . . . . ee 11.12Rfrences sur chiers . . . . . . . . . . . . ee 11.13Rfrences sur fonctions . . . . . . . . . . . ee 11.14Un dernier mot sur les rfrences . . . . . . ee 5

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Introduction a la programmation en Perl `

c sylvain@lhullier.org

12 Utilisation de modules 125 12.1 Utilisation dun premier module . . . . . . . . . . . . . . . . . 125 12.2 Dautres modules . . . . . . . . . . . . . . . . . . . . . . . . . 127 12.3 O` trouver les modules ? . . . . . . . . . . . . . . . . . . . . . 127 u 13 Ecrire un module 13.1 Premier exemple . . . . . . . . . . . 13.2 Et les variables ? . . . . . . . . . . . 13.3 De la derni`re ligne dun module . . e 13.4 Rpertoires . . . . . . . . . . . . . . e 13.5 Blocs BEGIN et END . . . . . . . . . . 13.6 Introduction a lexport de symboles . ` 13.7 Export par dfaut de symboles . . . e 13.8 Export individuel de symboles . . . . 13.9 Export par tags de symboles . . . . 13.10Exemple complet dexports . . . . . 13.11Fonctions inaccessibles . . . . . . . . 13.12Documentation des modules . . . . . 13.13Un dernier mot sur les modules . . . 14 Programmation objet 14.1 Vous avez dit objet ? . . . . . . 14.2 Prparatifs . . . . . . . . . . . e 14.3 Ecrire un constructeur . . . . . 14.4 Appeler le constructeur . . . . 14.5 Manipulations de lobjet . . . . 14.6 Plusieurs constructeurs . . . . . 14.7 Ecrire une mthode . . . . . . . e 14.8 Reparlons des champs . . . . . 14.9 Composition . . . . . . . . . . 14.10Destruction dun objet . . . . . 14.11Hritage . . . . . . . . . . . . . e 14.12Classes dun objet . . . . . . . 14.13Champs et mthodes statiques e 14.14Exemple complet . . . . . . . . Conclusion Lauteur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 129 130 131 132 133 134 135 135 136 137 138 139 142 143 143 144 144 146 147 149 150 152 153 156 157 160 161 163 169 171

Licence
c 2002-2003 Sylvain Lhullier Version 1.0.5 21 novembre 2004 Vous trouverez le derni`re version de ce document a cette adresse : e ` http://sylvain.lhullier.org/publications/perl.html Ce document est y disponible en version HTML, PDF et sources DocBook. Permission est accorde de copier, distribuer et/ou modier ce document e selon les termes de la Licence de Documentation Libre GNU (GNU Free Documentation License), version 1.1 ou toute version ultrieure publie par e e la Free Software Foundation. Pas de section inaltrable. Pas de texte de e premi`re page de couverture. Pas de texte de derni`re page de couverture. e e Vous trouverez le texte ociel de la FDL a ladresse : ` http://www.gnu.org/licenses/fdl.html Une traduction non-ocielle en franais peut tre lue a ladresse : c e ` http://cesarx.free.fr/gfdlf.html

Introduction a la programmation en Perl `

c sylvain@lhullier.org

Introduction
Voici un cours introductif a la programmation en Perl. Il est issu de la ` srie darticles que jai crits pour GNU/Linux & Hurd Magazine France e e entre juillet 2002 et fvrier 2003. e Ce langage tr`s riche et puissant est une bo a outils fort utile dans e te ` de nombreuses situations : administration syst`me, manipulation de textes e (mail, logs, linguistique, gntique), programmation rseau (CGI, mod_perl, e e e etc), bases de donnes, interfaces graphiques etc. Ses nombreuses biblioth`e e ques le rendent vite irremplaable aux yeux de ceux qui en acqui`rent la c e ma trise. La prise en main du langage est facilite par de nombreux rapproe chements possibles avec le C, le shell ou awk. Sa conformit POSIX en fait e un alli indispensable a ladministrateur syst`me. e ` e Ce document a la dlicate ambition de sadresser a la fois au programe ` meur dbutant et a celui qui conna e ` trait bien le C ou le shell. Que le premier me pardonne de faire des comparaisons avec dautres langages et de taire peut-tre certains points qui me semblent vidents. Que le second mexcuse e e de passer a son go t trop de temps a expliquer des notions qui lui semblent ` u ` simples ; les choses se corseront au fur et a mesure de la lecture ... ` Le dbut du document aborde des notions importantes en Perl et ne e cessaires pour bien comprendre la suite. Vous serez sans doute un peu dcu e de ne pas faire des choses extrmement puissantes immdiatement, mais e e patience : qui veut aller loin mnage sa monture. e Pour vous mettre en apptit, voici un petit exemple de la concision de e 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 une liste de mots (la phrase de la premi`re ligne), ee e transforme les majuscules de ces mots en minuscules, supprime les chires 9

Introduction a la programmation en Perl `

c sylvain@lhullier.org

appartenant aux mots, supprime les mots vides et ache la liste des mots ainsi transforms dans lordre lexical. Et dites-vous que vous aurez en main e toutes les notions ncessaires avant la n de la lecture du document ... e Perl est un langage de haut niveau, qui a la prtention de combiner les e avantages de plusieurs autres langages. Premi`re facilit, il g`re lui mme la e e e e mmoire (ramasse-miettes, pas de limite de buers, pas dallocation a faire e ` etc). De plus, les tableaux, les listes et les tables de hachage sont natifs, ils sont intgrs a la grammaire mme du langage. Rcursivit, modularit, e e ` e e e e programmation objet, acc`s au syst`me et au rseau, interface avec le C, e e e 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 faon de le faire). c

10

Chapitre 1

Premiers pas
1.1 Excuter un programme en Perl e

Il existe principalement deux types de langages : les langages compils e et les langages interprts. Pour les premiers (on retrouve par exemple dans ee cette catgorie le C et le C++), il existe deux phases distinctes : la come pilation des sources par un compilateur (gcc par exemple) puis lexcution e du programme ainsi obtenu par le syst`me. Pour les seconds (les shells par e exemple), il ny a pas de phase de compilation, un interprteur va lire le e code et directement agir en fonction de celui-ci. Perl est un langage a la fois interprt et compil. Il ny a pas de phase ` ee e intermdiaire de compilation car linterprteur (qui se nomme perl en mie e nuscules, alors que le langage prend une majuscule) compile le code sans que le programmeur ne sen rende compte, puis lexcute. Linterprteur se e e charge donc a la fois de la compilation et de lexcution. ` e Il existe trois faons distinctes de faire tourner un programme Perl : c Mettre du code en ligne de commande. On peut crire ceci dans un e shell : perl -w -e print("Salut Larry\n"); Le programme perl est lanc avec du code Perl comme argument, e directement sur la ligne de commande (option -e). En anglais, on appelle cela un one-liner (pas de traduction tablie en franais, peute c tre monoligne, uniligne, soliligne ...). Le code sera alors excut : la e e e fonction print ache son argument. Salut Larry Ce nest pas la faon la plus courante dcrire du Perl, mais cest une c e mani`re facile et rapide de faire un petit calcul ou de faire appel a une e ` 11

Introduction a la programmation en Perl `

c sylvain@lhullier.org

fonction Perl. Loption -w, que lon retrouvera tout le temps, est positionne dans e le but que linterprteur ache des messages davertissement (ware nings) a dirents propos : il indique les variables utilises une seule ` e e fois ou utilises avant dtre initialises, il signale les rednitions de e e e e fonctions, etc. Pour marquer les esprits, on pourrait faire un parall`le e avec loption -Wall de gcc pour ceux qui connaissent. Je vous conseille donc de toujours utiliser cette option. La seconde mani`re de faire est de crer un chier salut.pl contee e nant : print("Salut Larry\n"); Puis de lancer la commande suivante depuis un shell : perl -w salut.pl Le programme perl est lanc avec le nom du chier en argument. Il e va alors lire le contenu de ce chier et linterprter comme du code e Perl. La troisi`me faon de faire est de crer un chier salut2.pl contee c e nant : #!/usr/bin/perl -w print("Salut Larry\n"); La premi`re ligne est le shebang, bien connu des habitus des scripts e e en shell. Cette ligne (qui doit toujours tre la premi`re du chier) e e indique au syst`me dexploitation le chemin de lexcutable a lancer e e ` pour interprter ce chier. Le premier caract`re doit tre un di`se, ce e e e e qui a pour eet que cette ligne est considre comme un commentaire ee Perl par linterprteur. Ensuite un point dexclamation. Puis le chemin e absolu vers lexcutable perl (` adapter selon votre installation, voir e a ce que rpond type perl ou which perl). Enn les options que lon e souhaite passer a linterprteur. ` e Il faut maintenant rendre ce chier excutable et le lancer : e chmod +x salut2.pl ./salut2.pl Grce a la ligne de shebang, le syst`me le reconna donc comme a ` e t un programme ncessitant un interprteur pour tre excut. Cet ine e e e e terprteur est lanc avec pour param`tres les options fournies dans le e e e shebang ainsi que le nom du chier. Cette derni`re faon de faire est sans doute la plus courante d`s que e c e lon crit un programme qui sera utilis plusieurs fois. e e Avant de continuer, quelques commentaires sur la syntaxe Perl. Except e dans les cha nes de caract`res, la prsence ou labsence despaces, de sauts e e 12

c sylvain@lhullier.org

Introduction a la programmation en Perl `

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 termine par un point-virgule. Les fonctions peuvent prendre leurs argue ments entre parenth`ses (comme en C) ; il faut aussi savoir que lon peut se e passer de ces parenth`ses. On aurait pu crire : e e print "Salut Larry\n"; Les deux syntaxes sont tout a fait valides. Dans les cas simples (ap` pel dune fonction avec un ou deux param`tres), on pourra omettre les e parenth`ses. Dans le cas de combinaisons plus complexes (plusieurs fonce tions appeles en param`tre dautres fonctions, listes en argument...), je e e vous conseille de les mettre pour lever toute ambigu e possible. t Un commentaire commence par un di`se (#) et se termine en n de ligne e (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 donnes e

Perl est un langage faiblement typ, ce qui signie quune donne naura e e pas spcialement de type : les nombres, les cha e nes de caract`res, les boolens e e etc seront tous des scalaires et ne seront direncis que par leur valeur et e e par le contexte de leur utilisation. Il existe principalement trois structures de donnes : les scalaires, les e tableaux et les tables de hachage. Chaque structure de donnes est lie a un e e ` caract`re spcial (lire la suite). e e Un scalaire est une donne atomique. Par exemple, ce pourrait tre une e e cha de caract`res (suite de caract`res) ou un nombre (entier ou ottant). ne e e On verra plus tard que les rfrences (cest-`-dire les pointeurs de Perl) sont ee a des scalaires, mme sils sont un peu spciaux. Les variables scalaires sont e e prcdes dun dollar ($) : $x est donc une variable scalaire. e e e Les tableaux permettent de stocker plusieurs scalaires en les indiant. c De la mme faon quen C, on pourra demander le i`me lment dun tae c e ee bleau, i tant un entier. Lacc`s a un lment sera en temps constant, il ne e e ` ee dpendra pas de son indice dans le tableau. Les variables de type tableau e sont prcdes dun arobase (@) : @t est donc une variable de type tableau. e e e Lorsque lon utilise la syntaxe @t, on dsigne la totalit du tableau ; si nous e e voulons parler du i`me lment, nous allons manipuler un scalaire, il faudra e ee donc prxer par un dollar : $t[4] est llment dindice 4 dans le tableau e ee 13

Introduction a la programmation en Perl `

c sylvain@lhullier.org

@t, les crochets [] dlimitant lindice (nul besoin de mettre larobase, Perl e sait grce aux crochets quil sagit dun lment de tableau). a ee Une table de hachage en Perl est une structure de donnes permettant e dassocier une cha de caract`res a un scalaire ; on parle de clefs et de ne e ` valeurs : une valeur est associe a une clef. Naturellement, dans une mme e ` e table de hachage les clefs sont uniques ; les valeurs, par contre, peuvent tre tout a fait quelconques. Les variables de type table de hachage sont e ` prcdes dun caract`re pourcent (%) : %h est donc une variable de type e e e e table de hachage. De la mme faon que pour les tableaux, %h reprsente la e c e totalit de la table de hachage ; accder a un lment se fera avec un dollar : e e ` ee $h{uneclef} est llment de clef uneclef de la table de hachage %h, les ee accolades {} dlimitant la clef. Fonctionnellement, on pourrait voir une table e de hachage comme un tableau dont les indices peuvent tre non-numriques. e e Nous reviendrons sur ces types de donnes tout au long du document. e

1.3

La notion de contexte

Chaque opration en Perl est value dans un contexte spcique. La e e e e faon dont lopration se comportera peut dpendre de ce contexte. Il peut c e e jouer un rle important sur le type des oprandes dune expression et/ou o e 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 valuera cette expression dans un contexte scalaire ; de la mme e e faon, une aectation a une variable de type liste valuera le membre droit c ` e en contexte de liste. Autre exemple que je dtaillerai un peu plus loin, les e oprateurs de test imposent un contexte prcis a leurs oprandes. e e ` e Certains oprateurs et fonctions savent dans quel contexte ils sont ape pels et renvoient un scalaire ou une liste selon ce contexte dappel. La e 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 loprateur scalar(). e Il existe plusieurs contextes scalaires : le contexte de cha nes de caract`res, le contexte numrique et le contexte tolrant. Par exemple une e e e addition impose un contexte numrique a ses deux oprandes ; cela signie e ` e que les oprandes sont transforms en nombres quels que soient leur type e e et leur valeur (reste ensuite au programmeur a savoir ce que vaut une liste ` ou une cha quelconque en contexte scalaire...). Le contexte de cha ne nes est un contexte o` , comme son nom lindique, les scalaires seront considrs u ee 14

c sylvain@lhullier.org

Introduction a la programmation en Perl `

comme des cha nes de caract`res. Le contexte tolrant nest ni de cha e e nes ni numrique, il est simplement scalaire. e Il existe aussi un contexte vide (void context in english) qui correspond au fait que la valeur dune expression est ignore. Cest par exemple le contexte e utilis lorsque lon appelle une fonction sans rcuprer sa valeur de retour, e e e comme lappel a la fonction print dans la section prcdente. Ce contexte ` e e napporte pas grand chose au programmeur, mais permet a linterprteur ` e Perl appel avec loption -w de prvenir en cas dusage dune expression e e sans eet de bord en contexte vide (cest-`-dire une expression qui ne fait a rien et dont on ne se sert pas). Par exemple, 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. Mme si cela nest pas forcment explicite a chaque e e ` instant, le contexte est souvent important.

15

Introduction a la programmation en Perl `

c sylvain@lhullier.org

16

Chapitre 2

Les scalaires
Les scalaires sont le type de donnes atomique de Perl, dit autrement un e scalaire est une donne atome. Cela signie que la granularit de donnes e e e ne va pas au del`. a Comme dit prcdemment, une variable scalaire peut contenir une cha e e ne de caract`res (String en Java et autres) ou un nombre (entier ou nome bre 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` le caract`re \0 de code ASCII 0 (zro) est le u e e marqueur de n de cha ne, en Perl les cha nes de caract`res peuvent sans e souci contenir ce caract`re : "a\0f" est une cha comportant 3 caract`res. e ne e On aura donc aucun mal a traiter des chiers binaires en Perl. `

2.1

Les dlimiteurs de cha e nes de caract`res e

Les cha nes de caract`res ont, comme en shell, principalement deux e dlimiteurs possibles : les doubles quotes (") et les simples quotes (). Elles e nont pas le mme rle : e o Dans une cha dlimite par des doubles quotes, le contenu est inne e e terprt : ee "Bonjour\n" est une cha suivie dune n de ligne. De la mme ne e mani`re "\t" est une tabulation (il existe dautres caract`res spciaux). e e e Dans "Bonjour $prenom" la variable $prenom est substitue par son e contenu ; cest-`-dire que ce scalaire contiendra la cha Bonjour, a ne suivie dune espace, suivie du contenu de la variable $prenom. Sil faut accoler un texte immdiatement apr`s une variable, on utilie e 17

Introduction a la programmation en Perl `

c sylvain@lhullier.org

sera les accolades pour dlimiter le nom de la variable ; par exemple e dans "il ${prefixe}donn$suffixe", cest bien la variable $prefixe qui sera utilise, puis la cha donn et enn la variable $suffixe. e ne On notera que ces accolades nont rien a voir avec celles des tables de ` hachage. Certains caract`res doivent tre protgs avec un anti-slash (\) si on e e e e veut les faire appara telsquels dans la cha de caract`res ; ce sont tre ne e les quatre suivants : " $ @ \. La cha "\$v" ne contient donc pas ne la valeur dune suppose variable $v mais contient le caract`re dollar e e et le caract`re v. e Dans une cha dlimite par des simples quotes, aucune interprtation ne e e e du contenu na lieu : Bonjour\n est une cha comportant les caract`res B o n j o u r \ ne e et n, cest-`-dire 9 caract`res (notez que \n comporte 2 caract`res). a e e La cha Bonjour $prenom ne comporte pas le contenu dune hyne pothtique variable $prenom mais le caract`re dollar suivi de la cha e e ne prenom. Puisque les variables ne sont pas substitues, les caract`res a protger e e ` e sont moins nombreux ; seuls et \ ont besoin dtre prcds dun e e e e anti-slash pour appara tels-quels dans une cha dlimite par de tre ne e e simples quotes. Les nombres nont quant a eux pas besoin de dlimiteurs pour tre ma` e e nipuls : $x = 10.2 aecte le nombre 10,2 a la variable $x. e `

2.2

Dclaration et utilisation des variables e

En Perl, il nest pas obligatoire de dclarer les variables. Par dfaut, e e lusage dune variable la cre ; si cest un scalaire, elle aura la valeur undef e (lire plus loin) ; sil sagit dune liste ou une table de hachage, elle sera vide. Pour dvidentes raisons de relecture et pour viter des erreurs btes, je e e e vous conseille de toujours dclarer vos variables avant de les utiliser (sauf e peut-tre dans le cas de scripts de quelques lignes). Pour dclarer une vae e riable, il nous faut utiliser my : my $x; my $y = 10; my $z = "hello"; Nous venons ici de dclarer trois variables scalaires. Ces variables seront e visibles (accessibles) dans toute la suite du bloc ainsi que dans les sous-blocs 18

c sylvain@lhullier.org

Introduction a la programmation en Perl `

(comme en C) ; comme on sy attend, elles ne le seront par contre pas dans les fonctions appeles depuis ces blocs. Le placement des dclarations est e e libre dans le bloc (comme en C++), il nest pas ncessaire de les mettre en e dbut de bloc. e Voici quelques exemples dutilisation de variables (on suppose quelles sont dj` dclares) : ea e e $x = $y + 3; $prenom = "Jules"; $phrase = "Bonjour $prenom"; print("$phrase\n"); Cette derni`re ligne achera a lcran Bonjour Jules suivi dun cae ` e ract`re de nouvelle ligne. Les habitus du shell noterons bien quune vae e riable est toujours prcde de son dollar mme si elle est a gauche dun gal e e e e ` e daectation.

2.3

La valeur undef

Cest une valeur particuli`re signiant non-dni. Cest aussi la valeur e e par dfaut des variables scalaires non initialises : my $x; est quivalent a e e e ` my $x=undef; On peut aecter cette valeur a une variable apr`s son initia` e lisation : $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 dnie, cest-`-dire si elle ne vaut pas undef. Une erreur classique est e a dcrire : *incorrect* if($x!=undef) *incorrect* Ne surtout pas tenter e de comparer une variable a undef, car cela ne fait pas ce quon attend. ` La valeur undef est une valeur fausse pour les tests. Le test if( $x ) ... est faux si $x est non-dnie. Mais comme on le verra plus tard, il est e galement faux si $x vaut 0 (zro) ou bien la cha vide. Donc un test e e ne if( $x ) ... est potentiellement dangereux. Pour tester si une variable est dnie, une seule bonne faon : if(defined($x))... e c

2.4

Oprateurs, fonctions et contexte numriques e e

Sur les nombres, les oprateurs classiques sont disponibles : + - / * % ; e ce dernier oprateur % est le modulo, cest-`-dire le reste de la division enti`re e a e du premier oprande par le second. Notez que la division eectue par lope e e rateur / nest pas une division enti`re mais une division relle, cela mme si e e e 19

Introduction a la programmation en Perl `

c sylvain@lhullier.org

ses oprandes sont entiers (2/3 vaut 0.6666...) ; si vous voulez eectuer une e division enti`re, il vous faut tronquer le rsultat de la division prcdente e e e e avec int() : lexpression int($x/$y) vaut le quotient de la division enti`re e de $x par $y. Des raccourcis existent : += -= *= /= %=. Ces oprateurs sont a la e ` fois une opration arithmtique et une aectation : $x+=3 est quivalent e e e a $x=$x+3 mais en plus synthtique : on ajoute 3 a $x. Linstruction $y*=5 ` e ` multiplie $y par 5. Il existe aussi des auto-incrmenteurs et des auto-dcrmenteurs : ++ e e e et -- qui peuvent tre placs avant ou apr`s une variable : ils ajoutent ou e e e dduisent 1 a cette variable. $x++ a le mme eet que $x+=1 ou que $x=$x+1. e ` ` e Loprateur ** correspond a la puissance : 2**10 vaut 1024. e ` 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 carre de $x. e Voici quelques r`gles de conversion en contexte numrique. Les cha e e nes de caract`res reprsentant exactement un nombre sont converties sans probl`me ; e e e "30" + "12" vaut 42. Dans tous les autres cas (numrs dans ce qui suit), e ee loption -w provoquera un message davertissement. Les scalaires commenant c 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

Oprateurs, fonctions et contexte de cha e nes

Les cha nes de caract`res ont aussi leurs oprateurs. Le point (.) permet e e de concatner deux cha e nes : linstruction $x="bon"."jour" a pour eet daecter la cha bonjour a $x (pas de gestion de la mmoire a eectuer). ne ` e ` Cet oprateur est, entre autres cas, utile lorsque certaines parties de la e cha sont les valeurs de retour de fonctions ; en eet, il sut souvent dutine liser les substitutions eectues dans les cha e nes dlimites par des doubles e e quotes pour concatner deux cha e nes. Loprateur x est la multiplication pour les cha e nes de caract`res : "bon"x3 e vaut "bonbonbon". Fort sympathique ... Les raccourcis suivant peuvent tre utiliss : .= x= Lexpression $x.=$y e e est quivalente a $x=$x.$y et concat`ne donc $y a la n de $x. e ` e ` 20

c sylvain@lhullier.org

Introduction a la programmation en Perl `

Voici un certain nombre de fonctions utiles qui manipulent les cha nes de caract`res : e length($x) renvoie la longueur de la cha $x. Par exemple ne length("bonjour\n") vaut 8 et length(bonjour\n) vaut 9. chop($x) supprime le dernier caract`re de la cha $x (la variable $x e ne est modie). Ce caract`re est renvoy par la fonction : $c = chop($l); e e e chomp($x) supprime le dernier caract`re de $x sil sagit dune n e de ligne (la variable $x est modie). Cette fonction peut prendre e plusieurs arguments, chacun subira un sort similaire. Ne pas crire e *incorrect* $x=chomp($x) *incorrect* car chomp renvoie le nombre de caract`res supprims. Cette fonction nous sera tr`s utile lorsque e e e nous lirons des chiers ligne a ligne. ` reverse($x) en contexte scalaire, renvoie la cha compose des cane e ract`res de $x dans lordre inverse. Par exemple e $v = reverse("bonjour\n") aecte "\nruojnob" a $v. On rencon` trera aussi cette fonction chez les listes (son comportement dpend du e contexte). substr($x,oset,length) vaut la sous-cha de position oset et de ne longueur length. Les positions commencent a 0 : ` substr("bonjour",1,2) vaut on. La longueur peut tre omise, dans e ce cas toute la partie droite de la cha est slectionne. ne e e Cette fonction peut tre une lvalue, cest-`-dire quon peut lui aece a ter une valeur (lvalue pour left-value : a la gauche du signe gal de ` e laectation) : my $v = "salut toi"; substr($v,5,1) = "ation a "; ` $v vaut alors "salutation a toi". Cest l` que lon se rend compte ` a que Perl g`re vraiment la mmoire tout seul ! e e index($cha^ne,$sousCha^ne,$position) renvoie la position de la premi`re occurrence de $sousCha^ne dans $cha^ne. Le troisi`me pae e ram`tre, sil est fourni, indique la position du dbut de la recherche ; e e sinon la recherche part du dbut de la cha (position 0). e ne rindex($cha^ne,$sousCha^ne,$position) eectue la mme recher e che que la fonction index mais en partant de la n de la cha (la ne recherche est eectue de droite a gauche). e ` En contexte de cha de caract`res, undef vaut la cha vide ; loption ne e ne -w provoquera un message davertissement. Dans ce contexte, un nombre vaut la cha de sa reprsentation dcimale. ne e e 21

Introduction a la programmation en Perl `

c sylvain@lhullier.org

2.6

Les oprateurs de test e

Les boolens (type de donnes ayant pour seules valeurs vrai et faux) e e nexistent pas en tant que tels en Perl, on utilise les scalaires pour eectuer les test (comme C le fait avec les entiers). Il me faut donc prciser quelles e sont les valeurs scalaires vraies et quelles sont les fausses. Les valeurs fausses sont : 0, cest-`-dire lentier valant zro, a e "0" ou 0, cest-`-dire la cha de caract`res ne comportant que le a ne e caract`re zro (pas le caract`re \0 de code ASCII zro, mais 0 de code e e e e 48), la cha vide :"" ou (ce qui est la mme chose), ne e 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 oprations nume e riques, mais qui est vraie ... Il existe deux catgories doprateurs de test : ceux pour lesquels on e e impose un contexte numrique aux oprandes et ceux pour lesquels on ime e pose un contexte de cha de caract`res. Par exemple == teste lgalit de ne e e e deux nombres (contexte numrique) et eq teste lgalit de deux cha e e e nes (contexte de cha ne). ("02"=="2") est vrai alors que ("02" eq "2") est faux. La dirence est encore plus agrante pour les oprateurs dinfriorit e e e e et de supriorit ; < teste lordre entre nombres, lt teste lordre ASCII entre e e cha ; donc (9<12) est vrai alors que (9 lt 12) est faux car 9 est apr`s nes e 1 dans la table ASCII. Confondre ou mlanger ces deux types doprateurs e e est une erreur tr`s courante que font les dbutants, ainsi que les initis qui e e e ne font pas attention ... Sachez que loption -w permet souvent de reprer e ces situations. Voici un tableau dcrivant les oprateurs de tests : e e contexte impos e galit e e dirence e infriorit e e supriorit e e inf ou gal e sup ou gal e comparaison numrique e == != < > <= >= <=> de cha nes eq ne lt gt le ge cmp

Les oprateurs boolens classiques sont prsents : e e e 22

c sylvain@lhullier.org

Introduction a la programmation en Perl `

expr1&&expr2 est vrai si expr1 et expr2 sont vraies (si expr1 est faux expr2 nest pas value), e e expr1||expr2 est vrai si expr1 ou expr2 est vraie (si expr1 est vrai expr2 nest pas value), e e !expr est vrai si expr est fausse. Il existe aussi les oprateurs and or et not. Ceux-ci ont la mme table e e de vrit que les prcdents, mais sont dune priorit plus faible. e e e e e Les deux oprateurs cits a la derni`re ligne du tableau ne sont pas des e e ` e oprateurs de test mais des oprateurs de comparaison ; ils sont prsents e e e dans ce tableau en raison des similitudes quils ont avec les oprateurs de e test en ce qui concerne le contexte impos aux oprandes. Ces oprateurs e e e renvoient un nombre qui dpend de lordre entre leurs deux param`tres. e e Lexpression ($x<=>$y) est : positive si $x est un nombre plus petit que $y, ngative si $x est un nombre plus grand que $y, e nulle si $x et $y sont des nombres gaux. e Cet oprateur <=> est surnomm spaceship (vaisseau spatial en franais) e e c en raison de sa forme ;-) ... Pour loprateur cmp, la comparaison se fait e sur lordre des cha nes selon la table ASCII. Ces oprateurs seront fort utiles e lorsque nous parlerons de la fonction sort qui eectue le tri des listes.

23

Introduction a la programmation en Perl `

c sylvain@lhullier.org

24

Chapitre 3

Structures de contrle o
Ici nous allons apprendre a contrler le ux des instructions en Perl. En ` o eet un programme nest pas quune simple suite dinstructions se droulant e linairement une fois et une seule. e 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 vtres. o

3.1

Les instructions de test

Ces instructions permettent de conditionner lexcution dinstructions a e ` la valeur de vrit dune expression. Linstruction la plus usite est le if (si e e e en franais) qui a besoin dune expression et dun bloc dinstructions. Cette c expression sera value en contexte scalaire et servira de condition ; si elle e e est vrie, le bloc dinstructions sera excut. e e e 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 tre places dans le bloc, elles seront alors e e toutes excutes si la condition est vraie. Notez que les accolades ({}) sont e e obligatoires pour dlimiter le bloc (contrairement au C). e Il est possible dexcuter dautres instructions dans le cas o` la condition e u est fausse. On utilise pour cela loprateur else (sinon en franais) qui, lui e c aussi, est suivi dun bloc dinstructions : 25

Introduction a la programmation en Perl ` if( $x == $y ) { print "\$x et \$y sont egaux\n"; } else { print "\$x et \$y sont diffrents\n"; e }

c sylvain@lhullier.org

Le fait que les accolades sont obligatoires a pour consquence que le e programme suivant est incorrect : if( condition1 ) { instructions1 } 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 forts difs, il faudrait donc quil utilise de multiples couples daccolades. e Pour ne pas rencontrer les mmes probl`mes que le Lisp en rencontre pour e e les parenth`ses ;-), Perl met a notre disposition linstruction elsif qui e ` permet de cumuler le comportement dun else et dun if tout en faisant lconomie dun couple daccolades : e 26

c sylvain@lhullier.org

Introduction a la programmation en Perl `

if( condition1 ) { instructions1 } elsif( condition2 ) { instructions2 } else { instructions3 } Linstruction switch de C na pas dquivalent direct en Perl ; il faut e pour cela planter une fort difs, comme dans lexemple prcdent. e e e Mais Perl nen reste pas l`. Il existe une syntaxe tr`s utilise pour eeca e e tuer une unique instruction si une condition est vrie : e e instruction if( condition ); On parle ici de modicateur dinstruction. Pour cette syntaxe, les parenth`ses sont optionnelles autour de la condition, mais je vous conseille de e les mettre systmatiquement pour une meilleure lisibilit. Le code suivant e e ache la variable $s si elle est dnie : e print "$s\n" if( defined($s) ); On notera que cette syntaxe ne permet pas lusage dun else. Linstruction unless a exactement le mme rle que le if, a la dirence e o ` e que les instructions seront eectues si la condition est fausse (il est aussi e moins dpaysant den faire des forts). unless( expression ) est quivalent e e e a if( !(expression) ) dans toutes les constructions prcdemment cites. ` e e e

3.2

Les boucles

Les boucles permettent dexcuter plusieurs fois les mmes instructions e e sans avoir a crire plusieurs fois les mmes lignes de code. Bien souvent ` e e nous avons besoin de modier une variable a chaque tape ; dans ce cas ` e nous utiliserons linstruction for (pour en franais) dont voici la syntaxe : c 27

Introduction a la programmation en Perl ` for( initialisation; condition; incrment ) e { instructions; }

c sylvain@lhullier.org

La boucle for prend trois expressions entre parenth`ses : la premi`re e e expression permet dinitialiser la variable de boucle, la deuxi`me est une e condition de continuation et la derni`re permet de modier la valeur de la e variable de boucle. Quand la boucle dmarre, la variable est initialise (expression 1) et e e le test est eectu (expression 2). Si cette condition est vrie, le bloc e e e dinstructions est excut. Quand le bloc se termine, la variable est modie e e e (expression 3) et le test est de nouveau eectu (expression 2). Si la condition e est vrie, le bloc dinstructions est r-excut avec la nouvelle valeur pour e e e e e la variable de boucle. Tant que le test reste vrai, le bloc dinstructions et lexpression de modication de la variable sont excuts. A larrt de la boucle, les instructions e e ` e qui suivent la boucle sont excutes. e e 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 sarrte lorsque $i vaut 22. Cette variable est dclare dans e e e le bloc dinitialisation et nexiste donc que dans la boucle. Notez quil est tout a fait possible dutiliser une variable pr-existante comme variable de ` e boucle (et donc de ne pas faire de my dans la partie initialisation) ; dans ce cas, apr`s excution de la boucle, la variable vaut la derni`re valeur qui lui e e e a t aecte au cours de la boucle. ee e Une autre boucle existe : la boucle while (tant que en franais) dont c voici la syntaxe : while( condition ) { instructions; } Les instructions sont eectues tant que la condition est vraie. La partie e initialisation doit avoir t eectue avant la boucle ; la partie modication ee e de la variable doit avoir lieu dans le bloc dinstructions. 28

c sylvain@lhullier.org

Introduction a la programmation en Perl `

Lexemple suivant ache lui aussi les entiers pairs de 0 a 20 : ` my $i = 0; while( $i <= 20 ) { print "$i\n"; $i+=2; } La seule dirence entre les deux exemples est le fait que, dans le cas du e while, la variable $i existe apr`s la boucle. e Comme pour le if, certaines facilits sont oertes pour le while. Tout e dabord, la syntaxe suivante est correcte : instruction while( condition ); Elle permet dexcuter plusieurs fois une instruction et une seule tant e quune condition est vrie. e e Ensuite, il existe une instruction until (jusqu` en franais) qui a la a c mme syntaxe que le while mais qui demande une condition darrt (comme e e unless pour if) : until(condition) est quivalent a while(!(condition)) e ` Lors de lexcution dune boucle, il est frquent de rencontrer des cas e e 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. Linstructions next (suivant en franais) provoque la n de lexcution c e du bloc, le programme value directement lincrment (dans le cas dune e e boucle for) puis le test est eectu. e Linstructions last (dernier en franais) provoque la n de la boucle, ni c lincrment ni le test ne sont eectus. e e Linstructions redo (refaire en franais) provoque le redmarrage du bloc c e dinstructions sans que la condition ni lincrmentation ne soient eectues. e e Lexemple suivant est une autre faon dimprimer a lcran les entiers c ` e pairs de 0 a 20 : ` my $i = -1; while( 1 ) # 1 est vrai { $i++; last if( $i > 20 ); next if( $i%2 != 0 ); 29

Introduction a la programmation en Perl ` print "$i\n"; }

c sylvain@lhullier.org

Dans le cas o` lon souhaite excuter le bloc dinstruction une fois avant u e 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 ditrer sur les lments dune liste (notion que nous e ee aborderons a cette occasion). Vous verrez alors quen Perl on utilise beau` coup le foreach et assez peu le for(;;).

3.3

Un exemple

Voici un petit exemple de programme Perl ; il nest pas tr`s utile dans la e vie de tous les jours, mais il utilise beaucoup des notions abordes jusquici. e Si vous parvenez a comprendre tout ce quil fait, vous naurez pas perdu ` votre temps a le lire ! ` 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: #!/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 dtail du rle des lignes : e o 1 : Le shebang Perl avec loption -w (achage de messages davertissement) 30

c sylvain@lhullier.org

Introduction a la programmation en Perl `

2 : Cette instruction rend le langage moins permissif, je vous conseille de toujours la placer au dbut de vos programmes. e 3 : Nous dclarons et initialisons une variable scalaire. e 4 : Une boucle for. Dclaration et initialisation a 9 de la variable de e ` boucle $i. Nous continuerons tant quelle est strictement positive ; a ` chaque tape nous la dcrmenterons : elle variera donc de 9 a 1. e e e ` 5 et 11 : accolades dlimitant le bloc de la boucle. e 6 et 7 : achage dune cha dans le cas o` $i est impair. ne u 8 et 9 : achage dune cha dans le cas o` $i est multiple de 3. ne u Cette cha comporte $i caract`res moins (-). ne e 10 : insertion de $i dans la cha $v en position $i (une longueur de ne 0 provoque une insertion et non un remplacement). 12 : 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 tous compris ?

31

Introduction a la programmation en Perl `

c sylvain@lhullier.org

32

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 porte. Cest le cas des listes, des tableaux et de limpres` e sionnant 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 ordonne) de valeurs scalaires. Nous verrons e comment crer une liste, la manipuler, la parcourir etc. e Une variable de type tableau peut contenir plusieurs valeurs scalaires. Cette notion est prsente dans de nombreux langages de programmation et e ne posera sans doute probl`me a personne. e ` Les passerelles entre listes et tableaux sont nombreuses et tr`s intuitives e en Perl. Cest pour cela que nous nentrerons pas ici dans les dtails de la dise tinction entre liste et tableau. Dans ce document, jutiliserai chacun des deux termes a bon escient sans forcement indiquer explicitement pourquoi jutilise ` lun plutt que lautre, mais les notions pourront appara o tre naturelles au lecteur sans quil ne soit ncessaire de prciser les choses formellement. e e

4.1

Valeurs de listes

En Perl, une liste peut tre reprsente par les valeurs quelle doit contee e e nir encadres par un couple de parenth`ses. Par exemple (2,5,-3) est une e e 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 empche den constituer une comportant des nombres et des cha e nes de caract`res mls. La liste vide se reprsente sous la forme suivante : () e ee e 33

Introduction a la programmation en Perl `

c sylvain@lhullier.org

Loprateur dintervalle .. permet de crer une liste comportant des e e valeurs successives entre deux bornes. La liste (1..10) comporte tous les entiers de 1 a 10 ; on aurait pu aussi crire (1,2,3,4,5,6,7,8,9,10), mais ` e cette derni`re notation est bien plus lourde. Il faut savoir que les valeurs e des bornes ne doivent pas obligatoirement tre des nombres : par exemple, e la liste (a..z) comporte toutes les lettres de lalphabet, en minuscule et dans lordre. Il est aussi possible de spcier les bornes a laide de vae ` riables : ($debut..$fin) On comprendra quil nest pas toujours possible de rsoudre ce type de liste (par exemple si $debut vaut 1 et $fin vaut e a), dans ce cas la liste est vide. Dernier exemple, la liste (1..10, "age", "a".."z") comporte 37 lments (10+1+26). ee La liste (1,2,("nom",12),"aaa",-1) nest pas une liste a 5 lments ` ee dont le troisi`me serait une autre liste, cest en fait une liste a 6 lments. e ` ee On aurait pu crire (1,2,"nom",12,"aaa",-1) et on aurait obtenu la mme e e liste. On appelle cela laplatissement (ou la linarisation) des listes. Pour e constituer une liste de listes, il faudra faire usage de rfrences (notion que ee nous aborderons plus tard). Loprateur de rptition (x), que lon a dj` appliqu aux cha e e e ea e nes de caract`res prcdemment, sapplique aussi aux listes : (2,10) x 3 est une e e e liste a 6 lments valant (2,10,2,10,2,10). ` ee

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 dclare de la sorte : my @t; On a alors e un tableau vide, cest-`-dire sans lment. De mani`re plus explicite, voici a ee e comment dclarer un tableau vide : e my @t = (); Pour lui donner une valeur lors de sa dclaration, il faut faire ainsi : e my @t = (3,chaine,"bonjour $prenom"); On a alors dclar ce tableau en linitialisant au moyen dune liste. e e On peut accder directement a un lment dun tableau grce a son e ` ee a ` indice : $t[indice] reprsente llment dindice indice du tableau @t. Notez e ee bien que la globalit du tableau se reprsente au moyen dune arobase @t e e alors quun lment particulier est dsign a laide dun dollar $t[indice], ee e e ` cette derni`re expression tant bien une variable de type scalaire (le dollar e e est rserv aux scalaires en Perl). e e 34

c sylvain@lhullier.org

Introduction a la programmation en Perl `

Les indices des tableaux en Perl commencent a 0 (comme en C), ce qui ` signie que le premier lment du tableau @t est $t[0] et le deuxi`me $t[1] ee e etc. Voici un petit exemple dutilisation de tableau : my @t = (3,5); # dclaration et initialisation e $t[1] = 4; # affectation dun elment e print "$t[0]\n"; # affichage dun elment e Il est intressant de savoir quil est possible daccder au dernier lment e e ee dun tableau en utilisant lindice -1 : $t[-1] est le dernier lment de @t. ee De la mme faon, $t[-2] est lavant-dernier, etc. e c Il est possible de conna tre lindice du dernier lment dun tableau ee @t grce a la variable $#t On a donc $t[$#t] quivalent a $t[-1] (ce a ` e ` dernier tant bien plus lisible). Il peut tre utile de savoir que lexprese e sion scalar(@t) (cest-`-dire lutilisation dun tableau en contexte scalaire) a donne le nombre dlments du tableau @t (ce qui vaut 1 de plus que $#t) ; ee $x=@t donnerait la mme chose. e Il faut savoir que vous ne gnrerez pas derreur (dbordement ou autre) e e e si vous tentez daccder a un lment au-del` du dernier. La valeur de cet e ` ee a lment sera simplement undef et le programme continuera. Depuis la veree sion 5.6 de Perl, linstruction exists (que lon retrouvera pour les tables de hachage) permet de tester lexistence dun lment dun tableau : ee if( exists( $t[100] ) ) { ... } Ce test sera vrai si llment dindice 100 du tableau @t existe. Ce qui ee est dirent du test suivant : e if( defined( $t[100] ) ) { ... } Car on teste ici si lexpression $t[100] vaut undef ou non, ce qui peut tre vrai dans deux cas : soit llment existe et vaut undef, soit llment e ee ee nexiste pas ... Voici une autre illustration du fait que vous navez pas a vous soucier de ` probl`mes dallocation mmoire : e e my @t = (3,23.4,"as"); $t[1000] = 8; 35

Introduction a la programmation en Perl `

c sylvain@lhullier.org

Ce programme est correct et fonctionne parfaitement : laectation a lin` dice 1000 agrandit le tableau dautant ... Les lments dindice compris entre ee 3 et 999 valent undef et scalar(@t) vaut 1001. Cest si facile nalement ! Un tableau quil est utile de conna est @ARGV. Cette variable spciale tre e est toujours dnie (mme dans les fonctions) et ne ncessite pas de dclae e e e ration. Elle contient les arguments de la ligne de commande du programme. Les trois faons de lancer un programme en Perl sont susceptibles dutiliser c @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 lancs avec les trois mmes arguments. Sachez e e 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 spciale $0 (comme en shell) contient le nom du programme (nul e besoin de dclarer cette variable pour lutiliser). e

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 celle 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 mlant tableaux et listes : e ($a,$b) = (1,2); Cette instruction aecte une valeur a chacune des ` variables de la liste de gauche : $a reoit 1 et $b reoit 2. c c ($a,$b) = (1,2,3); Les mmes aectations sont eectues ici, la e e valeur 3 ntant daucune utilit. e e ($a,$b) = (1); Laectation a $a de la valeur 1 est eectue et $b ` e est mis a undef (son ancienne valeur est perdue). ` ($a,$b) = @t; Les variables cites a gauche reoivent les premi`res e ` c e valeurs du tableau @t : $a en reoit le premier lment ou undef si @t c ee est vide ; $b reoit le deuxi`me lment ou undef si @t il ne contient c e ee quun lment. ee 36

c sylvain@lhullier.org

Introduction a la programmation en Perl `

@t = (1,2); Cette instruction rinitialise le tableau @t (dont les ane ciennes valeurs sont toutes perdues, y compris celles dindice dirent e de 0 et 1) en lui aectant les valeurs de droite : on obtient donc un tableau a deux lments. ` ee ($a,$b) = Fonction(); Nous verrons un peu plus loin comment crire e une fonction, et comment lui faire renvoyer une liste : ici laectation se fait dans les mmes conditions que pour les trois premiers cas. e ($a,$b) = ($b,$a); Cette instruction est la plus savoureuse : on peut changer deux variables Perl sans avoir a en utiliser une troisi`me ... e ` e (Ai-je dj` dit que Perl soccupe lui-mme de la mmoire ?) ea e e

4.4

Multi-dclaration e

Pour dclarer plusieurs variables avec un seul my, le dbutant aurait e e tendance a crire la chose suivante (il ny a pas de honte !) : `e 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 cres et valent undef. Pour leur aecter des ee valeurs, il faut l` aussi utiliser une liste (ou un tableau) : a my ($a,$b) = (1,2); my ($c,$d) = @t; Les mmes r`gles que pour laectation de listes sappliquent ici. e e

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 lments dont celui du milieu serait ee lui-mme un tableau, mais contient les cinq lments, rsultat de laplatissee ee e ment du tableau @t dans la liste de droite lors de laectation de @t2. Cette aectation a eu le mme rsultat quaurait eu la suivante : e e @t2 = (10,1,2,"age",20); 37

Introduction a la programmation en Perl `

c sylvain@lhullier.org

4.6

Absorption dune liste par un tableau

La syntaxe suivante est intressante a conna : e ` tre ($a,@t) = @s; Le membre gauche de laectation est constitu dune liste comportant e une variable scalaire et un tableau. Il ny a pas a proprement parler dapla` tissement de liste car il sagit ici dune l-value (membre gauche dune aectation), mais la variable $a reoit le premier lment du tableau @s et le c ee tableau @t absorbe tous les autres (@s ntant bien-s r pas modi). e u e En fait dans cette syntaxe, le premier tableau rencontr dans la liste de e gauche reoit tous les lments restant de la liste de droite. Dventuelles c ee e autres variables qui le suivraient (cas idiot, mais bon...) serait mises a undef ` sil sagit de scalaires et a vide sil sagit de tableaux. Par exemple, laec` tation suivante : @s = (10,1,2,"age",20); ($a, @t, @u, $b) = @s; quivaut a : e ` @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 implmentation ope timise dans linterprteur Perl rend son usage bien plus ecace quun pare e cours qui utiliserait une variable indicielle incrmente a chaque tour dune e e ` boucle for. Sa syntaxe est la suivante : foreach variable ( liste ) { instructions } ` A chaque tour de boucle, la variable aura pour valeur un lment de la ee liste, la liste tant parcourue dans lordre. Aucune modication ni supprese sion dans la liste nest eectue par dfaut dans ce type de boucle. Il vous est e e 38

c sylvain@lhullier.org

Introduction a la programmation en Perl `

possible de modier la variable de boucle (ce qui aura pour eet de modier llment en question), mais, par dfaut, le parcours nest pas destructif. ee e Par exemple : foreach $v (1,43,"toto") { print "$v\n"; } Ce petit programme ache chaque lment de la liste sur une ligne. Ces ee autres exemples sont valides eux-aussi : foreach $v (@t) { .... } foreach $v (32,@t,"age",@t2) { .... } Dans le premier cas, les lments du tableau @t sont parcourus. Le second ee exemple illustre les phnom`nes daplatissement des listes qui se retrouvent e e ici aussi. Il est possible de dclarer la variable de boucle dans le foreach de la e mani`re suivante : e 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 spciale $_ qui sera automatiquement utilise : e e foreach (@t) { print "$_\n"; } Comme pour les autres boucles, linstruction next passe a la valeur sui` vante sans excuter les instructions qui la suivent dans le bloc. Linstruction e last met n a la boucle. ` Voici un petit exemple dutilisation de foreach achant des tables de multiplication : 39

Introduction a la programmation en Perl ` #!/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. `

c sylvain@lhullier.org

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 dclar de la sorte : e e 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 ajoutes au dbut du tableau : e e unshift(@t,5,6); @t vaut alors la liste (5,6,1,2,3,4). 40

c sylvain@lhullier.org

Introduction a la programmation en Perl `

La fonction shift prend un tableau en argument ; elle supprime son premier lment (les autres sont alors dcals) et renvoie cet ee e e lment : ee $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 ajoutes a la n du tableau : e ` 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 lment et renvoie cet lment : ee ee $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 inverse, cest-`-dire celle dont les lments sont pris e a ee dans le sens oppos : e @s = reverse(@t); @s vaut alors la liste (4,3,2,1) et @t nest pas modie. e 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 que le dernier lment a y tre entr sera le premier e ee ` e e a en sortir (last in-rst out) comme pour une pile dassiettes sur une tag`re ` e e de placard. On peut utiliser pour cela un tableau, avec les fonctions push pour ajouter un lment et pop pour en prendre un. De faon analogue, une ee c le est un endroit o` le premier entr est le premier a sortir (rst in-rst out) u e ` comme pour une le a une caisse de magasin. On peut par exemple utiliser ` les fonctions push pour ajouter un lment et shift pour en prendre un. ee Dautre manipulations plus complexes du contenu dun tableau sont possibles avec la fonction splice, mais je vous renvoie a la documentation pour ` les dtails. e

4.9

Loprateur qw e

Loprateur qw nous permet de crer facilement une liste de cha e e nes de caract`res. En eet, il peut sembler pnible de constituer une longue liste e e de tels lments en raison du fait quil faut dlimiter chacun dentre eux au ee e moyen de simples ou de doubles quotes : 41

Introduction a la programmation en Perl ` @t = ( Ceci, est, quelque, peu, pnible, e `, crire, ,, non, ? ); a e Avec qw, ceci devient tout a coup plus lisible : ` @t = qw(Cela est bien plus facile a faire non ?); `

c sylvain@lhullier.org

La cha de caract`re sera dcoupe selon les espaces, les tabulations et ne e e e les retours a la ligne. ` Les dlimiteurs les plus souvent utiliss sont les parenth`ses (comme dans e e e lexemple prcdent) ainsi que les slashs : e e @t = qw/Ou alors comme cela .../; Cette fonction est bien pratique mais peut tre source derreurs, voyez e lexemple suivant : @t = qw/ attention aux erreurs b^tes /; e Les simples quotes () semblent indiquer que le programmeur souhaite constituer un seul lment comportant les mots aux et erreurs ; ce nest ee 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 loprateur qw. La liste e ainsi cre comporte donc 4 lments ; on aurait pu crire : ee ee e ("attention","aux","erreurs","b^tes"). e

42

Chapitre 5

Ecrire une fonction


Une fonction est un ensemble dinstructions regroupes de mani`re a tre e e `e utilises plusieurs fois sans avoir a dupliquer du code. e `

5.1

Dclaration e

Le mot-clef sub permet de dnir des fonctions en Perl. Les arguments e 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`tres sont accessibles via la variable spciale @_ (qui est donc un tableau). e e 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 dnissent une nouvelle fonction dont le nom est e maJolieFonction. Cette fonction copie dans trois variables locales les trois premi`res valeurs du tableau @_, cest-`-dire ses trois premiers param`tres e a e (les r`gles classiques daectation entre listes et tableaux sappliquent ici). e 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 spcial). Si votre fonction attend un seul param`tre, la syntaxe peut tre e e e la suivante : 43

Introduction a la programmation en Perl ` my ($x) = @_; mais ne peut pas tre : e my $x = @_; #incorrect

c sylvain@lhullier.org

Cette ligne est incorrect car, dans ce cas, la variable $x aurait pour valeur le nombre de param`tres (aectation dun tableau a un scalaire). La syntaxe e ` suivante peut aussi tre utile : e my ($x,@t) = @_; la variable $x reoit le premier param`tre et le tableau @t reoit tous les c e c param`tres restants. e Enn, une autre criture que vous verrez souvent dans les programmes e Perl est la suivante : my $x = shift; celle-ci sappuie sur le fait que dans une sous-routine, la fonction shift travaille par dfaut sur @_. e Linstruction return met n a lexcution de la fonction et on peut lui ` e fournir une expression qui sera alors la valeur de retour de la fonction.

5.2

Appel

La fonction ainsi dnie peut tre appele au moyen de la syntaxe suie e e vante : maJolieFonction(10,20,30); Dans ce cas, lventuelle valeur de retour est ignore. Pour rcuprer e e e e cette valeur : $v = maJolieFonction(10,20,30); Il est possible domettre les parenth`ses lors de lappel a une fonction : e ` maJolieFonction 10,20,30; # ` eviter A 44

c sylvain@lhullier.org

Introduction a la programmation en Perl `

mais cela peut crer des ambigu es et je vous dconseille donc cette e t e syntaxe. Sil est possible en Perl dimposer le nombre darguments pour une fonction (nous nen parlerons pas ici), cela nest pas fait par dfaut. Rien ne e nous empche en eet dappeler la fonction maJolieFonction prcdemment e e e dnie avec deux ou quatre arguments, alors quelle semble en attendre e 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 ignores. Mais cette particularit du langage est parfois bien pratique, e e notamment pour crire des fonctions a nombre variable darguments. e `

5.3

Visibilit des variables e

Les variables dclares au moyen de my dans une fonction ne seront e e visibles qu` lintrieur mme de la fonction, dans le code qui suit la dclaa e e e ration. Dans une fonction, il est possible daccder aux variables dnies a e e ` la racine du programme (cest-`-dire en dehors de toute fonction) : il sagit a donc de variables globales. Si une variable locale a le mme nom quune e variable globale, cette derni`re est masque par la variable locale : e e my $a = 3; my $b = 8; my $c = 12; sub maJolieFonction { my $a = 5; print "$a\n"; print "$b\n"; $c = 15; print "$c\n"; } maJolieFonction(); print "$a\n"; print "$b\n"; print "$c\n";

# # # #

affiche 5 affiche 8 modification de la variable globale affiche 15

# affiche 3 # affiche 8 # affiche 15

De mani`re plus gnrale, les variables dclares au moyen de my sont e e e e e visibles jusqu` la n du plus petit bloc qui les englobe. En particulier, dans a une fonction... 45

Introduction a la programmation en Perl ` sub maJolieFonction2 { my $d = -3; if( ... ) { my $d = 4; my $e = 8; print "$d\n"; print "$e\n"; } print "$d\n"; print "$e\n"; }

c sylvain@lhullier.org

# 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 a une fonc` ` tion, il sut juste dutiliser une liste. Voici des exemples de syntaxe de liste renvoye par des fonctions : e return ($x,$z); return @t; Dans le second cas, le tableau est converti en liste. Et voici comment il est possible de rcuprer ces valeurs : e e @s = fonction(...); ($j,$k) = fonction(...); Ces deux mani`res de procder peuvent parfaitement tre utilises chae e e e cune dans les deux cas de return pr-cits (ce sont toujours les mmes r`gles e e e e daectation qui sappliquent).

5.5

Premier exemple de fonction

Voici un exemple complet de programme en Perl avec une fonction : 1: 2: 3: #!/usr/bin/perl -w use strict; my $t = "Bonjour Larry";

# variable globale 46

c sylvain@lhullier.org

Introduction a la programmation en Perl `

4: 5: 6: 7: 8: 9: 10: 11: 12: 13:

print "$t\n"; # avec ou sans parenth`ses e sub f { my ($x,$z) = @_; # deux arguments attendus my $m = $x*$z; printf("%d\n", $m); return ($x+$z,$m); # retourne une liste } my @t = f(3,5); print "$t $t[0] $t[1]\n";

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

5.6

Autre exemple : une fonction rcursive e

Voici un exemple de fonction. Elle est rcursive (cest-`-dire quelle fait e a appel a elle-mme) : nous allons calculer la factorielle dun nombre. Par ` e dnition, F(0)=F(1)=1 et F(n)=nF(n-1) pour tout n suprieur a 1 : e e ` 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.

47

Introduction a la programmation en Perl `

c sylvain@lhullier.org

48

Chapitre 6

Autres fonctions sur les listes


Vous savez maintenant manipuler des tableaux et des listes, vous savez aussi crire des fonctions : vous voila arms pour aborder les tr`s puissantes e e e et bien pratiques fonctions de gestion qui suivent.

6.1

Joindre les lments dans une cha avec join ee ne

La fonction join prend en param`tre un scalaire et une liste ; elle renvoie e une cha de caract`res comportant les lments de la liste, concatns et ne e ee e e spars par ce premier param`tre scalaire. Les arguments passs ne sont pas e e e e modis. e scalaire = join( sparateur, liste ); e Voici quelques exemples : $s = join(" ",1,2,3); La variable $s vaut alors la cha "1 2 3". ne $s = join(,,$x,$y,$y); Les valeurs des trois variables sont jointes en les alternant avec des virgules. Le rsultat est aect a $s. e e` $s = join(" : ",@t); La variable vaut alors la concatnation des e valeurs du tableau @t avec " : " pour sparateur. e

6.2

Dcouper une cha de caract`res en liste avec e ne e split

La fonction split prend en param`tre un sparateur et une cha de cae e ne ract`res ; elle renvoie la liste des lments de la cha de caract`res dlimits e ee ne e e e par le sparateur. Le sparateur est une expression rguli`re, notion que nous e e e e aborderons dans la suite, mais dont le minimum de connaissances sut a ` 49

Introduction a la programmation en Perl `

c sylvain@lhullier.org

cette fonction ; admettez ici quune telle expression est a placer entre slashs ` (/). Les arguments passs ne sont pas modis. e e liste = split( /sparateur/, chane ); e Voici quelques exemples : @t = split(/-/,"4-12-455"); Le tableau comporte alors les lments ee 4, 12 et 455. ($x,$y) = split(/==/,$v); Les deux variables auront pour valeur les deux premi`res cha e nes de caract`res qui soient spares par deux e e e signes dgalit. e e print join(:,split(/ /,salut ici)); Ache salut:ici (il existe des mthodes plus ecaces et plus lisibles de faire cela...). e

6.3

Trier une liste avec sort

La fonction sort prend en param`tre un bloc dinstructions optionnel et e une liste ; elle renvoie une liste trie conformment au crit`re de tri constitu e e e e par le bloc dinstructions. La liste passe en argument nest pas modie. e e 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 dinstruction sera valu pour comparer deux e e valeurs de la liste ; ces deux valeurs sont localement aectes aux variables e spciales $a et $b qui ne sont dnies que dans le bloc et sur lesquels il e e faut donc eectuer la comparaison. Il faut faire particuli`rement attention e au fait que sil existe des variables $a et $b dans le programme elles seront localement masques par ces variables spciales (source courante derreurs). e e Le bloc doit tre compos dune expression dont la valeur est : e e positive, si $a doit tre avant $b dans la liste rsultat. e e ngative, si $b doit tre avant $a. e e nulle, sils sont quivalents. e Cest l` quentrent en jeu les oprateurs de comparaison cmp et <=> : a e ils permettent de comparer respectivement les cha nes de caract`res selon e lordre lexical et les nombres selon lordre numrique. Si la fonction sort est e appele sans bloc dinstruction, la liste est trie selon lordre lexical. e e Voici quelques exemples : @s = sort( {$a cmp $b} @t ); La liste @s a pour valeur la liste @t trie selon lordre lexical. e @s = sort( @t ); Le fonctionnement est identique a lexemple pr` e cdent. e 50

c sylvain@lhullier.org

Introduction a la programmation en Perl `

@s = sort( {$a <=> $b} @t ); Le crit`re de tri est ici numrique. e e @s = sort( {$a <=> $b or $a cmp $b} @t ); Une expression compose peut bien s r servir de crit`re : le tri est ici dabord numrique e u e e puis lexical. Cela permet de placer 8 navets avant 12 carottes, et 12 carottes avant 12 navets. @s = sort( { fonction($a,$b) } @t ); Vous pouvez crire votre e propre fonction de tri (` deux arguments) ; elle doit renvoyer un noma bre dont la valeur dpend de lordre voulu (voir juste avant). e

6.4

Slectionner des lments avec grep e ee

La fonction grep prend en param`tre un crit`re de slection et une liste ; e e e elle renvoie la liste des lments correspondant au crit`re. La liste passe en ee e e argument nest pas modie. e Le crit`re de slection peut tre soit une expression rguli`re (cas sur e e e e e lequel nous reviendrons plus tard), soit un bloc dinstructions (cas sur lequel nous allons nous tendre) : e liste2 = grep { slection } liste1; (attention : pas de parenth`ses ni de e e virgule) Les lments renvoys sont ceux pour lesquels lvaluation du bloc dinsee e e tructions a pour valeur vrai. Durant cette valuation, chacune des valeurs e sera localement aecte a la variable spciale $_ sur laquelle les tests devront e ` e donc tre eectus. e e Voici quelques exemples : @t = grep { $_<0 } $x,$y,$z; Aecte a @t les lments ngatifs de ` ee e la liste. @s = grep { $_!=8 and $_!=4 } @t; Met dans @s les lments de ee @t dirents de 4 et de 8. e @s = grep { fonction($_) } @t; Vous pouvez crire votre propre e fonction de slection ; elle doit renvoyer vrai ou faux selon si llment e ee est a garder ou non. ` En contexte scalaire, la fonction grep renvoie le nombre dlments qui ee correspondent au crit`re : $n = grep { .... } @t; e La syntaxe de grep comportant une expression rguli`re est la suivante : e e liste2 = grep( /regexp/, liste1 ); En quelques mots, les lments renvoys seront ceux qui correspondront ee e a lexpression rguli`re. Par exemple @s = grep( /^aa/, @t ); aecte a ` e e ` @s les lments de @t qui commencent par deux lettres a. Plus dexplications ee sur les expressions rguli`res seront donnes dans la suite. e e e 51

Introduction a la programmation en Perl `

c sylvain@lhullier.org

Jai arm que la liste dorigine ntait pas modie, mais il vous est e e e possible de le faire. Si, durant la slection, vous aectez une valeur a $_, la e ` liste sera modie. Mais cela est sans doute une mauvaise ide de modier la e e liste passe en param`tre dun grep car la fonction map est faite pour cela. e e

6.5

Appliquer un traitement ` tous les lments a ee avec map

La fonction map prend en param`tre un bloc dinstructions et une liste ; e elle applique le bloc a chacun des lments de la liste (modication possible ` ee de la liste) et renvoie la liste constitue des valeurs successives de lexpression e value. e e liste2 = map( { expression } liste1 ); (attention a ne pas mettre de ` virgule entre le bloc dinstructions et la liste) La variable spciale $_ vaut localement (dans le bloc dinstructions) e chaque lment de la liste. La valeur de la derni`re expression du bloc sera ee e place dans la liste rsultat. e e Voici quelques exemples : @s = map( { -$_ } @t ); Le tableau @s aura pour valeurs les opposs des valeurs de @t. e @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`res des valeurs de @t. e @s = map( { fonction($_) } @t ); Vous pouvez crire votre propre e fonction ; les valeurs quelle renverra seront places dans @s. e Dans les exemples qui prc`dent, la liste dorigine nest pas modie e e e (sauf dans le dernier exemple o` elle peut ltre dans la fonction). Voici un u e exemple de modication de liste : map( { $_*=4 } @t ); Tous les lments de @t sont multiplis par ee e quatre.

6.6

Un exemple : le crible dEratosth`ne e

Nous allons ici illustrer lusage des listes et des tableaux par un exemple mathmatique : le crible dEratosth`ne. Cet algorithme permet de calculer e e tous les nombres premiers infrieurs a un nombre donn n. e ` e Son principe est le suivant : nous construisons tout dabord la liste de tous les entiers de 2 a n. Ensuite, a chaque itration, nous supprimons de la ` ` e 52

c sylvain@lhullier.org

Introduction a la programmation en Perl `

liste tous les multiples du premier nombre de la liste et signalons ce premier nombre comme tant premier. Au premier tour de boucle, je supprime tous e 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 dbut de la liste (4 tant multiple de 2, il a dj` t supprim), jenl`ve e e eaee e e de la liste les multiples de 5 et annonce la primalit de 5 etc ... Lalgorithme e se termine lorsque la liste est vide, jai alors dtermin tous les nombres e e premiers infrieurs a n. e ` Voici la fonction ralisant cet algorithme en Perl : e sub Crible { my ($n) = @_; # Liste initiale : my @nombres = (2..$n); # Liste des nombres premiers trouvs : e my @premiers = (); # Tant quil y a des elments (un tableau e # en contexte boolen vaut faux sil est vide) : e 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 dj` ralis cet algorithme en C ou C++ comprendra la ea e e joie que cette concision procure ...

53

Introduction a la programmation en Perl `

c sylvain@lhullier.org

54

Chapitre 7

Tables de hachage
Les tables de hachage de Perl ne se retrouvent pas dans beaucoup dautres langages ; pour les avoir souvent utilises en Perl, il est dur de repasser a des e ` langages qui nen sont pas pourvus. Une table de hachage (hash table en anglais) est un type de donne en e Perl permettant dassocier une valeur a une clef. On peut dire dun tableau ` (notion aborde prcdemment) quil associe une valeur scalaire a un entier : e e e ` a la position i (pour i entier), une certaine valeur scalaire est prsente. ` e Une table de hachage va nous permettre daller au-del` : on pourra faire a correspondre une valeur scalaire (comme pour un tableau) a toute cha de ` ne caract`res (plutt qu` un entier). e o a Je peux, par exemple, avoir envie de grer en Perl un index tlphonique e ee simple : chacun de mes amis a un numro de tlphone, je veux pouvoir e ee retrouver leur numro a partir de leur prnom. Je vais donc associer le e ` e numro au prnom : e e "Paul" -> "01.23.45.67.89" "Virginie" -> "06.06.06.06.06" "Pierre" -> "heu ..." Les prnoms seront les clefs, cest-`-dire le point dentre dans la table e a e de hachage (comme les indices numraux le sont pour les tableaux). Les e numros de tlphone seront les valeurs associes a ces clefs. Il sagit bien e ee e ` dune association cha de caract`res vers scalaire. ne e Vous lavez sans doute compris, dans une table de hachage, une clef nest prsente quune seule fois et ne peut donc avoir quune seule valeur (comme e llment dun indice donn dun tableau). Par contre, une valeur peut tre ee e e associe a plusieurs clefs. e ` 55

Introduction a la programmation en Perl `

c sylvain@lhullier.org

7.1

Dclaration et initialisation e

Une variable de type table de hachage se dclare de la sorte : e my %h; On a alors une table de hachage vide (aucune clef). Il est possible de signaler explicitement que lon dclare une table de hachage vide : e my %h = (); Pour donner des valeurs initiales a notre table de hachage, on peut uti` liser la syntaxe suivante : my %h = ( "Paul" => "01.23.45.67.89", "Virginie" => "06.06.06.06.06", "Pierre" => "heu ..." ); Cette derni`re table de hachage est dclare et initialise avec les clefs e e e e Paul, Virginie et Pierre ayant respectivement pour valeurs 01.23.45.67.89, 06.06.06.06.06 et heu ...

7.2

Accder ` un lment e a ee

Dans une table de hachage %h, on peut accder a la valeur dune clef e ` au moyen de la syntaxe suivante : $h{clef} ; par exemple $h{Paul} vaut 01.23.45.67.89. Si la clef comporte dautres caract`res que des lettres, e des chires et le soulign (underscore en anglais _), il faut la dlimiter au e e moyen de simples ou de doubles quotes : $h{"Marie-Pierre"} ou $h{Marie-Pierre} En fait, cette syntaxe force un contexte de cha de caract`res entre les ne e accolades, ce qui fait quun mot simple (bareword en anglais) sera converti silencieusement en cha de caract`res (mme en positionnant loption -w). ne e e De faon similaire aux tableaux avec larobase (@t), la totalit dune c e table de hachage se reprsente au moyen du signe pourcentage (%h), alors e quune valeur particuli`re est dsigne a laide dun dollar $h{clef}, cette e e e ` derni`re expression tant bien une variable de type scalaire. e e Voici quelques exemples de manipulation dlments de la table de haee chage %h : 56

c sylvain@lhullier.org

Introduction a la programmation en Perl `

$h{Jacques} = "02.02.02.02.02"; print "Tl : $h{Jacques}\n"; e $h{Jean-Paul} = "03.03.03.03.03"; if( $h{"Jean-Paul"} ne "Heu ..." ) { ... } La clef utilise pour cette syntaxe peut tout a fait tre contenue dans e ` e une variable scalaire (qui sera value en contexte de cha de caract`res) : e e ne e my $k = "Jacques"; $h{$k} = "02.02.02.02.02"; Elle peut mme tre une expression plus complexe : e e sub f { return "Jac"; } $h{f().ques} = "02.02.02.02.02";

7.3

Parcours

Il existe trois fonctions permettant de parcourir une table de hachage. Dans les exemples fournis, nous considrerons que la table %h a t dclare e ee e e 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`tre une table de hachage et renvoie e une liste comportant toutes les clefs de la table. Lordre des clefs est quelconque, seule lexhaustivit des clefs est garantie. e 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"; } 57

Introduction a la programmation en Perl `

c sylvain@lhullier.org

La variable de boucle $k prendra pour valeurs successives lensemble des clefs de la table, lexpression $h{$k} est la valeur associe a la clef e ` $k. Ce petit programme achera donc tous les couples clef/valeur de la table %h. values : obtenir une liste des valeurs De la mme faon que keys renvoie une liste des clefs dune table de e c hachage, la fonction values fournit une liste des valeurs ; pour cette fonction non plus lordre nest pas garanti et seule lexhaustivit lest. e Lexemple suivant foreach my $v (values(%h)) { print "Valeur=$v\n"; } achera tous les numros de tlphone (cest-`-dire les valeurs) de la e ee a table %h. Il nest bien s r pas possible de retrouver la clef des valeurs que lon u manipule ainsi. Il peut tre intressant de savoir que lordre des clefs renvoyes par e e e keys et celui des valeurs par values sera le mme a condition de ne e ` pas modier la table de hachage entre temps. each : itration sur les couples (clef,valeur) e Cette fonction renvoie un a un tous les couples (clef,valeur) dune table ` de hachage. Elle a un comportement un peu spcial du fait quil faut e lappeler autant de fois quil y a de couples : cest une fonction avec tat, cest-`-dire quelle ne renvoie pas toujours la mme chose dun e a e 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.

7.4

Autovivication

Sous ce terme barbare se cache une ide simple : si vous tentez de modier e un lment dune table de hachage qui nexiste pas, il sera cr. Sil est ee ee utilis dans un contexte numrique, il prendra pour valeur initiale zro. Sil e e e 58

c sylvain@lhullier.org

Introduction a la programmation en Perl `

est utilis dans un contexte de cha de caract`res, il prendra pour valeur e ne e la cha vide (depuis Perl 5.6). ne Par exemple, considrons une table de hachage qui ne comporte pas la e clef hello ; lexpression suivante $h{hello} .= "apr`s"; e associe a la clef hello la valeur cha vide puis lui concat`ne la cha ` ne e ne "apr`s". De la mme faon, lexpression e e c $h{bye}++; cre un lment de valeur 1. e ee Cette proprit dautovivication est bien pratique dans le cas o` lon ee u ne conna pas les clefs avant de devoir y accder. Par exemple nous allons t e pouvoir compter le nombre doccurrences des mots dans un texte de mani`re e tr`s simple. Supposons que les mots du texte soient dj` dans un tableau e ea (par exemple en utilisant la fonction qw ; elle ne r`gle pas les probl`mes des e e ponctuations, des majuscules et des lettres accentues, mais elle sura a e ` 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 prsent $v fois\n"; e } Ce qui donne lachage suivant : Le mot vous est prsent 1 fois e Le mot bonjour est prsent 2 fois e Dans la suite nous verrons comment dcouper un texte en mots au moyen e des expressions rguli`res. e e 59

Introduction a la programmation en Perl `

c sylvain@lhullier.org

7.5

Existence et suppression dune clef

` A la lecture de ce qui prc`de, il peut sembler impossible de savoir si e e un lment dune table de hachage existe ou non. Rassurez-vous, les auteurs ee de Perl ont tout prvu :-) Loprateur exists renvoie vrai si llment de e e ee table de hachage quon lui donne en param`tre existe ; sinon il renvoie faux. e Par exemple : if( exists( $h{hello} ) ) { print "La clef hello existe\n"; } Il est important de noter quun test eectu au moyen de loprateur e e defined aurait t possible, mais dangereux. En eet, lexpression defined( ee $h{hello} ) est fausse dans deux cas tr`s dirents : soit si llment nexiste e e ee pas, soit si llment existe et vaut undef ; elle sera vraie si llment existe ee ee et ne vaut pas undef. Il est donc impossible de distinguer le cas dun lment ee absent et celui dun lment indni (valant undef) avec defined. ee e Cette distinction entre absent et indni peut para e tre articielle dans ce cas (elle peut tout de mme tre importante dans certaines situations !), e e 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 lope rateur 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 mme faon que exists est la bonne mthode pour tester e c e lexistence dun lment, delete est la bonne mthode pour en supprimer ee e un. Le dbutant pourrait tre tent dcrire : e e e e $h{hello} = undef; # attention!

Ce qui est fort dirent car, dans ce cas, la clef hello aura une valeur e indnie, mais existera toujours ! On la retrouvera, par exemple, dans les e parcours eectus au moyen des oprateurs keys, values ou each ; ce qui e e nest sans doute pas le but recherch. e Pour rsumer, on peut dire que pour tester lexistence dune clef, il faut e utiliser exists et que pour en supprimer une, il faut utiliser delete. 60

c sylvain@lhullier.org

Introduction a la programmation en Perl `

En marge de ces deux fonctions, voici une mani`re de savoir si une table e 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 de caract`res, par exemple de cette faon : ne e c 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) utilises par rapport au nombre e total disponibles dans le hachage. Une table vide est un cas particulier, elle renverra 0.

7.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; La premi`re instruction cre un tableau @t initialis a une liste a 6 e e e ` ` lments. La seconde cre une table de hachage %h initialise au moyen ee e e du prcdent tableau. Les valeurs du tableau sont prises deux a deux : la e e ` premi`re de chaque couple sera la clef dans la table de hachage, la seconde e la valeur. Si le nombre dlments de la liste est impair, la derni`re clef cre ee e ee aura undef pour valeur. Si une clef venait a tre prsente plusieurs fois dans `e e la liste, cest la derni`re valeur qui sera prise en compte dans la table de e hachage. On aurait aussi pu crire : e my %h = ("Paul", "01.23.45.67.89", "Virginie", "06.06.06.06.06", "Pierre", "heu ..."); Il est a noter que cette syntaxe rappelle trangement lun des premiers ` e exemple de cration de table de hachage qui utilisait => pour sparer clefs e e 61

Introduction a la programmation en Perl `

c sylvain@lhullier.org

et valeurs. Cette similarit est en fait une quasi quivalence, car loprateur e e e => peut tre utilis a la place de la virgule pour crer des listes ; il na t e e` e ee ajout au langage Perl que pour faciliter la lecture des aectations de tables e de hachage, car il force un contexte de cha a sa gauche, ce qui permet ne ` justement dcrire %a = ( toto => titi ); e La conversion dans lautre sens est aussi possible. Lvaluation dune e 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 prcdent peut tre e e e aecte a un tableau : e ` my @t2 = %h; Le tableau @t2 sera initialis, par exemple, avec la liste suivante : e ("Pierre", "heu ...", "Paul", "01.23.45.67.89", "Virginie", "06.06.06.06.06") ; chaque clef prc`de sa valeur, mais lordre des couples e e (clef,valeur) est quelconque (un peu comme pour la fonction each). Une table de hachage se convertit en liste sans encombre d`s quelle est e 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 tre e employe pour inverser une table de hachage : e %h = reverse(%h); Les valeurs deviennent les clefs et inversement. Si plusieurs valeurs identiques sont prsentes le comportement est imprvisible car, certes, lors de e e la transformation de liste en table de hachage la derni`re valeur compte, e mais lors de la transformation de table de hachage en liste lordre est quelconque ... Lassociation individu - numro de tlphone est idale pour illustrer e ee e cela : my %h = ("Paul", "01.23.45.67.89", "Virginie", "06.06.06.06.06", "Pierre", "heu ..."); my %quidonc = reverse %h; 62

c sylvain@lhullier.org

Introduction a la programmation en Perl `

On pourra alors retrouver la personne a partir de son numro de tlphone. ` e ee Si, par contre, Paul et Virginie avaient eu le mme numro, on naurait pas e e pu prdire quel serait la personne renvoye. e e

7.7

Exemples

Voici quelques exemples dutilisation des tables de hachage. Le premier concerne la variable spciale %ENV qui contient les variables e denvironnement du programme. $ENV{PATH} contient le path, $ENV{HOME} vaut le nom du rpertoire personnel de lutilisateur qui excute le proe e gramme, etc. Deuxi`me exemple, les tables de hachage peuvent servir a constituer des e ` tableaux a plusieurs dimensions ; on pourrait en eet imaginer avoir des ` clefs qui seraient la concatnation des coordonnes dans les n dimensions : e e 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 btir de rels tableaux a a e ` plusieurs dimensions en utilisant des rfrences. ee 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 elments dans des tableaux e my @ensA = (1, 3, 5, 6, 7, 8); my @ensB = (2, 3, 5, 7, 9); # Voici mon union et mon intersection, # les elments des ensembles en seront les clefs e my %union = (); my %inter = ();

63

Introduction a la programmation en Perl ` # Je mets tous les elments de A dans lunion : e foreach my $e (@ensA) { $union{$e} = 1; } # Pour tous les elments de B : e foreach my $e (@ensB) {

c sylvain@lhullier.org

# Sil est dj` dans lunion, cest quil est e a # dans A : je le mets donc dans lintersection : $inter{$e} = 1 if ( exists( $union{$e} ) ); # Je le mets dans lunion $union{$e} = 1; } # # # # Tous sont Tous sont les des les des elments e clefs de elments e clefs de prsents e la table prsents e 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 mme probl`me, voici une solution nutilisant quune seule table e e de hachage, je vous laisse le soin den apprcier le principe : e 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}++; } 64

c sylvain@lhullier.org

Introduction a la programmation en Perl `

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 comprhension de cet exemple demande davoir assimil plusieurs e e notions importantes vues jusquici.

65

Introduction a la programmation en Perl `

c sylvain@lhullier.org

66

Chapitre 8

Tranches
En Perl, il est possible de manipuler plusieurs lments dun tableau ou ee dune table de hachage a la fois. Cela sappelle une tranche (slice en anglais). `

8.1

Tranches de tableau

Une tranche de tableau est un sous-ensemble des lments du tableau. ee Imaginons par exemple un tableau @t duquel nous souhaiterions manipuler les lments dindice 4 et 10 ; pour cela nous allons prendre la tranche coree respondante de ce tableau : @t[4,10] est une liste a deux lments qui est ` ee quivalente a ($t[4],$t[10]) Quelques explications sur la syntaxe. Tout e ` dabord, lexpression commence par une arobase, car il sagit dune liste dlments ; le dollar est rserv aux scalaires, par exemple $t[4] est un scaee e e laire. Ensuite, comme dhabitude pour les tableaux, les crochets permettent de spcier les indices. Enn, lensemble des indices est indiqu par une liste e e dentiers : @t[2,10,4,3] @t[3..5] @t[fonction()] ... Une telle tranche est utilisable comme valeur (passage de param`tres, e etc) et comme l-value (expression a gauche du signe gal daectation) : ` e @t[4,10] = (4321,"age"); cette instruction aecte 4321 a lindice 4 du tableau @t et la cha age ` ne a lindice 10. On aurait pu crire ` e ($t[4],$t[10]) = (4321,"age"); Un autre utilisation des tranches de tableau appara avec les fonctions t qui renvoient une liste. Par exemple la fonction stat prend en param`tre e 67

Introduction a la programmation en Perl `

c sylvain@lhullier.org

un nom de chier et renvoie toute sorte dinformations sur le chier : taille, dates, propritaire etc. Il est courant dcrire : e e ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat($filename); La fonction renvoie une liste qui est aecte aux variables de la liste e de gauche. Les tranches peuvent intervenir si seules quelques informations vous intressent et que vous ne voulez pas dclarer de variables inutiles. Par e e exemple, si seules les dates de modication (indice 9) et de cration (indice e 10) vous intressent, vous pouvez crire : e e ($mtime,$ctime) = ( stat($filename) )[9,10]; Lappel a la fonction est plac entre parenth`ses et on ne prend que les ` e e lments dindice 9 et 10 de sa valeur de retour. On a alors une liste a deux ee ` lments, celle-ci est aecte a la liste a gauche du signe gal et donc ces ee e ` ` e deux lments sont aects aux deux variables. ee e

8.2

Tranches de table de hachage

De la mme faon quil existe des tranches pour les tableaux et les listes, e c il en existe pour les tables de hachage. La slection seectue bien s r sur les e u clefs. Par exemple, si %h est une table de hachage, alors @h{clef1,clef2} est une liste quivalente a ($h{clef1},$h{clef2}) Il est ensuite pose ` sible dutiliser cette liste comme bon vous semble (aectation, passage en param`tre, etc). e Une utilisation (assez complexe) des tranches serait indique lorsque lon e veut construire automatiquement une liste de valeurs uniques a partir dun ` tableau dont on nest pas s r que ses valeurs soient uniques : u # Un tableau avec des valeurs dupliques : e my @t = qw(hello toto hello vous); # Dclaration dune table de hachage : e my %h; # On prend la tranche de %h dont les clefs # sont les valeurs du tableau @t # et on leur associe la valeur undef 68

c sylvain@lhullier.org

Introduction a la programmation en Perl `

@h{@t} = (); # Les clefs de %h sont donc constitues des e # valeurs de @t, et on est s^r de ne les u # retrouver quune seule fois : @t = keys %h; Le tableau @t comporte alors une fois et une seule chacun de ses lments. ee

69

Introduction a la programmation en Perl `

c sylvain@lhullier.org

70

Chapitre 9

Manipulation des chiers


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

9.1

Oprateurs sur les noms de chier e

Perl dispose doprateurs prenant en param`tre un nom de chier ; ce e e nom de chier doit tre un scalaire (une variable ou une constante). Leur e valeur de retour est souvent boolenne et quelquefois numrique. Les coutue e miers du shell retrouveront de nombreuses options de la commande test. -e teste si son param`tre est un chemin valable dans le syst`me de e e chier (rpertoire, chier, etc). On pourrait lutiliser ainsi : e if( -e "/usr/tmp/fichier" ) { print "Le fichier existe\n"; } -f teste si son param`tre est un chier normal. e -d teste si son param`tre est un rpertoire. e e -l teste si son param`tre est un lien symbolique. Ceci nexclut pas que e -f ou -d renvoie vrai. -r teste si le programme a le droit de lire le chier/rpertoire/etc pass e e en param`tre. e -w teste si le programme a le droit dcrire. e -x teste si le programme a le droit dexcuter le chier ou daccder e e 71

Introduction a la programmation en Perl `

c sylvain@lhullier.org

(ou axder :-)) au rpertoire. e e -o teste si le chier appartient a lutilisateur qui excute le programme. ` e -z teste si le chier est vide. -s teste si le chier est non vide ; en fait cet oprateur renvoie la taille e du chier. -M renvoie lge en jour du chier (depuis le dbut de lexcution du a e e programme). Il existe tout plein dautres oprateurs sur les chiers ; pour en conna e tre la liste complte, je vous invite a lancer la commande perldoc -f -X e ` Voici quelques exemple dutilisation de ces oprateurs : e my $file = "/usr/doc/perl"; if( -f $file && -w $file ) { .... } my $taille = -s $file; my $age = -M $file; Simple et ecace.

9.2

La fonction glob

La fonction glob prend en argument une expression et renvoie une liste de noms de chiers. Cette liste correspond a lvaluation de lexpression ` e selon les wildcards du shell. Par exemple, glob( *.o ) renvoie la liste des chiers du rpertoire e courant ayant lextension .o Notez bien quil ne sagit pas dune expression rguli`re (pour ceux qui e e 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 commenant par une majuscule ayant lextension .h c Il existe une syntaxe plus concise et au comportement identique a cette ` fonction : lexpression peut tre mise entre chevrons. Les deux lignes suie vantes eectuent la mme opration : e e @l = glob(/usr/include/*.h); @l = </usr/include/*.h>; Apr`s lexcution dune de ces deux lignes, le tableau @l contient la liste e e des noms absolus des chiers dinclude pour le C du rpertoire /usr/include e 72

c sylvain@lhullier.org

Introduction a la programmation en Perl `

9.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 rpertoire courant. e 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-rpertoires du rpertoire e e courant sur lesquels jai les droits dcriture (y-compris ceux commenant e c par un point, donc . et ..).

9.4

Ouverture de chier

Pour lire ou crire dans un chier, il est ncessaire de louvrir pralablement. e e e La fonction eectuant cette opration en Perl se nomme open et sa syntaxe e est la suivante : open( HANDLE, expression ) Le param`tre HANDLE sera lidentiant du chier apr`s ouverture (on e e pourrait parler de descripteur de chier). Cest ce descripteur qui devra tre e fourni aux fonctions de lecture et dcriture pour manipuler le chier. Pour e ne pas rentrer trop dans les dtails, un descripteur de chier se reprsente e e dans le code Perl par une simple cha de caract`res (sans quotes pour ne e la dlimiter, ni de $ pour la dbuter) ; la convention veut quon le mettre e e toujours en majuscules. 73

Introduction a la programmation en Perl `

c sylvain@lhullier.org

Le param`tre expression est un scalaire (cha de caract`res) compore ne e tant le nom du chier a ouvrir prcd de zro, un ou deux caract`res indi` e e e e e quant le mode douverture : Caract`re(s) e aucun < > >> +> +< Mode douverture lecture lecture criture (crasement) e e criture (ajout) e lecture et criture (crasement) e e lecture et criture (ajout) e

Le habitus du shell retrouveront certaines notations connues. e Par exemple open(FIC1,"<index.html") ouvre le chier index.html en lecture et open(FIC2,">index.html") louvre en criture-crasement (ceste e a-dire que le chier sera vid avant que le curseur ne soit plac au dbut du ` e e e chier). Cette fonction open renvoie une valeur boolenne vrai ou faux indiquant e le bon droulement ou non de lopration. Il est tr`s important de tester les e e e valeurs de retour des fonctions manipulant les chiers (cela est vrai quel que soit le langage), car on ne peux jamais tre s r de rien. Voici deux exemples e u 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, on appelle la fonction exit qui met n au programme e (la valeur 1 signale une erreur ; la valeur 0 signalant la n normal du programme, les autres valeurs sont utilises pour signaler au shell appelant une e erreur). Vous noterez que lutilisateur qui excute le programme nest pas e inform de la cause de lchec ; le programme se termine, tout au plus sait-il e e quil y a eu un probl`me avec louverture de ce chier, mais il nen conna e t pas la cause. Lexemple suivant va nous permettre de lui acher un joli message derreur : open(FIC2,"</tmp/$a") or die("open: $!"); 74

c sylvain@lhullier.org

Introduction a la programmation en Perl `

Nous cherchons ici a ouvrir en lecture le chier dont le nom serait la ` concatnation de la cha /tmp/ et du contenu de la variable $a. La fonce ne tion die met n au programme comme exit le ferait, mais ache en plus le param`tre quon lui passe. En loccurrence, le param`tre fourni est la e e cha de caract`res comportant le nom de la fonction qui cause lchec (on ne e e aurait pu ajouter le nom du chier) ainsi que la variable $!. En contexte de cha de caract`res, cette variable magique $! contient le message errno de ne e la derni`re erreur survenue, par exemple No such file or directory ou e Permission denied etc. Lutilisateur est donc inform de la cause de la n e du programme. La syntaxe open() or die(); ainsi que sa signication proviennent de lvaluation paresseuse du or. En eet, dans lexpression (a or b) si a est vrai, e il nest pas ncessaire dvaluer b pour conna e e tre la valeur de lexpression. Cest ce quil se passe ici : si open() renvoie vrai, il nest pas ncessaire e dvaluer die(). e Les descripteurs de chier sont dune esp`ce trange en Perl, le dbutant e e e sabstiendra de chercher a trop comprendre les mcanismes sous-jacents. ` e Ce que lon pourrait dire, cest quil nest pas ncessaire de dclarer un e e descripteur de chier, la fonction open valant dclaration. e

9.5

Lecture, criture et fermeture de chier e

Une fois un chier ouvert, il nous est possible dcrire et/ou de lire dedans e (selon le mode douverture) et de le fermer. La lecture des chiers texte seectue typiquement au moyen de loprae teur chevrons, cette lecture se faisant ligne par ligne. $l = <FIC>; Cette instruction lit la prochaine ligne disponible du chier FIC. Vous noterez bien que loprateur chevrons (diamond operator en anglais) est ici e 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 place dans le tableau @t. e Pour itrer sur les lignes dun chier, il est courant de faire ainsi : e 75

Introduction a la programmation en Perl ` while( defined( $l = <FIC> ) ) { chomp $l; print "$. : $l\n"; }

c sylvain@lhullier.org

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`re sil sagit e dun retour a la ligne. La variable spciale $. vaut le numro de la ligne ` e e courant du dernier chier lu (ici FIC). Si vous utilisez la variable spciale omni-prsente $_, la construction e e while( defined( $_ = <FIC> ) ) peut mme sabrger en : e e while( <FIC> ) Pour crire dans un chier, nous allons utiliser les fonctions print et e printf que nous avons dj` vues. Elles prennent en premier argument le ea descripteur de chier : print( FIC "toto\n" ); printf( FIC "%03d", $i ); Il faut noter quil ny a pas de virgule apr`s le descripteur de chier (il e ne faut pas en mettre !). Les parenth`ses sont comme toujours optionnelles e autour des arguments, mais permettent de lever certaines ambigu es. La t fonction printf fonctionne comme printf ou fprintf du C et ne sera donc pas dtaille ici (voir man 3 printf). e e Pour fermer un descripteur de chier (et donc vider les buers associs), e il faut faire appel a la fonction close : ` close( FIC ); ` A noter que si vous rutilisez un descripteur de chier dans un open sans e faire de close au pralable, Perl ne rousptera pas et fermera consciencieue e sement le premier chier avant douvrir le deuxi`me. e Il existe plusieurs chiers ouverts automatiquement par Perl d`s le lane cement du programme : STDIN : lentre standard (souvent le clavier). e 76

c sylvain@lhullier.org

Introduction a la programmation en Perl `

STDOUT : la sortie standard (souvent le terminal). Par dfaut print et e printf crivent sur ce ux. e STDERR : la sortie derreur standard (souvent le terminal). Par dfaut e warn et die crivent sur ce ux. e ARGV : ce descripteur est un peu spcial, mais souvent bien pratique. e Les lignes lues sont celles des chiers de la ligne de commande (donc les arguments passs au programme sont considrs comme des noms e ee de chier) ; si le programme est lanc sans argument, lentre standard e e est lue. NB : vous pouvez crire soit <ARGV> soit <> La variable spciale e e $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 donns jusquici ne conviennent pas a de tels chiers mais e ` plutt a des chiers contenant du texte. Vous pouvez, pour cela, utiliser la o ` fonction getc qui renvoie le prochain caract`re disponible : $c = getc(FIC); e Vous pouvez aussi faire usage de la fonction read qui lit un nombre dtermin e e de caract`res : $tailleLue = read( FIC, $tampon, $tailleALire ); Les e ` donnes seront places dans la variable $tampon A la n du chier, ou sil e e y a un probl`me, le tampon nest pas compl`tement rempli. Cest pour cela e e que lon rcup`re la valeur de retour de read. e e Pour crire des donnes non textuelles dans un chier, vous pouvez tout e e a fait utiliser les fonctions print et printf car les cha ` nes de caract`res de e Perl peuvent contenir le caract`re de code ASCII zro. On notera que la e e fonction write existe, mais nest pas linverse de read. Sil vous est ncessaire dutiliser les fonctions dentre/sortie bas niveau, e e voici leurs noms en Perl : sysopen, sysread, syswrite et close.

9.6

Deuxi`me exemple e

Voici le prolongement de lexemple donn pour les tables de hachage. e Nous nallons plus considrer que les mots sont contenus dans un tableau, e mais nous allons les extraire dun chier. #!/usr/bin/perl -w use strict; open(FILE,"<$filename.txt") or die"open: $!"; my($line,@words,$word,%total); while( defined( $line = <FILE> ) ) { @words = split( /\W+/, $line ); foreach $word (@words) 77

Introduction a la programmation en Perl ` { $mot =~ tr/A-Z/a-z/; $total{$word}++; }

c sylvain@lhullier.org

} close(FILE); foreach $word (sort keys %total) { print "$word a et rencontr $total{$word} fois.\n"; e e } On eectue une boucle while sur les lignes du chier. Chaque ligne est alors dcoupe en mots par la fonction split (\W+ correspond aux suites de e e caract`res non-alphanumriques, nous verrons cela dans la suite lorsque nous e e tudierons les expressions rguli`res). Chaque mot est mis en minuscules au e e e moyen de loprateur tr (que nous expliquerons avec les expressions rgue e li`res). e

9.7

Excution de commandes avec open e

Il est facile en Perl de lancer une commande shell et de rcuprer sa e e sortie standard ou de fournir son entre standard. e 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 seront celles que la ee commande aurait aches a lcran si on lavait lance depuis un terminal. e ` e e La syntaxe open(HANDLE,"|commande") permet de lancer une commande. Les lignes crites dans le descripteur de chier constitueront son e entre standard, par exemple : e open(FIC3,"|gzip > $a.gz") open(FIC4,"|mail robert\@bidochon.org") Quoi de plus simple ? 78

c sylvain@lhullier.org

Introduction a la programmation en Perl `

9.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. Il existe en dehors de Perl. e 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 synchronises. Pour y accder nous utiliserons les fonctions e e dbmopen et dbmclose Nous allons directement passer a un exemple. Il comporte deux phases : ` dans la premi`re nous allons crer un chier DBM comportant un couple e e 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. Ces chiers sont ensuite ee 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.

79

Introduction a la programmation en Perl `

c sylvain@lhullier.org

80

Chapitre 10

Expressions rguli`res e e
Nous abordons ici un sujet tr`s riche en dveloppements : les expressions e e rguli`res. Perl en tire une partie de sa grande puissance pour lanalyse et le e e traitement des donnes textuelles. La lecture de cette partie du document e peut aussi intresser toute personne utilisant grep, sed, Python, PHP, C, e C++ et mme Java. e Atout important de Perl par rapport a dautres langages, les expres` sions rguli`res permettent de manipuler le texte de faon tr`s puissante et e e c e tr`s concise. Lacquisition de leur ma e trise peut savrer dicile au dbut, e e mais en vaut tr`s largement la chandelle, aussi bien pour programmer en e Perl que pour utiliser les outils classiques du shell ou les autres langages prcdemment cits. e e e Au niveau vocabulaire, on utilise en anglais le terme regular expression (souvent abrg en regexp voire regex), ce qui a donn en franais une trae e e c duction correcte expressions rationnelles et une traduction mot a mot ` expressions rguli`res. La seconde est entre dans les murs et sera donc e e e utilise ici. e On retrouve les expressions rguli`res dans certaines fonctions Perl que e e vous connaissez dj`, comme par exemple split ou grep ; mais elles existent ea aussi par le biais doprateurs spciques. e e

10.1

Fonctionnalits e

Il existe deux types principaux de fonctionnalits dans les expressions e rguli`res : la correspondance (pattern matching en anglais : pattern=motif, e e matching=correspondance) et la substitution. La correspondance est le fait de tester (vrier) si une cha de cae ne 81

Introduction a la programmation en Perl `

c sylvain@lhullier.org

ract`res comporte un certain motif. Par exemple, on pourrait se poser les e questions suivantes et y rpondre par un match : la variable $v commencee t-elle par un chire ? Comporte-t-elle au moins deux lettres majuscules ? Contient-elle une sous-cha rpte deux fois dau moins 5 caract`res ? ne e e e e Etc. Sa syntaxe est la suivante : m/motif/ Le m indique que nous voulons faire un match, les slashes (/) servent a ` dlimiter le motif recherch (on verra plus loin comment utiliser dautres e e sparateurs). e Cette fonctionnalit nous permettra aussi dextraire des sous-cha e nes dune variable donne sans la modier. Par exemple, si je veux rcuprer e e e 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 souscha nes toto par titi. Supprimer de $v tous les mots entre guillemets. Etc. Sa syntaxe est la suivante : s/motif/chane/ Le s indique que nous voulons faire une substitution, les slashes (/) servent a dlimiter le motif recherch ainsi que la cha de remplacement. ` e e ne

10.2

Bind

Pour lier une variable a une telle expression, il faut utiliser loprateur ` e =~ (dit bind en anglais). $v =~ m/sentier/ vrie si la variable $v comporte le mot sentier. On e dit alors que la variable est lie a lexpression rguli`re. Cette expression e ` e e vaut vrai ou faux ; nous lutiliserons donc tr`s souvent dans une structure e de contrle de type if : o if( $v =~ m/sentier/ ) { instructions } Dans les cas o` le test est vrai, cest-`-dire si la variable contient le motif u a (ici si $v contient sentier), les instructions seront excutes. e e Par cette opration de bind, nous venons de lier une expression rguli`re e e e a une variable. Par dfaut, une telle expression sapplique a la variable $_ ` e ` (comme beaucoup de fonctions Perl). De la mme faon, e c 82

c sylvain@lhullier.org

Introduction a la programmation en Perl `

$v =~ s/voiture/pieds/; remplace la premi`re occurrence de voiture dans la variable $v par e pieds (on verra plus loin comment remplacer toutes les occurrences). Le reste de $v nest pas modi. Le point-virgule indique la n de linstruction. e Pour la correspondance, il existe aussi loprateur !~ qui quivaut a =~ e e ` suivi dune ngation de lexpression. e if( $w !~ m/pieds/ ) { ... } est plus concis et est quivalent a e ` if( ! ( $w =~ m/pieds/ ) ) { ... } Les instructions sont excutes si $w ne contient pas la cha pieds. e e ne

10.3

Caract`res e

Dans cette sous-partie et dans les suivantes, nous allons voir quels sont les motifs utilisables dans les expressions rguli`res. e e Dans le cas gnral, un caract`re vaut pour lui mme ; comprenez que e e e e lorsque lon utilise lexpression rguli`re m/a/ on vrie si la variable (ici e e e non cite) contient le caract`re a. Cela semble vident, mais il est bon de le e e e dire. En eet, pour certains caract`res spciaux, cela nest pas le cas. Ces e e caract`res ont un rle particulier dans les expressions rguli`res (nous allons e o e e voir cela dans la suite). Si vous avez besoin de rechercher ces caract`res, il e faut donc les dspcier au moyen dun anti-slash (\). Voici la liste de ces e e caract`res : \ | ( ) [ ] { } ^ $ * + ? . e Il faut ajouter a cette liste le caract`re choisi comme sparateur. Pour ` e e le moment, seul le slash (/) est utilis dans ce document, mais nous verrons e plus tard quil est possible den changer. Par exemple $x =~ m/to\.to/ est vrai si la variable $x comporte les caract`res t o . t o contigus. e Les caract`res spciaux habituels peuvent tre utiliss ; en voici quelques e e e e exemples : Motif \n \r \t \f \e Caract`re e saut de ligne retour chariot tabulation saut de page chappement e 83

Introduction a la programmation en Perl ` Seuls les plus utiles sont prsents ici. e e

c sylvain@lhullier.org

10.4

Ensembles

Le caract`re . (point) correspond a un caract`re quel quil soit (sauf e ` e \n (ce comportement peut tre chang : nous verrons cela plus loin)). Cela e e signie qu` lemplacement de ce point dans le motif pourra (devra) cora respondre un caract`re quelconque dans la variable. Par exemple, le motif e m/t.t./ reconna tra toute variable comportant une lettre t suivie dun caract`re quelconque, puis une autre lettre t, puis un autre caract`re quele e conque ; par exemple toute variable comportant une des cha nes suivantes correspondra au motif : tata, t%tK, tot9 ... Vous comprenez pourquoi il faut dspcier le caract`re point avec un e e e anti-slash si vous voulez chercher un point littral : sans cela un point matche e avec nimporte quel caract`re. e Le motif [caract`res] matche un caract`re parmi ceux prsents entre e e e crochets. Par exemple [qwerty] peut reconna une de ces six lettres. Le tre motif m/t[oa]t[ie]/ reconna toute variable comportant une des quatre tra cha nes suivantes : toti, tati, tote ou tate. On comprendra aisment que e si un caract`re est prsent plusieurs fois dans cette liste, cela a le mme eet e e e que sil tait prsent une seule fois : [aeiouyie] est quivalent a [aeiouy]. e e e ` Il est possible de dnir des intervalles de caract`res dans ces ensembles. e e Par exemple a-z quivaut aux 26 lettres minuscules de lalphabet. Par e 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 numro ASCII du pree mier caract`re est infrieur a celui du second. Autre exemple, le motif [ -~] e e ` correspond a un caract`re ASCII imprimable et de numro infrieur a 127. ` e e e ` 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`re tiret (-) doit tre prsent dans lensemble, il faut le mettre e e e en premi`re ou en derni`re position an de lever toute ambigu e possible e e t avec un intervalle. Par exemple [a-z4-] matche soit une minuscule, soit un 4, soit un tiret. Le caract`re ^ (accent circonexe) a un rle particulier sil est plac en e o e dbut dintervalle ; il prend le complmentaire de lensemble, il faut le lire e e tout caract`re sauf .... Par exemple [^ao] matche tout caract`re sauf le e e a et le o. Le motif [^0-9] matche tout caract`re non numrique. e e 84

c sylvain@lhullier.org

Introduction a la programmation en Perl `

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

10.5

Quanticateurs

Les quanticateurs sappliquent au motif atomique (cest-`-dire le plus a petit possible) le prcdant dans lexpression rguli`re. Ils permettent de e e e e spcier un nombre de fois o` ce motif peut/doit tre prsent. e u e e Par exemple ltoile * indique que le motif peut tre prsent zro fois ou e e e e 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` que dans lexpression rguli`re m/za*/ a e e ltoile sapplique uniquement a la lettre a et non au mot za. Nous verrons e ` plus loin comment faire cela. Il est par ailleurs important de noter quun tel quanticateur est par dfaut gourmand, cest-`-dire quil se met en correspondance avec le plus e a de caract`res possible dans la variable lie. Cela a son importance dans le e e cas dune substitution : si la variable $v contient la cha vbaaal, et si ne on eectue linstruction suivante : $v =~ s/ba*/hello/; la cha matche ne e par la premi`re expression ba* sera baaa (le quanticateur matche le plus de e caract`res possible) et la substitution aura pour eet de donner pour valeur e vhellol a la variable $v. ` Voici un tableau des quanticateurs : * + ? {n} {n,} {,n} {n,m} le motif prsent e 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 matchs e 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

On remarquera que * est un raccourci pour {0,} ainsi que + pour {1,}, de mme que ? pour {0,1}. e Dans les exemples prcdents, tous les quanticateurs sont appliqus a e e e ` un caract`re. On peut les appliquer a tout motif, par exemple a un ensemble : e ` ` m/[0-9-]{4,8}/ recherche une cha comportant entre 4 et 8 caract`res ne e numriques ou tirets contigus. e 85

Introduction a la programmation en Perl `

c sylvain@lhullier.org

10.6

Ensembles (suite)

Nous allons ici numrer un certain nombre de raccourcis pour des ene e sembles courants : \d : un chire, quivalent a [0-9] (d comme digit, chire en anglais) e ` \D : un non-numrique, quivalent a [^0-9] e e ` \w : un alphanumrique, quivalent a [0-9a-zA-Z_] (w comme word, e e ` cest un caract`re dun mot) e \W : un non-alphanumrique, quivalent a [^0-9a-zA-Z_] e e ` \s : un espacement, quivalent a [ \n\t\r\f] (s comme space) e ` \S : un non-espacement, quivalent a [^ \n\t\r\f] e ` On remarquera quun ensemble et son complmentaire sont nots par la e e mme lettre, lune est minuscule, lautre majuscule. e Par exemple, lexpression rguli`re suivante : m/[+-]?\d+\.\d+/ pere e met de reconna un nombre dcimal, sign ou non : un caract`re + ou tre e e e optionnel, au moins un chire, un point et enn au moins un chire.

10.7

Regroupement

Si dans notre exemple prcdent, nous souhaitons rendre optionnelle la e e partie dcimale, on pourrait crire : m/[+-]?\d+\.?\d*/ rendant ainsi none e obligatoire la prsence du point et celle des chires apr`s la virgule. Le e e probl`me de cette expression est que la prsence du point et de ces chires e e sont dcorrles : lexpression rguli`re reconna un nombre o` lune de ces e ee e e tra u deux parties serait prsente et lautre absente. Or ce que lon veut, cest que e le point et les chires qui le suivent soient rendus solidaires dans labsence ou la prsence. e Pour cela nous allons utiliser des parenth`ses pour eectuer un regroue pement entre plusieurs motifs (ici le point et les chires) pour leur appliquer conjointement le mme quanticateur. Lexpression rguli`re e e e m/[+-]?\d+(\.d+)?/ reconna donc les nombres tels que nous les souhait tons. Pour marquer la mmoire de mes tudiants, jaime a leur dire que e e ` m/meuh{3}/ permet de meugler longtemps et que m/(meuh){3}/ de meugler plusieurs fois ! 86

c sylvain@lhullier.org

Introduction a la programmation en Perl `

10.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 les t mots comportant soit Fred, soit Paul, soit Julie. De la mme faon, lexpression m/Fred|Paul|Julie Martin/ reconna e c 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 que cela se fasse (dans ces deux derniers e cas, seul le prnom est reconnu, pas le nom). Pour cela, vous lavez compris, e un regroupement est ncessaire. Lexpression rguli`re e e e m/(Fred|Paul|Julie) Martin/ reconna les trois fr`res et soeur de la fat e mille Martin.

10.9

Assertions

Une assertion marque une position dans lexpression, elle ne correspond a aucun caract`re (aucune consommation de caract`res nest eectue). ` e e e Par exemple, laccent circonexe (^) correspond au dbut de la cha e ne. Lexpression $v =~ m/^a/ est vraie si la variable $v commence par la lettre a. Le signe ^ a donc plusieurs rles. Sil est au dbut dun ensemble entre o e crochets, il permet den prendre le complmentaire ; sil est au dbut de e e lexpression rguli`re, il marque le dbut de la cha e e e ne. On veillera a ne pas ` les confondre. Le dollar ($) correspond a la n de la cha Lexpression $v =~ m/c$/ ` ne. est vraie si la variable $v se termine par la lettre c. Ces deux assertions sont les plus courantes. Il en existe dautres dont \b qui marque un dbut ou une n de mot ; cest-`-dire entre \w et \W e a (ou entre \w et une n ou dbut de cha e ne). Par exemple m/\btoto\b/ matche toto, toto autreMot, unMot toto autreMot, etc. mais pas unMot totoMotColl car le deuxi`me \b ne peut pas tre vrai entre la e e e lettre o et la lettre M.

10.10

Rfrences arri`res ee e

Le regroupement au moyen des parenth`ses est dit mmorisant. Cela e e signie que lexpression matche par ce regroupement est gard en mmoire e e e 87

Introduction a la programmation en Perl `

c sylvain@lhullier.org

par le moteur dexpressions rguli`res et quelle pourra servir a nouveau e e ` dans la suite de lexpression. Lexemple typique consiste a se demander si une variable contient le ` mme mot rpt deux fois. Lexpression m/\w+.*\w+/ ne saurait nous sae e ee tisfaire ; en eet elle matche toute valeur comportant deux mots pouvant tre dirents. La solution est dutiliser les notations \1, \2 etc qui font e e rfrence aux sous-cha ee nes matches par (respectivement) la premi`re, la e e deuxi`me, etc. expression entre parenth`ses (il nest pas possible daccder e e e a une expression au-del` de \9, mais cela nous donne dj` une expression ` a ea tr`s lourde a grer). e ` e Par exemple, la rponse a notre probl`me de deux occurrences dun mme e ` e e mot est la suivante : m/(\w+).*\1/ Le \w+ matchera un mot, les parenth`ses e mmoriseront la valeur alors trouve, le .* permet comme avant quil y ait e e un nombre indni de caract`res quelconques entre les deux occurrences, e e enn \1 fait rfrence a la valeur trouve par le \w+ prcdent. ee ` e e e Autre exemple basique, m/(.+), (.+), \2 et \1/ matchera une cha ne de caract`res comportant un certain premier motif suivi dune virgule et e dune espace, puis un certain second motif galement suivi dune virgule et e dune espace, puis ce second motif doit tre rpt suivi dune espace, du e e ee mot et puis dune autre espace et enn du premier motif. Ces motifs mmoriss sont aussi accessibles depuis le second membre e e 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`s que lon fait un regroupee ment, le moteur dexpressions rguli`res mmorise la valeur et si lon nutilise e e e pas certains regroupements et que dautres sont au-del` de 9, on ne peut a donc pas sen servir ... Je vais alors vous dire : il existe un regroupement non-mmorisant ! La notation (?:motifs) permet de regrouper les motifs e (pour leur appliquer le mme quanticateur par exemple) sans pour autant e quune mmorisation nait lieu. e 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 88

c sylvain@lhullier.org

Introduction a la programmation en Perl `

10.11

Variables dnies e

Ces variables spciales $1, $2 etc. sont aussi accessibles apr`s lexpression e e rguli`re (jusqu` la n du bloc courant ou une autre expression rguli`re). e e a e e Elles correspondent bien s r aux sous-cha u nes matches entre parenth`ses. e e Nous pouvons nous en servir pour extraire certaines sous-cha nes et les utiliser ensuite. Il existe aussi trois autres variables, dont je vous dconseille lusage, mais e qui peuvent tre intressantes : e e $& vaut toute la sous-cha matchant, ne $ vaut toute la sous-cha qui prc`de la sous-cha matchant, ne e e ne $ vaut toute la sous-cha qui suit la sous-cha matchant. ne ne Je vous dconseille en eet lusage de ces trois variables spciales car leur e e prsence dans un script active pour tout le script des mcanismes particuliers e e dans le moteur dexpressions rguli`res, qui ont pour eet secondaire den e e ralentir fortement la vitesse dexcution. Si vous avez besoin de ces variables e dans un petit script qui ne sert qu` cela, pas de probl`me pour les utiliser, a e mais vitez leur usage dans un projet de plusieurs milliers de lignes ou dans e un script CGI appel 10 fois par seconde. e 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.

10.12

Valeurs de retour de m//

Je vous ai dit jusquici que loprateur de correspondance m// retournait e vrai ou faux ; cela est exact en contexte scalaire. Cest par exemple le cas lorsquon crit : e if( $w =~ m/motif/ ) { ... } 89

Introduction a la programmation en Perl `

c sylvain@lhullier.org

On parle alors de correspondance. Mais en contexte de liste, cet oprateur retourne la liste des lments e ee matchs entre parenth`ses (les fameux $1, $2 etc, et cela sans limite a 9). e e ` Par exemple : ($x,$y) = ( $v =~ m/^(A+).*(B+)$/ ); place dans $x les caract`res A du dbut de la cha $v et dans $y la e e ne suite de caract`res B terminant la cha e ne. On parle ici dextraction. Il se peut tout a fait que cette opration choue (en cas dabsence des ` e e lettres aux endroits attendus par exemple). Cet usage peut tre combin e e avec lutilisation dun test. On peut en eet crire : e if( ($x,$y) = ( $v =~ m/^(A+).*(B+)$/ ) ) { ... } auquel cas, on nexcute les instructions du if que si $v comporte au e moins un A en son dbut et un B a sa n. Dans ce cas, les variables $x et $y e ` reoivent les valeurs entre parenth`ses. On a alors combin correspondance c e e et extraction.

10.13

Exemples de probl`mes e

Dans cette partie, je vais vous prsenter dirents petits exercices prae e tiques sur les expressions rguli`res. Les solutions se trouvent un peu plus e e loin. Essayez de ne pas vous prcipiter pour les lire, prenez le temps de e chercher dans ce qui prc`de ce quil vous faut pour rsoudre les probl`mes. e e e e 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/; 90

c sylvain@lhullier.org

Introduction a la programmation en Perl `

$v =~ s/^C="([^"]*)"/D=$1/; $v =~ s/ +/ /; Ecrivez les instructions ralisant les actions suivantes : e Vrier que $v comporte velo. e Vrier que $v nit par une lettre majuscule. e Vrier que $v comporte deux fois de suite un mme nombre (spares e e e e par un signe dopration mathmatique). e e Extraire de $v chacun des deux premiers caract`res. e Extraire de $v les deux premiers mots. Extraire de $v le dernier caract`re non-numrique. e e 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`ve les copies dans 30 minutes ;-))) e

10.14

Solutions des probl`mes e

Voici les solutions de la premi`re partie des probl`mes : e e if( $v =~ m/\w+ \d* ?:/ ) { ... } On vrie que $v comporte un mot dune lettre ou plus (\w+) suivi e dune espace, puis ventuellement dun nombre (\d*), puis dune ese pace optionnelle ( ?) et enn du signe deux-points. Si cest le cas, les instructions du if sont excutes. e e if( $v =~ m/^"([a-z]{4,})",/ ) { print "$1\n"; } On vrie que $v commence par un guillemet, suivi dau moins quatre e lettres minuscules (que lon mmorise), dun autre guillemet puis dune e virgule. Si la variable est du bon format, ces quatre lettres (ou plus) sont aches. e if( $v =~ m/([a-z]+)[a-z]*\1/ ) { print "$1\n"; } On recherche quelque chose de la forme : une suite de caract`res en e minuscules (au moins 1) puis une deuxi`me suite de caract`res en e e 91

Introduction a la programmation en Perl `

c sylvain@lhullier.org

minuscules (ventuellement aucun) et enn la mme suite de caract`res e e e que la premi`re suite. On cherche donc un mot (suite de lettres) dont e un certain nombre de lettres se rp`tent. Si la variable $v comporte e e un tel mot, on achera ces lettres rptes. e ee ($n,$m) = ( $v =~ m/(\w+)=(\d+)/ ); On recherche une suite alphanumrique, un signe gal puis un nombre. e e Il sagit dune aectation. La variable et le nombre sont respectivement aects aux variables $n et $m. e if( ($n,$m) = ( $v =~ m/(\w+)=(\d+)/ ) ) { print "$n $m\n"; } Si la variable $v est du format prcdemment cit, on ache la variable e e e et le nombre de laectation. $v =~ s/^ServerRoot/DocumentRoot/; On remplace ServerRoot par DocumentRoot sil est en dbut de cha e ne. $v =~ s/^C="([^"]*)"/D=$1/; On recherche en dbut de cha une sous-cha C="motif" dont motif e ne ne ne comporte pas de ". Tout cela est remplac par D=motif o` motif e u est inchang. e $v =~ s/ +/ /; Remplace dans $v la premi`re suite despaces par une seule espace. e

Voici les solutions de la seconde partie des probl`mes : e Vrier que $v comporte velo. e Pas trop dur : il sagit dun simple match. if( $v =~ m/velo/ ) { ... } Vrier que $v nit par une lettre majuscule. e Match ici aussi. Le dollar nous permet de nous accrocher en n de cha : ne if( $v =~ m/[A-Z]$/ ) { ... } Vrier que $v comporte deux fois de suite un mme nombre (spares e e e e par un signe dopration mathmatique). e e Encore un match. Nous cherchons un nombre \d+ que nous mmorisons e (parenth`ses). Un signe doit suivre (il faut dspcier le signe de la e e e division car il est aussi le sparateur de lexpression rguli`re). Finae e e lement le mme nombre quavant doit tre prsent (\1) : e e e 92

c sylvain@lhullier.org

Introduction a la programmation en Perl `

if( $v =~ m/(\d+)[+*\/-]\1/ ) { ... } Extraire de $v chacun des deux premiers caract`res. e Nous allons utiliser un match pour faire de lextraction : on se place en dbut de cha avec ^, on prend un caract`re avec . que lon e ne e mmorise, puis de la mme faon pour le deuxi`me. Vous noterez que, e e c e 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 mthode est la mme que pour lexemple prcdent. Le seul point e e e e un peu dlicat a voir, cest quentre deux mots (\w+), il doit forcement e ` y avoir des caract`res non-mot (\W+) : e ($prem,$deux) = ( $v =~ m/^\W+(\w+)\W+(\w+)/ ); Extraire de $v le dernier caract`re non-numrique. e e De la mme faon, apr`s le dernier caract`re non-numrique, il ny a e c e e e que des numriques (zro ou plus), le dollar pour se placer a la n de e e ` la cha : ne ($c) = ( $v =~ m/(\D)\d*$/ ); Remplacer dans $v rouge par bleu. Facile (seule la premi`re occurrence est remplace) : e e $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 mmorisant ce fameux nombre : e $v =~ s/"(\d+)"/$1/; Les fonctionnalits les plus importantes ont t abordes vous voila pars e ee e e pour la suite des oprations. Voici dautres fonctionnalits plus pousses et e e e donc plus intressantes. Les quanticateurs non-gourmands et surtout les e options sont des points importants. 93

Introduction a la programmation en Perl `

c sylvain@lhullier.org

10.15

Choisir son sparateur e

Il est tout a fait possible de choisir un autre caract`re que le slash (/) e comme sparateur. Il se peut par exemple que nous ayons a manipuler des e ` URL ; dans ce cas, le caract`re slash fait partie des motifs que lon est suse ceptible de rechercher ; il est de ce fait fort fastidieux de devoir dspcier e e chaque slash utilis, comme par exemple dans lexpression suivante (ici une e version simplie de lexpression rguli`re qui reconna les URL) : e e e t if( $v =~ m/http:\/\/\w+/(\w+\/)*\w\.html/ ) Il serait plus lisible de prendre un autre sparateur, le signe gal par e e exemple : if( $v =~ m=http://\w+/(\w+/)*\w\.html= ) La plupart des caract`res est utilisable comme sparateur. e e Si vous utilisez le slash comme sparateur, la lettre m nest pas obligatoire e pour faire un match : $v =~ /velo/ est quivalent a $v =~ m/velo/ e ` Libre a vous de choisir le bon sparateur, sachant que dans la grande ` e majorit des cas le slash est utilis. e e

10.16

Options

Apr`s le dernier sparateur des oprateurs de correspondance (m ou rien) e e e 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 rguli`res. Voici la liste de quelques options parmi les plus utiles : e e Loption i rend le motif insensible a la case (minuscules/majuscules) : ` lexpression rguli`re m/toto/i recherche le mot toto indiremment e e e en majuscules ou en minuscules. On aurait pu crire e m/[tT][oO][tT][oO]/ Loption g permet deectuer toutes les substitutions dans la variables. Par dfaut, loprateur s/// eectue la transformation de la premi`re e e e occurrence du motif recherch et ne va pas plus loin. Si cette option est e spcie, le moteur dexpressions rguli`res avancera dans la variable e e e e 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 ` 94

c sylvain@lhullier.org

Introduction a la programmation en Perl `

prcdents o` lexpression rguli`re ne remplaait que la premi`re oce e u e e c e currence 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 ` oprateur de fonctionner avec tat, cest-`-dire de poursuivre sa ree e a cherche en partant du dernier motif trouv. On lutilise typiquement e dans une boucle ; voyez cet exemple : my $v = "aatobbtbvvtczz"; while( $v =~ m/t./g ) { print "$&\n"; } Lachage eectu est le suivant : e to tb tc Dans une substitution, loption e value le membre de droite comme e une expression Perl, et remplace le motif trouv par la valeur de cette e expression. Par exemple : $s =~ s/(\d+)/fonction($1)/e; remplace le premier nombre trouv dans la variable $s par la valeur e de retour de la fonction applique a ce nombre. e ` Autre exemple, avec des options combines celui-l` : e a $s =~ s/0x([0-9a-f]+)/hex($1)/gei; transforme tous les nombres hexadcimaux en nombres dcimaux dans e e la variable $s. Loption o a pour eet quune seule compilation de lexpression rguli`e e re a lieu. En temps normal, a chaque fois que linterprteur Perl passe ` e sur une expression rguli`re, il la compile (pour ceux qui connaissent, e e il construit lautomate) ; avec cette option, la compilation a lieu une seule fois lors de la premi`re excution. Le principal avantage est un e e temps dexcution plus court pour le programme, si cette expression e est utilise plusieurs fois. Les inconvnients sont une place mmoire e e e occupe (inutilement si lexpression rguli`re ne sert que peu de fois) e e e 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 95

Introduction a la programmation en Perl `

c sylvain@lhullier.org

changer certains comportements sur les dbuts et ns de cha e nes. Pour les exemples qui suivent, je pose $s = "mot\nlu"; : Par dfaut : mode intermdiaire. e e Les caract`res ^ $ se positionnent en dbut/n de cha Par exemple e e ne. ($s=~m/mot$/) est faux. Le caract`re . ne matche pas \n. Par exemple ($s=~m/t.lu$/) est e faux. Avec loption s : on travaille en ligne unique. Les caract`res ^ $ se positionnent en dbut/n de cha Par exemple e e ne. ($s=~m/mot$/s) est faux. Le caract`re . peut matcher \n. Par exemple ($s=~m/t.lu$/s) est e vrai. Avec loption m : on travaille en ligne multiple. Les caract`res ^ $ se positionnent en dbut/n de ligne. Par exemple e e ($s=~m/mot$/m) est vrai. Le caract`re . ne matche pas \n. Par exemple ($s=~m/t.lu$/m) est e faux.

10.17

Quanticateurs non-gourmands

Posons-nous le probl`me suivant. Nous avons une cha de la forme e ne "s r g e y" de laquelle nous souhaitons extraire les cha nes qui sont entre guillemets. La premi`re ide est dcrire quelque chose comme : /.*/ e e e ce qui nest pas satisfaisant, car dans notre exemple la cha r g e ne serait matche. En eet, je vous avais dis que les quanticateurs consomment e le plus de caract`res possible, nous voici dans une illustration du phnom`ne. e e e 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`res possible. On parle alors de quanticateurs e non-gourmands, conomes ou frugaux. Leur notation est la mme que celle e e des quanticateurs que vous connaissez mais suivie dun point dinterrogation : Gourmand * + ? {n,m} Non gourmand *? +? ?? {n,m}?

Pour revenir a notre exemple, on peut crire /.*?/ et la correspon` e 96

c sylvain@lhullier.org

Introduction a la programmation en Perl `

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

10.18

Substitution de variables dans les motifs

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

Cela peut aussi poser des probl`mes de scurit si le programmeur ne e e e sait pas ce que peut contenir la variable substitue (par exemple si sa valeur e provient de lutilisateur). Il existe pour cela une fonction quotemeta qui prend en param`tre une cha de caract`res et renvoie cette mme cha e ne e e ne en ayant dspci les caract`res spciaux. e e e e e 97

Introduction a la programmation en Perl ` $s = "fds(ds"; $s2 = quotemeta($s); print "$s2\n"; # affiche if( $v =~ m/$s2/ ) { ... }

c sylvain@lhullier.org

fds\(ds

Pensez a toujours utiliser cette fonction lorsque vous voulez placer une ` variable dans un motif ; cela rsout bien des probl`mes. e e

10.19

Oprateur tr e

Cet oprateur ne concerne pas vraiment les expressions rguli`res, mais e e e il en est proche. Mettez de ct ce que vous venez dapprendre sur celles-ci oe pour lire la suite. tr est un oprateur de translation lettre a lettre (on parle de transe ` littration). Voici sa syntaxe : tr/chane1/chane2/ ou encore e y/chane1/chane2/ Les deux cha nes doivent tre de la mme longueur car cet oprateur va e e e remplacer la premi`re lettre de la premi`re cha par la premi`re lettre de e e ne e la seconde cha ne, la deuxi`me lettre de la premi`re cha par la deuxi`me e e ne e lettre de la seconde cha ne, etc. Cette transformation a lieu sur la variable lie ou sur $_ par dfaut. e e Voici un petit exemple : $s = "azerty"; $s =~ tr/abcde/01234/; print "$s\n"; # affiche 0z4rty Dans la variable $s, tous les a seront transforms en 0, tous les b en 1, e 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 loprateur tr. e

10.20

Un dernier mot sur les expression rguli`res e e

Les expressions rguli`res sont un outil tr`s puissant. Les ma e e e triser ouvre des portes au programmeur. Certes, il est souvent dicile de rentrer dans le jeu, mais cet eort est rcompens par de nouvelles possibilits inimaginables e e e avant. 98

c sylvain@lhullier.org

Introduction a la programmation en Perl `

Les expressions rguli`res de Perl sont si puissantes et bien penses que e e e de nombreux langages les implmentent, en se vantant dtre perl5-regexes e e 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 fonctionnalits des expressions rguli`res e e e nont pas t traites ici. Les plus courantes ou importantes le sont, mais ee e il en existe dautres encore ... Sachez de plus que les expressions rguli`res, e e cest bien, mais il faut savoir quand les utiliser et quand ne pas les utiliser.

99

Introduction a la programmation en Perl `

c sylvain@lhullier.org

100

Chapitre 11

Rfrences ee
Les rfrences permettent de btir des structures complexes et comee a poses : tableau de tableaux ou de tables de hachage et inversement, table e de hachage de tableaux ou de tables de hachage ... Le terme de rfrence en Perl correspond a peu pr`s a celui de pointeur ee ` e ` en C et C++ et a celui de rfrence en Java. Les habitus du C ou C++ ` ee e noterons que les calculs sur rfrences sont interdits en Perl, ce qui permet ee dviter toutes sortes de probl`mes dus a des acc`s mmoire errons (plus e e ` e e e de Segmentation fault). Chaque variable, quelle soit scalaire, tableau ou table de hachage, est prsente a une position donne dans la mmoire. Une rfrence vers une e ` e e ee variable est (schmatiquement) ladresse mmoire de cette variable. Une e e telle rfrence peut elle-mme tre stocke dans une variable scalaire. ee e e e

11.1

Rfrences sur scalaire ee

Loprateur qui permet de prendre la rfrence dune variable est lantie ee slash (\) : \$v est la rfrence de la variable $v ee my $refv = \$v;

Ici la variable $refv (on aurait pu choisir un tout autre nom pour cette variable) est une rfrence vers la variable $v. Une variable de type rfrence, ee ee quelque soit celui de la variable quelle rfrence (scalaire, tableau ou table ee de hachage), est un scalaire. On peut reprsenter la relation entre ces deux e variables de la faon suivante : c 101

Introduction a la programmation en Perl `

c sylvain@lhullier.org

$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 reprsente ce lien par une `che de $refv vers e e $v. Il nous est alors possible de manipuler $v au travers de $refv. La notation $$refv (donc avec deux dollars) est quivalente a $v tant que $refv e ` pointe vers $v. Autrement dit, la notation $$refv quivaut a la variable e ` scalaire pointe par la rfrence $refv. Dit de mani`re plus prosa e ee e que, on va accder a la variable quil y a au bout de la rfrence (au bout de la e ` ee `che du schma). On dit alors que lon drfrence la variable $refv. Pour e e e ee faire un parall`le avec le langage C, il sagit de lquivalent de ltoile (*) e e e applique a un pointeur. e ` Revenons sur notre exemple. Nous dclarons une variable scalaire $v que e nous initialisons. Nous dclarons ensuite une autre variable scalaire $refv a e ` laquelle on aecte ladresse de $v ; $refv est donc une rfrence sur $v : ee my $v = -43.5; my $refv = \$v; On ache la valeur de la rfrence : ee print "$refv\n"; # affiche SCALAR(0x80ff4f0)

On voit bien alors que la rfrence pointe vers une variable de type scaee laire (SCALAR) dont ladresse mmoire est ache en hexadcimal. Achons e e e maintenant la variable pointe par $refv (cest-`-dire $v ici) : e a print "$$refv\n"; # affiche -43.5

Lachage eectu est -43.5 (cest-`-dire la valeur de $v). Cette notae a tion $$refv est quivalente a $v puisque $refv est une rfrence sur $v. e ` ee Cette quivalence vaut aussi bien lorsque lon a besoin de la valeur de $v e (achage etc) que lorsque lon veut aecter une nouvelle valeur a $v : ` $$refv = 56; # affecte 56 a $v ` 102

c sylvain@lhullier.org

Introduction a la programmation en Perl `

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

Rien de bien sorcier.

11.2

Utilisation des rfrences sur scalaire ee

` A quoi peut bien servir une rfrence sur un scalaire ? Par exemple a le ee ` modier dans une fonction : sub f { my ($ref) = @_; $$ref = 0; } Cette fonction prend en argument une rfrence et aecte 0 a la variable ee ` scalaire pointe par cette rfrence. On pourrait lutiliser ainsi : e ee f( $refv ); Ce qui aurait pour eet de mettre la variable $v a la valeur 0. On pourrait ` aussi crire directement : e f( \$v ); Voici un autre exemple simple dutilisation des rfrences : ee sub f2 { my $w = 43; return \$w; } Cette fonction f2 dclare une variable locale $w et renvoie une rfrence e ee vers cette variable. Contrairement a ce quil se passe en C, ceci est tout a ` ` fait lgal et sans risque en Perl. Voici comment utiliser cette fonction : e my $reff = f2(); 103

Introduction a la programmation en Perl `

c sylvain@lhullier.org

La variable scalaire $reff devient donc une rfrence vers une variable ee 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 cre, elle na plus de nom. ee

$reff 0
En temps normal, une variable locale a une fonction est dtruite lorsque ` e lon sort de la fonction. Mais tant quil existe une rfrence vers la variable, ee elle est conserve en mmoire. Cest le garbage-collector (ramasse-miette e e ou glaneur de cellules) qui la librera lorsque plus aucune rfrence sur la e ee variable nexistera. Il faut noter que lors dun prochain appel a la fonction f2, une autre va` riable $w sera cre indpendante de la premi`re ; il ny aura donc pas deet ee e e de bord sur la premi`re rfrence renvoye. Nous sommes ici en prsence e ee e e dune fonction qui peut faire oce de gnrateur de rfrences sur scalaire e e ee ;-)

11.3

Rfrences sur tableau ee

Il est possible de crer une rfrence sur un tableau. Loprateur qui e ee e permet cela est le mme que pour les scalaires ; il sagit de lanti-slash (\) e appliqu a une variable de type tableau : e` my @t = (23, "ab", -54.4); my $reft = \@t; La variable scalaire $reft est donc une rfrence vers le tableau @t : ee

$reft @t 0 23 1 ab 2 54.4

Pour drfrencer une telle rfrence, il convient dutiliser une arobase eee ee (@) : @$reft est quivalent a @t. On peut ainsi utiliser la valeur de @t en e ` utilisant $reft : 104

c sylvain@lhullier.org

Introduction a la programmation en Perl `

my @t2 = @$reft; foreach my $e (@$reft) { .... } On peut aussi modier @t de la sorte : @$reft = (654.7, -9, "bonjour"); Si, pour accder au i`me lment de @t, il tait possible dcrire $t[i], il e e ee e e est maintenant possible dcrire $$reft[i]. On peut alors dire, de mani`re e e schmatique et pour xer les choses, que la notation $reft est quivalente e e au nom t de la variable dans toute les syntaxes utilisant ce tableau (partout o` lon peut crire t, on peut crire $reft a la place, tant que $reft pointe u e e ` sur @t). Voici, en eet, un rcapitulatif des quivalences de notations : e e Tableau t @t $t[i] $t[i] Rfrence ee $reft @$reft $$reft[i] $reft->[i]

Cette derni`re notation $reft->[i] est quivalente a $$reft[i] et core e ` respond donc au i`me lment du tableau rfrenc par $reft. Cest la e ee ee e notation la plus souvent utilise pour cela ; elle rappelle la mme notation e e `che (->) du langage C. e Lexpression $reft->[1] = "coucou"; aecte donc a llment dindice 1 du tableau point par $reft une ` ee e nouvelle valeur. Munis des rfrences, il va maintenant nous tre possible de crer des ee e e tableaux de tableaux. Cela tait pour le moment impossible en raison de e laplatissement des listes. Une rfrence tant un scalaire, il va nous tre ee e e possible de stocker une rfrence comme valeur dans un tableau : ee my @t1 = ( 16, -33 ); my @t2 = ( "el", 0.3, 4 ); my @t = ( 6, \@t1, \@t2, "s" ); Le tableau @t comporte donc un premier lment valant 6, un deuxi`me ee e tant une rfrence vers un tableau a deux lments, un troisi`me une e ee ` ee e rfrence vers un tableau a trois lments et enn un lment valant la ee ` ee ee cha "s". ne Ce qui peut se reprsenter sous la forme suivante : e 105

Introduction a la programmation en Perl `

c sylvain@lhullier.org

@t 0 6 1 2 3 s

el

0.3

16

33

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

11.4

Rfrences sur table de hachage ee

De la mme faon que pour les scalaires et pour les tableaux, la cration e c e dune rfrence vers une table de hachage utilise loprateur anti-slash (\) : ee e my %h = ( Paul => 21, Julie => 19 ); my $refh = \%h; La variable scalaire $refh est donc une rfrence vers la table de hachage ee %h :

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

106

c sylvain@lhullier.org

Introduction a la programmation en Perl `

Pour drfrencer une rfrence vers une table de hachage, il faut utiliser eee ee le caract`re pourcentage (%) ; %$refh est quivalent a %h : e e ` my %h2 = %$refh; foreach my $k (keys %$refh) { ... } Les deux notations suivantes permettent daccder a la valeur associe a e ` e ` la clef Paul : $$refh{Paul} et $refh->{Paul} sachant que la seconde est la plus utilise pour des raisons identiques aux cas des tableaux. e $refh->{Jacques} = 33; Voici un rcapitulatif des quivalences : e e Hash h %h $h{Paul} $h{Paul} Rfrence ee $refh %$refh $$refh{Paul} $refh->{Paul}

Voici une faon dacher tous les couples clef/valeur de la table de hac chage rfrence par $refh : ee e foreach my $k (keys %$refh) { print "$k $refh->{$k}\n"; } Cette notation `che rend lexpression plutt lisible. e o

11.5

Rexions ` propos des rfrences e a ee

On a vu que pour drfrencer une rfrence vers un scalaire on utilise eee ee le caract`re dollar ($), vers un tableau le caract`re arobase (@) et vers une e e table de hachage le caract`re pourcentage (%). Mais que se passerait-il sil e nous venait a lide de ne pas choisir le bon caract`re de drfrencement, ` e e eee par exemple dutiliser le dollar pour une rfrence sur tableau ou bien le ee pourcentage pour une rfrence sur scalaire ? Narriverons-nous pas a des ee ` incohrences comme en C ? e La rponse est non, car linterprteur veille au grain. Il refusera de e e considrer comme un tableau une variable scalaire par exemple. En cas dine compatibilit de type, un de ces trois messages sera ach lors de lexcution e e e et le programme prendra n : 107

Introduction a la programmation en Perl ` 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.

c sylvain@lhullier.org

Comme une rfrence peut pointer vers nimporte quel type de structure ee (scalaire, tableau, table de hachage), cette vrication ne peut avoir lieu e quau moment de lexcution. e De plus, les habitus du langage C seront invits a se mettre une bonne e e ` fois pour toute dans la tte :-) quil ny a pas darithmtique possible sur les e e rfrences en Perl. Ajouter 1 a une rfrence ne correspond pas a pointer vers ee ` ee ` llment dindice 1 dun tableau, mais a faire perdre le caract`re rfrence ee ` e ee a la variable (elle devient un scalaire comme un autre) : ` 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`re spcique de e e rfrence ; elle a toujours pour valeur ladresse de la variable (ici incrmente ee e e de 1 : 80fd4c4 est la reprsentation hexadcimale du nombre 135255236), e e mais nest plus une rfrence, il sera donc impossible de la drfrencer. ee eee Notez aussi quune rfrence peut changer de valeur, cest-`-dire de vaee a riable pointe et donc de type de variable pointe : e e 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`re chose importante, si vous passez une rfrence a une fonction, e ee ` vous devez bien voir que la copie de la seule rfrence est eectue, la strucee e ture pointe par la rfrence ne lest pas ; vous pourrez donc la modier dans e ee la fonction : sub f3 { my ($reftab) = @_; 108

c sylvain@lhullier.org

Introduction a la programmation en Perl `

$reftab->[2] = 32.3; } my @t = ( 49, "hello", -2 ); my $r = \@t; f3( $r ); f3( \@t ); # equivalent # @t est modifi e On peut schmatiser ce quil se passe de la mani`re suivante : e e

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

$reftab

Visibilit de la fonction f3
Les deux rfrences pointent donc vers la mme zone mmoire. ee e e

11.6

Rfrences anonymes vers scalaire ee

Une rfrence anonyme est une rfrence vers une variable qui na pas ee ee de nom. Nous avons dj` vu comment faire cela pour un scalaire avec une ea fonction (fonction f2 un peu avant), mais cela nest pas la faon de faire la c plus simple. La syntaxe pour crer directement une rfrence anonyme vers un scae ee laire est la suivante : \valeur-constante my $ref1 = \34; my $ref2 = \"er"; print "$$ref1 $$ref2\n"; 109

Introduction a la programmation en Perl `

c sylvain@lhullier.org

$ref1 34 $ref2 er
Une telle valeur est une constante, il est impossible de modier la valeur pointe par la rfrence (dirence avec le mcanisme de la fonction f2) : e ee e e $$ref1 = "hello"; Modification of a read-only value attempted at script.pl line 24. Ce nest pas dans le cas des scalaires que les rfrences anonymes sont ee les plus utilises ; elles le sont bien plus avec les tableaux et les tables de e hachage.

11.7

Rfrences anonymes vers tableau ee

Pour crer une rfrence anonyme vers un tableau, il faut utiliser la e ee notation suivante : [lment1, lment2, lment3, etc] est une rfrence ee ee ee ee vers un tableau comportant les lments en question. ee my $r = [ 34.4, "ac", -71 ]; my @t = ( 34.4, "ac", -71 ); La variable $r est une rfrence vers un tableau comportant trois lments ee ee alors que la variable @t est un tableau a trois lments (cette derni`re nota` ee e tion nous est dj` famili`re) : ea e

$r 0 34.4 1 ac 2 71

@t 0 34.4

ac

71

110

c sylvain@lhullier.org

Introduction a la programmation en Perl `

On acc`de aux lments de cette rfrence anonyme comme pour une e ee ee rfrence normale : ee print "$r->[0]\n"; $r->[2] = 901; foreach my $e (@$r) { ... } Attention a ne pas crire \(2,"er",$v) si vous voulez crer une rfrence ` e e ee vers un tableau, car cette syntaxe fait toute autre chose : elle est en fait quivalente a (\2,\"er",\$v), donc a une liste de rfrences, ce qui est fort e ` ` ee dirent. e Le structure prcdemment dcrite par e e e my @t1 = ( 16, -33 ); my @t2 = ( "el", 0.3, 4 ); my @t = ( 6, \@t1, \@t2, "s" ); peut donc scrire de la mani`re suivante : e e my @t = ( 6, [ 16, -33 ], [ "el", 0.3, 4 ], "s" ); Ce qui peut se reprsenter toujours sous la forme suivante : e

@t 0 6 1 2 3 s

el

0.3

16

33

On peut pousser le vice jusqu` utiliser une rfrence pour le premier a ee tableau : 111

Introduction a la programmation en Perl ` my $r = [ 6, [ 16, -33 ], [ "el", 0.3, 4 ], "s" ];

c sylvain@lhullier.org

$r

el

0.3

16

33

Comment accder aux lments des direntes profondeurs dune telle e ee e construction ? Il sut de suivre les rfrences ... ee print "$r->[0]\n"; # affiche 6 # $r->[1] est une rfrence vers tableau e e print "$r->[1]->[0]\n"; # affiche 16 print "$r->[1]->[1]\n"; # affiche -33 # $r->[2] est une rfrence vers tableau e e 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 pour peu que nous ayons un bon t schma sous la main ... Vous noterez que nous faisons usage de loprateur e e `che (->) plutt que de la syntaxe double-dollar ($$). e o De plus, si $r->[1] est une rfrence vers tableau, @{$r->[1]} est le ee tableau en question. On peut donc crire : e foreach my $e ( @{$r->[1]} ) { ... } # Parcourt 16 et -33

Il faut noter quen cas de drfrencements successifs, seule la premi`re eee e `che est ncessaire : $r->[2][1] est quivalent a $r->[2]->[1]. e e e ` 112

c sylvain@lhullier.org

Introduction a la programmation en Perl `

11.8

Rfrences anonymes vers table de hachage ee

De la mme faon il est possible de crer une rfrence anonyme vers une e c e ee table de hachage. La notation {clef1=>valeur1, clef2=>valeur2, etc} est une rfrence vers une table de hachage comportant les couples clef/valeur en ee question. my $r = { Paul Julie my %h = ( Paul Julie => => => => 21, "e" }; 21, "e" );

La variable $r est une rfrence vers une table de hachage alors que la ee variable %h est une table de hachage (notation famili`re) : e

$r Julie Paul => => e 21

%h Julie Paul => => e 21

De la mme faon quavec des tableaux, nous allons mettre sur pied des e c 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 }; 113

Introduction a la programmation en Perl ` Ou plus directement : my $r = { Paul => { rue tel Julie => { rue tel };

c sylvain@lhullier.org

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

$r

Julie Paul

=> =>

rue tel

=>

Jaures

=> 03729103

tel rue

=> 06461341 => Pasteur

Voici comment accder a tous les lments dune telle construction : e ` ee # $r->{Paul} est une rfrence vers une table de hachage e e print "$r->{Paul}->{tel}\n"; # affiche 06461341 114

c sylvain@lhullier.org

Introduction a la programmation en Perl `

print "$r->{Paul}{tel}\n"; # equivalent print "$r->{Paul}{rue}\n"; # affiche Pasteur # $r->{Julie} est une rfrence vers une table de hachage e e print "$r->{Julie}{tel}\n"; # affiche 03729103 print "$r->{Julie}{rue}\n"; # affiche Jaures

Il sut de suivre sur le schma, do` limportance de faire un bon schma. e u e

11.9

Rfrences anonymes diverses ee

Il est bient-s r tout a fait possible de mlanger les rfrences vers les u ` e ee tableaux et vers les tables de hachage :

my $r = [ [a,4], b, [1,z], {P=>[-2,"er",0],A=>7}, 8 ];

Voici le schma correspondant a cette structure (essayer de vous en e ` convaincre !) : 115

Introduction a la programmation en Perl `

c sylvain@lhullier.org

$r

A P

=> =>

er

Voici comment accder a un lment dune telle structure : e ` ee 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 acco` lades a la clef dune table de hachage. ` Je peux parcourir le premier tableau du deuxi`me niveau (celui qui come porte a et 4) de la mani`re suivante : e my $reft = $r->[0]; foreach my $v (@$reft) { print "$v\n; } Je cre une variable $reft qui est une rfrence vers ce tableau, je peux e ee ensuite parcourir @$reft qui reprsente le tableau en question. e 116

c sylvain@lhullier.org

Introduction a la programmation en Perl `

Il est possible dcrire cela sans crer de variable temporaire, la syntaxe e e est la suivante : @{rfrence} Ces accolades nont rien a voir avec les tables ee ` de hachage elles permettent juste de dlimiter la rfrence a laquelle on e ee ` applique larobase. Voici ce que cela donne : foreach my $v (@{$r->[0]}) { print "$v\n"; } On fait de la mme faon pour un table de hachage, les accolades dlimitent e c e la rfrence a laquelle on applique le pourcentage : ee ` foreach my $k (keys %{$r->[3]}) { print "$k $r->[3]{$k}\n"; } Commencez-vous a voir lintret de faire des schmas ? ` e e

11.10

Loprateur ref e

La question qui pourrait maintenant venir a lesprit est la suivante : ` comment pourrait-on crire une boucle sur les lments du tableau rfrenc e ee ee e par $r et surtout comment savoir de quel type ils sont pour pouvoir les utiliser ? Pour rpondre a cette question, voici un nouvel oprateur : ref(). e ` e Il permet de conna le type dune rfrence. tre ee Cette fonction renvoie : "SCALAR" si son argument est une rfrence sur scalaire, ee "ARRAY" si son argument est une rfrence sur tableau, ee "HASH" si son argument est une rfrence sur table de hachage, ee faux si son argument nest pas une rfrence (cest un scalaire clasee sique). On peut alors crire le code suivant : e foreach my $p (@$r) { if( ref($p) eq "ARRAY" ) { print "( "; 117

Introduction a la programmation en Perl ` 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 ( b ( P A 8 a 4 ) 1 z ) : ARRAY(0x8100c20) : 7

c sylvain@lhullier.org

Dans cet exemple, un seul premier niveau de rfrences est explor. Pour ee e aller au-del`, cest-`-dire, acher le tableau associ a la clef P, il faudrait a a e ` concevoir un ensemble de fonctions sappelant les unes les autres en fonction du type des rfrences rencontres. Ne vous fatiguez pas a les crire, il existe ee e ` e dj` une telle fonctionnalit en Perl : ea e use Data::Dumper; print Dumper($r); La premi`re ligne ajoute des fonctions a Perl (cest un peu le #include du e ` langage C) et ne doit donc tre prsente quune seule fois dans le programme e e (plutt au dbut). La seconde consiste en lachage de la valeur de retour de o e la fonction Dumper : cette fonction renvoie une (longue) cha de caract`res ne e reprsentant toute la structure rfrence par $r : e ee e $VAR1 = [ [ 118

c sylvain@lhullier.org

Introduction a la programmation en Perl `

a, 4 ], b, [ 1, z ], { P => [ -2, er, 0 ], A => 7 }, 8 ];

Vous noterez que lachage eectu est directement intgrable dans un e e code Perl.

11.11

Rfrences circulaires ee

La notion de rfrence circulaire na rien de compliqu ; cest juste le fait ee e que plusieurs tableaux et/ou tables de hachage et/ou scalaires peuvent se rfrencer entre elles. Par exemple : ee 119

Introduction a la programmation en Perl `

c sylvain@lhullier.org

$r

71

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

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

c sylvain@lhullier.org

Introduction a la programmation en Perl `

{ Ptt => { R5 => As4, Od => $VAR1 }, Hello => -34.7 } ]; Data::Dumper se rend compte quil passe sur une rfrence quil a dj` ee ea parcourue et lache comme telle ($VAR1). Pourquoi vous parler de rfrences circulaires ? Premi`rement parce quil ee e faut savoir quil est possible den faire (cela peut tre utile de crer des listes e e cha ees circulaires etc). Mais surtout parce quelles posent des probl`mes n e ` la suite a au garbage-collector dans sa tche de libration de la mmoire. A a e e ` lexemple prcdent, je pourrais crire : e e e $r = undef; En temps normal, tout ce que $r rfrenait serait libr. Mais ici, ce ee c ee nest pas le cas. En eet, chacun des tableaux et des tables de hachage ont encore au moins une rfrence vers elle, le garbage-collector ne se rend ee pas compte, quen fait, les trois objets peuvent tre librs. Nous sommes e ee donc en prsence de zones mmoires inaccessibles (aucune variable ne nous e e permet dy accder) et non librables : cette mmoire est perdue pour le e e e programme ! Elle sera bien s r libre quand le programme prendra n, u ee mais sil sagit dun dmon qui tourne en permanence, cette fuite mmoire e e nest pas forcment a ngliger. e ` e La solution pour viter cela est de casser la circularit avant de modie e er la valeur de la variable $r : $r->[1] = undef; Je viens de casser le lien indiqu par un astrisque, il ny a plus de boucle e e dans les rfrences. Maintenant et seulement maintenant, je puis sans risque ee crire : e $r = undef; Et la mmoire sera libre ... e ee 121

Introduction a la programmation en Perl `

c sylvain@lhullier.org

11.12

Rfrences sur chiers ee

Une ouverture de chier cre une variable dont il est possible de prendre e ladresse. Voici la syntaxe pour cela : open(FILE,">toto") or die("$!"); my $reff = \*FILE; La variable scalaire $reff est une rfrence vers le descripteur de chier ee FILE. Il nous est aussi possible de crer une rfrence vers un des trois chiers e ee pr-existant : e my $refo = \*STDOUT; Voici des exemples dutilisation de ces rfrences : ee open(FILE,">toto") or die("$!"); my $reff = \*FILE; print $reff "ok\n"; sub affiche { my ($ref) = @_; print $ref "ok\n"; } affiche( $reff ); affiche( \*FILE ); # equivalent close( $reff ); Cette derni`re ligne est quivalente a close(FILE); On peut sans rese e ` trictions stocker une rfrence vers chier dans une table de hachage ou dans ee un tableau.

11.13

Rfrences sur fonctions ee

Comme dans le langage C, une fonction a elle-aussi une adresse mmoire. e Cette adresse correspond a lendroit de la mmoire o` le code de la fonction ` e u est stock. On peut obtenir une rfrence vers une fonction de la mani`re e ee e suivante : sub affcoucou { 122

c sylvain@lhullier.org

Introduction a la programmation en Perl `

my ($p) = @_; print "Coucou $p\n"; } my $ref = \&affcoucou; La variable scalaire $ref est une rfrence vers la fonction affcoucou. ee Elle peut sutiliser des faons suivantes : c &$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 rfrence ` ee dans un tableau ou dans une table de hachage ...

11.14

Un dernier mot sur les rfrences ee

De telles structures nous donnent envie de faire de la programmation objet (champs et mthodes pourraient tre stockes dans une table de hae e e chage). Nallons pas trop vite car Perl a t prvu pour la programmation ee e objet et propose les fonctionnalits ncessaires (hritage ...) en se basant sur e e e les modules.

123

Introduction a la programmation en Perl `

c sylvain@lhullier.org

124

Chapitre 12

Utilisation de modules
Nous allons aborder ici lusage des modules, cest-`-dire de biblioth`ques a e ou encore librairies. Perl tire sa puissance de la richesse des modules existants ; peu dautres langages (voire aucun) ne peuvent prtendre tre aussi e e riche que Perl. Par exemple, quasiment tous les protocoles rseau auxquels e vous pouvez penser sont accessibles en Perl en utilisant un module existant. En quelques mots, un module est un ensemble de fonctions regroupes e dans un chier. Ces fonctions y sont regroupes car elles touchent toutes e a un mme domaine, a un mme ensemble de fonctionnalits autour dune ` e ` e e mme utilisation, dun mme protocole ... e e La premi`re chose que je vous invite a faire, cest a lancer la commande e ` ` perl -V : elle ache toute sorte dinformations, dont le contenu de la variable @INC. Cette variable de type tableau contient la liste des rpertoires e o` seront recherchs les modules. Le nom INC rappelle trangement (et cest u e e voulu) la notion dinclude en C. Lordre des rpertoires de cette variable est e important car si un module vient a tre prsent dans deux rpertoires, seule `e e e loccurrence prsente dans le premier rpertoire de la liste comptera (mais e e ce cas proviendrait plutt dune erreur de nommage ou dinstallation). o

12.1

Utilisation dun premier module

Il existe de nombreux modules dj` installs sur votre syst`me ; une ea e e distribution de Perl inclut les modules les plus utiliss. e Ainsi, le module nomm Math::Trig ; permet daccder a des fonce e ` tions mathmatiques de trigonomtrie autres que les seuls cosinus et sinus e e prdnis dans Perl sous les noms de cos et sin. e e Je vous invite a taper la commande perldoc Math::Trig dans un termi` 125

Introduction a la programmation en Perl `

c sylvain@lhullier.org

nal ; vous visualiserez ainsi la documentation de ce module. Cette commande perldoc fonctionne un peu comme la commande man ; vous verrez dtailles e e les fonctionnalits auxquelles vous avez acc`s avec un module donn. Vous e e e taperez q pour quitter. On voit ici que nous avons acc`s a des fonctions comme tan, acos ou e ` asin ainsi qu` des fonctions de conversion entre units dangles ou bien a e a la valeur de pi. De petits exemples simples dutilisations vous sont aussi ` fournis. La premi`re ligne de code a crire pour utiliser un module est la suivante : e `e use NomDuModule; 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 tre place dans chaque script qui fait usage du module e e et tre excute avant tout usage de fonctions ou de variables du module. e e e Typiquement toutes les lignes use sont regroupes au dbut du script. e e Vous remarquerez que la ligne use strict; que je vous ai conseill de e placer dans chaque script, nest en fait que le chargement dun module ; ce module ayant pour rle de rendre la syntaxe Perl plus coercitive. Le nom des o modules de ce type est en minuscule. Ils sont appels modules pragmatiques. e Ils ont pour objet de modier ou dtendre la smantique de Perl. Ainsi e e 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 franais). c 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 plutt comprendre) ce que font o ces instructions. Une fois charg, un module nest pas dchargeable. e e 126

c sylvain@lhullier.org

Introduction a la programmation en Perl `

12.2

Dautres modules

Voici lexemple dun autre module : File::Copy ; il permet certaines manipulations de chiers lourdes a mettre en uvre avec de simples ap` pels syst`me. Il est par exemple possible de copier un chier vers un autre e (chiers disque ou ux de donnes), ou den dplacer un dune partition e e vers une autre (impossible avec lappel syst`me rename). Comme lindique e 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 daccder tr`s simplement aux fonctionnalits dun client e e e FTP. Voici, par exemple, comment se connecter sur un serveur (en mode passif, car jai un rewall), changer de rpertoire et tlcharger un chier : e ee #!/usr/bin/perl -w use strict; 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. Mme si nous ne verrons la programmation objet que e dans une prochaine partie, il est ais de comprendre comment utiliser de e tels modules (de toute faon la documentation des modules comporte des c 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 ` modies depuis la derni`re fois ? ? ? e e

12.3

O` trouver les modules ? u

Cest tr`s bien tout cela, mais comment trouver le module qui rpond e e a mon probl`me ? Pour cela je dois vous prsenter larchive de tous les mo` e e 127

Introduction a la programmation en Perl `

c sylvain@lhullier.org

dules Perl, jai nomm CPAN (Comprehensive Perl Archive Network). Cette e archive recense tous les modules diuss pour Perl. e Je vous invite a visiter le site http://www.cpan.org/ vous y trouverez de ` tout a propos de Perl. Vous pouvez tlcharger les sources de linterprteur ` ee e (Perl source code), des versions compiles (Perl binary distributions) dispoe nibles pour de tr`s nombreuses plate-formes, ainsi que de la documentation e sur les modules et de quoi les tlcharger. Le lien intressant est : CPAN ee e modules, distributions, and authors (search.cpan.org). Une page vous est propose avec de nombreuses sections listant des modules regroups par th`me, e e e 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 varit des modules qui ` ` ee gravitent autour de ce protocole ; le module le plus intressant est s rement e u Net::SMTP (plus le nom dun module est court et semble canonique, plus il y a de chance quil soit intressant). Dirents liens permettent de visualie e ser la documentation (le perldoc correspondant) ainsi que de tlcharger le ee module le cas chant. e e 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`s. Les modules CPAN sont prsents sous forme de package e e dans toute bonne distribution Linux. Par exemple sous Debian, il sagit des paquets libxxx-yyy-perl (o` xxx-yyy correspond au nom du module u Xxx::Yyy mis en minuscules). Mme si vous ninstallez pas de module, CPAN nen reste pas moins e la source majeure dinformations sur les modules de votre syst`me. Vous e vous rendez par exemple compte que le module Net::SMTP rpond a vos e ` besoins, vous vriez alors que ce module est prsent sur votre syst`me en e e e tapant perl -e use Net::SMTP et vous navez plus qu` lutiliser. La a documentation sera accessible par perldoc Net::SMTP Juste pour sourire deux minutes, je vous invite a rechercher dans CPAN ` un module nomm Sex crit un premier avril et den lire la documentation e e (ainsi que le code) ...

128

Chapitre 13

Ecrire un module
Apr`s avoir manipul des modules existants et avoir parl de CPAN, e e e nous allons maintenant apprendre a crire nos propres modules. `e

13.1

Premier exemple

Pour crire un module, nous devons crer un chier indpendant du ou e e e des scripts qui lutilisent. Lextension de ce chier est imprativement .pm : e par exemple Utils.pm Ce chier doit tre plac dans un des rpertoires e e e lists dans la variable @INC ; pour commencer vous pourriez le placer dans e votre rpertoire de travail a ct du script qui lutilisera, car le rpertoire . e ` oe e est prsent dans ce tableau @INC. e Ce chier doit contenir une premi`re ligne indiquant le nom du module ; e pour cela, vous devez crire : e package Utils; Il est important de voir que le nom du package doit tre le mme que celui e e du chier (` lextension pr`s). Le chier peut ensuite contenir des dnitions a e e 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"; 129

Introduction a la programmation en Perl ` } 1;

c sylvain@lhullier.org

Il est important de ne pas oublier la derni`re ligne, celle qui contient 1; ; e nous reviendrons plus tard sur son rle. o Pour pouvoir utiliser ce module dans un script, il est ncessaire dine voquer linstruction use suivie du nom du module. Voici un exemple de lutilisation du module prcdent : e e #!/usr/bin/perl -w # --- fichier script.pl --use strict; use Utils; # chargement du module Utils::bonjour( "Paul" ); La derni`re ligne correspond a lappel de la fonction bonjour du module e ` Utils. La syntaxe est la suivante : le nom du module est suivi de deux signes deux-points puis du nom de la fonction.

13.2

Et les variables ?

Il est possible de dclarer des variables propres au module. Ces variables e seront : soit accessibles exclusivement aux fonctions prsentes dans le module e (on pourrait parler de variables prives, correspondant aux variables e static dclares en dehors des fonctions en C), e e soit aussi accessibles a lextrieur du module (on pourrait parler de ` e variables publiques ou variables globales). Une variable accessible exclusivement aux fonctions du module se dclare e avec my (que lon conna dj`). Une variable aussi accessible depuis lextrieur t e a e du module se dclare avec our (my pour dire ` moi, our pour dire ` e a a nous). Avant la version 5.6 de Perl, on utilisait un autre mcanisme dont e je ne parlerai pas ici, assurez-vous davoir une version rcente de Perl (cf e perl -v). Ces variables doivent tre dclares en dehors de toute fonction ; e e e les variables dclares dans les fonctions sont comme toujours locales au bloc e e dans lequel elles sont dclares. e e # --- fichier Utils.pm --package Utils; use strict; 130

c sylvain@lhullier.org

Introduction a la programmation en Perl `

# 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 dclare avec my ou avec our, il est tout a fait possible e e ` ` dy accder depuis une fonction du module (ici bonjour). A linverse, depuis e lextrieur du module, cest-`-dire depuis le script, seule la variable $x est e a 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 mme que pour les fonctions, les noms de variable sont prxs par e e e le nom du module puis deux signes deux-points. Ici, le nom complet de la variable est donc Utils::x quil faut faire prcder dun signe dollar, ce qui e e donne : $Utils::x au nal. Il ny a pas derreur de ma part : on ncrit pas e Utils::$x ! :-)

13.3

De la derni`re ligne dun module e

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

Introduction a la programmation en Perl `

c sylvain@lhullier.org

module (valeur de linstruction use Utils;) et quelle indique si ce chargement sest bien pass ou non : une valeur fausse indique un probl`me, une e e valeur vraie (comme ici 1) indique au contraire que le chargement sest bien droul. Une valeur fausse mettra n au script qui fait appel a linstruction e e ` 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`re inse truction pour vrier si les conditions sont runies pour lusage du module. e e On pourrait imaginer conditionner le chargement du module a louverture ` dun chier, dune connexion rseau (ou je-ne-sais-quoi encore...). Je ne done nerai pas dexemple ici car le cas est rare de la ncessit dun tel usage, mais e e il faut savoir que cela est possible.

13.4

Rpertoires e

Voyons maintenant comment crer des modules aux noms composs e e comme Truc::Utils (nous avons par exemple vu le module Net::FTP). Ces noms composs permettent de regrouper les modules par type dusages ; par e exemple Net correspond a tout ce qui concerne le rseau. ` e Revenons a notre exemple Truc::Utils. Ce nom Truc correspond a un ` ` rpertoire qui doit tre prsent dans un des rpertoires de la variable @INC e e e e (par exemple .) et le chier Utils.pm doit tre prsent dans ce rpertoire e e e 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 --132

c sylvain@lhullier.org

Introduction a la programmation en Perl `

use strict; use Truc::Utils; Truc::Utils::bonjour( "Paul" ); print "$Truc::Utils::x\n"; Rien de sorcier.

13.5

Blocs BEGIN et END

Les amoureux de awk retrouveront ici deux de leurs enfants prfrs eee :-)). Dans un module, il est possible de prvoir deux blocs dinstructions e qui seront excuts soit d`s le chargement du module (bloc BEGIN) soit lors e e e de la n de lusage du module (bloc END). 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 labliss. Le bloc BEGIN sera excut lors de linstruction e e e e use Utils; avant toute autre instruction du module (y compris les use placs dans le module). Le bloc END sera excut lors de la n du programme. e e e Lusage de ces deux blocs peut tre ncessaire lorsque lutilisation du e e module est conditionne par lobtention dune ou plusieurs ressources comme e un chier ou une connexion rseau. Ces blocs vont nous servir a prparer le e ` e terrain au dbut et a librer les ressources a la n. e ` e ` Lorsque dans un module sont prsentes dautres instructions que des e dnitions de variables et des dnitions de fonctions, ces instructions sont e e excutes au moment du chargement du module. Tout se passe comme si e e 133

Introduction a la programmation en Perl `

c sylvain@lhullier.org

ces instructions gurent dans un BEGIN implicite. Lusage dun bloc BEGIN permet juste au programmeur dcrire un code un peu plus lisible et e propre, dans la mesure o` toutes ces instructions sont regroupes sous un u e nom (BEGIN) qui rappelle explicitement quelles sont excutes au dbut. e e e Notez bien que la programmation objet (lire la suite) a quelque peu rendu ces deux blocs obsol`tes voire inutiles. e

13.6

Introduction ` lexport de symboles a

Sous ce titre barbare se cache une ide simple : il peut tre pnible de e e e toujours crire le nom complet des fonctions de modules. Je veux dire par e l` que dcrire Utils::bonjour a chaque fois que vous voulez appeler cette a e ` fonction est sans doute lourd et est quelque peu pnible a la longue. Il existe e ` un moyen pour navoir qua crire bonjour sans avoir a rappeler le nom e ` 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 dexporter des symboles, notre module future exportateur doit comporter les lignes suivantes : package Utils; use Exporter; our @ISA = qw(Exporter); Ces deux nouvelles lignes dinstructions doivent tre places juste apr`s e e e linstruction package. La premi`re est linvocation du module Exporter ; e 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 exports pas dfaut : le script utilisant le module na e e rien besoin de faire de spcial (autre que de faire le use) pour que ces e symboles soient exports, e 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, 134

c sylvain@lhullier.org

Introduction a la programmation en Perl `

ceux qui ne sont pas exportables (cest-`-dire quil faudra toujours a faire prcder leur nom par le nom complet du module). e e Chacun des trois premiers ensembles est associ a une variable dclare e` e e avec our.

13.7

Export par dfaut de symboles e

Les symboles exports par dfaut doivent tre lists dans la variable e e e e @EXPORT ; il sagit donc dun tableau. Il est courant dinitialiser ce tableau avec loprateur qw que nous avons dj` vu et sur lequel je ne reviendrai e ea donc pas : our @EXPORT = qw(&bonjour &hello $var); Cette ligne place dans le module Utils a la suite de la ligne e ` our @ISA = qw(Exporter); va permettre dutiliser les fonctions bonjour et hello ainsi que la variable scalaire $var sans prxe dans le script utilisateur. Notez bien que, si e les variables doivent tre cites avec leur caract`re de direntiation de type e e e e (le dollar, larobase ou le pourcentage), il en est de mme avec les fonctions e et le signe et-commercial (&). Sachez juste que ce et-commercial peut tre e omis. Voici comment on peut maintenant utiliser le module en question : use Utils; bonjour("Paul"); hello("Peter"); print "$var\n"; Plutt simple. o

13.8

Export individuel de symboles

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

Introduction a la programmation en Perl ` our @EXPORT_OK = qw(&gutenTag &ciao $var2);

c sylvain@lhullier.org

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 demands et ces derniers sont e donc utilisables sans prxe. e Il se trouve quune telle ligne nimporte plus les symboles par dfaut e (ceux de la variable @EXPORT) ; ne me demandez pas pourquoi, je trouve cela aussi stupide que vous ... Pour remdier a cela, il nous faut ajouter a la liste e ` ` des imports le tag :DEFAULT : use Utils qw(:DEFAULT &ciao $var2); bonjour("Paul"); hello("Peter"); print "$var\n"; ciao("Paula"); print "$var2\n"; Ce mcanisme de slection des symboles exports permet a lutilisateur e e e ` du module de ne pas trop polluer son espace de nommage et de choisir les seules fonctions dont il aura besoin.

13.9

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 ici en jeu est %EXPORT_TAGS ; il sagit ` donc dune table de hachage. A chaque tag est associe une rfrence vers e ee un tableau contenant la liste des symboles du tag : our %EXPORT_TAGS=(T1=>[qw(&ciao &gutenTag)], T2=>[qw(&ciao $var2)]); 136

c sylvain@lhullier.org

Introduction a la programmation en Perl `

Le tag T1 est associ aux fonctions ciao et gutenTag. Le tag T2 est e associ a la fonction ciao et a la variable $var2. Le nom des tags est par e ` ` convention en majuscules. Remarque importante : les symboles prsents dans les listes associes e e aux tags doivent absolument tre prsents dans @EXPORT et/ou @EXPORT_OK. e e 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 dans la liste des modules prcd par le signe e e e e deux-points. Il est possible de combiner les dirents types dacc`s : e e 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.

13.10

Exemple complet dexports

Voici un exemple complet dusage des exports dans les modules ; jai essay de regrouper toutes les congurations. e 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"; } 137

Introduction a la programmation en Perl ` sub sub sub sub sub 1; f2 f3 f4 f5 f6 { { { { { print print print print print "f2\n"; "f3\n"; "f4\n"; "f5\n"; "f6\n"; } } } } }

c sylvain@lhullier.org

Et voici un script lutilisant (apr`s chaque appel de fonction est signale e e la raison qui fait quil est possible de lappeler sans prxe) : e #!/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 importe e f6(); # tag T2 Notez bien le cas de la fonction f5 qui nest pas importe, mais qui nen e reste pas moins utilisable. Pour plus dinformations et dexemples je vous invite a vous rfrer a ` ee ` perldoc Exporter.

13.11

Fonctions inaccessibles

Vous allez me poser la question suivante : comment faire pour rendre une fonction dun module inaccessible depuis le script ? Et je vous rpondrai : e cela nest a priori pas possible (vous allez voir que si nalement). Vous lavez compris, Perl nest pas un langage extrmement coercitif, e notamment par rapport a des langages comme Java ou C++. Il ny a donc ` rien de prvu dans le langage pour rendre certaines fonctions uniquement e accessibles depuis lintrieur du module. Est alors apparue la convention e suivante : toute fonction ou variable dont le nom commence par un soulign e (ou under-score _) est prive et ne doit pas tre utilise a lextrieur du e e e ` e module. Cette conance en lutilisateur du module est souvent susante et les modules CPAN sont btis sur ce mod`le. a e 138

c sylvain@lhullier.org

Introduction a la programmation en Perl `

Nanmoins, si vous tes outr par ce que je viens dcrire car vous tes e e e e e un fanatique de Java ou autres, il existe un moyen dcrire des fonctions e vraiment internes aux modules. Il faut pour cela dclarer une variable avec e my (donc invisible depuis lextrieur du module) et den faire une rfrence e ee anonyme vers fonction : package Utils; use strict; my $affiche = sub { my ($n,$m) = @_; print "$n, $m\n"; }; La variable $affiche est donc une variable prive qui pointe vers une e fonction anonyme. Son usage est donc rserv aux fonctions dclares dans e e e e 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.

13.12

Documentation des modules

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

Introduction a la programmation en Perl `

c sylvain@lhullier.org

=head1 SYNOPSIS use Utils; bonjour("Paul"); =head1 DESCRIPTION Blabla blabla =head2 Exports =over =item :T1 Blabla =item :T2 Blabla =back =cut Les tags =head1 dnissent des en-ttes de premier niveau (des gros e e titres) et les tags =head2 dnissent des en-ttes de deuxi`me niveau (des e e e 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 mme recommand de documenter une fonction et den faire suivre le code. e e Pour cela vous devez savoir que lapparition en dbut de ligne dun tag POD e indique la n temporaire du code Perl et le dbut dun bloc de documentae tion. La n de ce POD est signale a laide du tag =cut et le code Perl peut e ` alors reprendre. package Utils; =head1 FUNCTION hello This function prints hello.

140

c sylvain@lhullier.org

Introduction a la programmation en Perl `

=cut sub hello { my ($firstName) = @_; print "Hello $firstName\n"; } =head1 FUNCTION bonjour This function prints hello in french. =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 ! Tapez donc perldoc Utils e (ou tout autre nom que vous aurez choisi de donner a votre module) et ` sa documentation appara au format man comme tout bon module CPAN. t Quoi de plus simple ? NAME Utils.pm - Useful functions SYNOPSIS use Utils; bonjour("Paul"); DESCRIPTION Blabla blabla Exports :T1 Blabla :T2 Blabla

141

Introduction a la programmation en Perl ` FUNCTION hello This function prints hello. FUNCTION bonjour This function prints hello in french.

c sylvain@lhullier.org

Pour plus dinformations et de dtails sur ce format, je vous invite a e ` consulter perldoc perlpod o` de nombreux exemples sont donns. Vous u e pouvez aussi jeter un oeil au code dun module ou deux dont le perldoc vous intrigue ...

13.13

Un dernier mot sur les modules

Jesp`re que la lecture de cette partie vous a donn envie de structurer e e votre code en regroupant vos fonctions dans de telles biblioth`ques. Vous e vous rendrez compte de cette ncessit lorsque vous aurez un chier de e e code trop gros a grer ... Mais mme sans cela, nhsitez pas a faire des ` e e e ` modules, ne serait-ce que pour une r-utilisation de fonctionnalits dans e e dautres scripts ou pour partager votre code avec des amis, des coll`gues e voire avec la communaut. e

142

Chapitre 14

Programmation objet
La programmation objet est le concept nouveau de ces vingt derni`res e annes. C++ est bti sur le C et apporte lobjet. Java a t mis au point e a ee (entre autres) pour passer outre les nombreux pi`ges et probl`mes de C++. e e Ruby est un langage interprt bas sur ce concept objet. ee e Perl, qui utilisait un garbage collector bien avant que Java nexiste, ne pouvait pas tre en reste et la communaut Perl a rapidement propos les e e e extensions du langage ncessaires a ce type de programmation. e ` On notera que ces extensions sont peu nombreuses car lide a t de e ee rutiliser au maximum ce qui existait dj` en Perl et de lappliquer a la e ea ` programmation objet. Le C++ tant compil et devant rester compatible e e 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`ges. Perl, e de par sa nature interprte, na pas pos de probl`me pour stendre a ee e e e ` lobjet. La programmation par objets ouvre le champ des possibilits oertes au e programmeur ; allie a un langage puissant et exible comme Perl, elle ore e ` la souplesse, la richesse et la facilit dcriture quil manque aux langages e e uniquement objet. Toutefois, de par sa nature permissive, le langage Perl ne saurait tre aussi strict que des langages exclusivement objet. Le programe meur est invit a faire les choses proprement, mais rien de ly oblige. e`

14.1

Vous avez dit objet ?

Sans revenir sur la thorie de la programmation objet, je vais tenter ici e dy faire une courte introduction. La programmation oriente objet est un e type de programmation qui se concentre principalement sur les donnes. La e 143

Introduction a la programmation en Perl `

c sylvain@lhullier.org

question qui se pose en programmation OO (oriente objet) est quelles sont e les donnes du probl`me ? a linstar de la programmation procdurale par e e ` e 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 (proprits) et des fonctions/actions (mthodes). ee e On parle de classe, qui est une mani`re de reprsenter des donnes e e e et comporte des traitements : une classe Chaussure dcrit, par exemple, e les caractristiques dune chaussure. Elle contient un champ dcrivant la e e pointure, la couleur, la mati`re etc. Une telle classe comporte de plus des e traitements sur ces donnes ; ces traitements sont appels mthodes. Grose e e si`rement une mthode est une fonction applique a un objet. e e e ` Une fois dnie une telle classe, il est possible den construire des inse tances : une instance dune classe est dite tre un objet de cette classe. Dans e notre exemple, il sagirait dune chaussure dont la pointure, la couleur et la mati`re sont renseignes. e e

14.2

Prparatifs e

Nous allons maintenant voir comment crire une classe en Perl. Vous e verrez, cela est tr`s simple et dmystie la programmation objet. e e En Perl, une classe nest autre quun module et un objet (instance de cette classe) nest autre quune rfrence associe a cette classe. Dans le ee e ` constructeur, nous allons donc crer une rfrence (typiquement vers une e ee table de hachage) et nous allons lassocier au package en question ; lors de cette association, on dit en Perl que lon bnit (bless en anglais) la rfrence. e ee Les champs de lobjet seront en fait stocks dans cette table de hachage, e sous forme de la clef pour le nom du champ et de la valeur pour la valeur du champ. Voyons un exemple : dnissons une classe Vehicule qui comporte deux e champs : un nombre de roues et une couleur.

14.3

Ecrire un constructeur

Nous dnissons un package Vehicule dans un chier Vehicule.pm e comme nous le faisons pour tout module. 1: 2: 3: # --- fichier Vehicule.pm --package Vehicule; use strict; 144

c sylvain@lhullier.org

Introduction a la programmation en Perl `

4: 5: 6: 7: 8: 9: 10: 11: 12: 13:

sub new { my ($class,$nbRoues,$couleur) = @_; my $this = {}; bless($this, $class); $this->{NB_ROUES} = $nbRoues; $this->{COULEUR} = $couleur; return $this; } 1; # ` ne pas oublier... A

La ligne numro 2 indique le nom du package actuel ; il est conseill de e e choisir le mme nom que pour le chier, simplement pour des raisons dorgae nisation et de maintenance. La ligne 13 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 dnit e doit tre compos de majuscules et de minuscules, avec typiquement une e e majuscule au dbut de chaque mot ; les noms de package exclusivement en e minuscules sont rservs pour les modules pragmatiques de Perl (dits moe e dules pragma comme strict etc), les noms exclusivement en majuscules sont inlgants. :-) ee Nous dnissons une fonction new (ligne 4) dont le but est de construire e 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 la classe (si on est un habitu de C++ ou de Java), mais on verra par la e suite que cela nest pas forcment une bonne ide. e e Cette fonction prend en premier param`tre le nom de la classe ; cela e semble superu, mais on verra quil nen est rien. Les param`tres suivants e sont laisss a la discrtion du programmeur : bien souvent on passe ici les e ` e valeurs de champs pour linitialisation. Cest ce que lon fait ici : le nombre de roues et la couleur sont transmis (ligne 6). Ligne 7, nous crons une rfrence anonyme vers une table de hachage e ee vide {}. Cette rfrence est stocke dans une variable scalaire nomme $this ee e e 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 frquent que le nom de lobjet dans les e mthodes soit plutt $self en Perl (vous trouverez ce nom dans la plupart e o 145

Introduction a la programmation en Perl `

c sylvain@lhullier.org

des modules objet de CPAN). Ligne 8, nous indiquons que cette rfrence est lie au package (` la ee e a classe) $class. Cette variable $class vaudra ici Vehicule. Loprateur e bless associe le package en question a la rfrence. La rfrence est main` ee ee tenant lie au package. e Dans les lignes 9 et 10, les champs NB_ROUES et COULEUR sont initialiss. e Le champ dun objet nest rien dautre quune entre dans la table de hachage e qui constitue lobjet. Pour aecter un champ de lobjet que nous sommes en train de construire, il sut de crer un couple clef/valeur dans la table e de hachage rfrence par $this. Jai pris lhabitude de mettre le nom des ee e 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 mme classe. ` e Libre au programmeur de faire ce quil veut : si le but est de vraiment programmer objet de faon formelle, il va respecter les habitudes de ce type c de programmation qui veut que toutes les instances dune mme classe aient e les mmes champs ; mais sil ne tient pas a respecter ces contraintes, il est e ` libre de faire ce quil veut de chacun de ses objets. La ligne 11 consiste en un return de la rfrence vers la table de hachage ee ainsi construite.

14.4

Appeler le constructeur

Pour faire usage de cette classe, nous allons devoir disposer dun script crit dans un autre chier (par exemple script.pl) : e #!/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 dni : e my $v = Vehicule->new( 2, "bleu" ); my $v2 = Vehicule->new( 4, "rouge" ); 146

c sylvain@lhullier.org

Introduction a la programmation en Perl `

Nous venons ici de crer deux instances de la classe Vehicule. On dit e que ces deux variables $v et $v2 sont des Vehicule. Ces deux objets sont donc indpendants lun de lautre ; ils sont de la mme classe Vehicule, mais e e en constituent des instances autonomes, la modication de lun ne modiant pas lautre. Voici un schma de ltat de notre mmoire : e e e

$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 dcrire. La variable $v est initialise a la valeur de retour e e ` de cette fonction. Elle est donc une rfrence vers une table de hachage dont ee deux champs sont initialiss et qui a t bnie (bless) en Vehicule. Idem e ee e 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 habitus de Java ou de e C++, mais peut induire le programmeur en erreur. En eet, cette derni`re e syntaxe semble indiquer que new est un oprateur spcique pour appeler un e e constructeur et est donc un mot rserv du langage. Il nen est rien ; comme e e on le verra un peu plus loin, ce nom est totalement arbitraire.

14.5

Manipulations de lobjet

Revenons a notre exemple. En plus de savoir quelle pointe vers une ` table de hachage, la rfrence $v sait de quelle classe elle est. En eet, si ee 147

Introduction a la programmation en Perl ` nous lachons : print "$v\n"; Nous obtenons la chose suivante a lcran : ` e Vehicule=HASH(0x80f606c)

c sylvain@lhullier.org

Je vous rappelle que dans le cas de lachage dune rfrence vers une ee table de hachage non bnie, nous obtenons quelque chose de la forme : e HASH(0x80fef74) Un objet (` partir de maintenant nommons ainsi une rfrence vers une a ee table de hachage bnie) sait donc de quelle classe il est. Cela va lui permettre e de choisir le bon package quand on appelera une mthode sur cet objet (lire e la suite). Voyons maintenant ce que donne le module Data::Dumper (dont jai dj` ea parl) sur une telle rfrence : e ee 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 renvoye est directement intgrable dans un code Perl est ne e e respecte : mme lopration de bndiction (bless) est prsente. e e e e e e Il faut bien voir que $v est une rfrence vers un objet. Autrement dit, ee si on fait une copie de cette variable my $w = $v; nous obtenons deux variables qui pointent vers le mme objet. e 148

c sylvain@lhullier.org

Introduction a la programmation en Perl `

$v

Vehicule NB_ROUES => => 2 bleu

$w COULEUR

$v2

Vehicule NB_ROUES COULEUR => => 4 rouge

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

14.6

Plusieurs constructeurs

Comment crire plusieurs constructeurs pour une mme classe ? Rien e e 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 rfrence bnie. Seule la syntaxe dappel change par rapport a ce que ee e ` lon a vu pour les modules. Je peux donc crire un autre constructeur (donc e 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`tre (la e ` couleur) et naecte pas de champs NB_ROUES car rien de ne ly oblige. A moi 149

Introduction a la programmation en Perl `

c sylvain@lhullier.org

de savoir comment je veux grer mes vhicules, a savoir comment jautorise e e ` quils soient construits. Pour tre propre et cohrent, nous allons tout de mme considrer quil e e e e 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 mme faon que pour le prcdent constructeur, il est possible e c e e dutiliser la syntaxe suivante : my $v2 = nouveau Vehicule( "bleu" ); Ce qui est, reconnaissons-le, quelque peu droutant. Cest pour cela que e je vous conseille dutiliser plutt la premi`re syntaxe Vehicule->nouveau() o e ou alors de vous en tenir a un constructeur new pour crire new Vehicule(). ` e

14.7

Ecrire une mthode e

Une mthode est une fonction qui sapplique a une instance de la classe. e ` Cela est vrai dans tous les langages objet, mais bien souvent cela est masqu ; e dans notre cas rien de masqu, le premier param`tre de la fonction sera e e lobjet (la rfrence bnie) : ee e sub roule { my ($this,$vitesse) = @_; print "Avec $this->{NB_ROUES} roues, je roule a $vitesse.\n"; ` } 150

c sylvain@lhullier.org

Introduction a la programmation en Perl `

Cette fonction dclare dans le chier Vehicule.pm a donc pour premier e e param`tre lobjet sur lequel elle est appele. Vous noterez une fois de plus e e que rien noblige le programmeur a nommer cette variable $this ; la seule ` contrainte est sa premi`re place parmi les arguments. e Cette mthode peut d`s maintenant tre appele depuis le chier e e e e script.pl sur les objets de type Vehicule. Il ny pas de ncessit de faire e e usage du lourd mcanisme dExporter car nous navons pas besoin de moe dier lespace de nom des fonctions des scripts appelant. Pour appeler la mthode, il sut dcrire dans le chier script.pl : e e $v->roule( 15 ); La fonction appele sera celle qui a pour nom roule dnie dans le e e package li a la rfrence $v lors de sa bndiction. e` ee e e Lachage suivant a donc lieu : Avec 2 roues, je roule a 15. ` Ecrivons par exemple une mthode dachage : e sub toString { my ($this) = @_; return "(Vehicule:$this->{NB_ROUES},$this->{COULEUR})"; } Cette mthode renvoie une cha de caract`res, reprsentation de lobe ne e e jet. Les habitus de Java noterons que jai choisi le nom de cette fonction e pour leur rappeler des souvenirs, mais quil na rien de spcial. Voici come ment lutiliser dans le script : print $v->toString()."\n"; Et lachage a lieu : (Vehicule:2,bleu) Libre a vous de choisir un plus bel achage. ` 151

Introduction a la programmation en Perl `

c sylvain@lhullier.org

14.8

Reparlons des champs

Un champ est une donne propre a une instance de classe. En Perl, e ` ces champs sont stocks comme clef/valeur dans la table de hachage qui e constitue lobjet (si on utilise une table de hachage comme objet, ce qui est souvent le cas). Nos vhicules comportent deux champs : NB_ROUES et e COULEUR. Ces champs tant de simple clef/valeur dune table de hachage dont on e dispose dune rfrence dans le script, ils y sont accessibles. Dans le script, ee nous pouvons crire dans le chier script.pl : e foreach my $k (keys %$v) { print "$k : $v->{$k}\n"; } Cest-`-dire que je peux accder sans restriction a lensemble des champs a e ` de lobjet. En eet, jai en main une rfrence vers une table de hachage ; ee le fait quelle soit bnie ne change rien au fait que je peux la drfrencer e eee et accder aux diverses valeurs quelle contient. Je peux aussi bien modier e ces valeurs ou mme en ajouter ou en supprimer, car il sagit en eet dune e table de hachage comme les autres. Comment protger les donnes dun objet ? allez-vous alors me demane e der. Et bien, Perl na rien prvu pour ca. Cela va sans doute faire hurler e les puristes de la programmation objet, mais cest comme cela ... Perl vous propose les principaux mcanismes pour faire de la programmation objet e tout en restant cohrent avec le reste du langage, certaines choses ne sont e donc pas possibles. Faute de champs privs en Perl, il existe une convention qui dit que e les champs dont la clef commence par un underscore (soulign _) sont des e champs privs et les scripts qui utilisent les objets ainsi faits sont pris de e e respecter cette convention. Cest le cas de beaucoup de modules CPAN. Cette convention est aussi valable pour les mthodes (une mthode dont le e e nom commence par une underscore est une mthode prive). e e De faon gnral, un programmeur Perl est quelquun de bonne ducation c e e e (sinon il programmerait en Java ;-))) et il ne modiera pas une instance dune classe quil na pas crite. En eet, pourquoi modier un objet Net::FTP e alors quil fait tr`s bien son travail ? De toute faon, il a forcment acc`s au e c e e code source de cette classe et sil veut la modier, il peut en faire une copie et la modier ! 152

c sylvain@lhullier.org

Introduction a la programmation en Perl `

La protection des donnes est donc plus une ncessit sociale (manque de e e e conance en lesp`ce humaine a laquelle les dveloppeurs prtendent encore e ` e e faire partie :-))) quune ncessit technique. Pas dramatique pour faire de e e lobjet.

14.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 vhicules. e Je dcide quun garage aura une taille limite : il sagira du nombre maxie mal de vhicules quil pourra contenir. Un garage devra donc contenir une e liste de vhicules. e Nous devons crer un chier Garage.pm contenant : e package Garage; use strict; # ... ici les mthodes qui vont suivre e 1; Voyons ensuite le constructeur : sub new { my ($class,$places) = @_; my $this = {}; bless($this, $class); $this->{PLACES} = $places; $this->{VEHICULE} = []; return $this; } Ce constructeur prendra en param`tre le nombre de places disponibles e du garage ; cette valeur est enregistre dans le champ PLACES. Le champ e VEHICULE comportera la liste des vhicules ; pour cela elle est initialise a e e ` la rfrence anonyme vers une liste vide. La mthode ajoute se chargera ee e dajouter les vhicules dans la limite du nombre de places : e sub ajoute { 153

Introduction a la programmation en Perl ` my ($this,$vehicule) = @_; if( @{$this->{VEHICULE}} < $this->{PLACES} ) { push @{$this->{VEHICULE}}, $vehicule; return 1; } return 0; }

c sylvain@lhullier.org

Cette mthode prend en param`tre une rfrence vers un vhicule. Elle e e ee e compare la longueur de la liste des vhicules au nombre total de places e (lexpression @{$this->{VEHICULE}} est la liste pointe par la rfrence e ee $this->{VEHICULE} ; value en contexte numrique, elle vaut son nombre e e e dlments). Sil reste de la place, le vhicule est ajout (fonction push) et ee e e 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 mthode dachage pour un tel objet : e sub toString { my ($this) = @_; my $s = "{Garage:$this->{PLACES},"; foreach my $v ( @{$this->{VEHICULE}} ) { $s .= $v->toString(); } return $s."}"; } 154

c sylvain@lhullier.org

Introduction a la programmation en Perl `

On appelle sur chaque objet Vehicule la mthode toString de faon a e c ` le faire appara dans la cha que nous allons renvoyer. Voici comment tre ne appeler cette mthode dans le script : e print $g->toString()."\n"; Ce qui donne lachage suivant : {Garage:3,(Vehicule:2,bleu)(Vehicule:4,vert)(Vehicule:1,jaune)} On pourrait crire cette mthode diremment si on voulait sparer e e e e chaque vhicule par une virgule : e 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, je dcide de trier les vhicules par e e e 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 proposs pour que vous vous tore turiez un peu les mninges ;-)) e 155

Introduction a la programmation en Perl `

c sylvain@lhullier.org

14.10

Destruction dun objet

Un objet est dtruit d`s quaucune rfrence ne pointe vers cet objet. e e ee La ligne suivante, par exemple, lib`re la place mmoire occupe par lobjet e e e Vehicule rfrenc par $v2 : ee e $v2 = undef; ` A cet instant, Perl se rend compte que lobjet en question nest plus accessible, la mmoire sera donc automatiquement libre par le mcanisme e ee e du garbage collector. La mme chose a lieu dans le cas de la disparition dune variable locale : e if( ..... ) { my $v3 = Vehicule->new(3,jaune); ... ... } La variable $v3 cesse dexister a la fermeture de laccolade du if. Lobjet ` qui a t cr dans le bloc sera donc dtruit (sauf si on a fait en sorte quune e e ee e autre variable dont la visibilit dpasse ce bloc pointe aussi vers lobjet). e e Cette libration nest peut-tre pas faite en temps rel, mais ce nest pas e e e au programmeur de sen occuper. Il existe une mthode tr`s spciale, dont le nom est rserv, qui est ape e e e e pele lors de la destruction dune instance dun objet. Il sagit de la mthode e e DESTROY. Cette mthode sera appele (si elle existe dans la classe) par le gare e bage collector juste avant la libration de la mmoire de lobjet. e e sub DESTROY { my ($this) = @_; print "` la casse Vehicule ! "; A print "($this->{NB_ROUES} $this->{COULEUR})\n"; } Cette mthode doit tre dnie dans le package de lobjet en question et e e e reoit en premier argument une rfrence vers lobjet qui va tre dtruit. c ee e e Cette mthode est tr`s utile pour librer des ressources (chier, connexion e e e rseau etc) qui ont t alloues lors de la cration de lobjet. e ee e e 156

c sylvain@lhullier.org

Introduction a la programmation en Perl `

14.11

Hritage e

Lhritage est un des apports de la programmation objet. Perl dispose e de tout ce quil faut pour le mettre en uvre. Imaginons quen plus de vhicules, nous avons besoin de manipuler des e vlos et des voitures. Ces objets ont en commun davoir un nombre de roues e et une couleur. Ils ont des caractristiques supplmentaires qui leur sont e e propres ; les vlos ont un nombre de vitesses et les voitures, un nombre de e si`ges. Ces classes Velo et Voiture vont donc hriter de la classe Vehicule, e e cest-`-dire quelles vont comporter tous les champs et les mthodes de cette a e classe. On dit alors que la classe Vehicule est la classe m`re ; les classes Velo e et Voiture tant des classes lles. Notez bien que je prends comme exemple e deux classes lles et quil nest nullement ncessaire davoir deux classes lles e pour mettre en uvre lhritage, une seule est susante. e Voyons le cas de la classe Velo, crons pour cela un chier Velo.pm qui e contient : package Velo; use strict; use Vehicule; our @ISA = qw(Vehicule); # ... ici les mthodes qui vont suivre e 1; On signale le lien de liation entre classes au moyen de la variable @ISA positionne a la valeur dune liste contenant le nom de la classe m`re. ISA e ` e vient de langlais is a, est un : on dit quun vlo est un vhicule. Il hrite e e e donc des champs et mthodes de la classe Vehicule. e Dnissons lui un constructeur : e sub new { my ($class,$couleur,$nbVitesses) = @_; my $this = $class->SUPER::new( 2, $couleur ); $this->{NB_VITESSES} = $nbVitesses; return bless($this,$class); } 157

Introduction a la programmation en Perl `

c sylvain@lhullier.org

Ce constructeur prend donc deux param`tres. Il appelle le construce teur de la classe m`re (syntaxe $class->SUPER::new). Il ajoute un champ e NB_VITESSE et renvoie une rfrence bnie en Velo. Notez bien quaucun ee e appel au constructeur de la classe m`re nest fait par dfaut, il faut le faire e e explicitement dans tous les cas. Le lecteur aura not que, comme les champs de la classe m`re et de la e e classe lle sont stocks dans la mme table de hachage, il ny a pas moyen e e simple de faire de surcharge ou de masquage des champs. Les noms des champs devront tre minutieusement choisis pour ne pas entrer en conit e les uns avec les autres. Voyons a prsent comment crire une mthode pour cet objet : ` e e e sub pedale { my ($this,$ici) = @_; print "Sur mon vlo $this->{COULEUR} "; e print "je pdale avec $this->{NB_VITESSES} vitesses"; e 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); Un vlo dispose de la mthode roule car il est aussi un vhicule. Lae e e chage suivant est eectu : e Sur mon vlo blanc je pdale avec 18 vitesses dans les bois. e e Avec 2 roues, je roule a 10. ` Voyons a prsent comment acher un tel objet. Nous laisserons le soin ` e a la classe Vehicule dacher le vlo comme tant un vhicule et nous ` e e e neectuerons dans la classe Velo que lachage de ce que nous avons ajout e a la classe m`re : ` e sub toString { my ($this) = @_; 158

c sylvain@lhullier.org

Introduction a la programmation en Perl `

my $s = "[Velo:$this->{NB_VITESSES}"; $s .= $this->SUPER::toString(); $s .= "]"; } La syntaxe $this->SUPER::toString() correspond a lappel de la mthode ` e toString de la classe m`re. Nous pouvons maintenant lappeler dans notre e script : print $velo->toString()."\n"; Lachage suivant est eectu : e [Velo:18(Vehicule:2,blanc)] Rien de plus simple ! Seule chose pas extrmement pratique, lappel au destructeur sarrte e e au premier destructeur rencontr. Si dans notre exemple nous dnissions e e une mthode DESTROY pour la classe Velo, la mthode DESTROY de la classe e e Vehicule ne sera pas appele. Cela peut tre gnant si des ressources impore e e tantes sont libres dans cette mthode ; il faut alors lappeler explicitement. ee e Voici un exemple de mthode DESTROY pour la classe Velo : e sub DESTROY { my ($this) = @_; $this->SUPER::DESTROY(); print "Bye bye Velo ! "; print "($this->{NB_VITESSES} $this->{NB_ROUES} ". "$this->{COULEUR})\n"; } La deuxi`me ligne de la mthode fait un appel a la mthode de la classe e e ` e m`re. e Pour faire de lhritage multiple en Perl, rien de plus simple. Vous aurez e peut-tre not que la variable @ISA est un tableau, elle peut donc contenir e e plusieurs noms de classe : package Voiture; our @ISA = qw(Vehicule Danger Pollution); La dtermination de la bonne mthode a appeler est eectue dynae e ` e miquement par une recherche en profondeur dans larbre dhritage. Je ne e mtendrai pas plus sur cette question de lhritage multiple. e e 159

Introduction a la programmation en Perl `

c sylvain@lhullier.org

14.12

Classes dun objet

Dans cette partie nous allons voir comment conna la classe dun objet tre ainsi que tester lappartenance a une classe pour un objet. ` Souvenez-vous de loprateur ref qui, appliqu a une rfrence, renvoie e e` ee le type de structure de donnes vers laquelle elle pointe (scalaire, tableau, e table de hachage etc). Appliqu a un objet, il renvoie la classe de lobjet : e` print ref($velo)."\n"; print "Ouf, tout va bien !\n" if( ref($velo) eq "Velo" ); Lachage eectu est le suivant : e Velo Ouf, tout va bien ! Il sagit donc de la classe principale de lobjet. Sachant quun vlo e est aussi un vhicule, il peut tre utile de pouvoir tester lappartenance de e e lobjet a une classe plutt que de conna sa classe principale. Par exemple, ` o tre si nous manipulons un tableau comportant des objets divers et varis et si e nous souhaitons y retrouver tous les objets de classe Vehicule pour appeler leur mthode roule, nous ne pouvons pas crire e e if( ref($r) eq "Vehicule" ) { ... } car les vlos ne seront pas slectionns. En fait la question que nous e e e 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 sousclasses, 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. 160

c sylvain@lhullier.org

Introduction a la programmation en Perl `

14.13

Champs et mthodes statiques e

Un champ statique est un champ qui est commun a tous les objets dune ` classe, cest-`-dire quil nest pas li a une instance particuli`re mais a une a e` e ` classe. Cest une sorte de variable globale (dont lacc`s peut ventuellement e e tre contrl) qui est situe dans une classe. e oe e Pour faire cela en Perl, nous utiliserons des variables dclares dans le e e package de la classe en question. package Vehicule; my $privateVar = 0; our $publicVar = "hello"; Avec le qualicateur my, nous dclarons des variables prives (car visibles e e uniquement depuis lintrieur du package). Avec our, sont dclares des e e e variables publiques (accessibles depuis nimporte quel package). Je rappelle que pour accder a la variable $publicVar du package e ` Vehicule, on doit crire $Vehicule::publicVar ; depuis les fonctions et e mthodes de ce package, il est susant dcrire $publicVar (sauf masquage e e par une variable locale). On pourrait par exemple compter le nombre de vhicules crs au moyen e ee 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 vhicule de plus e return $this; } ` A chaque appel au constructeur de cette classe, la variable $nbVehicules sera donc incrmente. e e Maintenant, comment crire une mthode statique ? Une mthode stae e e tique (ou mthode de classe) est une mthode qui nest pas appele sur une e e e instance de la classe (donc pas de variable $this) mais pour toute la classe. 161

Introduction a la programmation en Perl `

c sylvain@lhullier.org

Ce nest ni plus ni moins quune brave fonction prsente dans le package. e Cette fonction pourra donc uniquement accder aux champs statiques de la e classe. Nous pourrions, par exemple, crire une mthode statique qui renvoie le e e nombre de vhicules crs (variable $nbVehicules) : e ee sub getNbVehicules { my ($class) = @_; return $nbVehicules; } On notera que la mthode prend en premier argument le nom de la classe. e Cela a pour consquence que lappel a la mthode ne se fait pas tout a fait e ` e ` comme pour une fonction dun package (comme vu pour les modules), mais de la mani`re suivante : e print Vehicule->getNbVehicules()."\n"; Le nom de la classe est suivi dune `che, du nom de la mthode et des e e ventuels arguments entre parenth`ses. Ncrivez pas e e e Vehicule::getNbVehicules() car le nom de la classe nest pas transmis et surtout car les mcanismes dhritage ne sont pas mis en uvre. Sil e e est possible dcrire Velo->getNbVehicules(), il nest pas permis dcrire e e Velo::getNbVehicules(). Le lecteur notera que les constructeurs sont des mthodes statiques. Ils e retournent des rfrences bnies, mais nont rien de particulier par rapport ee e a dautres mthodes de classe. ` e Il est tout a fait possible dappeler cette mthode sur une instance de la ` e classe Vehicule print $v->getNbVehicules()."\n"; mais dans ce cas le premier argument reu nest pas le nom de la classe c mais lobjet en question (cest donc une mthode dinstance et de classe ...). e Cela ne change rien pour notre mthode getNbVehicules car elle nutilise e pas son premier argument, mais le cas est gnant pour les constructeurs e qui ont a bnir une rfrence. Pour cela, tout constructeur devrait commen` e ee cer par dterminer sil a en premier argument le nom de la classe ou une e rfrence. Linstruction qui suit place dans la variable $class la classe acee tuelle, que cette variable ait pour valeur initiale le nom de la classe ou une instance de la classe : 162

c sylvain@lhullier.org

Introduction a la programmation en Perl `

$class = ref($class) || $class; Il convient dornavant dcrire le constructeur ainsi : e e sub new { my ($class,$nbRoues,$couleur) = @_; $class = ref($class) || $class; my $this = {}; bless($this, $class); $this->{NB_ROUES} = $nbRoues; $this->{COULEUR} = $couleur; $nbVehicules++; # un vhicule de plus e return $this; } Il est maintenant possible dcrire la ligne suivante dans le script : e $v2 = $v->new( 1, "noir" ); Le constructeur est appel sur une instance de la classe plutt que sur la e o classe. On pourrait faire de mme pour toutes les mthodes statiques (cest e e mme plutt conseill). e o e

14.14

Exemple complet

Voici le contenu exact des chiers dexemple btis tout au long de cette a 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; 163

Introduction a la programmation en Perl ` $this->{COULEUR} = $couleur; $nbVehicules++; # un vhicule de plus e return $this;

c sylvain@lhullier.org

} 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; # ` ne pas oublier... A 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; 164

c sylvain@lhullier.org

Introduction a la programmation en Perl `

return bless($this,$class); } sub pedale { my ($this,$ici) = @_; print "Sur mon vlo $this->{COULEUR} "; e print "je pdale avec $this->{NB_VITESSES} vitesses"; e print " dans $ici.\n"; } sub toString { my ($this) = @_; my $s = "[Velo:$this->{NB_VITESSES}"; $s .= $this->SUPER::toString(); $s .= "]"; } 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; } 165

Introduction a la programmation en Perl ` 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); 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); } 166

c sylvain@lhullier.org

c sylvain@lhullier.org

Introduction a la programmation en Perl `

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"; print Velo->getNbVehicules()."\n"; print $v->getNbVehicules()."\n"; $v2 = $v->new( 1, "noir" ); 167

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

Introduction a la programmation en Perl `

c sylvain@lhullier.org

168

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 tre autonome en Perl. e Noubliez pas que la documentation de Perl est tr`s bien faite et est dispoe nible sur votre ordinateur au moyen de la commande perldoc : perldoc perl vous donne acc`s a la liste des th`mes consultables avec perldoc. Par e ` e exemple perldoc perldata vous explique les structures de donnes en Perl. e Pour une fonction particuli`re, utilisez loption -f : perldoc -f chomp Pour e un module particulier, utilisez perldoc sans option : perldoc Data::Dumper Vous avez maintenant en main beaucoup de notions importantes de Perl. ` A vous de les mettre en uvre pour vos propres probl`mes. Il nest pas e forcement facile dexprimer son besoin en termes directement exploitable dans un langage particulier, mais en ayant un peu dexprience de Perl, e vous trouverez vite votre mani`re de rsoudre un probl`me. Vous allez alors e e e commencer a faire connaissance avec Tim Towtdi (There is more than one ` way to do it). ;-)

169

Introduction a la programmation en Perl `

c sylvain@lhullier.org

170

Lauteur
Sylvain Lhullier <sylvain@lhullier.org> http://sylvain.lhullier.org/ ` A lUniversit de Marne-la-Valle (http://www.univ-mlv.fr/), il est e e charg chaque anne dun module complet denseignement en ma e e trise informatique ; ce module porte sur des sujets tels que Perl, Perl/Tk, Perl/DBI, Apache, CGI/Perl et consiste en dix semaines dun cours en amphithatre e et de trois travaux dirigs, ainsi quen un examen nal et un projet. e Il a travaill pour Linagora (http://www.linagora.com/) comme consule tant formateur et dveloppeur ; il intervenait principalement pour des projets e et prestations concernant le dveloppement (Perl, Java, C++, programmae tion syst`me, PHP, Apache, MySQL, XML etc.). e Il a dvelopp chez feue-Atrid des projets btis en Perl (LogTrend, Mioga) e e a et publis sous GPL. e Il a donn une confrence Perl : pour quoi faire ? lors du salon Linuxe e Solutions de janvier 2004. Entre autres associations, il est membre et administrateur de lassociation Les Mongueurs de Perl dont lobjet est de promouvoir le langage Perl en France par des runions, des confrences etc (http://www.mongueurs.net/). e e Il y coordonne le groupe de travail Articles dont le but est de publier un article dans la presse francophone technique, notamment dans GNU/Linux & Hurd Magazine France (http://www.linuxmag-france.org/) chaque mois. Lauteur tient a remercier tr`s chaleuseusement les autres membres de las` e sociation pour leur aide, leur soutien et les relectures eectues. e

171