Sie sind auf Seite 1von 129

Guide Perl

dbuter et progresser en Perl e

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

Version 1.2.4 fvrier 2012 e

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

Table des mati`res e


Licence Introduction 1 Premier pas 1.1 Excuter un programme en Perl . . . . . . . . . . . . . . . . . . . . . . . . . . . . e 1.2 Les types de donnes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e 1.3 La notion de contexte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 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 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 9 11 11 12 13 15 15 16 16 17 17 18 21 21 23 24 27 27 28 29 30 30 31 31 32 33 34 34 35 35 36

3 Structures de contrle o 3.1 Les instructions de test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 Les boucles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3 Un exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Listes et tableaux 4.1 Valeurs de listes . . . . . . . . . . . . . . . . . . . . . . 4.2 Manipulation de tableaux . . . . . . . . . . . . . . . . 4.3 Aectations . . . . . . . . . . . . . . . . . . . . . . . . 4.4 Multi-dclaration . . . . . . . . . . . . . . . . . . . . . e 4.5 Retour sur laplatissement des listes . . . . . . . . . . 4.6 Absorption dune liste par un tableau . . . . . . . . . 4.7 La structure de boucle foreach . . . . . . . . . . . . . 4.8 Fonctions de manipulation de tableaux . . . . . . . . . 4.9 Loprateur qw . . . . . . . . . . . . . . . . . . . . . . e 4.10 Joindre les lments dans une cha avec join . . . . ee ne 4.11 Dcouper une cha de caract`res en liste avec split e ne e 4.12 Trier une liste avec sort . . . . . . . . . . . . . . . . . 4.13 Slectionner des lments avec grep . . . . . . . . . . e ee 4.14 Appliquer un traitement ` tous les lments avec map . a ee . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

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 5.7 Dernier exemple : le crible dEratosth`ne e 6 Tables de hachage 6.1 Dclaration et initialisation . . . . e 6.2 Accder ` un lment . . . . . . . e a ee 6.3 Parcours . . . . . . . . . . . . . . . 6.4 Autovivication . . . . . . . . . . . 6.5 Existence et suppression dune clef 6.6 Tables de hachage et listes . . . . . 6.7 Exemples . . . . . . . . . . . . . . 6.8 Tranches de tableau . . . . . . . . 6.9 Tranches de table de hachage . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

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

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

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

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

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

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

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

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

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

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

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

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

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

7 Manipulation de chiers 7.1 Oprateurs sur les noms de chier . . . . . . . . . . . e 7.2 La fonction glob . . . . . . . . . . . . . . . . . . . . . 7.3 Premiers exemples . . . . . . . . . . . . . . . . . . . . 7.4 Ouverture de chier . . . . . . . . . . . . . . . . . . . 7.5 Lecture, criture et fermeture de chier . . . . . . . . e 7.6 Deuxi`me exemple . . . . . . . . . . . . . . . . . . . . e 7.7 Excution de commandes avec open . . . . . . . . . . e 7.8 Ecrire une table de hachage sur disque avec les chiers 8 Expressions rguli`res e e 8.1 Fonctionnalits . . . . . e 8.2 Bind . . . . . . . . . . . 8.3 Caract`res . . . . . . . . e 8.4 Ensembles . . . . . . . . 8.5 Quanticateurs . . . . . 8.6 Ensembles (suite) . . . . 8.7 Regroupement . . . . . 8.8 Alternatives . . . . . . . 8.9 Assertions . . . . . . . . 8.10 Rfrences arri`res . . . ee e 8.11 Variables dnies . . . . e 8.12 Valeurs de retour de m// 8.13 Exemples de probl`mes e 8.14 Solutions des probl`mes e 8.15 Choisir son sparateur . e 8.16 Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

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

c Sylvain Lhullier

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

http://formation-perl.fr/

8.17 8.18 8.19 8.20

Quanticateurs non-gourmands . . . . . . . Substitution de variables dans les motifs . . Oprateur tr . . . . . . . . . . . . . . . . . e Un dernier mot sur les expression rguli`res e e

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

http://formation-perl.fr/

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

c Sylvain Lhullier

11.8 Reparlons des champs . . . . . 11.9 Composition . . . . . . . . . . 11.10Destruction dun objet . . . . . 11.11Hritage . . . . . . . . . . . . . e 11.12Classes dun objet . . . . . . . 11.13Champs et mthodes statiques e 11.14Exemple complet . . . . . . . . Conclusion Lauteur

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

113 114 117 117 120 120 122 127 129

Licence
c 2002-2012 Sylvain Lhullier Version 1.2.4 - fvrier 2012 e Vous trouverez la derni`re version de ce document ` cette adresse : e a http://formation-perl.fr/guide-perl.html Ce document est y disponible en version HTML et PDF. Permission est accorde de copier et distribuer ce document sans modication. e

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

Introduction
Une formation au langage Perl : un moyen ecace de gagner en comptences par lapprene tissage de cet outil polyvalent et performant. Cette introduction ` la programmation en Perl est initialement une synth`se des articles que a e jai crits pour Linux Magazine France et parus dans les numros de juillet 2002 ` fvrier 2003 e e a e puis r-dit au printemps 2004 dans les Dossiers Linux 2. Depuis, ce document est rguli`rement ee e e e mis ` jour. a Ce langage tr`s riche et puissant est une bo ` outils fort utile dans de nombreuses site te a uations : administration syst`me, manipulation de textes (mail, logs, linguistique, gntique), e e e programmation rseau (CGI, mod_perl, etc), bases de donnes, interfaces graphiques etc. Ses e e nombreuses biblioth`ques le rendent vite irremplaable aux yeux de ceux qui en acqui`rent la e c e ma trise. La prise en main du langage est facilite par de nombreux rapprochements possibles e avec le C, le shell ou awk. Sa conformit POSIX en fait un alli indispensable ` ladministrateur e e a syst`me. e Ce document a la dlicate ambition de sadresser ` la fois au programmeur dbutant et ` e a e a celui qui conna trait bien le C ou le shell. Que le premier me pardonne de faire des comparaisons avec dautres langages et de taire peut-tre certains points qui me semblent vidents. Que le e e second mexcuse de passer ` son got trop de temps ` expliquer des notions qui lui semblent a u a simples ; les choses se corseront au fur et ` mesure de la lecture ... a Le dbut du document aborde des notions importantes en Perl et ncessaires pour bien e e comprendre la suite. Vous serez sans doute un peu du de ne pas faire des choses extrmement ec e puissantes immdiatement, mais patience : qui veut aller loin mnage sa monture. e e Pour vous mettre en apptit, voici un petit exemple de la concision de Perl et de sa puissance : e 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), transforme les majusee e cules de ces mots en minuscules, supprime les chires appartenant aux mots, supprime les mots vides et ache la liste des mots ainsi transforms dans lordre lexical. Et dites-vous que vous e aurez en main 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 avantages de plusieurs e autres langages. Premi`re facilit, il g`re lui mme la mmoire (ramasse-miettes, pas de limite de e e e e e buers, pas dallocation ` faire etc). De plus, les tableaux, les listes et les tables de hachage sont a natifs, ils sont intgrs ` la grammaire mme du langage. Rcursivit, modularit, programmation e e a e e e e objet, acc`s au syst`me et au rseau, interface avec le C, avec (g)Tk, avec Apache sont aussi au e e e

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

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

Premier pas
1.1 Excuter un programme en Perl e

Il existe principalement deux types de langages : les langages compils et les langages ine terprts. Pour les premiers (on retrouve par exemple dans cette catgorie le C et le C++), il ee e existe deux phases distinctes : la compilation des sources par un compilateur (gcc par exemple) puis lexcution du programme ainsi obtenu par le syst`me. Pour les seconds (les shells par exe e emple), il ny a pas de phase de compilation, un interprteur va lire le code et directement agir e en fonction de celui-ci. Perl est un langage ` la fois interprt et compil. Il ny a pas de phase intermdiaire de a ee e e compilation car linterprteur (qui se nomme perl en minuscules, alors que le langage prend e une majuscule) compile le code sans que le programmeur ne sen rende compte, puis lexcute. e Linterprteur se charge donc ` la fois de la compilation et de lexcution. e a 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 shell : e perl -w -e print("Salut Larry\n"); Le programme perl est lanc avec du code Perl comme argument, directement sur la ligne e de commande (option -e). En anglais, on appelle cela un one-liner (pas de traduction tablie en franais, peut-tre monoligne, uniligne, soliligne ...). Le code sera alors excut : e c e e e la fonction print ache son argument. Salut Larry Ce nest pas la faon la plus courante dcrire du Perl, mais cest une mani`re facile et c e e rapide de faire un petit calcul ou de faire appel ` une fonction Perl. a Loption -w, que lon retrouvera tout le temps, est positionne dans le but que linterprteur e e ache des messages davertissement (warnings) ` dirents propos : il indique les variables a e utilises une seule fois ou utilises avant dtre initialises, il signale les rednitions de e e e e e fonctions, etc. Pour marquer les esprits, on pourrait faire un parall`le avec loption -Wall e 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 contenant : e e 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 va alors lire le contenu e de ce chier et linterprter comme du code Perl. e

11

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

La troisi`me faon de faire est de crer un chier salut2.pl contenant : e c e #!/usr/bin/perl -w print("Salut Larry\n"); La premi`re ligne est le shebang, bien connu des habitus des scripts en shell. Cette ligne e e (qui doit toujours tre la premi`re du chier) indique au syst`me dexploitation le chemin e e e de lexcutable ` lancer pour interprter ce chier. Le premier caract`re doit tre un e a e e e di`se, ce qui a pour eet que cette ligne est considre comme un commentaire Perl par e ee linterprteur. Ensuite un point dexclamation. Puis le chemin absolu vers lexcutable e e perl (` adapter selon votre installation, voir ce que rpond type perl ou which perl). a e Enn les options que lon souhaite passer ` linterprteur. a e Il faut maintenant rendre ce chier excutable et le lancer : e chmod +x salut2.pl ./salut2.pl Grce ` la ligne de shebang, le syst`me le reconna donc comme un programme ncessitant a a e t e un interprteur pour tre excut. Cet interprteur est lanc avec pour param`tres les e e e e e e e options fournies dans le shebang ainsi que le nom du chier. Cette derni`re faon de faire est sans doute la plus courante d`s que lon crit un programme e c e e qui sera utilis plusieurs fois. e Avant de continuer, quelques commentaires sur la syntaxe Perl. Except dans les cha e nes de caract`res, la prsence ou labsence despaces, de sauts de ligne ou de tabulations ne change e e 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 arguments e entre parenth`ses (comme en C) ; il faut aussi savoir que lon peut se passer de ces parenth`ses. e e On aurait pu crire : e print "Salut Larry\n"; Les deux syntaxes sont tout ` fait valides. Dans les cas simples (appel dune fonction avec a un ou deux param`tres), on pourra omettre les parenth`ses. Dans le cas de combinaisons plus e e complexes (plusieurs fonctions appeles en param`tre dautres fonctions, listes en argument...), e e je 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 (comme en shell). e 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 pas spcialement e e e de type : les nombres, les cha nes de caract`res, les boolens etc seront tous des scalaires et ne e e seront direncis que par leur valeur et par le contexte de leur utilisation. e e Il existe principalement trois structures de donnes : les scalaires, les tableaux et les tables e de hachage. Chaque structure de donnes est lie ` un caract`re spcial (lire la suite). e e a e e Un scalaire est une donne atomique. Par exemple, ce pourrait tre une cha de caract`res e e ne e (suite de caract`res) ou un nombre (entier ou ottant). On verra plus tard que les rfrences e ee (cest-`-dire les pointeurs de Perl) sont des scalaires, mme sils sont un peu spciaux. Les a e e variables scalaires sont prcdes dun dollar ($) : $x est donc une variable scalaire. e e e

12

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

Les tableaux permettent de stocker plusieurs scalaires en les indiant. De la mme faon quen c e c C, on pourra demander le i`me lment dun tableau, i tant un entier. Lacc`s ` un lment e ee e e a ee sera en temps constant, il ne dpendra pas de son indice dans le tableau. Les variables de type e tableau sont prcdes dun arobase (@) : @t est donc une variable de type tableau. Lorsque lon e e e utilise la syntaxe @t, on dsigne la totalit du tableau ; si nous voulons parler du i`me lment, e e e ee nous allons manipuler un scalaire, il faudra donc prxer par un dollar : $t[4] est llment e ee dindice 4 dans le tableau @t, les crochets [] dlimitant lindice (nul besoin de mettre larobase, e Perl sait grce aux crochets quil sagit dun lment de tableau). a ee Une table de hachage en Perl est une structure de donnes permettant dassocier une cha e ne de caract`res ` un scalaire ; on parle de clefs et de valeurs : une valeur est associe ` une clef. e a e a Naturellement, dans une mme table de hachage les clefs sont uniques ; les valeurs, par contre, e peuvent tre tout ` fait quelconques. Les variables de type table de hachage sont prcdes dun e a e e e caract`re pourcent (%) : %h est donc une variable de type table de hachage. De la mme faon e e c que pour les tableaux, %h reprsente la totalit de la table de hachage ; accder ` un lment se e e e a ee fera avec un dollar : $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 de hachage comme e 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 faon dont lopration e e e e c e se comportera peut dpendre de ce contexte. Il peut jouer un rle important sur le type des e o oprandes dune expression et/ou sur le type de sa valeur. Il existe deux contextes principaux : e le contexte scalaire et le contexte de liste. Par exemple, une aectation dune expression ` une variable de type scalaire valuera cette a e expression dans un contexte scalaire ; de la mme faon, une aectation ` une variable de type e c a liste valuera le membre droit en contexte de liste. Autre exemple que je dtaillerai un peu plus e e loin, les oprateurs de test imposent un contexte prcis a leurs oprandes. e e ` e Certains oprateurs et fonctions savent dans quel contexte ils sont appels et renvoient un e e scalaire ou une liste selon ce contexte dappel. La fonction grep en est un bon exemple (nous verrons cela lorsque nous parlerons des listes). On peut forcer le contexte dune expression au contexte scalaire en utilisant loprateur scalar(). e Il existe plusieurs contextes scalaires : le contexte de cha nes de caract`res, le contexte nue mrique et le contexte tolrant. Par exemple une addition impose un contexte numrique ` ses e e e a deux oprandes ; cela signie que les oprandes sont transforms en nombres quels que soient e e e leur type et leur valeur (reste ensuite au programmeur ` savoir ce que vaut une liste ou une a cha quelconque en contexte scalaire...). Le contexte de cha ne nes est un contexte o`, comme u son nom lindique, les scalaires seront considrs comme des cha ee nes de caract`res. Le contexte e tolrant nest ni de cha 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 utilis lorsque lon appelle une fonce e tion sans rcuprer sa valeur de retour, comme lappel ` la fonction print dans la section pre e a e cdente. Ce contexte napporte pas grand chose au programmeur, mais permet ` linterprteur e a e Perl appel avec loption -w de prvenir en cas dusage dune expression sans eet de bord en e e contexte vide (cest-`-dire une expression qui ne fait rien et dont on ne se sert pas). Par exemple, a

13

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

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

14

Chapitre 2

Les scalaires
Les scalaires sont le type de donnes atomique de Perl, dit autrement un scalaire est une e donne atome. Cela signie que la granularit de donnes ne va pas au-del`. e e e a Comme dit prcdemment, une variable scalaire peut contenir une cha de caract`res e e ne e (String en Java et autres) ou un nombre (entier ou nombre ` virgule ottante : int ou float a 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 marqueur de n de u e e cha ne, en Perl les cha nes de caract`res peuvent sans souci contenir ce caract`re : "a\0f" est e e une cha comportant 3 caract`res. On naura donc aucun mal ` traiter des chiers binaires en ne e a 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 dlimiteurs possibles : e e les doubles quotes (") et les simples quotes (). Elles nont pas le mme rle : e o Dans une cha dlimite par des doubles quotes, le contenu est interprt : ne e e ee "Bonjour\n" est une cha suivie dune n de ligne. De la mme mani`re "\t" est une ne e e tabulation (il existe dautres caract`res spciaux). e e Dans "Bonjour $prenom" la variable $prenom est substitue par son contenu ; cest-`-dire e a que ce scalaire contiendra la cha Bonjour, suivie dune espace, suivie du contenu de la ne variable $prenom. Sil faut accoler un texte immdiatement apr`s une variable, on utilisera les accolades e e pour dlimiter le nom de la variable ; par exemple dans "il ${prefixe}donn$suffixe", e cest bien la variable $prefixe qui sera utilise, puis la cha donn et enn la variable e ne $suffixe. On notera que ces accolades nont rien ` voir avec celles des tables de hachage. a Certains caract`res doivent tre protgs avec un anti-slash (\) si on veut les faire e e e e appara tels quels dans la cha de caract`res ; ce sont les quatre suivants : " $ @ \. tre ne e La cha "\$v" ne contient donc pas la valeur dune suppose variable $v mais contient ne e le caract`re dollar et le caract`re v. e e Dans une cha dlimite par des simples quotes, aucune interprtation du contenu na ne e e e lieu : Bonjour\n est une cha comportant les caract`res B o n j o u r \ et n, cest-`-dire 9 ne e a caract`res (notez que \n comporte 2 caract`res). e e

15

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

La cha Bonjour $prenom ne comporte pas le contenu dune hypothtique variable ne e $prenom mais le caract`re dollar suivi de la cha prenom. e ne Puisque les variables ne sont pas substitues, les caract`res ` protger sont moins nome e a e breux. Le caract`re a besoin dtre prcd dun anti-slash pour appara e e e e e tre tels-quels dans une cha dlimite par de simples quotes. Il en est de mme pour le caract`re \ si ne e e e e celui-ci est suivi dun autre caract`re \ e Les nombres nont quant ` eux pas besoin de dlimiteurs pour tre manipuls : $x = 10.2 a e e e aecte le nombre 10,2 ` la variable $x. a

2.2

Dclaration et utilisation des variables e

En Perl, il nest pas obligatoire de dclarer les variables. Par dfaut, lusage dune variable e e la cre ; si cest un scalaire, elle aura la valeur undef (lire plus loin) ; sil sagit dune liste ou une e table de hachage, elle sera vide. Pour dvidentes raisons de relecture et pour viter des erreurs btes, je vous conseille de e e e toujours dclarer vos variables avant de les utiliser (sauf peut-tre dans le cas de scripts de e e quelques lignes). Pour dclarer une variable, il nous faut utiliser my : e my $x; my $y = 10; my $z = "hello"; Nous venons ici de dclarer trois variables scalaires. Ces variables seront visibles (accessibles) e dans toute la suite du bloc ainsi que dans les sous-blocs (comme en C) ; comme on sy attend, elles ne le seront par contre pas dans les fonctions appeles depuis ces blocs. Le placement des e dclarations est libre dans le bloc (comme en C++), il nest pas ncessaire de les mettre en e 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 ` lcran Bonjour Jules suivi dun caract`re de nouvelle ligne. e a e e Les habitus du shell noteront bien quune variable est toujours prcde de son dollar mme si e e e e e elle est ` gauche dun gal daectation. a e

2.3

La valeur undef

Cest une valeur particuli`re signiant non-dni. Cest aussi la valeur par dfaut des e e e variables scalaires non initialises : my $x; est quivalent ` my $x=undef; On peut aecter e e a cette valeur ` une variable apr`s son initialisation : $x=undef; ou undef($x); a e 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 e a pas undef. Une erreur classique est dcrire : *incorrect* if($x!=undef) *incorrect* Ne e surtout pas tenter de comparer une variable ` undef, car cela ne fait pas ce quon attend. a

16

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

La valeur undef est une valeur fausse pour les tests. Le test if( $x ) ... est faux si $x est non-dnie. Mais comme on le verra plus tard, il est galement faux si $x vaut 0 (zro) ou e e e bien la cha vide. Donc un test if( $x ) ... est potentiellement dangereux. Pour tester si ne 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 : + - / * % ; ce dernier oprateur e e % est le modulo, cest-`-dire le reste de la division enti`re du premier oprande par le second. a e e Notez que la division eectue par loprateur / nest pas une division enti`re mais une division e e e relle, cela mme si ses oprandes sont entiers (2/3 vaut 0.6666...) ; si vous voulez eectuer e e e une division enti`re, il vous faut tronquer le rsultat de la division prcdente avec int() : e e e e lexpression int($x/$y) vaut le quotient de la division enti`re de $x par $y (pour des nombres e positifs). Des raccourcis existent : += -= *= /= %=. Ces oprateurs sont ` la fois une opration e a e arithmtique et une aectation : $x+=3 est quivalent ` $x=$x+3 mais en plus synthtique : e e a e on ajoute 3 ` $x. Linstruction $y*=5 multiplie $y par 5. a Il existe aussi des auto-incrmenteurs et des auto-dcrmenteurs : ++ et -- qui peuvent tre e e e e placs avant ou apr`s une variable : ils ajoutent ou dduisent 1 ` cette variable. $x++ ` le mme e e e a a e eet que $x+=1 ou que $x=$x+1. Loprateur ** correspond ` la puissance : 2**10 vaut 1024. e a 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 e e exactement un nombre sont converties sans probl`me ; "30" + "12" vaut 42. Dans tous les autres e cas (numrs dans ce qui suit), loption -w provoquera un message davertissement. Les scalaires e ee commenant par un nombre sont converties en ce nombre : "34.2blabla" vaudra 34,2. Les autres c 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 de concatner deux e e e cha nes : linstruction $x="bon"."jour" a pour eet daecter la cha bonjour ` $x (pas de ne a gestion de la mmoire ` eectuer). e a Cet oprateur est, entre autres cas, utile lorsque certaines parties de la cha sont les valeurs e ne de retour de fonctions ; en eet, il sut souvent dutiliser les substitutions eectues dans les e cha nes dlimites par des doubles quotes pour concatner deux cha e e e nes. Loprateur x est la multiplication pour les cha e nes de caract`res : "bon"x3 vaut "bonbonbon". e Fort sympathique ... Les raccourcis suivants peuvent tre utiliss : .= x= Lexpression $x.=$y est quivalente ` e e e a $x=$x.$y et concat`ne donc $y ` la n de $x. e a Voici un certain nombre de fonctions utiles qui manipulent les cha nes de caract`res : e

17

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

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

2.6

Les oprateurs de test e

Les boolens (type de donnes ayant pour seules valeurs vrai et faux) nexistent pas en tant e e que tels en Perl, on utilise les scalaires pour eectuer les tests (comme C le fait avec les entiers). Il me faut donc prciser quelles sont les valeurs scalaires vraies et quelles sont les fausses. e 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 caract`re zro (pas a ne e e e le caract`re \0 de code ASCII zro, mais 0 de code 48), e e 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 numriques, mais qui est vraie ... e e Il existe deux catgories doprateurs de test : ceux pour lesquels on impose un contexte e e

18

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

numrique aux oprandes et ceux pour lesquels on impose un contexte de cha de caract`res. e e ne e Par exemple == teste lgalit de deux nombres (contexte numrique) et eq teste lgalit de e e e e e deux cha 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 et de supriorit ; < teste e e e e e e lordre entre nombres, lt teste lordre ASCII entre cha ; donc (9<12) est vrai alors que nes (9 lt 12) est faux car 9 est apr`s 1 dans la table ASCII. Confondre ou mlanger ces deux types e e doprateurs est une erreur tr`s courante que font les dbutants, ainsi que les initis qui ne font e e e e pas attention ... Sachez que loption -w permet souvent de reprer ces situations. e 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 expr1&&expr2 est vrai si expr1 et expr2 sont vraies (si expr1 est faux expr2 nest pas value), e e expr1expr2 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 de vrit que les e e e e prcdents, mais sont dune priorit plus faible. e e e Les deux oprateurs cits ` la derni`re ligne du tableau ne sont pas des oprateurs de test e e a e e mais des oprateurs de comparaison ; ils sont prsents dans ce tableau en raison des similitudes e e quils ont avec les oprateurs de test en ce qui concerne le contexte impos aux oprandes. Ces e e e oprateurs renvoient un nombre qui dpend de lordre entre leurs deux param`tres. Lexpression e e e ($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) en raison de sa e e c forme ;-) ... Pour loprateur cmp, la comparaison se fait sur lordre des cha e nes selon la table ASCII. Ces oprateurs seront fort utiles lorsque nous parlerons de la fonction sort qui eectue e le tri des listes.

19

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

20

Chapitre 3

Structures de contrle o
Ici nous allons apprendre ` contrler le ux des instructions en Perl. En eet un programme a o nest pas quune simple suite dinstructions se droulant linairement une fois et une seule. e 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 ` la valeur de vrit e a e e dune expression. Linstruction la plus usite est le if (si en franais) qui a besoin dune exprese c sion et dun bloc dinstructions. Cette expression sera value en contexte scalaire et servira de e e condition ; si elle 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 toutes excutes si la condition est vraie. e e e e Notez que les accolades ({}) sont obligatoires pour dlimiter le bloc (contrairement au C). e Il est possible dexcuter dautres instructions dans le cas o` la condition est fausse. On utilise e u pour cela loprateur else (sinon en franais) qui, lui aussi, est suivi dun bloc dinstructions : e c if( $x == $y ) { print "\$x et \$y sont gaux\n"; e } else { print "\$x et \$y sont diffrents\n"; e } Le fait que les accolades sont obligatoires a pour consquence que le programme suivant est e incorrect : if( condition1 ) { instructions1

21

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

} else # Attention ce code est incorrect if { instructions2 } Il faut en eet entourer le second if par des accolades comme ceci : if( condition1 ) { instructions1 } else { if( condition2 ) { instructions2 } } Si le programmeur se sent des envies de devenir sylviculteur en plantant des forts difs, il e faudrait donc quil utilise de multiples couples daccolades. Pour ne pas rencontrer les mmes e probl`mes que le Lisp en rencontre pour les parenth`ses ;-), Perl met ` notre disposition line e a struction elsif qui permet de cumuler le comportement dun else et dun if tout en faisant lconomie dun couple daccolades : e if( condition1 ) { instructions1 } elsif( condition2 ) { instructions2 } else { instructions3 } Linstruction switch de C na pas dquivalent direct en Perl ; il faut pour cela planter une e fort difs, comme dans lexemple prcdent. e e e Mais Perl nen reste pas l`. Il existe une syntaxe tr`s utilise pour eectuer une unique a e e instruction si une condition est vrie : e e instruction if( condition ); On parle ici de modicateur dinstruction. Pour cette syntaxe, les parenth`ses sont optione nelles autour de la condition, mais je vous conseille de les mettre systmatiquement pour une e meilleure lisibilit. Le code suivant ache la variable $s si elle est dnie : e 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, ` la dirence que les instructions e o a e seront eectues si la condition est fausse (il est aussi moins dpaysant den faire des forts). e e e unless( expression ) est quivalent ` if( !(expression) ) dans toutes les constructions e a prcdemment cites. e e e

22

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

3.2

Les boucles

Les boucles permettent dexcuter plusieurs fois les mmes instructions sans avoir ` crire e e ae plusieurs fois les mmes lignes de code. Bien souvent nous avons besoin de modier une variable e a ` chaque tape ; dans ce cas nous utiliserons linstruction for (pour en franais) dont voici la e c syntaxe : for( initialisation; condition; incrment ) { e instructions; } La boucle for prend trois expressions entre parenth`ses : la premi`re expression permet e e dinitialiser la variable de boucle, la deuxi`me est une condition de continuation et la derni`re e e permet de modier la valeur de la variable de boucle. Quand la boucle dmarre, la variable est initialise (expression 1) et le test est eectu e e e (expression 2). Si cette condition est vrie, le bloc dinstructions est excut. Quand le bloc e e e e se termine, la variable est modie (expression 3) et le test est de nouveau eectu (expression e e 2). Si la condition 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 qui suivent la boucle sont excutes. e e ` e e e Lexemple suivant ache tous les entiers pairs de 0 ` 20 inclus : a for( my $i=0; $i<=20; $i+=2 ) { print "$i\n"; } La boucle sarrte lorsque $i vaut 22. Cette variable est dclare dans le bloc dinitialisation e e e et nexiste donc que dans la boucle. Notez quil est tout ` fait possible dutiliser une variable pra e existante comme variable de 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 a t aecte e e e ee e au cours de la boucle. Une autre boucle existe : la boucle while (tant que en franais) dont voici la syntaxe : c while( condition ) { instructions; } Les instructions sont eectues tant que la condition est vraie. La partie initialisation doit e avoir t eectue avant la boucle ; la partie modication de la variable doit avoir lieu dans le ee e bloc dinstructions. Lexemple suivant ache lui aussi les entiers pairs de 0 ` 20 : a my $i = 0; while( $i <= 20 ) { print "$i\n"; $i+=2; }

23

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

La seule dirence entre les deux exemples est le fait que, dans le cas du while, la variable e $i existe apr`s la boucle. e Comme pour le if, certaines facilits sont oertes pour le while. Tout dabord, la syntaxe e suivante est correcte : instruction while( condition ); Elle permet dexcuter plusieurs fois une instruction et une seule tant quune condition est e vrie. e e Ensuite, il existe une instruction until (jusqu` en franais) qui a la mme syntaxe que le a c e while mais qui demande une condition darrt (comme unless pour if) : until(condition) e est quivalent ` while(!(condition)) e a Lors de lexcution dune boucle, il est frquent de rencontrer des cas particuliers que lon e e souhaiterait sauter ou pour lesquels on aimerait mettre n a la boucle. Les instructions next, ` last et redo vont nous servir ` cela dans les boucles for, while ou until. a Linstruction next (suivant en franais) provoque la n de lexcution du bloc, le programme c e value directement lincrment (dans le cas dune boucle for) puis le test est eectu. e e e Linstruction last (dernier en franais) provoque la n de la boucle, ni lincrment ni le test c e ne sont eectus. e Linstruction redo (refaire en franais) provoque le redmarrage du bloc dinstructions sans c e que la condition ni lincrmentation ne soient eectues. e e Lexemple suivant est une autre faon dimprimer ` lcran les entiers pairs de 0 ` 20 : c a e a my $i = -1; while( 1 ) { # 1 est vrai $i++; last if( $i > 20 ); next if( $i%2 != 0 ); print "$i\n"; } Dans le cas o` lon souhaite excuter le bloc dinstructions une fois avant deectuer le test, u e on peut utiliser la syntaxe suivante : do { instruction; } while( condition ); Pour des raisons trop longues ` exposer ici, il ne faut pas utiliser les instructions next, last a 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 aborderons ` cette occasion). Vous verrez e ee a alors quen Perl on utilise beaucoup le foreach et assez peu le for(;;).

3.3

Un exemple

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

24

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

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

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

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

25

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

26

Chapitre 4

Listes et tableaux
Les scalaires et les expressions de base nont maintenant plus aucun secret pour vous. Des notions plus complexes et des fonctions plus puissantes sont alors ` notre porte. Cest le cas des a e listes, des tableaux et de limpressionnant arsenal de fonctions Perl permettant de les manipuler ; vous verrez tout ce quil est possible de faire en Perl avec ces deux concepts a priori anodins. Une liste est une suite (donc ordonne) de valeurs scalaires. Nous verrons comment crer une e e liste, la manipuler, la parcourir etc. Une variable de type tableau peut contenir plusieurs valeurs scalaires. Cette notion est prsente dans de nombreux langages de programmation et ne posera sans doute probl`me ` e e a personne. Les passerelles entre listes et tableaux sont nombreuses et tr`s intuitives en Perl. Cest pour e cela que nous nentrerons pas ici dans les dtails de la distinction entre liste et tableau. Dans ce e document, jutiliserai chacun des deux termes ` bon escient sans forcement indiquer explicitement a 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 contenir encadres par e e e e un couple de parenth`ses. Par exemple (2,5,-3) est une liste de 3 scalaires : 2, 5 et -3. Autre e 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 Loprateur dintervalle .. permet de crer une liste comportant des valeurs successives e e entre deux bornes. La liste (1..10) comporte tous les entiers de 1 ` 10 ; on aurait pu aussi a crire (1,2,3,4,5,6,7,8,9,10), mais cette derni`re notation est bien plus lourde. Il faut savoir e e que les valeurs des bornes ne doivent pas obligatoirement tre des nombres : par exemple, la e liste (a..z) comporte toutes les lettres de lalphabet, en minuscule et dans lordre. Il est aussi possible de spcier les bornes ` laide de variables : ($debut..$fin) On comprendra quil e a nest pas toujours possible de rsoudre ce type de liste (par exemple si $debut vaut 1 et $fin e vaut 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 ` 5 lments dont le troisi`me serait a ee e une autre liste, cest en fait une liste ` 6 lments. On aurait pu crire (1,2,"nom",12,"aaa",-1) a ee e

27

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

et on aurait obtenu la mme liste. On appelle cela laplatissement (ou la linarisation) des listes. e e Pour constituer une liste de listes, il faudra faire usage de rfrences (notion que nous aborderons ee plus tard). Loprateur de rptition (x), que lon a dj` appliqu aux cha e e e ea e nes de caract`res prcdemment, e e e sapplique aussi aux listes : (2,10) x 3 est une liste ` 6 lments valant (2,10,2,10,2,10). a 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 un tableau vide, cest-`-dire sans e a lment. De mani`re plus explicite, voici comment dclarer un tableau vide : ee e 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 ` un lment dun tableau grce ` son indice : $t[indice] e a ee a a reprsente llment dindice indice du tableau @t. Notez bien que la globalit du tableau se e ee e reprsente au moyen dune arobase @t alors quun lment particulier est dsign ` laide dun e ee e ea dollar $t[indice], cette derni`re expression tant bien une variable de type scalaire (le dollar est e e rserv aux scalaires en Perl). e e Les indices des tableaux en Perl commencent ` 0 (comme en C), ce qui signie que le premier a lment du tableau @t est $t[0] et le deuxi`me $t[1] etc. Voici un petit exemple dutilisation ee e de tableau : my @t = (3,5); # dclaration et initialisation e $t[1] = 4; # affectation dun lment e e print "$t[0]\n"; # affichage dun lment e e Il est intressant de savoir quil est possible daccder au dernier lment dun tableau en e e ee utilisant lindice -1 : $t[-1] est le dernier lment de @t. De la mme faon, $t[-2] est lavantee e c dernier, etc. Il est possible de conna lindice du dernier lment dun tableau @t grce ` la variable $#t tre ee a a On a donc $t[$#t] quivalent ` $t[-1] (ce dernier tant bien plus lisible). Il peut tre utile de e a e e savoir que lexpression 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) ; $x=@t donnerait la ee mme chose. e Il faut savoir que vous ne gnrerez pas derreur (dbordement ou autre) si vous tentez e e e daccder ` un lment au-del` du dernier. La valeur de cet lment sera simplement undef et le e a ee a ee programme continuera. Depuis la version 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] ) ) { ... }

28

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

Ce test sera vrai si llment dindice 100 du tableau @t existe. Ce qui est dirent du test ee e suivant : if( defined( $t[100] ) ) { ... } Car on teste ici si lexpression $t[100] vaut undef ou non, ce qui peut tre vrai dans deux e cas : soit llment existe et vaut undef, soit llment nexiste pas ... ee ee Voici une autre illustration du fait que vous navez pas ` vous soucier de probl`mes dalloa e cation mmoire : e my @t = (3,23.4,"as"); $t[1000] = 8; Ce programme est correct et fonctionne parfaitement : laectation ` lindice 1000 agrandit a le tableau dautant ... Les lments dindice compris entre 3 et 999 valent undef et scalar(@t) ee vaut 1001. Cest si facile nalement ! Un tableau quil est utile de conna est @ARGV. Cette variable spciale est toujours dnie tre e e (mme dans les fonctions) et ne ncessite pas de dclaration. Elle contient les arguments de e e e la ligne de commande du programme. Les trois faons de lancer un programme en Perl sont c susceptibles dutiliser @ARGV : perl -w -e ... code perl ... arg1 arg2 arg3 perl -w script.pl arg1 arg2 arg3 ./script.pl arg1 arg2 arg3 Ces trois programmes sont lancs avec les trois mmes arguments. Sachez que, contrairement e e 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 e (nul besoin de dclarer cette variable pour lutiliser). e

4.3

Aectations

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

29

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

($a,$b) = (1); Laectation ` $a de la valeur 1 est eectue et $b est mis ` undef (son a e a ancienne valeur est perdue). ($a,$b) = @t; Les variables cites ` gauche reoivent les premi`res valeurs du tableau e a c e @t : $a en reoit le premier lment ou undef si @t est vide ; $b reoit le deuxi`me lment c ee c e ee ou undef si @t il ne contient quun lment. ee @t = (1,2); Cette instruction rinitialise le tableau @t (dont les anciennes valeurs sont e toutes perdues, y compris celles dindice dirent de 0 et 1) en lui aectant les valeurs de e droite : on obtient donc un tableau ` deux lments. a ee ($a,$b) = Fonction(); Nous verrons un peu plus loin comment crire une fonction, et e comment lui faire renvoyer une liste : ici laectation se fait dans les mmes conditions que e pour les trois premiers cas. ($a,$b) = ($b,$a); Cette instruction est la plus savoureuse : on peut changer deux e variables Perl sans avoir ` en utiliser une troisi`me ... (Ai-je dj` dit que Perl soccupe a e ea lui-mme de la mmoire ?) e e

4.4

Multi-dclaration e

Pour dclarer plusieurs variables avec un seul my, le dbutant aurait tendance ` crire la e e a e chose suivante (il ny a pas de honte !) : my $a,$b; # Incorrect !

Ceci est incorrect. Pour pouvoir faire cela, il nous faut utiliser une liste : my ($a,$b); Les variables $a et $b sont cres et valent undef. Pour leur aecter des valeurs, il faut l` ee a aussi utiliser une liste (ou un tableau) : 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 lui-mme un ee e tableau, mais contient les cinq lments, rsultat de laplatissement du tableau @t dans la liste ee e de droite lors de laectation de @t2. Cette aectation a eu le mme rsultat quaurait eu la e e suivante : @t2 = (10,1,2,"age",20);

30

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

4.6

Absorption dune liste par un tableau

La syntaxe suivante est intressante ` conna : e a tre ($a,@t) = @s; Le membre gauche de laectation est constitu dune liste comportant une variable scalaire e et un tableau. Il ny a pas ` proprement parler daplatissement de liste car il sagit ici dune a l-value (membre gauche dune aectation), mais la variable $a reoit le premier lment du c ee tableau @s et le tableau @t absorbe tous les autres (@s ntant bien-sr pas modi). e u e En fait dans cette syntaxe, le premier tableau rencontr dans la liste de gauche reoit tous les e c lments restant de la liste de droite. Dventuelles autres variables qui le suivraient (cas idiot, ee e mais bon...) seraient mises ` undef sil sagit de scalaires et ` vide sil sagit de tableaux. Par a a exemple, laectation suivante : @s = (10,1,2,"age",20); ($a, @t, @u, $b) = @s; quivaut ` : e a @s $a @t @u $b = = = = = (10,1,2,"age",20); 10; (1,2,"age",20); (); undef;

Simple et intuitif.

4.7

La structure de boucle foreach

Cette instruction permet de parcourir une liste. Son implmentation optimise dans line e terprteur Perl rend son usage bien plus ecace quun parcours qui utiliserait une variable e indicielle incrmente ` chaque tour dune boucle for. Sa syntaxe est la suivante : e e a foreach variable ( liste ) { instructions } ` A chaque tour de boucle, la variable aura pour valeur un lment de la liste, la liste tant ee e parcourue dans lordre. Aucune modication ni suppression dans la liste nest eectue par e dfaut dans ce type de boucle. Il vous est possible de modier la variable de boucle (ce qui aura e 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 autres exemples ee sont valides eux-aussi : foreach $v (@t) { .... } foreach $v (32,@t,"age",@t2) { .... }

31

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

Dans le premier cas, les lments du tableau @t sont parcourus. Le second exemple illustre ee les phnom`nes daplatissement des listes qui se retrouvent ici aussi. e e Il est possible de dclarer la variable de boucle dans le foreach de la mani`re suivante : e 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 ` la valeur suivante sans excuter a e les instructions qui la suivent dans le bloc. Linstruction last met n ` la boucle. a Voici un petit exemple dutilisation de foreach achant des tables de multiplication : #!/usr/bin/perl -w use strict; die("Usage: $0 <n> <n>\n") if( !defined( $ARGV[1] ) ); foreach my $i (1..$ARGV[0]) { foreach my $j (1..$ARGV[1]) { printf( "%4d", $i*$j ); } print "\n"; } Et le voici ` luvre : a ./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 ` la suite. a

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

32

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

my @t = (1,2,3,4); Ajout et suppression ` gauche a 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). La fonction shift prend un tableau en argument ; elle supprime son premier lment ee (les autres sont alors dcals) et renvoie cet lment : e e ee $v = shift(@t); $v vaut alors 1 et @t la liste (2,3,4). Ajout et suppression ` droite a La fonction push prend en argument un tableau et une liste de valeurs scalaires ; ces valeurs sont ajoutes ` la n du tableau : e a 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 ee renvoie cet lment : 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 dans le sens oppos : e a ee 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 e dernier lment ` y tre entr sera le premier ` en sortir (last in-rst out) comme pour une pile ee a e e a dassiettes sur une tag`re de placard. On peut utiliser pour cela un tableau, avec les fonctions e e push pour ajouter un lment et pop pour en prendre un. De faon analogue, une le est un ee c endroit o` le premier entr est le premier ` sortir (rst in-rst out) comme pour une le ` une u e a a caisse de magasin. On peut par exemple utiliser les fonctions push pour ajouter un lment et ee shift pour en prendre un. Dautres manipulations plus complexes du contenu dun tableau sont possibles avec la fonction splice, mais je vous renvoie ` la documentation pour les dtails. a 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, e il peut sembler pnible de constituer une longue liste de tels lments en raison du fait quil faut e ee dlimiter chacun dentre eux au moyen de simples ou de doubles quotes : e @t = ( Ceci, est, quelque, peu, pnible, e `, crire, ,, non, ? ); a e Avec qw, ceci devient tout ` coup plus lisible : a

33

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

@t = qw(Cela est bien plus facile ` faire non ?); a La cha de caract`res sera dcoupe selon les espaces, les tabulations et les retours ` la ne e e e a ligne. Les dlimiteurs les plus souvent utiliss sont les parenth`ses (comme dans lexemple prce e e e e dent) ainsi que les slashs : @t = qw/Ou alors comme cela .../; Cette fonction est bien pratique mais peut tre source derreurs, voyez lexemple suivant : e @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 pas ce qui est fait ici. En eet, ni les ee simples quotes ni les doubles quotes ne constituent un moyen de regrouper des mots pour lope rateur qw. La liste ainsi cre comporte donc 4 lments ; on aurait pu crire : ee ee e ("attention","aux","erreurs","b^tes"). e

4.10

Joindre les lments dans une cha avec join ee ne

La fonction join prend en param`tre un scalaire et une liste ; elle renvoie une cha de e ne caract`res comportant les lments de la liste, concatns et spars par ce premier param`tre e ee e e e e e scalaire. Les arguments passs ne sont pas modis. e 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 ` $s. e ea $s = join(" : ",@t); La variable vaut alors la concatnation des valeurs du tableau @t e avec " : " pour sparateur. e

4.11

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

La fonction split prend en param`tres un sparateur et une cha de caract`res ; elle e e ne e renvoie la liste des lments de la cha de caract`res dlimits par le sparateur. Le sparateur ee ne e e e e e est une expression rguli`re, notion que nous aborderons dans la suite, mais dont le minimum e e de connaissances sut ` cette fonction ; admettez ici quune telle expression est ` placer entre a a 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 4, 12 et 455. ee ($x,$y) = split(/==/,$v); Les deux variables auront pour valeur les deux premi`res e cha nes de caract`res qui soient spares par deux signes dgalit. e e e e e print join(:,split(/ /,salut ici)); Ache salut:ici (il existe des mthodes e plus ecaces et plus lisibles de faire cela...).

34

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

4.12

Trier une liste avec sort

La fonction sort prend en param`tres un bloc dinstructions optionnel et une liste ; elle e renvoie une liste trie conformment au crit`re de tri constitu par le bloc dinstructions. La e e e e liste passe en argument nest pas modie. e e liste2 = sort( liste1 ); liste2 = sort( { comparaison } liste1 ); (attention ` ne pas mettre de virgule entre le a bloc dinstructions et la liste) Tout au long du tri, le bloc dinstructions sera valu pour comparer deux valeurs de la liste ; e e ces deux valeurs sont localement aectes aux variables spciales $a et $b qui ne sont dnies que e e e dans le bloc et sur lesquelles il faut donc eectuer la comparaison. Il faut faire particuli`rement e attention au fait que sil existe des variables $a et $b dans le programme elles seront localement masques par ces variables spciales (source courante derreurs). Le bloc doit tre compos dune e e e e expression dont la valeur est : 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 <=> : ils permettent de a e comparer respectivement les cha nes de caract`res selon lordre lexical et les nombres selon e lordre numrique. Si la fonction sort est appele sans bloc dinstructions, la liste est trie selon e e e lordre lexical. Voici quelques exemples : @s = sort( {$a cmp $b} @t ); La liste @s a pour valeur la liste @t trie selon lordre e lexical. @s = sort( @t ); Le fonctionnement est identique ` lexemple prcdent. a e e @s = sort( {$a <=> $b} @t ); Le crit`re de tri est ici numrique. e e @s = sort( {length($b) <=> length($a) or $a cmp $b} @t ); Une expression compose peut bien sr servir de crit`re : le tri est ici dabord numrique inverse sur la longueur e u e e puis lexical. Cela permet deectuer un second tri pour les lments gaux selon le crit`re ee e e du premier tri. @s = sort( { fonction($a,$b) } @t ); Vous pouvez crire votre propre fonction de e tri (` deux arguments) ; elle doit renvoyer un nombre dont la valeur dpend de lordre a e voulu (voir juste avant).

4.13

Slectionner des lments avec grep e ee

La fonction grep prend en param`tres un crit`re de slection et une liste ; elle renvoie la liste e e e des lments correspondant au crit`re. La liste passe en argument nest pas modie. ee e e e Le crit`re de slection peut tre soit une expression rguli`re (cas sur lequel nous reviendrons e e e e e 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 virgule) e e Les lments renvoys sont ceux pour lesquels lvaluation du bloc dinstructions a pour ee e e valeur vrai. Durant cette valuation, chacune des valeurs sera localement aecte ` la variable e e a spciale $_ sur laquelle les tests devront donc tre eectus. e e e Voici quelques exemples : @t = grep { $_<0 } $x,$y,$z; Aecte ` @t les lments ngatifs de la liste. a ee e

35

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

@s = grep { $_!=8 and $_!=4 } @t; Met dans @s les lments de @t dirents de 4 et ee e de 8. @s = grep { fonction($_) } @t; Vous pouvez crire votre propre fonction de slection ; e e elle doit renvoyer vrai ou faux selon que llment est ` garder ou non. ee a En contexte scalaire, la fonction grep renvoie le nombre dlments qui correspondent au ee 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 ` lexpression rguee e a e li`re. Par exemple @s = grep( /^aa/, @t ); aecte ` @s les lments de @t qui commencent e a ee par deux lettres a. Plus dexplications sur les expressions rguli`res seront donnes dans la suite. e e e Jai arm que la liste dorigine ntait pas modie, mais il vous est possible de le faire. e e e Si, durant la slection, vous aectez une valeur ` $_, la liste sera modie. Mais cela est sans e a e doute une mauvaise ide de modier la liste passe en param`tre dun grep car la fonction map e e e est faite pour cela.

4.14

Appliquer un traitement ` tous les lments avec map a ee

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

36

Chapitre 5

Ecrire une fonction


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

5.1

Dclaration e

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

37

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

la variable $x reoit le premier param`tre et le tableau @t reoit tous les param`tres restants. c e c e Enn, une autre criture que vous verrez souvent dans les programmes Perl est la suivante : e my $x = shift; celle-ci sappuie sur le fait que dans une sous-routine, la fonction shift travaille par dfaut e sur @_. Linstruction return met n ` lexcution de la fonction et on peut lui fournir une expression a e 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 suivante : e e e maJolieFonction(10,20,30); Dans ce cas, lventuelle valeur de retour est ignore. Pour rcuprer cette valeur : e e e e $v = maJolieFonction(10,20,30); Il est possible domettre les parenth`ses lors de lappel a une fonction : e ` maJolieFonction 10,20,30; # ` viter A e

mais cela peut crer des ambigu es et je vous dconseille donc cette syntaxe. e t e 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 nous empche en eet dappeler la e e fonction maJolieFonction prcdemment dnie avec deux ou quatre arguments, alors quelle e e e semble en attendre trois ; si on lappelle avec deux arguments, la variable $t vaudra undef ; par contre si on lappelle avec plus de trois arguments, les valeurs suivantes seront ignores. Mais e cette particularit du langage est parfois bien pratique, notamment pour crire des fonctions ` e e a nombre variable darguments.

5.3

Visibilit des variables e

Les variables dclares au moyen de my dans une fonction ne seront visibles qu` lintrieur e e a e mme de la fonction, dans le code qui suit la dclaration. Dans une fonction, il est possible e e daccder aux variables dnies ` la racine du programme (cest-`-dire en dehors de toute e e a a fonction) : il sagit 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"; # affiche 5

38

c Sylvain Lhullier

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

http://formation-perl.fr/

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

# affiche 3 # affiche 8 # affiche 15

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

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

5.4

Une liste pour valeur de retour

Il est tout ` fait possible de faire renvoyer plusieurs scalaires par une fonction, il sut juste a 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 chacune dans les deux cas e e e e de return pr-cits (ce sont toujours les mmes r`gles daectation qui sappliquent). e e e e

5.5

Premier exemple de fonction

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

39

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

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

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

# variable globale # avec ou sans parenth`ses e # deux arguments attendus

# retourne une liste

Un bon programme Perl commence toujours par les premi`re et deuxi`me lignes. Si la variable e e scalaire $t, elle, est globale, en revanche les variables $x, $z et $m sont locales ` la fonction. En a ligne 11, le tableau @t reoit pour valeur la liste renvoye par la fonction. Notez bien quil ny c e a aucun conit entre les variables $t et @t ; en eet, linstruction de la derni`re ligne proc`de e e dabord ` lachage de la variable scalaire $t puis du premier et deuxi`me lments du tableau a e ee @t (les crochets permettent de savoir quil 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 appel ` elle-mme) : e a a e nous allons calculer la factorielle dun nombre. Par dnition, F(0)=F(1)=1 et F(n)=nF(n-1) e pour tout n suprieur ` 1 : e a sub Fact { my ($n) = @_; return 1 if( $n == 1 || $n == 0 ); return $n * Fact($n-1); } print Fact(5)."\n"; # affiche 120 Aussi lisible que dans tout autre langage.

5.7

Dernier exemple : le crible dEratosth`ne e

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

40

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

(4 tant multiple de 2, il a dj` t supprim), jenl`ve de la liste les multiples de 5 et annonce e eaee e e la primalit de 5 etc ... Lalgorithme se termine lorsque la liste est vide, jai alors dtermin tous e e e les nombres premiers infrieurs ` n. e a 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 lments (un tableau e 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 joie que cette concision ea e e procure ...

41

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

42

Chapitre 6

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

6.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 = ();

43

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

Pour donner des valeurs initiales ` notre table de hachage, on peut utiliser la syntaxe suiva ante : 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 Paul, Virginie et e e e e Pierre ayant respectivement pour valeurs 01.23.45.67.89, 06.06.06.06.06 et heu ...

6.2

Accder ` un lment e a ee

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

44

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

6.3

Parcours

Il existe trois fonctions permettant de parcourir une table de hachage. Dans les exemples fournis, nous considrerons que la table %h a t dclare ainsi : e ee e e

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 une liste comportant e toutes les clefs de la table. Lordre des clefs est quelconque, seule lexhaustivit des clefs e est garantie. my @t = keys(%h); Le tableau @t peut par exemple valoir la liste ("Virginie", "Pierre", "Paul"). Cette fonction va nous permettre de parcourir toute la table de hachage en eectuant une boucle sur la liste des clefs : foreach my $k (keys(%h)) { print "Clef=$k Valeur=$h{$k}\n"; } La variable de boucle $k prendra pour valeurs successives lensemble des clefs de la table, lexpression $h{$k} est la valeur associe ` la clef $k. Ce petit programme achera donc e a 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 hachage, la fonction e c 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 table %h. e ee a Il nest bien sr pas possible de retrouver la clef des valeurs que lon manipule ainsi. u Il peut tre intressant de savoir que lordre des clefs renvoyes par keys et celui des valeurs e e e par values sera le mme ` condition de ne pas modier la table de hachage entre temps. e a each : itration sur les couples (clef,valeur) e Cette fonction renvoie un ` un tous les couples (clef,valeur) dune table de hachage. Elle a a un comportement un peu spcial du fait quil faut lappeler autant de fois quil y a de e couples : cest une fonction avec tat, cest-`-dire quelle ne renvoie pas toujours la mme e a e chose dun appel ` lautre : en eet, elle renvoie le couple suivant ! De ce fait, je vous a conseille de toujours lutiliser dans la syntaxe qui suit : while( my ($k,$v) = each(%h) ) { print "Clef=$k Valeur=$v\n"; } Libre ` vous de parcourir vos tables de hachage avec la fonction qui vous convient le mieux. a

45

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

6.4

Autovivication

Sous ce terme barbare se cache une ide simple : si vous tentez de modier un lment dune e ee table de hachage qui nexiste pas, il sera cr. Sil est utilis dans un contexte numrique, il ee e e prendra pour valeur initiale zro. Sil est utilis dans un contexte de cha de caract`res, il e e ne e prendra pour valeur la cha vide (depuis Perl 5.6). ne Par exemple, considrons une table de hachage qui ne comporte pas la clef hello ; lexpression e suivante $h{hello} .= "apr`s"; e associe ` la clef hello la valeur cha vide puis lui concat`ne la cha "apr`s". De la mme a ne e ne e e faon, lexpression c $h{bye}++; cre un lment de valeur 1. e ee Cette proprit dautovivication est bien pratique dans le cas o` lon ne conna pas les clefs ee u t avant de devoir y accder. Par exemple nous allons pouvoir compter le nombre doccurrences e des mots dans un texte de mani`re tr`s simple. Supposons que les mots du texte soient dj` e e ea dans un tableau (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 ` notre exemple). Nous e a allons utiliser chaque mot comme une clef de la table et nous allons ajouter 1 ` la valeur de cette a 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 des expressions e rguli`res. e e

6.5

Existence et suppression dune clef

` A la lecture de ce qui prc`de, il peut sembler impossible de savoir si un lment dune table e e ee de hachage existe ou non. Rassurez-vous, les auteurs de Perl ont tout prvu :-) Loprateur e e exists renvoie vrai si llment de table de hachage quon lui donne en param`tre existe ; sinon ee e il renvoie faux. Par exemple :

46

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

if( exists( $h{hello} ) ) { print "La clef hello existe\n"; } Il est important de noter quun test eectu au moyen de loprateur defined aurait t e e ee possible, mais dangereux. En eet, lexpression defined( $h{hello} ) est fausse dans deux cas tr`s dirents : soit si llment nexiste pas, soit si llment existe et vaut undef ; elle sera vraie e e ee ee si llment existe et ne vaut pas undef. Il est donc impossible de distinguer le cas dun lment ee ee absent et celui dun lment indni (valant undef) avec defined. ee e Cette distinction entre absent et indni peut para articielle dans ce cas (elle peut tout e tre de mme tre importante dans certaines situations !), mais dans le cas de la suppression dune e e clef, il en est tout autrement. Pour supprimer une clef dans une table de hachage, il faut utiliser loprateur delete. Line struction 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 lexistence dun lment, delete e c e ee est la bonne mthode pour en supprimer un. Le dbutant pourrait tre tent dcrire : e e e e e $h{hello} = undef; # attention!

Ce qui est fort dirent car, dans ce cas, la clef hello aura une valeur indnie, mais existera e e toujours ! On la retrouvera, par exemple, dans les parcours eectus au moyen des oprateurs e e keys, values ou each ; ce qui nest sans doute pas le but recherch. e Pour rsumer, on peut dire que pour tester lexistence dune clef, il faut utiliser exists et e que pour en supprimer une, il faut utiliser delete. En marge de ces deux fonctions, voici une mani`re de savoir si une table de hachage est vide e 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 total disponibles dans le hachage. Une table vide est un cas e particulier, elle renverra 0.

6.6

Tables de hachage et listes

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

47

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

La premi`re instruction cre un tableau @t initialis ` une liste ` 6 lments. La seconde e e e a a ee cre une table de hachage %h initialise au moyen du prcdent tableau. Les valeurs du tableau e e e e sont prises deux ` deux : la premi`re de chaque couple sera la clef dans la table de hachage, la a e seconde la valeur. Si le nombre dlments de la liste est impair, la derni`re clef cre aura undef ee e ee pour valeur. Si une clef venait ` tre prsente plusieurs fois dans la liste, cest la derni`re valeur ae e e qui sera prise en compte dans la table de 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 ` noter que cette syntaxe rappelle trangement lun des premiers exemples de cration a e e de table de hachage qui utilisait => pour sparer clefs et valeurs. Cette similarit est en fait e e une quasi-quivalence, car loprateur => peut tre utilis ` la place de la virgule pour crer des e e e ea e listes ; il na t ajout au langage Perl que pour faciliter la lecture des aectations de tables ee e de hachage, car il force un contexte de cha ` sa gauche, ce qui permet justement dcrire ne a e %a = ( toto => titi ); La conversion dans lautre sens est aussi possible. Lvaluation dune table de hachage dans e 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 e e peut tre aecte ` un tableau : e e a 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 (clef,valeur) est e e quelconque (un peu comme pour la fonction each). Une table de hachage se convertit en liste sans encombre d`s quelle est en contexte de liste. e 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 employe pour inverser e e une table de hachage : %h = reverse(%h); Les valeurs deviennent les clefs et inversement. Si plusieurs valeurs identiques sont prsentes e le comportement est imprvisible car, certes, lors de la transformation de liste en table de hachage e la derni`re valeur compte, mais lors de la transformation de table de hachage en liste lordre est e quelconque ... Lassociation individu - numro de tlphone est idale pour illustrer cela : e ee e my %h = ("Paul", "01.23.45.67.89", "Virginie", "06.06.06.06.06", "Pierre", "heu ..."); my %quidonc = reverse %h;

48

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

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

6.7

Exemples

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

49

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

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

# Je reconstitue des tableaux ` partir a # 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 de hachage, je vous e e 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}++; } 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 notions importantes e e vues jusquici.

50

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

6.8

Tranches de tableau

Maintenant que nous connaissons tous les types de donnes de Perl, notamment les tableaux e et les tables de hachage, nous allons maintenant voir comment on peut manipuler plusieurs lments dun tableau ou dune table de hachage ` la fois. Cela sappelle une tranche (slice en ee a anglais). Une tranche de tableau est un sous-ensemble des lments du tableau. Imaginons par exee emple un tableau @t duquel nous souhaiterions manipuler les lments dindice 4 et 10 ; pour ee cela nous allons prendre la tranche correspondante de ce tableau : @t[4,10] est une liste ` a deux lments qui est quivalente ` ($t[4],$t[10]) Quelques explications sur la syntaxe. Tout ee e a dabord, lexpression commence par une arobase, car il sagit dune liste dlments ; le dollar ee est rserv aux scalaires, par exemple $t[4] est un scalaire. Ensuite, comme dhabitude pour e e les tableaux, les crochets permettent de spcier les indices. Enn, lensemble des indices est e indiqu par une liste dentiers : @t[2,10,4,3] @t[3..5] @t[fonction()] ... e Une telle tranche est utilisable comme valeur (passage de param`tres, etc) et comme l-value e (expression ` gauche du signe gal daectation) : a e @t[4,10] = (4321,"age"); cette instruction aecte 4321 ` lindice 4 du tableau @t et la cha age ` lindice 10. On a ne a aurait pu crire e ($t[4],$t[10]) = (4321,"age"); Une autre utilisation des tranches de tableau appara avec les fonctions qui renvoient une t liste. Par exemple la fonction stat prend en param`tre un nom de chier et renvoie toute sorte e 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 de gauche. Les tranches e peuvent intervenir si seules quelques informations vous intressent et que vous ne voulez pas e dclarer de variables inutiles. Par exemple, si seules les dates de modication (indice 9) et de e cration (indice 10) vous intressent, vous pouvez crire : e e e ($mtime,$ctime) = ( stat($filename) )[9,10]; Lappel ` la fonction est plac entre parenth`ses et on ne prend que les lments dindice 9 a e e ee et 10 de sa valeur de retour. On a alors une liste ` deux lments, celle-ci est aecte ` la liste a ee e a a ` gauche du signe gal et donc ces deux lments sont aects aux deux variables. e ee e

6.9

Tranches de table de hachage

De la mme faon quil existe des tranches pour les tableaux et les listes, il en existe pour les e c tables de hachage. La slection seectue bien sr sur les clefs. Par exemple, si %h est une table de e u hachage, alors @h{clef1,clef2} est une liste quivalente ` ($h{clef1},$h{clef2}) e a

51

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

Il est ensuite possible dutiliser cette liste comme bon vous semble (aectation, passage en param`tre, etc). e Une utilisation (assez complexe) des tranches serait indique lorsque lon veut construire e automatiquement une liste de valeurs uniques ` partir dun tableau dont on nest pas sr que a u ses valeurs soient uniques : # 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 @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

52

Chapitre 7

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

7.1

Oprateurs sur les noms de chier e

Perl dispose doprateurs prenant en param`tre un nom de chier ; ce nom de chier doit e e tre un scalaire (une variable ou une constante). Leur valeur de retour est souvent boolenne e e et quelquefois numrique. Les coutumiers du shell retrouveront de nombreuses options de la e commande test. -e teste si son param`tre est un chemin valable dans le syst`me de chier (rpertoire, e e e chier, etc). On pourrait lutiliser ainsi : 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 -f ou -d renvoie e vrai. -r teste si le programme a le droit de lire le chier/rpertoire/etc pass en param`tre. e e e -w teste si le programme a le droit dcrire. e -x teste si le programme a le droit dexcuter le chier ou daccder (ou axder :-)) au e e e rpertoire. e -o teste si le chier appartient ` lutilisateur qui excute le programme. a e -z teste si le chier est vide. -s teste si le chier est non vide ; en fait cet oprateur renvoie la taille du chier. e -M renvoie lge en jour du chier (depuis le dbut de lexcution du programme). a e e Il existe tout plein dautres oprateurs sur les chiers ; pour en conna la liste compl`te, e tre e je vous invite ` lancer la commande perldoc -f -X a Voici quelques exemples dutilisation de ces oprateurs : e my $file = "/usr/doc/perl";

53

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

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

7.2

La fonction glob

La fonction glob prend en argument une expression et renvoie une liste de noms de chiers. Cette liste correspond ` lvaluation de lexpression selon les wildcards du shell. a e Par exemple, glob( *.o ) renvoie la liste des chiers du rpertoire courant ayant lextene sion .o Notez bien quil ne sagit pas dune expression rguli`re (pour ceux qui connaissent ; pour les e e autres, nous en parlerons plus tard), mais bien dune expression telle quon la donnerait ` un a 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 ` cette fonction : lexpression a peut tre mise entre chevrons. Les deux lignes suivantes eectuent la mme opration : e 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 des noms absolus e e des chiers dinclude pour le C du rpertoire /usr/include e

7.3

Premiers exemples

Voici un premier exemple de manipulation de noms de chiers : #!/usr/bin/perl -w use strict; foreach my $name ( <*> ) { print "$name\n" if( -l $name ); } Il ache les liens symboliques du 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 courant sur lesquels e e jai les droits dcriture (y-compris ceux commenant par un point, donc . et ..). e c

54

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

7.4

Ouverture de chier

Pour lire ou crire dans un chier, il est ncessaire de louvrir pralablement. La fonction eece e e tuant cette opration en Perl se nomme open et sa syntaxe est la suivante : open( HANDLE, expression ) e Le param`tre HANDLE sera lidentiant du chier apr`s ouverture (on pourrait parler de e e descripteur de chier). Cest ce descripteur qui devra tre fourni aux fonctions de lecture et e dcriture pour manipuler le chier. Pour ne pas rentrer trop dans les dtails, un descripteur de e e chier se reprsente dans le code Perl par une simple cha de caract`res (sans quotes pour la e ne e dlimiter, ni de $ pour la dbuter) ; la convention veut quon le mette toujours en majuscules. e e Le param`tre expression est un scalaire (cha de caract`res) comportant le nom du chier e ne e a ` ouvrir prcd de zro, un ou deux caract`res indiquant le mode douverture : e e e e e 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

Les 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.htm louvre en criture-crasement (cest-`-dire que le chier sera vid avant que le curseur ne soit e e a e plac au dbut du chier). e e Cette fonction open renvoie une valeur boolenne vrai ou faux indiquant le bon droulement e e ou non de lopration. Il est tr`s important de tester les valeurs de retour des fonctions manipulant e e les chiers (cela est vrai quel que soit le langage), car on ne peut jamais tre sr de rien. Voici e u deux exemples de tests de la valeur de retour dopen : if( ! open(FIC,">>data.txt") ) { exit(1); } Dans ce premier exemple, on tente douvrir en ajout un chier data.txt ; en cas dimpossibilit, on appelle la fonction exit qui met n au programme (la valeur 1 signale une erreur ; la e valeur 0 signalant la n normale du programme, les autres valeurs sont utilises pour signaler e au shell appelant une 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 quil y a eu un e e probl`me avec louverture de ce chier, mais il nen conna pas la cause. Lexemple suivant va e t nous permettre de lui acher un joli message derreur : open(FIC2,"</tmp/$a") or die("open: $!"); Nous cherchons ici ` ouvrir en lecture le chier dont le nom serait la concatnation de la a e cha /tmp/ et du contenu de la variable $a. La fonction die met n au programme comme ne exit le ferait, mais ache en plus le param`tre quon lui passe. En loccurrence, le param`tre e e fourni est la cha de caract`res comportant le nom de la fonction qui cause lchec (on aurait ne e e pu ajouter le nom du chier) ainsi que la variable $!. En contexte de cha de caract`res, ne e

55

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

cette variable magique $! contient le message errno de la derni`re erreur survenue, par exemple e No such file or directory ou Permission denied etc. Lutilisateur est donc inform de la e cause de la n du programme. La syntaxe open() or die(); ainsi que sa signication proviennent de lvaluation pae resseuse du or. En eet, dans lexpression (a or b) si a est vrai, il nest pas ncessaire dvaluer e e b pour conna la valeur de lexpression. Cest ce quil se passe ici : si open() renvoie vrai, il tre nest pas ncessaire dvaluer die(). e e Les descripteurs de chier sont dune esp`ce trange en Perl, le dbutant sabstiendra de e e e chercher ` trop comprendre les mcanismes sous-jacents. Ce que lon pourrait dire, cest quil a e nest pas ncessaire de dclarer un descripteur de chier, la fonction open valant dclaration. e e e

7.5

Lecture, criture et fermeture de chier e

Une fois un chier ouvert, il nous est possible dcrire et/ou de lire dedans (selon le mode e douverture) et de le fermer. La lecture des chiers texte seectue typiquement au moyen de loprateur chevrons, cette e lecture se faisant ligne par ligne. $l = <FIC>; Cette instruction lit la prochaine ligne disponible du chier FIC. Vous noterez bien que lope rateur chevrons (diamond operator en anglais) est ici en contexte scalaire. En contexte de liste, il renvoie la liste de toutes les lignes restant dans le chier : @t = <FIC>; Cette instruction absorbe toutes les lignes du chier dans une liste qui est place dans le e tableau @t. Pour itrer sur les lignes dun chier, il est courant de faire ainsi : e while( defined( $l = <FIC> ) ) { chomp $l; print "$. : $l\n"; } La boucle while donne pour valeur ` la variable $l une ` une toutes les lignes du chier. a a La fonction chomp supprime le dernier caract`re sil sagit dun retour ` la ligne. La variable e a spciale $. vaut le numro de la ligne courante du dernier chier lu (ici FIC). e e Si vous utilisez la variable spciale omniprsente $_, 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 printf que nous avons e dj` vues. Elles prennent en premier argument le descripteur de chier : ea

56

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

print( FIC "toto\n" ); printf( FIC "%03d", $i ); Il faut noter quil ny a pas de virgule apr`s le descripteur de chier (il ne faut pas en mettre !). e Les parenth`ses sont comme toujours optionnelles autour des arguments, mais permettent de e lever certaines ambigu es. La fonction printf fonctionne comme printf ou fprintf du C et t ne sera donc pas dtaille ici (voir man~3~printf). e e Pour fermer un descripteur de chier (et donc vider les buers associs), il faut faire appel e a ` la fonction close : close( FIC ); ` A noter que si vous rutilisez un descripteur de chier dans un open sans faire de close au e pralable, Perl ne rousptera pas et fermera consciencieusement le premier chier avant douvrir e e le deuxi`me. e Il existe plusieurs chiers ouverts automatiquement par Perl d`s le lancement du programme : e STDIN : lentre standard (souvent le clavier). e STDOUT : la sortie standard (souvent le terminal). Par dfaut print et printf crivent sur e e ce ux. STDERR : la sortie derreur standard (souvent le terminal). Par dfaut warn et die crivent e e sur ce ux. ARGV : ce descripteur est un peu spcial, mais souvent bien pratique. Les lignes lues sont e celles des chiers de la ligne de commande (donc les arguments passs au programme sont e considrs comme des noms de chier) ; si le programme est lanc sans argument, lentre ee e e standard est lue. NB : vous pouvez crire soit <ARGV> soit <> La variable spciale $ARGV e e 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 plutt ` des chiers contenant e ` o a du texte. Vous pouvez, pour cela, utiliser la fonction getc qui renvoie le prochain caract`re e disponible : $c = getc(FIC); Vous pouvez aussi faire usage de la fonction read qui lit un nombre dtermin de caract`res : $tailleLue = read(~FIC,~$tampon,~$taille`Lire ); Les e e e A ` donnes seront places dans la variable $tampon. A la n du chier, ou sil y a un probl`me, le e e e tampon nest pas compl`tement rempli. Cest pour cela que lon rcup`re la valeur de retour de e e e read. Pour crire des donnes non textuelles dans un chier, vous pouvez tout ` fait utiliser les e e a fonctions print et printf car les cha nes de caract`res de Perl peuvent contenir le caract`re de e e code ASCII zro. On notera que la fonction write existe, mais nest pas linverse de read. e Sil vous est ncessaire dutiliser les fonctions dentre/sortie bas niveau, voici leurs noms en e e Perl : sysopen, sysread, syswrite et close.

7.6

Deuxi`me exemple e

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

57

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

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

7.7

Excution de commandes avec open e

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

7.8

Ecrire une table de hachage sur disque avec les chiers DBM

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

58

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

Nous allons directement passer ` un exemple. Il comporte deux phases : dans la premi`re nous a e allons crer un chier DBM comportant un couple clef/valeur, dans la seconde nous utiliserons e 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 exploitables de la sorte : ee my %h; dbmopen(%h,"data",0644) or die($!); print "$h{prenom}\n"; dbmclose(%h) or die($!); Lors de cet appel ` dbmopen la table %h retrouve la valeur quelle avait lors du dbmclose du a premier script.

59

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

60

Chapitre 8

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

8.1

Fonctionnalits e

Il existe deux types principaux de fonctionnalits dans les expressions rguli`res : la corree e e spondance (pattern matching en anglais : pattern=motif, matching=correspondance) et la substitution. La correspondance est le fait de tester (vrier) si une cha de caract`res comporte un e ne e certain motif. Par exemple, on pourrait se poser les questions suivantes et y rpondre par un e match : la variable $v commence-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 ? Etc. ne e e e e Sa syntaxe est la suivante : m/motif/ Le m indique que nous voulons faire un match, les slashes (/) servent ` dlimiter le motif a e recherch (on verra plus loin comment utiliser dautres sparateurs). e e Cette fonctionnalit nous permettra aussi dextraire des sous-cha e nes dune variable donne e sans la modier. Par exemple, si je veux rcuprer le premier nombre que comporte $v, jutiliserai e e aussi la correspondance. La substitution permet de faire subir des transformations a la valeur dune variable. Par ` exemple : remplacer dans la variable $v toutes les sous-cha nes toto par titi. Supprimer de $v tous les mots entre guillemets. Etc.

61

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

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

8.2

Bind

Pour lier une variable ` une telle expression, il faut utiliser loprateur =~ (dit bind en a e anglais). $v =~ m/sentier/ vrie si la variable $v comporte le mot sentier. On dit alors que la e variable est lie ` lexpression rguli`re. Cette expression vaut vrai ou faux ; nous lutiliserons e a e e donc tr`s souvent dans une structure de contrle de type if : e o if( $v =~ m/sentier/ ) { instructions } Dans les cas o` le test est vrai, cest-`-dire si la variable contient le motif (ici si $v contient u a sentier), les instructions seront excutes. e e Par cette opration de bind, nous venons de lier une expression rguli`re ` une variable. Par e e e a dfaut, une telle expression sapplique ` la variable $_ (comme beaucoup de fonctions Perl). e a De la mme faon, e c $v =~ s/voiture/pieds/; remplace la premi`re occurrence de voiture dans la variable $v par pieds (on verra plus loin e comment remplacer toutes les occurrences). Le reste de $v nest pas modi. Le point-virgule e indique la n de linstruction. Pour la correspondance, il existe aussi loprateur !~ qui quivaut ` =~ suivi dune ngation e e a e de lexpression. if( $w !~ m/pieds/ ) { ... } est plus concis et est quivalent ` e a if( ! ( $w =~ m/pieds/ ) ) { ... } Les instructions sont excutes si $w ne contient pas la cha pieds. e e ne

8.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 lorsque lon utilise e e e e lexpression rguli`re m/a/ on vrie si la variable (ici non cite) contient le caract`re a. Cela e e e e e semble vident, mais il est bon de le dire. e En eet, pour certains caract`res spciaux, cela nest pas le cas. Ces caract`res ont un rle e e e o particulier dans les expressions rguli`res (nous allons voir cela dans la suite). Si vous avez besoin e e

62

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

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

8.4

Ensembles

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

63

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

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

8.5

Quanticateurs

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

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

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

8.6

Ensembles (suite)

Nous allons ici numrer un certain nombre de raccourcis pour des ensembles courants : e e \d : un chire, quivalent ` [0-9] (d comme digit, chire en anglais) e a \D : un non-numrique, quivalent ` [^0-9] e e a \w : un alphanumrique, quivalent ` [0-9a-zA-Z_] (w comme word, cest un caract`re e e a e dun mot) \W : un non-alphanumrique, quivalent ` [^0-9a-zA-Z_] e e a \s : un espacement, quivalent ` [~\n\t\r\f] (s comme space) e a \S : un non-espacement, quivalent ` [^~\n\t\r\f] e a

64

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

On remarquera quun ensemble et son complmentaire sont nots par la mme lettre, lune e e e est minuscule, lautre majuscule. Par exemple, lexpression rguli`re suivante : m/[+-]?\d+\.\d+/ permet de reconna un e e tre nombre dcimal, sign ou non : un caract`re + ou - optionnel, au moins un chire, un point et e e e enn au moins un chire.

8.7

Regroupement

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

8.8

Alternatives

Il est possible davoir le choix entre des alternatives ; il faut pour cela utiliser le signe pipe () : lexpression m/FredPaulJulie/ reconna les mots comportant soit Fred, soit Paul, t soit Julie. De la mme faon, lexpression m/FredPaulJulie Martin/ reconna les cha e c t nes comportant soit Fred, soit Paul, soit Julie Martin mais rien noblige Fred ` sappeler Fred Martin a ni Paul ` sappeler Paul Martin, comme on aurait sans doute aim que cela se fasse (dans ces a e deux derniers cas, seul le prnom est reconnu, pas le nom). Pour cela, vous lavez compris, un e regroupement est ncessaire. Lexpression rguli`re e e e m/(FredPaulJulie) Martin/ reconna les trois fr`res et sur de la famille Martin. t e

8.9

Assertions

Une assertion marque une position dans lexpression, elle ne correspond ` aucun caract`re a e (aucune consommation de caract`res nest eectue). e e Par exemple, laccent circonexe (^) correspond au dbut de la cha Lexpression $v =~ m/^a/ e ne. est vraie si la variable $v commence par la lettre a. Le signe ^ a donc plusieurs rles. Sil est au dbut dun ensemble entre crochets, il permet o e den prendre le complmentaire ; sil est au dbut de lexpression rguli`re, il marque le dbut e e e e e de la cha ne. On veillera ` ne pas les confondre. a Le dollar ($) correspond ` la n de la cha Lexpression $v =~ m/c$/ est vraie si la variable a ne. $v se termine par la lettre c.

65

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

Ces deux assertions sont les plus courantes. Il en existe dautres dont \b qui marque un dbut e ou une n de mot ; cest-`-dire entre \w et \W (ou entre \w et une n ou dbut de cha a 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 lettre o et la lettre e e e M.

8.10

Rfrences arri`res ee e

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

8.11

Variables dnies e

Ces variables spciales $1, $2 etc. sont aussi accessibles apr`s lexpression rguli`re (jusqu` e e e e a la n du bloc courant ou une autre expression rguli`re). Elles correspondent bien sr aux e e u sous-cha nes matches entre parenth`ses. Nous pouvons nous en servir pour extraire certaines e e sous-cha nes et les utiliser ensuite.

66

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

Il existe aussi trois autres variables, dont je vous dconseille lusage, mais qui peuvent tre e e intressantes : 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 prsence dans e e e un script active pour tout le script des mcanismes particuliers dans le moteur dexpressions e rguli`res, qui ont pour eet secondaire den ralentir fortement la vitesse dexcution. Si vous e e e avez besoin de ces variables dans un petit script qui ne sert qu` cela, pas de probl`me pour les a e utiliser, mais vitez leur usage dans un projet de plusieurs milliers de lignes ou dans un script e 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.

8.12

Valeurs de retour de m//

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

67

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

8.13

Exemples de probl`mes e

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

8.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 dune espace, puis e ventuellement dun nombre (\d*), puis dune espace optionnelle ( ?) et enn du signe e deux-points. Si cest le cas, les instructions du if sont excutes. e e

68

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

if( $v =~ m/^"([a-z]{4,})",/ ) { print "$1\n"; } On vrie que $v commence par un guillemet, suivi dau moins quatre lettres minuscules e (que lon mmorise), dun autre guillemet puis dune virgule. Si la variable est du bon e 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 minuscules (au moins e 1) puis une deuxi`me suite de caract`res en minuscules (ventuellement aucun) et enn la e e e mme suite de caract`res que la premi`re suite. On cherche donc un mot (suite de lettres) e e e dont un certain nombre de lettres se rp`tent. Si la variable $v comporte un tel mot, on e e achera ces lettres rptes. e ee ($n,$m) = ( $v =~ m/(\w+)=(\d+)/ ); On recherche une suite alphanumrique, un signe gal puis un nombre. Il sagit dune e e 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 et le nombre de e e e 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 ne comporte pas e ne ne de ". Tout cela est remplac par D=motif o` motif est inchang. e u 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 par un signe e e e e dopration mathmatique). e e Encore un match. Nous cherchons un nombre \d+ que nous mmorisons (parenth`ses). Un e e signe doit suivre (il faut dspcier le signe de la division car il est aussi le sparateur de e e e lexpression rguli`re). Finalement le mme nombre quavant doit tre prsent (\1) : e e e e e

69

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

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 e ne avec ^, on prend un caract`re avec . que lon mmorise, puis de la mme faon pour le e e e c deuxi`me. Vous noterez que, dans ce cas, lusage de la fonction substr est possible (et e 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 un peu dlicat ` voir, e e e e e a cest quentre deux mots (\w+), il doit forcement 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 que des numriques e c e e e e (zro ou plus), le dollar pour se placer ` la n de la cha : e a 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 voil` pars pour la suite des e ee e a e oprations. Voici dautres fonctionnalits plus pousses et donc plus intressantes. Les quantie e e e cateurs non-gourmands et surtout les options sont des points importants.

8.15

Choisir son sparateur e

Il est tout ` fait possible de choisir un autre caract`re que le slash (/) comme sparateur. Il a e e se peut par exemple que nous ayons ` manipuler des URL ; dans ce cas, le caract`re slash fait a e partie des motifs que lon est susceptible de rechercher ; il est de ce fait fort fastidieux de devoir dspcier chaque slash utilis, comme par exemple dans lexpression suivante (ici une version e e e 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 exemple : e e

70

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

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 pour faire un e match : $v =~ /velo/ est quivalent ` $v =~ m/velo/ e a Libre ` vous de choisir le bon sparateur, sachant que dans la grande majorit des cas le a e e slash est utilis. e

8.16

Options

Apr`s le dernier sparateur des oprateurs de correspondance (m ou rien) ou de substitution e e e (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. e e Voici la liste de quelques options parmi les plus utiles : Loption i rend le motif insensible ` la casse (minuscules/majuscules) : lexpression rgua e li`re m/toto/i recherche le mot toto indiremment en majuscules ou en minuscules. On e e aurait pu crire e m/[tT][oO][tT][oO]/ Loption g permet deectuer toutes les substitutions dans la variable. Par dfaut, lope e rateur s/// eectue la transformation de la premi`re occurrence du motif recherch et ne e e va pas plus loin. Si cette option est spcie, le moteur dexpressions rguli`res avancera e e e e dans la variable tant quil pourra y faire des substitutions. Par exemple, lexpression $v =~ s/ +/ /g; remplace chaque groupe de plusieurs espaces par une seule (contrairement ` un des exercices prcdents o` lexpression rguli`re ne a e e u e e remplaait que la premi`re occurrence du motif trouv). c e 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 ` cet oprateur de fonctionner a e avec tat, cest-`-dire de poursuivre sa recherche en partant du dernier motif trouv. On e a e lutilise typiquement 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 une expression Perl, e et remplace le motif trouv par la valeur de cette expression. Par exemple : e $s =~ s/(\d+)/fonction($1)/e; remplace le premier nombre trouv dans la variable $s par la valeur de retour de la fonction e applique ` ce nombre. e a

71

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

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 la variable $s. e e Loption o a pour eet quune seule compilation de lexpression rguli`re a lieu. En temps e e normal, ` chaque fois que linterprteur Perl passe sur une expression rguli`re, il la compile a e e e (pour ceux qui connaissent, il construit lautomate) ; avec cette option, la compilation a lieu une seule fois lors de la premi`re excution. Le principal avantage est un temps e e dexcution plus court pour le programme, si cette expression est utilise plusieurs fois. e e Les inconvnients sont une place mmoire occupe (inutilement si lexpression rguli`re ne e e e e e sert que peu de fois) et que, si le motif peut changer (voir la suite concernant les variables dans les motifs), ce changement ne sera pas pris en compte. Il existe deux options (exclusives lune de lautre) qui permettent de changer certains comportements sur les 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 ($s=~m/mot$/) e e ne. est faux. Le caract`re . ne matche pas \n. Par exemple ($s=~m/t.lu$/) est faux. e Avec loption s : on travaille en ligne unique. Les caract`res ^ $ se positionnent en dbut/n de cha Par exemple ($s=~m/mot$/s) e e ne. est faux. Le caract`re . peut matcher \n. Par exemple ($s=~m/t.lu$/s) est vrai. e Avec loption m : on travaille en ligne multiple. Les caract`res ^ $ se positionnent en dbut/n de ligne. Par exemple ($s=~m/mot$/m) e e est vrai. Le caract`re . ne matche pas \n. Par exemple ($s=~m/t.lu$/m) est faux. e

8.17

Quanticateurs non-gourmands

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

Pour revenir ` notre exemple, on peut crire /.*?/ et la correspondance sera eectue a e e telle que nous la souhaitions.

72

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

Vous allez me dire, car vous avez tout compris aux expressions rguli`res ;-) , quil est e e possible de faire cela sans utiliser ces quanticateurs non-gourmands. Dans notre exemple, on peut tout ` fait crire : /[^]*/ ce qui permet de ne pas accepter de guillemets entre les a e guillemets. Je rpondrais que je suis daccord avec vous. e Mais voici un autre exemple o` les quanticateurs non-gourmands nous sauvent la mise. Si u 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 e en les marqueurs START et STOP, il nous est fort ais dcrire : /START.*?STOP/ e e

8.18

Substitution de variables dans les motifs

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

Cela peut aussi poser des probl`mes de scurit si le programmeur ne sait pas ce que peut e e e contenir la variable substitue (par exemple si sa valeur provient de lutilisateur). Il existe pour e cela une fonction quotemeta qui prend en param`tre une cha de caract`res et renvoie cette e ne e mme cha en ayant dspci les caract`res spciaux. e ne e e e e e $s = "fds(ds"; $s2 = quotemeta($s); print "$s2\n"; # affiche if( $v =~ m/$s2/ ) { ... }

fds\(ds

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

8.19

Oprateur tr e

Cet oprateur ne concerne pas vraiment les expressions rguli`res, mais il en est proche. e e e Mettez de ct ce que vous venez dapprendre sur celles-ci pour lire la suite. oe

73

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

tr est un oprateur de translation lettre ` lettre (on parle de translittration). Voici sa e a e syntaxe : tr/chane1/chane2/ ou encore y/chane1/chane2/ Les deux cha nes doivent tre de la mme longueur car cet oprateur va remplacer la premi`re e e e e lettre de la premi`re cha par la premi`re lettre de la seconde cha la deuxi`me lettre de la e ne e ne, e premi`re cha par la deuxi`me lettre de la seconde cha etc. Cette transformation a lieu sur e ne e ne, 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, etc, tous les e en 4 e 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

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

74

Chapitre 9

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

9.1

Rfrences sur scalaire ee

Loprateur qui permet de prendre la rfrence dune variable est lanti-slash (\) : \$v est la e ee 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, quel que soit celui de la variable ee ee quelle rfrence (scalaire, tableau ou table de hachage), est un scalaire. On peut reprsenter la ee e relation entre ces deux variables de la faon suivante : c

$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 e e de $refv vers $v.

75

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

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

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

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

Rien de bien sorcier.

9.2

Utilisation des rfrences sur scalaire ee

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

76

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

Cette fonction prend en argument une rfrence et aecte 0 a la variable scalaire pointe par ee ` e cette rfrence. On pourrait lutiliser ainsi : ee f( $refv ); Ce qui aurait pour eet de mettre la variable $v ` la valeur 0. On pourrait aussi crire a e directement : 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 vers cette variable. e ee Contrairement ` ce quil se passe en C, ceci est tout ` fait lgal et sans risque en Perl. Voici a a e comment utiliser cette fonction : my $reff = f2(); La variable scalaire $reff devient donc une rfrence vers une variable scalaire valant 43. ee 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 ` cette fonction qui la cre, elle na plus de nom. a ee

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

9.3

Rfrences sur tableau ee

Il est possible de crer une rfrence sur un tableau. Loprateur qui permet cela est le mme e ee e e que pour les scalaires ; il sagit de lanti-slash (\) appliqu ` une variable de type tableau : ea

77

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

my @t = (23, "ab", -54.4); my $reft = \@t; La variable scalaire $reft est donc une 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 (@) : @$reft est e ee ee quivalent ` @t. On peut ainsi utiliser la valeur de @t en utilisant $reft : e a 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 est maintenant e e ee e e possible dcrire $$reft[i]. On peut alors dire, de mani`re schmatique et pour xer les choses, e e e que la notation $reft est quivalente au nom t de la variable dans toutes les syntaxes utilisant e ce tableau (partout o` lon peut crire t, on peut crire $reft ` la place, tant que $reft pointe u e e a 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 ` $$reft[i] et correspond donc au i`me e e a e lment du tableau rfrenc par $reft. Cest la notation la plus souvent utilise pour cela ; elle ee ee e e rappelle la mme notation `che (->) du langage C. e e Lexpression $reft->[1] = "coucou"; aecte donc ` llment dindice 1 du tableau point par $reft une nouvelle valeur. a ee e Munis des rfrences, il va maintenant nous tre possible de crer des tableaux de tableaux. ee e e Cela tait pour le moment impossible en raison de laplatissement des listes. Une rfrence tant e ee e un scalaire, il va nous tre possible de stocker une rfrence comme valeur dans un tableau : e ee my @t1 = ( 16, -33 ); my @t2 = ( "el", 0.3, 4 ); my @t = ( 6, \@t1, \@t2, "s" );

78

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

Le tableau @t comporte donc un premier lment valant 6, un deuxi`me tant une rfrence ee e e ee vers un tableau ` deux lments, un troisi`me une rfrence vers un tableau ` trois lments et a ee e ee a ee enn un lment valant la cha "s". ee ne Ce qui peut se reprsenter sous la forme suivante : e

@t 0 6 1 2 3 s

el

0.3

16

33

Vous noterez bien que la syntaxe suivante correspond ` la cration dun tableau ` sept a e a 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.

9.4

Rfrences sur table de hachage ee

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

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

Pour drfrencer une rfrence vers une table de hachage, il faut utiliser le caract`re poure ee ee e centage (%) ; %$refh est quivalent ` %h : e a

79

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

my %h2 = %$refh; foreach my $k (keys %$refh) { ... } Les deux notations suivantes permettent daccder ` la valeur associe ` la clef Paul : e a e a $$refh{Paul} et $refh->{Paul} sachant que la seconde est la plus utilise pour des raisons e identiques aux cas des tableaux. $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 hachage rfrence par c ee e $refh : foreach my $k (keys %$refh) { print "$k $refh->{$k}\n"; } Cette notation `che rend lexpression plutt lisible. e o

9.5

Rexions ` propos des rfrences e a ee

On a vu que pour drfrencer une rfrence vers un scalaire on utilise le caract`re dollar e ee ee e ($), vers un tableau le caract`re arobase (@) et vers une table de hachage le caract`re poure e centage (%). Mais que se passerait-il sil nous venait ` lide de ne pas choisir le bon caract`re a e e de drfrencement, par exemple dutiliser le dollar pour une rfrence sur tableau ou bien le e ee ee pourcentage pour une rfrence sur scalaire ? Narriverons-nous pas ` des incohrences comme ee a e en C ? La rponse est non, car linterprteur veille au grain. Il refusera de considrer comme un e e e tableau une variable scalaire par exemple. En cas dincompatibilit de type, un de ces trois e messages sera ach lors de lexcution et le programme prendra n : e e Not a SCALAR reference at script.pl line 23. Not an ARRAY reference at script.pl line 23. Not a HASH reference at script.pl line 23. Comme une rfrence peut pointer vers nimporte quel type de structure (scalaire, tableau, ee table de hachage), cette vrication ne peut avoir lieu quau moment de lexcution. e e De plus, les habitus du langage C seront invits ` se mettre une bonne fois pour toutes dans e e a la tte :-) quil ny a pas darithmtique possible sur les rfrences en Perl. Ajouter 1 ` une e e ee a rfrence ne correspond pas ` pointer vers llment dindice 1 dun tableau, mais ` faire perdre ee a ee a le caract`re rfrence ` la variable (elle devient un scalaire comme un autre) : e ee a

80

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

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

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

On voit bien ici que la variable $r perd son caract`re spcique de rfrence ; elle a toue e ee jours pour valeur ladresse de la variable (ici incrmente de 1 : 80fd4c4 est la reprsentation e e e hexadcimale du nombre 135255236), mais nest plus une rfrence, il sera donc impossible de e ee la drfrencer. e ee Notez aussi quune rfrence peut changer de valeur, cest-`-dire de variable pointe et donc ee a e de type de variable pointe : 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 ` une fonction, vous devez bien voir e ee a que la copie de la seule rfrence est eectue, la structure pointe par la rfrence ne lest pas ; ee e e ee vous pourrez donc la modier dans la fonction : sub f3 { my ($reftab) = @_; $reftab->[2] = 32.3; } my @t = ( 49, "hello", -2 ); my $r = \@t; f3( $r ); f3( \@t ); # quivalent e # @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

81

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

Les deux rfrences pointent donc vers la mme zone mmoire. ee e e

9.6

Rfrences anonymes vers scalaire ee

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

$ref1 34 $ref2 er

Une telle valeur est une constante, il est impossible de modier la valeur pointe par la e rfrence (dirence avec le mcanisme de la fonction f2) : 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 les plus utilises ; elles ee e le sont bien plus avec les tableaux et les tables de hachage.

9.7

Rfrences anonymes vers tableau ee

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

82

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

$r 0 34.4 1 ac 2 71

@t 0 34.4 1 ac 2 71

On acc`de aux lments de cette rfrence anonyme comme pour une rfrence normale : e ee ee ee print "$r->[0]\n"; $r->[2] = 901; foreach my $e (@$r) { ... } Attention ` ne pas crire \(2,"er",$v) si vous voulez crer une rfrence vers un tableau, a e e ee car cette syntaxe fait toute autre chose : elle est en fait quivalente ` (\2,\"er",\$v), donc ` e a a une liste de rfrences, ce qui est fort dirent. ee e La 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

el

0.3

16

33

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

83

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

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

$r

el

0.3

16

33

Comment accder aux lments des direntes profondeurs dune telle construction ? Il sut e ee e 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 schma sous la t e main ... Vous noterez que nous faisons usage de loprateur `che (->) plutt que de la syntaxe e e o double-dollar ($$). De plus, si $r->[1] est une rfrence vers tableau, @{$r->[1]} est le tableau en question. ee 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 `che est ncessaire : e ee e e e $r->[2][1] est quivalent ` $r->[2]->[1]. e a

9.8

Rfrences anonymes vers table de hachage ee

De la mme faon il est possible de crer une rfrence anonyme vers une table de hachage. e c e ee La notation {clef1=>valeur1, clef2=>valeur2, etc} est une rfrence vers une table de hachage ee comportant les couples clef/valeur en question.

84

c Sylvain Lhullier

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

http://formation-perl.fr/

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

La variable $r est une rfrence vers une table de hachage alors que la variable %h est une ee 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 tables de hachage e c de tables de hachage : my %h1 = ( rue tel my %h2 = ( rue tel my $r = { Paul Julie => => => => => => Pasteur, 06461341 ); Jaures, 03729103 ); \%h1, \%h2 };

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

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

85

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

$r

Julie Paul

=> =>

rue tel

=>

Jaures

=> 03729103

tel rue

=> 06461341 => Pasteur

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

9.9

Rfrences anonymes diverses ee

Il est bient-sr tout ` fait possible de mlanger les rfrences vers les tableaux et vers les u a e ee tables de hachage : my $r = [ [a,4], b, [1,z], {P=>[-2,"er",0],A=>7},

86

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

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

$r

A P

=> =>

er

Voici comment accder ` un lment dune telle structure : e a ee print "$r->[3]->{P}->[1]\n"; # affiche "er" print "$r->[3]{P}[1]\n"; # quivalent e Les crochets correspondent ` une prise dindice dun tableau ; les accolades ` la clef dune a a table de hachage. Je peux parcourir le premier tableau du deuxi`me niveau (celui qui comporte a et 4) de la e 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 ensuite parcourir e ee @$reft qui reprsente le tableau en question. e Il est possible dcrire cela sans crer de variable temporaire, la syntaxe est la suivante : e e @{rfrence} Ces accolades nont rien a voir avec les tables de hachage elles permettent juste de ee ` dlimiter la rfrence ` laquelle on applique larobase. Voici ce que cela donne : e ee a

87

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

foreach my $v (@{$r->[0]}) { print "$v\n"; } On fait de la mme faon pour un table de hachage, les accolades dlimitent la rfrence ` e c e ee a laquelle on applique le pourcentage : foreach my $k (keys %{$r->[3]}) { print "$k $r->[3]{$k}\n"; } Commencez-vous ` voir lintret de faire des schmas ? a e e

9.10

Loprateur ref e

La question qui pourrait maintenant venir ` lesprit est la suivante : comment pourrait-on a crire une boucle sur les lments du tableau rfrenc par $r et surtout comment savoir de e ee ee e quel type ils sont pour pouvoir les utiliser ? Pour rpondre ` cette question, voici un nouvel e a oprateur : ref(). Il permet de conna le type dune rfrence. e 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 classique). ee On peut alors crire le code suivant : e foreach my $p (@$r) { if( ref($p) eq "ARRAY" ) { print "( "; foreach my $v (@$p) { print "$v "; } print ")\n"; } elsif( ref($p) eq "HASH" ) { foreach my $k (keys(%$p)) { print "$k : $p->{$k}\n"; } } elsif( !ref($p) ) { print "$p\n"; } } Lachage suivant est eectu : e ( a 4 ) b ( 1 z )

88

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

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

9.11

Rfrences circulaires ee

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

89

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

$r

71

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

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

90

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

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

9.12

Rfrences sur chiers ee

Une ouverture de chier cre une variable dont il est possible de prendre ladresse. Voici la e syntaxe pour cela : open(FILE,">toto") or die("$!"); my $reff = \*FILE; La variable scalaire $reff est une rfrence vers le descripteur de chier FILE. Il nous est ee aussi possible de crer une rfrence vers un des trois chiers pr-existant : e ee 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) = @_;

91

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

print $ref "ok\n"; } affiche( $reff ); affiche( \*FILE ); # quivalent e close( $reff ); Cette derni`re ligne est quivalente ` close(FILE); On peut sans restrictions stocker une e e a rfrence vers chier dans une table de hachage ou dans un tableau. ee

9.13

Rfrences sur fonctions ee

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

9.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 stocks dans une table de hachage). Nallons pas trop vite car Perl a e e e t prvu pour la programmation objet et propose les fonctionnalits ncessaires (hritage ...) ee e e e e en se basant sur les modules.

92

Chapitre 10

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

10.1

Utilisation dun premier module

Il existe de nombreux modules dj` installs sur votre syst`me ; une distribution de Perl ea e e inclut les modules les plus utiliss. e Ainsi, le module nomm Math::Trig ; permet daccder ` des fonctions mathmatiques de e e a e trigonomtrie autres que les seuls cosinus et sinus prdnis dans Perl sous les noms de cos et e e e sin. Je vous invite ` taper la commande perldoc Math::Trig dans un terminal ; vous visualiserez a ainsi la documentation de ce module. Cette commande perldoc fonctionne un peu comme la commande man ; vous verrez dtailles les fonctionnalits auxquelles vous avez acc`s avec un e e e e module donn. Vous taperez q pour quitter. e On voit ici que nous avons acc`s a des fonctions comme tan, acos ou asin ainsi qu` des e ` a fonctions de conversion entre units dangles ou bien ` la valeur de pi. De petits exemples simples e a dutilisations vous sont aussi fournis. La premi`re ligne de code ` crire pour utiliser un module est la suivante : e ae use NomDuModule;

93

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

Dans bien des cas, cette instruction ajoute des fonctions et des variables ` lespace de noma mage (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 et tre excute e e e e e avant tout usage de fonctions ou de variables du module. 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 placer dans chaque e script, nest en fait que le chargement dun module ; ce module ayant pour rle de rendre la o syntaxe Perl plus coercitive. Le nom des modules de ce type est en minuscule. Ils sont appels modules pragmatiques. Ils ont pour objet de modier ou dtendre la smantique de Perl. e e e Ainsi diagnostics permet davoir des messages derreurs plus complets (vous pouvez charger sur CPAN la version 1.2-alpha1 qui vous permet davoir ces messages avec des explications en franais). c Revenons ` notre module Math::Trig. Voici un exemple de code Perl lutilisant (jen plagie a 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 ces instructions. o Une fois charg, un module nest pas dchargeable. e e

10.2

Dautres modules

Voici lexemple dun autre module : File::Copy ; il permet certaines manipulations de chiers lourdes ` mettre en uvre avec de simples appels syst`me. Il est par exemple possible de copier un a e chier vers un autre (chiers disque ou ux de donnes), ou den dplacer un dune partition vers e e une autre (impossible avec lappel syst`me rename). Comme lindique perldoc File::Copy : e 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 FTP. Voici, par exemple, comment se e e e connecter sur un serveur (en mode passif, car jai un rewall), changer de rpertoire et tlcharger e ee un chier : #!/usr/bin/perl -w use strict;

94

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

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

10.3

O` trouver les modules ? u

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

95

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

10.4

Ecrire un premier module

Apr`s avoir manipul des modules existants et avoir parl de CPAN, nous allons maintenant e e e apprendre ` crire nos propres modules. ae Pour crire un module, nous devons crer un chier indpendant du ou des scripts qui lue e e tilisent. Lextension de ce chier est imprativement .pm : par exemple Utils.pm Ce chier doit e tre plac dans un des rpertoires lists dans la variable @INC ; pour commencer vous pourriez e e e e le placer dans votre rpertoire de travail ` ct du script qui lutilisera, car le rpertoire . est e a oe e prsent dans ce tableau @INC. e Ce chier doit contenir une premi`re ligne indiquant le nom du module ; pour cela, vous e devez crire : e package Utils; Il est important de voir que le nom du package doit tre le mme que celui du chier (` e e a lextension pr`s). Le chier peut ensuite contenir des dnitions de fonctions. Voici un exemple e e simple dun tout petit module complet : # --- fichier Utils.pm --package Utils; use strict; sub bonjour { my ($prenom) = @_; print "Bonjour $prenom\n"; } 1; Il est important de ne pas oublier la derni`re ligne, celle qui contient 1; ; nous reviendrons e plus tard sur son rle. o Pour pouvoir utiliser ce module dans un script, il est ncessaire dinvoquer linstruction use e 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 ` lappel de la fonction bonjour du module Utils. La syntaxe e a est la suivante : le nom du module est suivi de deux signes deux-points puis du nom de la fonction.

10.5

Et les variables ?

Il est possible de dclarer des variables propres au module. Ces variables seront : e soit accessibles exclusivement aux fonctions prsentes dans le module (on pourrait parler e de variables prives, correspondant aux variables static dclares en dehors des fonctions e e e en C),

96

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

soit aussi accessibles ` lextrieur du module (on pourrait parler de variables publiques ou a e variables globales). Une variable accessible exclusivement aux fonctions du module se dclare avec my (que lon e conna dj`). Une variable aussi accessible depuis lextrieur du module se dclare avec our t e a e e (my pour dire ` moi, our pour dire ` nous). Avant la version 5.6 de Perl, on utilisait un a a autre mcanisme dont je ne parlerai pas ici, assurez-vous davoir une version rcente de Perl (cf e e perl -v). Ces variables doivent tre dclares en dehors de toute fonction ; les variables dclares e e e e e dans les fonctions sont comme toujours locales au bloc dans lequel elles sont dclares. e e # --- fichier Utils.pm --package Utils; use strict; # variable accessible our $x = toto; # variable inaccessible my $y = toto; # fonction sub bonjour { # Variable locale my ($prenom) = @_; print "Bonjour $prenom\n"; print "$x $y\n"; } 1; Que la variable soit dclare avec my ou avec our, il est tout ` fait possible dy accder e e a e ` depuis une fonction du module (ici bonjour). A linverse, depuis lextrieur du module, cest-`e a dire depuis le script, seule la variable $x est accessible. #!/usr/bin/perl -w # --- fichier script.pl --use strict; use Utils; Utils::bonjour( "Paul" ); # Ok : print "$Utils::x\n"; # Erreur : print "$Utils::y\n"; De mme que pour les fonctions, les noms de variable sont prxs par le nom du module e e e 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 donne : $Utils::x au nal. Il ny a pas derreur de ma e e part : on ncrit pas Utils::$x ! :-) e

10.6

De la derni`re ligne dun module e

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

97

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

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

10.7

Rpertoires e

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

10.8

Blocs BEGIN et END

Les amoureux de awk retrouveront ici deux de leurs enfants prfrs :-)). Dans un module, ee e il est possible de prvoir deux blocs dinstructions qui seront excuts soit d`s le chargement du e e e e module (bloc BEGIN) soit lors de la n de lusage du module (bloc END).

98

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

package Utils; use strict; sub f { ... } BEGIN { print "Chargement du module\n"; } END { print "Fin dusage du module\n"; } 1; Notez bien quil ne sagit pas de fonctions (pas de mot clef sub), mais bien de blocs labliss. e e Le bloc BEGIN sera excut lors de linstruction use Utils; avant toute autre instruction du e e module (y compris les use placs dans le module). Le bloc END sera excut lors de la n du e e e programme. Lusage de ces deux blocs peut tre ncessaire lorsque lutilisation du module est conditionne e e e par lobtention dune ou plusieurs ressources comme un chier ou une connexion rseau. Ces blocs e vont nous servir ` prparer le terrain au dbut et ` librer les ressources ` la n. a e e a e a Lorsque dans un module sont prsentes dautres instructions que des dnitions de variables e e et des dnitions de fonctions, ces instructions sont excutes au moment du chargement du e e e module. Tout se passe comme si ces instructions guraient dans un BEGIN implicite. Lusage dun bloc BEGIN permet juste au programmeur dcrire un code un peu plus lisible et propre, e dans la mesure o` toutes ces instructions sont regroupes sous un nom (BEGIN) qui rappelle u e 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

10.9

Introduction ` lexport de symboles a

Sous ce titre barbare se cache une ide simple : il peut tre pnible de toujours crire le nom e e e e complet des fonctions de modules. Je veux dire par l` que dcrire Utils::bonjour ` chaque a e a fois que vous voulez appeler cette fonction est sans doute lourd et est quelque peu pnible ` e a la longue. Il existe un moyen pour navoir qu` crire bonjour sans avoir ` rappeler le nom du ae a 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 par le script. e Pour avoir la capacit dexporter des symboles, notre module futur-exportateur doit come porter les lignes suivantes : package Utils; use Exporter; our @ISA = qw(Exporter);

99

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

Ces deux nouvelles lignes dinstructions doivent tre places juste apr`s linstruction package. e e e La premi`re est linvocation du module Exporter ; avec la seconde on indique que notre module e 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 rien besoin de faire de e e spcial (autre que de faire le use) pour que ces symboles soient exports, e 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, ceux qui ne sont pas exportables (cest-`-dire quil faudra toujours faire prcder leur nom a e e par le nom complet du module). Chacun des trois premiers ensembles est associ ` une variable dclare avec our. ea e e

10.10

Export par dfaut de symboles e

Les symboles exports par dfaut doivent tre lists dans la variable @EXPORT ; il sagit donc e e e e dun tableau. Il est courant dinitialiser ce tableau avec loprateur qw que nous avons dj` vu e ea et sur lequel je ne reviendrai donc pas : our @EXPORT = qw(&bonjour &hello $var); Cette ligne place dans le module Utils ` la suite de la ligne e a 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 les variables doivent tre cites avec leur e e e caract`re de direntiation de type (le dollar, larobase ou le pourcentage), il en est de mme e e e avec les fonctions 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

10.11

Export individuel de symboles

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

100

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

our @EXPORT_OK = qw(&gutenTag &ciao $var2); Ces trois symboles sont maintenant exportables dans le script utilisant ce module. Pour cela il convient dajouter une liste de symboles ` linstruction use : a use Utils qw(&ciao $var2); ciao("Paula"); print "$var2\n"; Cette ligne importe donc les symboles demands et ces derniers sont donc utilisables sans e prxe. e Il se trouve quune telle ligne nimporte plus les symboles par dfaut (ceux de la variable e @EXPORT) ; ne me demandez pas pourquoi, je trouve cela aussi stupide que vous ... Pour remdier e a ` cela, il nous faut ajouter ` la liste des imports le tag :DEFAULT : a 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 du module de ne pas e e e ` trop polluer son espace de nommage et de choisir les seules fonctions dont il aura besoin.

10.12

Export par tags de symboles

Il est possible de regrouper les symboles dans des tags. Un tag est une liste de symboles. Limport dun tag provoque limport de tous les symboles composant ce tag. La variable qui entre ` ici en jeu est %EXPORT_TAGS ; il sagit donc dune table de hachage. A chaque tag est associe e une rfrence vers un tableau contenant la liste des symboles du tag : ee our %EXPORT_TAGS=(T1=>[qw(&ciao &gutenTag)], T2=>[qw(&ciao $var2)]); Le tag T1 est associ aux fonctions ciao et gutenTag. Le tag T2 est associ ` la fonction e e a ciao et ` la variable $var2. Le nom des tags est par convention en majuscules. a Remarque importante : les symboles prsents dans les listes associes aux tags doivent abe e solument tre prsents dans @EXPORT et/ou @EXPORT_OK. Dans le cas contraire, leur export sera e e 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 deux-points. Il est e e e e possible de combiner les dirents types dacc`s : e e

101

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

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

10.13

Exemple complet dexports

Voici un exemple complet dusage des exports dans les modules ; jai essay de regrouper e toutes les congurations. Voici le module Utils dans le chier Utils.pm : package Utils; use strict; use Exporter; our @ISA = qw(Exporter); our @EXPORT = qw(&f1 &f2); our @EXPORT_OK = qw(&f3 &f4 &f5 &f6); our %EXPORT_TAGS = (T1 => [qw(&f5 &f6)], T2 => [qw(&f4 &f6)]); sub f1 { print "f1\n"; } sub f2 { print "f2\n"; } sub f3 { print "f3\n"; } sub f4 { print "f4\n"; } sub f5 { print "f5\n"; } sub f6 { print "f6\n"; } 1; Et voici un script lutilisant (apr`s chaque appel de fonction est signale la raison qui fait e e 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 reste pas moins e utilisable. Pour plus dinformations et dexemples je vous invite ` vous rfrer ` perldoc Exporter. a ee a

102

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

10.14

Fonctions inaccessibles

Vous allez me poser la question suivante : comment faire pour rendre une fonction dun module inaccessible depuis le script ? Et je vous rpondrai : cela nest a priori pas possible (vous e allez voir que si nalement). Vous lavez compris, Perl nest pas un langage extrmement coercitif, notamment par rapport e a ` des langages comme Java ou C++. Il ny a donc rien de prvu dans le langage pour rendre e certaines fonctions uniquement accessibles depuis lintrieur du module. Est alors apparue la e convention suivante : toute fonction ou variable dont le nom commence par un soulign (ou e under-score _) est prive et ne doit pas tre utilise ` lextrieur du module. e e e a e Cette conance en lutilisateur du module est souvent susante et les modules CPAN sont btis sur ce mod`le. a e Nanmoins, si vous tes outr par ce que je viens dcrire car vous tes un fanatique de Java e e e e e ou autres, il existe un moyen dcrire des fonctions vraiment internes aux modules. Il faut pour e cela dclarer une variable avec my (donc invisible depuis lextrieur du module) et den faire une e e rfrence anonyme vers fonction : ee 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 fonction anonyme. e Son usage est donc rserv aux fonctions dclares dans le module : e e e e sub truc { $affiche->(4,5); } Remarquez que, comme le code Perl est toujours accessible en lecture, il est toujours possible ` a lutilisateur du module de prendre le code en copier-coller et den faire une fonction personnelle ... Perl nest pas fait pour les parano aques.

10.15

Documentation des modules

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

103

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

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

104

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

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

10.16

Un dernier mot sur les modules

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

105

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

106

Chapitre 11

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

11.1

Vous avez dit objet ?

Sans revenir sur la thorie de la programmation objet, je vais tenter ici dy faire une courte e introduction. La programmation oriente objet est un type de programmation qui se concentre e principalement sur les donnes. La question qui se pose en programmation OO (oriente objet) e e est quelles sont les donnes du probl`me ? ` linstar de la programmation procdurale par e e a e exemple, qui pose la question quelles sont les fonctions/actions ` faire ?. En programmation a OO, on parle ainsi dobjets, auxquels on peut aecter des variables/attributs (proprits) et des ee fonctions/actions (mthodes). e On parle de classe, qui est une mani`re de reprsenter des donnes et comporte des traitee e e ments : une classe Chaussure dcrit, par exemple, les caractristiques dune chaussure. Elle e e contient un champ dcrivant la pointure, la couleur, la mati`re etc. Une telle classe comporte de e e plus des traitements sur ces donnes ; ces traitements sont appels mthodes. Grossi`rement e e e e une mthode est une fonction applique ` un objet. e e a Une fois dnie une telle classe, il est possible den construire des instances : une instance e dune classe est dite tre un objet de cette classe. Dans notre exemple, il sagirait dune chaussure e

107

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

dont la pointure, la couleur et la mati`re sont renseignes. e e

11.2

Prparatifs e

Nous allons maintenant voir comment crire une classe en Perl. Vous verrez, cela est tr`s e e simple et dmystie la programmation objet. e En Perl, une classe nest autre quun module et un objet (instance de cette classe) nest autre quune rfrence associe ` cette classe. Dans le constructeur, nous allons donc crer une rfrence ee e a e ee (typiquement vers une 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, sous forme de la e 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 champs : un nombre e de roues et une couleur.

11.3

Ecrire un constructeur

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

La ligne numro 2 indique le nom du package actuel ; il est conseill de choisir le mme nom e e e que pour le chier, simplement pour des raisons dorganisation et de maintenance. La ligne 12 comporte le fameux code de retour du chargement du module. La ligne 3 force une syntaxe plus rigoureuse. En Perl, le nom des modules et donc des classes que le programmeur dnit e doit tre compos de majuscules et de minuscules, avec typiquement une majuscule au dbut de e e e chaque mot ; les noms de package exclusivement en minuscules sont rservs pour les modules e e pragmatiques de Perl (dits modules 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 un objet Vehicule. e Il sagit donc dun constructeur ; un constructeur en Perl est une simple fonction renvoyant un objet. Il est bon de noter que le choix du nom pour cette fonction est totalement libre ; il est courant de lappeler new mais rien ne nous y oblige. On pourrait par exemple choisir le nom de

108

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

la classe (si on est un habitu de C++ ou de Java), mais on verra par la suite que cela nest pas e forcment une bonne ide. e e Cette fonction prend en premier param`tre le nom de la classe ; cela semble superu, mais on e verra quil nen est rien. Les param`tres suivants sont laisss ` la discrtion du programmeur : e e a e bien souvent on passe ici les valeurs de champs pour linitialisation. Cest ce que lon fait ici : le nombre de roues et la couleur sont transmis (ligne 5). Ligne 6, nous crons une rfrence anonyme vers une table de hachage vide {}. Cette rfrence e ee ee est stocke dans une variable scalaire nomme $this car il va sagir de notre futur objet. Le nom e e 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 mthodes soit plutt e e o $self en Perl (vous trouverez ce nom dans la plupart des modules objet de CPAN). Ligne 7, nous indiquons que cette rfrence est lie au package (` la classe) $class. Cette ee e a variable $class vaudra ici Vehicule. Loprateur bless associe le package en question ` la e a rfrence. La rfrence est maintenant lie au package. ee ee e Dans les lignes 8 et 9, les champs NB_ROUES et COULEUR sont initialiss. Le champ dun objet e nest rien dautre quune entre dans la table de hachage qui constitue lobjet. Pour aecter un e champ de lobjet que nous sommes en train de construire, il sut de crer un couple clef/valeur e dans la table de hachage rfrence par $this. Jai pris lhabitude de mettre le nom des champs ee e en lettres majuscules. Notez que le nombre, le nom et le contenu des champs peuvent donc varier dune instance de la classe ` une autre instance de cette mme classe. Libre au programmeur de faire ce quil veut : a e si le but est de vraiment programmer objet de faon formelle, il va respecter les habitudes de c ce type de programmation qui veut que toutes les instances dune mme classe aient les mmes e e champs ; mais sil ne tient pas ` respecter ces contraintes, il est libre de faire ce quil veut de a chacun de ses objets. La ligne 10 consiste en un return de la rfrence vers la table de hachage ainsi construite. ee

11.4

Appeler le constructeur

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

109

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

$v

Vehicule NB_ROUES COULEUR => => 2 bleu

$v2

Vehicule NB_ROUES COULEUR => => 4 rouge

Cette syntaxe Vehicule->new correspond ` lappel du constructeur new que nous venons a dcrire. La variable $v est initialise a la valeur de retour de cette fonction. Elle est donc une e e ` rfrence vers une table de hachage dont deux champs sont initialiss et qui a t bnie (bless) ee e ee e en Vehicule. Idem pour $v2. Il est aussi possible de faire usage de la syntaxe suivante : my $v = new Vehicule( 2, "bleu" ); Cette formulation va sans doute rassurer les habitus de Java ou de C++, mais peut induire e le programmeur en erreur. En eet, cette derni`re syntaxe semble indiquer que new est un ope e rateur spcique pour appeler un constructeur et est donc un mot rserv du langage. Il nen e e e est rien ; comme on le verra un peu plus loin, ce nom est totalement arbitraire.

11.5

Manipulations de lobjet

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

110

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

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

$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 lautre car il sagit du e e mme objet. e

111

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

11.6

Plusieurs constructeurs

Comment crire plusieurs constructeurs pour une mme classe ? Rien de plus simple. Le nom e e 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 ` ce ee e a que lon a vu pour les modules. Je peux donc crire un autre constructeur (donc avec un autre e 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 couleur) et naecte e ` moi de savoir comment je veux grer mes pas de champs NB_ROUES car rien de ne ly oblige. A e vhicules, ` savoir comment jautorise quils soient construits. e a Pour tre propre et cohrent, nous allons tout de mme considrer quil est sage daecter e e e e une valeur ` la clef NB_ROUES : a 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 ` ce constructeur : a my $v2 = Vehicule->nouveau( "bleu" ); De la mme faon que pour le prcdent constructeur, il est possible dutiliser la syntaxe e c e e suivante : my $v2 = nouveau Vehicule( "bleu" ); Ce qui est, reconnaissons-le, quelque peu droutant. Cest pour cela que je vous conseille e dutiliser plutt la premi`re syntaxe Vehicule->nouveau() ou alors de vous en tenir ` un cono e a structeur new pour crire new Vehicule(). e

11.7

Ecrire une mthode e

Une mthode est une fonction qui sapplique ` une instance de la classe. Cela est vrai dans e a tous les langages objet, mais bien souvent cela est masqu ; dans notre cas rien de masqu, le e e premier param`tre de la fonction sera lobjet (la rfrence bnie) : e ee e

112

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

sub roule { my ($this,$vitesse) = @_; print "Avec $this->{NB_ROUES} roues, je roule ` $vitesse.\n"; a } Cette fonction dclare dans le chier Vehicule.pm a donc pour premier param`tre lobjet e e e sur lequel elle est appele. Vous noterez une fois de plus que rien noblige le programmeur ` e 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 usage du lourd e e mcanisme dExporter car nous navons pas besoin de modier lespace de nom des fonctions e des scripts appelants. 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 package li ` la rfrence e e ea ee $v lors de sa bndiction. e e Lachage suivant a donc lieu : Avec 2 roues, je roule ` 15. a 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 lobjet. Les habitus de e ne e e e Java noteront que jai choisi le nom de cette fonction pour leur rappeler des souvenirs, mais quil na rien de spcial. Voici comment lutiliser dans le script : e print $v->toString()."\n"; Et lachage a lieu : (Vehicule:2,bleu) Libre ` vous de choisir un plus bel achage. a

11.8

Reparlons des champs

Un champ est une donne propre ` une instance de classe. En Perl, ces champs sont stocks e a e comme clef/valeur dans la table de hachage qui constitue lobjet (si on utilise une table de hachage comme objet, ce qui est souvent le cas). Nos vhicules comportent deux champs : e NB_ROUES et COULEUR. Ces champs tant de simples clef/valeur dune table de hachage dont on dispose dune e rfrence dans le script, ils y sont accessibles. Dans le script, nous pouvons crire dans le chier ee e script.pl :

113

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

foreach my $k (keys %$v) { print "$k : $v->{$k}\n"; } Cest-`-dire que je peux accder sans restriction ` lensemble des champs de lobjet. En eet, a e a jai en main une rfrence vers une table de hachage ; le fait quelle soit bnie ne change rien au ee e fait que je peux la drfrencer et accder aux diverses valeurs quelle contient. Je peux aussi e ee e bien modier ces valeurs ou mme en ajouter ou en supprimer, car il sagit en eet dune table e de hachage comme les autres. Comment protger les donnes dun objet ? allez-vous alors me demander. Et bien, Perl na e e rien prvu pour a. Cela va sans doute faire hurler les puristes de la programmation objet, mais e c cest comme cela ... Perl vous propose les principaux mcanismes pour faire de la programmae tion objet tout en restant cohrent avec le reste du langage, certaines choses ne sont donc pas e possibles. Faute de champs privs en Perl, il existe une convention qui dit que les champs dont la clef e commence par un underscore (soulign _) sont des champs privs et les scripts qui utilisent les e e objets ainsi faits sont pris de respecter cette convention. Cest le cas de beaucoup de mode ules CPAN. Cette convention est aussi valable pour les mthodes (une mthode dont le nom e e commence par une underscore est une mthode prive). e e De faon gnrale, un programmeur Perl est quelquun de bonne ducation (sinon il proc e e e grammerait en Java ;-))) et il ne modiera pas une instance dune classe quil na pas crite. e En eet, pourquoi modier un objet Net::FTP alors quil fait tr`s bien son travail ? De toute e faon, il a forcment acc`s au code source de cette classe et sil veut la modier, il peut en faire c e e une copie et la modier ! La protection des donnes est donc plus une ncessit sociale (manque de conance en lesp`ce e e e e humaine ` laquelle les dveloppeurs prtendent encore faire partie :-))) quune ncessit techa e e e e nique. Pas dramatique pour faire de lobjet.

11.9

Composition

Prenons le temps de faire un petit exemple pratique pour illustrer le concept de composition. La composition est le fait quun objet est constitu dautres objets. Par exemple un garage e comporte des vhicules. e Je dcide quun garage aura une taille limite : il sagira du nombre maximal de vhicules e e quil pourra contenir. Un garage devra donc contenir une 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 = {};

114

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

bless($this, $class); $this->{PLACES} = $places; $this->{VEHICULE} = []; return $this; } Ce constructeur prendra en param`tre le nombre de places disponibles du garage ; cette valeur e est enregistre dans le champ PLACES. Le champ VEHICULE comportera la liste des vhicules ; e e pour cela elle est initialise ` la rfrence anonyme vers une liste vide. La mthode ajoute se e a ee e chargera dajouter les vhicules dans la limite du nombre de places : e sub ajoute { my ($this,$vehicule) = @_; if( @{$this->{VEHICULE}} < $this->{PLACES} ) { push @{$this->{VEHICULE}}, $vehicule; return 1; } return 0; } Cette mthode prend en param`tre une rfrence vers un vhicule. Elle compare la longueur e e ee e de la liste des vhicules au nombre total de places (lexpression @{$this->{VEHICULE}} est la e liste pointe par la rfrence $this->{VEHICULE} ; value en contexte numrique, elle vaut son e ee e e e nombre dlments). Sil reste de la place, le vhicule est ajout (fonction push) et elle renvoie ee e e 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."}"; }

115

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

On appelle sur chaque objet Vehicule la mthode toString de faon ` le faire appara e c a tre dans la cha que nous allons renvoyer. Voici comment appeler cette mthode dans le script : ne 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 chaque vhicule par une e e e e e virgule : sub toString { my ($this) = @_; my $s = "{Garage:$this->{PLACES},"; $s .= join( ,, map( { $_->toString() } @{$this->{VEHICULE}} ) ); return $s."}"; } Ce qui donne lachage suivant : {Garage:3,(Vehicule:2,bleu),(Vehicule:4,vert),(Vehicule:1,jaune)} Pour ajouter encore une dicult, je dcide de trier les vhicules par nombre de roues croise e e sant : 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 torturiez un peu les e mninges ;-)) e

116

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

11.10

Destruction dun objet

Un objet est dtruit d`s quaucune rfrence ne pointe vers cet objet. La ligne suivante, par e e ee exemple, lib`re la place mmoire occupe par lobjet Vehicule rfrenc par $v2 : e e e ee e $v2 = undef; ` A cet instant, Perl se rend compte que lobjet en question nest plus accessible, la mmoire e sera donc automatiquement libre par le mcanisme du garbage collector. ee e 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 ` la fermeture de laccolade du if. Lobjet qui a t cr dans a e e ee le bloc sera donc dtruit (sauf si on a fait en sorte quune autre variable dont la visibilit dpasse e e e ce bloc pointe aussi vers lobjet). Cette libration nest peut-tre pas faite en temps rel, mais ce nest pas au programmeur e e e de sen occuper. Il existe une mthode tr`s spciale, dont le nom est rserv, qui est appele lors de la dee e e e e e struction dune instance dun objet. Il sagit de la mthode DESTROY. Cette mthode sera appele e e e (si elle existe dans la classe) par le garbage collector juste avant la libration de la mmoire de e e lobjet. 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 reoit en premier e e e c argument une rfrence vers lobjet qui va tre dtruit. ee e e Cette mthode est tr`s utile pour librer des ressources (chier, connexion rseau etc) qui e e e e ont t alloues lors de la cration de lobjet. ee e e

11.11

Hritage e

Lhritage est un des apports de la programmation objet. Perl dispose de tout ce quil faut e pour le mettre en uvre. Imaginons quen plus de vhicules, nous avons besoin de manipuler des vlos et des voitures. e e Ces objets ont en commun davoir un nombre de roues et une couleur. Ils ont des caractristiques e supplmentaires qui leur sont propres ; les vlos ont un nombre de vitesses et les voitures, un e e nombre de si`ges. Ces classes Velo et Voiture vont donc hriter de la classe Vehicule, cest-`e e a dire quelles vont comporter tous les champs et les mthodes de cette classe. e

117

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

On dit alors que la classe Vehicule est la classe m`re ; les classes Velo et Voiture tant des e e classes lles. Notez bien que je prends comme exemple deux classes lles et quil nest nullement ncessaire davoir deux classes lles pour mettre en uvre lhritage, une seule est susante. e e Voyons le cas de la classe Velo, crons pour cela un chier Velo.pm qui contient : e 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 ` la e a valeur dune liste contenant le nom de la classe m`re. ISA vient de langlais is a, est un : on e dit quun vlo est un vhicule. Il hrite donc des champs et mthodes de la classe Vehicule. e e e 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); } Ce constructeur prend donc deux param`tres. Il appelle le constructeur de la classe m`re e e (syntaxe $class->SUPER::new). Il ajoute un champ NB_VITESSE et renvoie une rfrence bnie ee e en Velo. Notez bien quaucun appel au constructeur de la classe m`re nest fait par dfaut, il e e faut le faire explicitement dans tous les cas. Le lecteur aura not que, comme les champs de la classe m`re et de la classe lle sont stocks e e e dans la mme table de hachage, il ny a pas moyen simple de faire de surcharge ou de masquage e des champs. Les noms des champs devront tre minutieusement choisis pour ne pas entrer en e conit les uns avec les autres. Voyons ` prsent comment crire une mthode pour cet objet : a 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);

118

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

Un vlo dispose de la mthode roule car il est aussi un vhicule. Lachage suivant est e e e eectu : e Sur mon vlo blanc je pdale avec 18 vitesses dans les bois. e e Avec 2 roues, je roule ` 10. a Voyons ` prsent comment acher un tel objet. Nous laisserons le soin ` la classe Vehicule a e a dacher le vlo comme tant un vhicule et nous neectuerons dans la classe Velo que lafe e e chage de ce que nous avons ajout ` la classe m`re : ea e sub toString { my ($this) = @_; my $s = "[Velo:$this->{NB_VITESSES}"; $s .= $this->SUPER::toString(); $s .= "]"; } La syntaxe $this->SUPER::toString() correspond ` lappel de la mthode toString de la a e classe m`re. Nous pouvons maintenant lappeler dans notre script : e 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 au premier destructeur e e rencontr. Si dans notre exemple nous dnissions une mthode DESTROY pour la classe Velo, e e e la mthode DESTROY de la classe Vehicule ne sera pas appele. Cela peut tre gnant si des e e e e ressources importantes 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 ` la mthode de la classe m`re. e e a e e Pour faire de lhritage multiple en Perl, rien de plus simple. Vous aurez peut-tre not que e e e la variable @ISA est un tableau, elle peut donc contenir plusieurs noms de classe : package Voiture; our @ISA = qw(Vehicule Danger Pollution); La dtermination de la bonne mthode ` appeler est eectue dynamiquement par une ree e a e cherche en profondeur dans larbre dhritage. Je ne mtendrai pas plus sur cette question de e e lhritage multiple. e

119

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

11.12

Classes dun objet

Dans cette partie nous allons voir comment conna tre la classe dun objet ainsi que tester lappartenance ` une classe pour un objet. a Souvenez-vous de loprateur ref qui, appliqu ` une rfrence, renvoie le type de structure e ea ee de donnes vers laquelle elle pointe (scalaire, tableau, table de hachage etc). Appliqu ` un objet, e ea il renvoie la classe de lobjet : 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 est aussi un vhicule, il e e peut tre utile de pouvoir tester lappartenance de lobjet ` une classe plutt que de conna e a o tre sa classe principale. Par exemple, si nous manipulons un tableau comportant des objets divers et varis et si nous souhaitons y retrouver tous les objets de classe Vehicule pour appeler leur e 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 devons ici nous poser nest e e e pas de savoir si la classe principale de lobjet est Vehicule, mais nous devons nous demander si lobjet est un objet de classe Vehicule (ce qui est vrai pour tout objet de classe Vehicule et ses sous-classes, comme Velo et Voiture). La fonction isa du package UNIVERSAL va nous permettre de faire cela : use UNIVERSAL qw(isa); if( isa( $r, "Vehicule" ) ) { $r->roule( 40 ); } On teste ainsi si la variable $r est un objet de classe Vehicule.

11.13

Champs et mthodes statiques e

Un champ statique est un champ qui est commun ` tous les objets dune classe, cest-`-dire a a quil nest pas li ` une instance particuli`re mais ` une classe. Cest une sorte de variable globale ea e a (dont lacc`s peut ventuellement tre contrl) qui est situe dans une classe. e e e oe e Pour faire cela en Perl, nous utiliserons des variables dclares dans le package de la classe e e en question. package Vehicule; my $privateVar = 0; our $publicVar = "hello";

120

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

Avec le qualicateur my, nous dclarons des variables prives (car visibles uniquement depuis e e lintrieur du package). Avec our, sont dclares des variables publiques (accessibles depuis e e e nimporte quel package). Je rappelle que pour accder ` la variable $publicVar du package e a Vehicule, on doit crire $Vehicule::publicVar ; depuis les fonctions et mthodes de ce package, e e il est susant dcrire $publicVar (sauf masquage par une variable locale). e On pourrait par exemple compter le nombre de vhicules crs au moyen dune telle variable : e ee 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 statique (ou mthode de e e e e classe) est une mthode qui nest pas appele sur une instance de la classe (donc pas de variable e e $this) mais pour toute la classe. Ce nest ni plus ni moins quune brave fonction prsente dans e le package. Cette fonction pourra donc uniquement accder aux champs statiques de la classe. e Nous pourrions, par exemple, crire une mthode statique qui renvoie le nombre de vhicules e e e crs (variable $nbVehicules) : ee sub getNbVehicules { my ($class) = @_; return $nbVehicules; } On notera que la mthode prend en premier argument le nom de la classe. Cela a pour e consquence que lappel ` la mthode ne se fait pas tout ` fait comme pour une fonction dun e a e a 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 ventuels arguments e e e entre parenth`ses. Ncrivez pas 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 est possible dcrire Velo->getNbVehicules(), e e e il nest pas permis dcrire Velo::getNbVehicules(). e Le lecteur notera que les constructeurs sont des mthodes statiques. Ils retournent des e rfrences bnies, mais nont rien de particulier par rapport ` dautres mthodes de classe. ee e a e Il est tout ` fait possible dappeler cette mthode sur une instance de la classe Vehicule a e

121

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

print $v->getNbVehicules()."\n"; mais dans ce cas le premier argument reu nest pas le nom de la classe mais lobjet en c question (cest donc une mthode dinstance et de classe ...). Cela ne change rien pour notre e mthode getNbVehicules car elle nutilise pas son premier argument, mais le cas est gnant pour e e les constructeurs qui ont ` bnir une rfrence. Pour cela, tout constructeur devrait commencer a e ee par dterminer sil a en premier argument le nom de la classe ou une rfrence. Linstruction qui e ee suit place dans la variable $class la classe actuelle, que cette variable ait pour valeur initiale le nom de la classe ou une instance de la classe : $class = ref($class) || $class; Il convient 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 classe. On pourrait e o faire de mme pour toutes les mthodes statiques (cest mme plutt conseill). e e e o e

11.14

Exemple complet

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

122

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

$nbVehicules++; # un vhicule de plus e return $this; } sub roule { my ($this,$vitesse) = @_; print "Avec $this->{NB_ROUES} roues, je roule ` $vitesse.\n"; a } 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; 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 .= "]";

123

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

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

124

c Sylvain Lhullier

Guide Perl

http://formation-perl.fr/

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

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

125

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

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

126

Conclusion
Nous sommes ici au terme de ce cours introductif ` la programmation en Perl. Vous avez a 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 disponible sur votre e ordinateur au moyen de la commande perldoc : perldoc perl vous donne acc`s ` la liste des e a th`mes consultables avec perldoc. Par exemple perldoc perldata vous explique les structures e de donnes en Perl. Pour une fonction particuli`re, utilisez loption -f : perldoc -f chomp Pour e 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 forcment facile dexprimer son besoin en e e termes directement exploitables dans un langage particulier, mais en ayant un peu dexprience e de Perl, vous trouverez vite votre mani`re de rsoudre un probl`me. Vous allez alors commencer e e e a ` faire connaissance avec Tim Towtdi (There is more than one way to do it). ;-)

127

http://formation-perl.fr/

Guide Perl

c Sylvain Lhullier

128

Lauteur
Sylvain Lhullier http://sylvain.lhullier.org/ Spcialiste du langage Perl, Sylvain Lhullier propose des formations professionnelles dans le e domaine de la programmation en Perl ` destination des administrateurs syst`mes comme des a e dveloppeurs (http://formation-perl.fr/). Il enseigne depuis 2000 ce langage ` lUniversit e a e de Marne-la-Valle, chez Ingnieurs 2000, ainsi qu` lEcole Ouverte Francophone depuis 2006. e e a Il est galement lauteur de confrences et dateliers sur la prise en main et lutilisation de Perl. e e Membre de lassociation de promotion du langage Perl en France Les Mongueurs de Perl (http://mongueurs.net/) depuis 2002, il a t le coordinateur du groupe de travail Artiee cles qui a pour vocation daider ` la publication darticles sur Perl et les technologies connexes. a En 2002 et 2003, il publie, avec laide de ce groupe de travail, une srie de 7 articles dans Linux e Magazine France sur le langage Perl. Ces articles sont repris en 2004 pour la parution dun hors-srie. e Lauteur tient ` remercier tr`s chaleureusement les autres membres de lassociation pour leur a e aide, leur soutien et les relectures eectues. e

129

Das könnte Ihnen auch gefallen