Vous êtes sur la page 1sur 129

D buter en Perl e

Francois Dagorn Olivier Salaun 19 avril 2004

R sum e e Ce document est une pr sentation tutoriale du langage Perl. Il ne couvre pas e tous les aspects du langage, sa lecture ne dispense pas de consulter les ouvrages de r f rences cit s dans la bibliographie. ee e

` Une version electronique est disponible a ladresse suivante : http://perso.univ-rennes1.fr/Francois.Dagorn/perl

` TABLE DES MATIERES

Table des mati` res e

Introduction 1.1 1.2 G n ralit s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e e e Un apercu de la syntaxe . . . . . . . . . . . . . . . . . . . . . . . . . . .

1 1 2

Les types de donn es e 2.1 Les scalaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.2 Les nombres . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les chanes de caract` res . . . . . . . . . . . . . . . . . . . . . . e Les variables scalaires . . . . . . . . . . . . . . . . . . . . . . . Interpr tation des variables dans une chane de caract` res . . . . . e e Des fonctions pour manipuler les scalaires . . . . . . . . . . . . .

3 3 3 4 5 7 7 8 8 9

Les tableaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.1 2.2.2 2.2.3 e Les el ments dun tableau . . . . . . . . . . . . . . . . . . . . . Les variables tableaux . . . . . . . . . . . . . . . . . . . . . . .

Des fonctions pour manipuler les variables tableaux . . . . . . . . 10

2.3

Les tableaux associatifs (hashes) . . . . . . . . . . . . . . . . . . . . . . 12

ii 2.3.1 2.3.2

` TABLE DES MATIERES Les variables tableaux associatifs . . . . . . . . . . . . . . . . . 12 Des fonctions adapt es aux tableaux associatifs . . . . . . . . . . 13 e

Les structures de contr le o 3.1 3.2 3.3 3.4 3.5 3.6

15

Linstruction if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 Linstruction unless . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Les instructions while et until . . . . . . . . . . . . . . . . . . . . . . . . 17 Linstruction for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Linstruction foreach . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 Ex cuter si lexpression pr c dente est vraie ou fausse . . . . . . . . . . 19 e e e

Entr e standard et sortie standard e 4.1 4.2

21

Lecture sur lentr e standard . . . . . . . . . . . . . . . . . . . . . . . . 21 e Ecriture sur la sortie standard . . . . . . . . . . . . . . . . . . . . . . . . 22

La variable $

23

6 Premiers exercices 6.1 6.2 6.3

25

Exercice num ro 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 e Exercice num ro 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 e Exercice num ro 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 e

Les expressions r guli` res e e 7.1

29

Lop rateur de recherche doccurrences dexpressions r guli` res . . . . . 29 e e e 7.1.1 Recherche sur une variable quelconque . . . . . . . . . . . . . . 30

` TABLE DES MATIERES 7.2

iii

Construction des expressions r guli` res . . . . . . . . . . . . . . . . . . 30 e e 7.2.1 7.2.2 7.2.3 7.2.4 7.2.5 7.2.6 7.2.7 Les s lecteurs de caract` res . . . . . . . . . . . . . . . . . . . . 30 e e Les multiplicateurs de s lecteurs . . . . . . . . . . . . . . . . . . 31 e Mise en m moire dune s lection partielle . . . . . . . . . . . . . 32 e e La s lection alternative . . . . . . . . . . . . . . . . . . . . . . . 33 e Balisage des fronti` res de s lection . . . . . . . . . . . . . . . . 33 e e s lection dun nombre exact doccurrences . . . . . . . . . . . . 34 e Priorit des op rateurs de construction dexpressions r guli` res . 34 e e e e

7.3 7.4 7.5 7.6

Lop rateur de substitution . . . . . . . . . . . . . . . . . . . . . . . . . 35 e Ignorer la casse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 D but de ligne, n de ligne, ... . . . . . . . . . . . . . . . . . . . . . . . 36 e Travailler sur les champs dune ligne . . . . . . . . . . . . . . . . . . . . 37 7.6.1 7.6.2 split . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 join . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

Exercices sur les expressions r guli` res e e 8.1 8.2 8.3 8.4

39

Exercice num ro 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 e Exercice num ro 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 e Exercice num ro 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 e Exercice num ro 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 e

Quelques trucs utiles 9.1

43

Ex cuter des commandes . . . . . . . . . . . . . . . . . . . . . . . . . . 43 e

iv 9.2 9.3 9.4

` TABLE DES MATIERES La fonction die . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 ` Evaluation a la vol e . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 e Les arguments de la ligne de commande . . . . . . . . . . . . . . . . . . 45

10 La port e des variables e

47

10.1 D clarer des variables locales avec my . . . . . . . . . . . . . . . . . . . 47 e 10.2 Une autre mani` re de d clarer des variables locales . . . . . . . . . . . . 48 e e 10.3 use strict . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49

11 Les fonctions

51

11.1 D nition dune fonction . . . . . . . . . . . . . . . . . . . . . . . . . . 51 e 11.2 Appel dune fonction . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 11.3 Prototyper les fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 11.4 Passer des arguments par r f rences . . . . . . . . . . . . . . . . . . . . 55 ee 11.4.1 Les r f rences de variables . . . . . . . . . . . . . . . . . . . . . 55 ee 11.4.2 Un exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 11.5 Exercice num ro 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 e

12 Acc` s au contenu des chiers e

59

12.1 Ouverture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 12.2 Lecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 12.3 Ecriture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 12.4 Fermeture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 12.5 Exercice num ro 9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 e

` TABLE DES MATIERES 13 Manipulations du syst` me de gestion de chiers e

v 63

13.1 Acc` s aux r pertoires . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 e e 13.1.1 Utiliser la convention * . . . . . . . . . . . . . . . . . . . . . . . 63 13.1.2 Utiliser une interface dacc` s . . . . . . . . . . . . . . . . . . . . 64 e 13.2 Manipulation des chiers et r pertoires . . . . . . . . . . . . . . . . . . . 64 e 13.2.1 Changer de r pertoire de travail . . . . . . . . . . . . . . . . . . 65 e 13.2.2 Cr er un r pertoire . . . . . . . . . . . . . . . . . . . . . . . . . 65 e e 13.2.3 Supprimer un r pertoire . . . . . . . . . . . . . . . . . . . . . . 65 e 13.2.4 Supprimer un chier . . . . . . . . . . . . . . . . . . . . . . . . 65 13.2.5 Renommer un chier . . . . . . . . . . . . . . . . . . . . . . . . 66 13.2.6 Modier les droits dacc` s . . . . . . . . . . . . . . . . . . . . . 66 e 13.3 Fonctions utiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 13.4 Exercice num ro 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 e

14 Les structures de donn es complexes e

71

14.1 Les listes de listes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 14.2 Les hashes de hashes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 14.3 Autres structures de donn es . . . . . . . . . . . . . . . . . . . . . . . . 74 e 14.4 Exercice num ro 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 e 14.5 Exercice num ro 12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 e 14.6 Exercice num ro 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 e

15 Le d bogueur de Perl e

83

vi 16 Ecriture et utilisation de modules

` TABLE DES MATIERES 87

16.1 Inclure du code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 16.2 Les packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 16.3 Remarques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 16.4 Exercice num ro 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 e 17 Ecriture orient e objet e

95

17.1 Un exemple limit a lusage classique des packages . . . . . . . . . . . . 95 e` 17.2 R f rencer une classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 ee 17.3 H riter dune classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 e 17.4 Exercice num ro 16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 e

18 L criture de scripts CGI e

105

18.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 18.2 Un exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 18.2.1 Utiliser cgi-lib.pl . . . . . . . . . . . . . . . . . . . . . . . . . . 107 18.2.2 Utiliser CGI.pm . . . . . . . . . . . . . . . . . . . . . . . . . . 109

18.3 Envoyer un chier (upload) . . . . . . . . . . . . . . . . . . . . . . . . . 110 18.4 Utiliser FastCGI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 18.4.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 18.4.2 Un exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112

19 La programmation dapplications r seaux e

115

19.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115

` TABLE DES MATIERES

vii

19.2 Un exemple dapplication client/serveur . . . . . . . . . . . . . . . . . . 115

Bibliographie

119

viii

` TABLE DES MATIERES

Chapitre 1

Introduction
1.1 G n ralit s e e e

Perl est un langage de programmation adapt au traitement des chiers textes ainsi quaux e t ches dadministration des syst` mes et des applications. Disponible dans le domaine pua e blic pour les environnements Unix, Linux, Windows ... il connait aujourdhui un d veloppement e tr` s important. e Cr e en 1986 par Larry Wall, Perl a depuis connu de nombreuses versions, aujourdhui e on utilise Perl5, la version 5.6 1 est maintenant d nitive. e Perl est un langage interpr t et les programmes Perl se diffusent en format source. Le ee terme interpr t est toutefois ambigu car un programme Perl sex cute en deux phases : ee e la pr -compilation du programme qui produit du pseudo-code, puis linterpr tation du e e pseudo-code (lex cution proprement dite). Le pseudo-code de Perl contient plus de 300 e ` m ta-instructions, a lissue de la pr -compilation on obtient une suite de pseudo-codes e e autonomes qui disposent de pointeurs vers leurs op randes et la m ta-instruction suivante. e e Perl est tr` s r f renc sur le Web, parmi les principaux sites citons : e ee e http://www.perl.org (tout sur Perl) http://www.perl.com (tout sur Perl egalement) http://www.cpan.org (distribution de Perl et des modules)

1. http://www.perl.com/pub/language/info/software.html#stable

CHAPITRE 1. INTRODUCTION

1.2

Un apercu de la syntaxe

` ` Perl est sensible a la casse (les majuscules et minuscules sont diff renci es), cest a dire e e que print est une fonction du langage, alors que Print ne lest pas, mais peut bien s r u ` etre un identicateur (de variables, de fonction, de chier) a la charge du programmeur. Il ny a pas de formatage particulier dans l criture dune instruction Perl, le s parateur e e ` peut etre un espace, une tabulation ou m me un retour a la ligne. Les instructions sont e s par es entre elles par le caract` re ; (le point virgule) et un commentaire est introduit en e e e ` placant le caract` re # a nimporte quel endroit dune ligne (mais il ne s tend que sur une e e ligne). Un programme Perl (souvent appel script) d bute en g n ral par une ligne qui ine e e e dique lendroit o` se trouve le compilateur/interpr teur 2 , cest ainsi que lon peut sur u e des syst` mes Unix d marrer une application Perl en citant simplement son nom. Il nest e e pas inopportun de proc der de m me sur des syst` mes Windows 3 , du moins dans un ene e e vironnement WWW/CGI (cf. section 18) car des serveurs http (tel APACHE) savent tenir compte de cette premi` re ligne et lancer Perl en fonction de ce quelle indique. e

2. #!/usr/local/bin/perl par exemple ... 3. Sur lesquels on lance une application Perl en la citant derri` re le chemin dacc` s a linterpr teur ou en e e ` e effectuant une association entre un sufxe de chier (.pl par exemple) et linterpr teur Perl. e

Chapitre 2

Les types de donn es e


En Perl il nexiste que 3 types de variables : les scalaires, les tableaux et les tableaux associatifs (hash).

2.1

Les scalaires

Une variable de type scalaire est un nombre ou une chane de caract` res. Il nexiste pas de e type particulier pour les valeurs enti` res, les nombres r els, les caract` res ... Lorsque dans e e e ` une expression gurent des variables scalaires correspondants a des valeurs de genres diff rents, Perl effectue des conversions totalement transparentes (et dangereuses). e

2.1.1

Les nombres

Les valeurs litt rales num riques qui peuvent etre affect es a une variable scalaire sexe e e ` priment classiquement :

12 +10 -34 +3.14 5e15 033 x1F

(une valeur enti`re positive) e (une autre valeur enti`re positive) e (une valeur enti`re ngative) e e (un rel positif) e (5 fois 10 puissance 15) (33 en code octal soit 27 en dcimal) e (1F en hexa soit 31 en dcimal) e

4 Les op rateurs pour les nombres e

CHAPITRE 2. LES TYPES DE DONNEES

Les op rateurs arithm tiques sont les suivants : e e

+ * /

(addition) (multiplication) (division)

** %

(soustraction) (puissance) (modulo)

Les op rateurs de comparaison de nombres sont les suivants : e

< (infrieur) e > (suprieur) e <= (infrieur ou gal) >= (suprieur ou gal) e e e e == (galit) e e != (diffrence) e

2.1.2

Les chanes de caract` res e

` Une chane de caract` res Perl comprend de 0 a n caract` res ASCII dont le code est com e e pris entre 0 et 255. Il ny a donc pas de restriction sur le caract` re NUL ou sur les autres e caract` res non imprimables. Il y a deux mani` res de sp cier la valeur litt rale dune e e e e chane : utiliser une simple quote comme d limiteur, le contenu est pris tel que, il ny a pas e dinterpr tation de caract` res particuliers. Dans ce cas pour introduire une simple e e quote dans la chane, il convient de la pr c der dun antislash (\) , pour introduire e e un antislash, il faut le doubler. Bonjour Bonjour \n L\cole e c:\\windows\\system une chane le \n na pas de sens ici le \ devant pour lapostrophe antislash doubls e chane vide

utiliser une double quote comme d limiteur, certaines s quences de caract` res see e e ront interpr t es. Lantislash (\) est utilis ici comme caract` re d chappement ee e e e et sutilise comme suit :

2.1. LES SCALAIRES

"\n" "\t" "\033" "\x1F" "\cA" "\\" "\""

une nouvelle ligne une tabulation un caract`re cod en octal (33 ici) e e un caract`re cod en hexa (1F ici) e e un caract`re de Contrle (Ctrl-A ici) e o un \ une double quote

Les chanes de caract` res pr sent es entre double quotes permettent egalement e e e dinterpr ter le contenu de variables (cf. 2.1.4). e Les op rateurs pour les chanes de caract` res e e Lop rateur de concat nation est le . (le point) : e e "Bonjour"."Monsieur" Il. ."fait beau \n" <==> "BonjourMonsieur" <==> "Il fait beau \n"

Les op rateurs de comparaison de chanes de caract` res sont les suivants : e e eq lt le (galit) e e (infrieur) e (infrieur ou gal) e e ne gt ge (diffrence) e (suprieur) e (suprieur ou gal) e e

Les op rateurs q et qq permettent de remplacer respectivement les d limiteurs de chane e e quote et double quote par un d limiteur au choix du programmeur : e $chaine=S\il vous plait; peut aussi scrire e $chaine=q@sil vous plait@; Cest le caract`re @ qui est ici utilis comme dlimiteur e e e

2.1.3

Les variables scalaires

Une variable scalaire est repr sent e par une suite de caract` re pr c d e du symbole $. e e e e e e Le premier caract` re suivant le $ doit etre une lettre, ensuite on peut trouver un nombre e

CHAPITRE 2. LES TYPES DE DONNEES

quelconque de chiffres et de lettres. Les majuscules et minuscules sont diff renci es et le e e caract` re (soulign ) est autoris : e e e

$Une_Variable $une_variable $une-variable

un nom de variable correct un autre nom de variable un nom de variable incorrect (- vs. _)

Laffectation des variables scalaires Lop rateur daffectation en Perl est le signe = e

` $I = 10; (affecte la constante 10 a la variable I) $K = $I + 1; (affectation de I + 1 ` la variable K soit 11) a $chaine = Bonjour . ` tous; (affectation dune chane) a

Les programmeurs SH ou CSH noteront que pour r f rencer une variable, il convient de ee pr c der son nom par le symbole $ de part et dautre de lop rateur daffectation (le signe e e e =). Il existe dautres op rateurs daffectation, ce sont des raccourcis d criture familiers aux e e programmeurs C : affectation et op ration combin e e e $var += 2; <==> $var = $var + 2; $var *= 3; <==> $var = $var * 3; $chaine .= xxx; <==> $chaine = $chaine . xxx; Incr mentation et d cr mentation automatique e e e $I = 10; $I++; $K = ++$I; $K = $I++;

<==> $I = $I + 1; donc I = 11 <==> $K = $I = $I + 1; donc K = I = 12 <==> $K = $I; $I = $I + 1; donc K = 12 et I = 13

Lincr ment se fait avant laffectation si lop rateur pr c` de le nom de la variable e e e e (++$I) ou apr` s laffectation si lop rateur suit le nom de la variable ($I++). e e

2.1. LES SCALAIRES

2.1.4

Interpr tation des variables dans une chane de caract` res e e

Des variables scalaires peuvent etre interpr t es lorsquelles sont contenues dans des ee ` chanes de caract` res pr sent es entre double quotes. A cet effet, Perl recherche le ca e e e ract` re $ et consid` re ce qui le suit comme un nom de variable potentiel. Si la variable e e existe, son contenu est int gr a la chane source, si elle nexiste pas, elle est remplac e e e` e par une chane vide. Il ny a quun seul niveau dinterpr tation, si une variable contient e ` elle m me une chane faisant r f rence a une autre variable, il ny aura aucun traitement. e ee Pour emp cher linterpr tation comme un nom de variable des caract` res qui suivent le e e e caract` re $, il convient de le pr c der dun antislash ou de placer le morceau de chane e e e consid r entre simple quotes. ee

$chaine1 $chaine2 $chaine3 $chaine4

= = = =

"Au revoir"; "$chaine1 les petits amis"; "au plaisir "; "${chaine3}de vous revoir"; Les accolades sont utilises ici comme en sh, csh pour indiquer e explicitement la variable ` interprter. a e

2.1.5

Des fonctions pour manipuler les scalaires

En plus des op rateurs du langage, Perl propose des fonctions (cf. section 11) adapt es e e au traitement des variables scalaires, parmi celles-ci citons : chop() enl` ve le dernier caract` re dune chane; e e chomp() enl` ve le dernier caract` re dune chane si celui-ci est un d limiteur de n e e e de ligne; chr() convertit une valeur enti` re en le caract` re correspondant du code ASCII; e e ` hex() renvoie la valeur d cimale correspondant a une chane de caract` res h xad cimaux; e e e e ` oct() renvoie la valeur d cimale correspondant a une chane de caract` re octaux; e e index() renvoie la position de la premi` re occurrence dune sous chane dans une e chane; lc() convertit une chane de caract` res en caract` res minuscules; e e length() indique la longueur en caract` re dune variable scalaire; e rindex() renvoie la position de la derni` re occurrence dune sous chane dans une e chane; substr() permet dextraire dune chane une sous chane d nie en position et lon e gueur.

CHAPITRE 2. LES TYPES DE DONNEES

$Esc $B10 $B10 $Min $Lg $Lg

= = = = = =

chr(27); hex("1F3C"); oct("1073"); lc("ABCDE"); length($Min); length($B10);

# # # # # #

convertit lentier 27 en ASCII $B10 vaut 7996 $B10 vaut 571 $Min vaut "abcde" $Lg vaut 5 (longueur en caract`res e $Lg vaut 3 dun scalaire)

2.2

Les tableaux

Une variable de type tableau est une liste de donn es scalaires (nombres et/ou chanes). e e Chaque el ment du tableau est une variable scalaire accessible comme telle.

e 2.2.1 Les el ments dun tableau


Les valeurs litt rales qui peuvent etre affect es a une variable de type tableau sexpriment e e ` comme une liste de valeurs s par es par des virgules et encadr es par des parenth` ses. e e e e

() <==> tableau vide (8,4,9,4,5) <==> 5 lments (des nombres) e e (toto,"$var",3) <==> 3 lments (la chane toto, e e la valeur courante de la variable $var et le nombre 3)

e Un op rateur de construction liste (..) peut etre utilis pour sp cier un el ment de tae e e bleau.

` (1..10) <==> 10 lments (les nombres de 1 a 10) e e (1..5,10,20..30) <==> 16 lments (les chiffres de 1 ` 5, e e a puis le nombre 10 et les 11 nombres de 20 ` 30 a ($debut..$fin) <==> (($fin+1) - $debut) lments ayant e e pour valeurs de $debut ` $fin par incrment de 1 a e

2.2. LES TABLEAUX

2.2.2

Les variables tableaux

Le nommage dune variable tableau suit les m mes conventions que celui dune variable e scalaire, hormis le premier caract` re qui est ici @ (un arobas). Cest le premier caract` re e e qui determine le type de la variable utilis e, si @tab est une variable de type tableau, e ` elle na rien a voir avec $tab qui est une variable de type scalaire. Une variable de type e tableau qui na jamais et affect e a pour valeur une liste vide (). e Laffectation des variables tableaux Le signe egal est lop rateur daffectation des variables tableaux. e

$I = 5; @tab1 = (); @tab2 = (5,3,15);

<==> @tab1 est vide <==> @tab2 contient 3 lments de e e valeurs 5, 3 et 15 @tab1 = @tab2; <==> @tab1 est une copie de @tab2 @tab2 = $I; <==> @tab2 recoit un scalaire et ne contient plus quun seul lment (de valeur 5) e e ($a,$b,$c) = @tab1; <==> $a = 5; $b = 3; $c = 15;

e acc` s aux el ments dune variable tableau e e Les el ments constitutifs dune variable de type tableau sont des scalaires, la r f rence ee ` e a un el ment commence donc par le symbole $, un indice exprim entre crochets ([]) e e indique loccurrence cibl e. Le premier el ment dun tableau est accessible par lindice e 0.

$I = 5; @tableau = (x,2,3,4,5,x); $tableau[0] = 1; <==> acc`s au 1er lment du tableau e e e $tableau[$I] = 6; <==> acc`s au I`me lment e e e e

e Lindice du dernier el ment dune variable tableau est accessible par la variable scae laire $#nom-du-tableau. Si on affecte un el ment au del` de cette limite, les trous sont a

10

CHAPITRE 2. LES TYPES DE DONNEES

e bouch s par des el` ments de valeur undef 1 . e

@tab = (10,20,30); $tab[$#tab+1] = 40; $tab[10] = 1000;

<==> $tab[3] = 40; $#tab vaut maintenant 3 <==> $#tab vaut maintenant 10, les lments intermdiaires $tab[4]..$tab[9] e e e prennent la valeur undef

Laffectation dune variable tableau dans une variable scalaire rend le nombre d l ments ee de la variable tableau :

@tab = (1,2,3,4); $scal = @tab; # $scal vaut 4

2.2.3

Des fonctions pour manipuler les variables tableaux

Diverses fonctions permettent deffectuer des d calages, des tris ... sur des listes (des e variables tableaux). Les fonctions push() et pop() Les fonctions push() et pop() permettent de travailler sur lextr mit droite dune liste e e (ajout ou suppression d l ments) : ee

@liste=(a,b); push(@liste,(c,d,e)); <==> @liste=(a,b,c,d,e) pop(@liste); <==> @liste=(a,b,c,d)

Les fonctions shift() et unshift()


1. undef vaut 0 pour un nombre ou vide pour une chane. On peut indiff remment utiliser les op rateurs e e ` de comparaison == ou eq pour comparer un scalaire a la valeur undef

2.2. LES TABLEAUX

11

Les fonctions shift() et unshift() permettent de travailler sur lextr mit gauche dune e e liste (ajout ou suppression d l ments) : ee

@liste=(c,d,e); unshift(@liste,(a,b)); <==> @liste=(a,b,c,d,e) shift(@liste); <==> @liste=(b,c,d,e)

La fonction sort() e La fonction sort() permet de trier une liste dans lordre ASCII de ses el ments (les nombres sont convertis en chanes avant le tri) :

@liste=(100,1,2,58,225); @tri=sort(@liste); <==> @tri=(1,100,2,225,58) @liste=(rouge,vert,bleu); @tri=sort(@liste); <==> @tri=(bleu,rouge,vert)

La fonction reverse() e La fonction reverse() permet dinverser les el ments dune liste :

@liste=(1,2,3,4,5); @rev=reverse(@liste);

<==> @rev=(5,4,3,2,1)

La fonction chop() e La fonction chop() permet de supprimer le dernier caract` re de tous les el ments dune e liste. Elle fonctionne egalement sur une variable scalaire et est surtout utilis e pour supe primer les caract` res de n de lignes contenus dans des lignes (r sultats de saisies ...) : e e

@liste=("tutu\n","toto\n"); chop(@liste); <==>

@liste=("tutu","toto")

La fonction chomp()

12

CHAPITRE 2. LES TYPES DE DONNEES

La fonction chomp() permet de supprimer le dernier caract` re (seulement sil sagit dun e e d limiteur de n de ligne) de tous les el ments dune liste. Il est donc pr f rable dutiliser e ee chomp() pour supprimer les eventuels d limiteurs de n de lignes r sultant dune saisie, e e dune lecture de chier, ... La fonction qw() Laffectation de constantes lit rales dans un tableau est fr quente et dune ecriture un peu e e fastidieuse, Perl propose la fonction qw() qui travaille sur une liste de mots :

@liste=("tutu","toto",machin); # est equivalent ` a @liste = qw(tutu toto machin); # ou mme ` e a @liste = qw(tutu toto machin);

2.3

Les tableaux associatifs (hashes)

e Un tableau associatif (ou hash) est un tableau dont les el ments (des scalaires) sont e acc d s au moyen dun index qui est une valeur scalaire quelconque. Les el ments dun e e hash sont des couples (clef, valeur).

2.3.1

Les variables tableaux associatifs

Le nommage dun tableau associatif suit les m mes conventions que celui dune variable e scalaire, hormis le premier caract` re qui est ici un % (le caract` re pour-cent). e e

%trad = (january,janvier,february,avril); # # # On affecte le hash %trad par une liste qui contient un nombre pair dlments correspondant ` des couples e e a clef, valeur.

$trad{february}=fevrier; # llment du hash %trad dont la clef est february recoit e e # une nouvelle valeur.

2.3. LES TABLEAUX ASSOCIATIFS (HASHES)

13

Une autre forme peut etre utilis e pour sp cier les valeurs dun tableau associatif, elle e e met en evidence la correspondance clef/valeur :

%trad = ( january => janvier, february => fevrier, march => mars );

2.3.2
keys

Des fonctions adapt es aux tableaux associatifs e

La fonction keys(%var hashee) rend une liste des clefs dun hash.

%hash = (un,1,deux,2,trois,3,quatre,4); @liste_clef = keys(%hash); # <==> @liste_clef = (un,deux,trois,quatre);

values La fonction values(%var hashee) rend une liste des valeurs dun hash.

%hash = (un,1,deux,2,trois,3,quatre,4); @liste_val = values(%hash); # <==> @liste_val = (1,2,3,4);

each ` e La fonction each(%var hashee) rend un couple clef,valeur dans une liste a deux el ments. Chaque appel de each sur une m me variable de type hash rend le couple suivant. e

%hash = (un,1,deux,2,trois,3,quatre,4); ($clef,$valeur) = each(%hash); # au 1er appel <==> $clef=un; et $valeur=1;

14

CHAPITRE 2. LES TYPES DE DONNEES

each est la fonction adapt e pour parcourir enti` rement un hash, elle rend une liste vide e e lorsque la n du hash est atteinte. delete e La fonction delete permet de supprimer un el ment dun hash en indiquant sa clef.

%hash = (un,1,deux,2,trois,3,quatre,4); delete($hash{deux});

15

Chapitre 3

Les structures de contr le o


Diverses structures de contr le sont propos es en Perl, elles evaluent une expression o e ` et proposent un traitement selon les sch mas algorithmiques classiques. Lexpression a e ` evaluer est convertie en chane, une chane non vide ou diff rente de 0 correspond a la e valeur vrai. Les op rateurs de comparaison (==,>,gt,...) retournent 1 pour vrai et 0 pour e faux (0 lorsque converti en chane), ci-dessous quelques exemples dexpressions vraies ou fausses :

0 <==> faux "0" <==> faux, cest 0 converti en chane <==> faux, chane vide 00 <==> vrai, diffrent de 0 ou 0 e 1 <==> vrai "nimporte quoi" <==> vrai undef <==> undef rend une chane vide donc faux

Perl permet de structurer des instructions en utilisant des blocs d limit s comme en C par e e les accolades ({}). La structuration en blocs a un impact sur la port e des variables (cf. e section 10).

16

CHAPITRE 3. LES STRUCTURES DE CONTROLE

3.1

Linstruction if

La syntaxe g n rale de linstruction if est la suivante : e e

if (expression_`_valuer) { a e instruction(s) ` excuter si lexpression est vraie a e } else { instructions ` excuter si lexpression est fausse a e }

` Si il ny a rien de particulier a faire dans le cas ou lexpression est fausse, on peut se passer ` e du else {...}. Par contre m me sil ny a quune seule instruction a ex cuter, il convient e de la placer dans un bloc {}.

if ($I == 0) { $I++; } <==> le else est omis if ((10 == 10) == 1) { ... } <==> vrai car == rend 1 si la condition est ralise e e

Le test de plusieurs cas peut etre enchain en utilisant elsif : e

if ($Couleur eq "Bleu") { ... } elsif ($Couleur eq "Rouge") { ... } elsif ($Couleur eq "Vert") { ... } else { ... } if ($Couleur eq "Noir") { ... } else if ($Couleur eq "Jaune") <==> erreur de syntaxe, un else doit tre suivi par une accolade { e

3.2. LINSTRUCTION UNLESS

17

3.2

Linstruction unless

Linstruction unless fonctionne comme un nif (non if : si lexpression est fausse alors faire).

unless ($I > 0) { ... } else { ... }

Un elsif peut suivre un unless, le elseunless nexiste pas.

3.3

Les instructions while et until

Perl dispose dune structure tant que (while) et dune structure jusqu` ce que (until). a

$I = 0; while ($I < 10) { $I++; }

<==> tant que I est inferieur ` 10 a

$I = 0 until ($I == 10) { $I++; } <==> jusqu` ce que a I soit gal ` 10 e a while (1) { ... } <==> sans fin while () { ... } <==> sans fin, une expression inexistante nest pas vide ! until (0) { ... } <==> sans fin

Pour forcer la sortie dune boucle while ou until sans soccuper de la condition darr t, on e utilise linstruction last (de la m me facon quun break en Langage C). Pour faire evaluer e la condition sans avoir d roul la totalit des instructions du bloc, on utilise linstruction e e e next.

3.4 Linstruction for


` Linstruction for correspond a une boucle pour dans laquelle on fournit une valeur de ` d part, une expression a evaluer et une expression permettant une r initialisation (incr ment, e e e

18 d cr ment, ...). e e

CHAPITRE 3. LES STRUCTURES DE CONTROLE

for ($I=0; $I < 10; $I++) { ... }

` Dans lexemple ci-dessus, on affecte 0 a I, on evalue ($I < 10), si cest vrai on ex cute e ` les instructions incluses dans le bloc et on passe a lincr mentation de I, si cest faux on e ` passe a linstruction suivante.

for (;;) { ... }

<==> boucle sans fin, les expressions ne sont pas obligatoires

Les instructions next et last fonctionnent de la m me mani` re que pour while et until (cf. e e section 3.3).

3.5

Linstruction foreach

Linstruction foreach charge dans une variable les valeurs successives dune liste et effectue le traitement sp ci dans le bloc dinstructions. Quand la n de la liste est atteinte, e e ` on passe a linstruction suivante :

foreach $Couleur (jaune,vert,bleu) { ... } la variable couleur prend successivement les valeurs jaune, vert et bleu foreach $var (@tableau1, @tableau2, $I, $K, 10) la variable $var prend successivement toutes les valeurs scalaires contenues dans $tableau1 ... jusqu` la valeur 10 a

` Ici aussi, last provoque une sortie forc e de la boucle et next un passage a la valeur e suivante.

3.6. EXECUTER SI LEXPRESSION PRECEDENTE EST VRAIE OU FAUSSE

19

3.6

Ex cuter si lexpression pr c dente est vraie ou fausse e e e

Lop rateur && permet d valuer une expression si celle qui la pr c` de est vraie, lop rateur e e e e e || permet d valuer une expression si celle qui la pr c` de est fausse : e e e

$J = $I % 2 && printf ("I est impair \n"); I modulo 2 vaut 0 ou 1, si 1 le nombre est impair si 0 le nombre est pair $J = $I % 2 || printf ("I est pair \n");

Les op rateurs && et || peuvent etre utilis s pour former des expressions conditionnelles e e evalu es par linstruction if : e

if (($a == $b) || ($a == $c)) { ... }

Une derni` re construction est possible, elle admet 3 expressions s par es par les op rateurs? e e e e et :, la seconde est evalu e si la premi` re est vraie, la troisi` me est evalu e si la premi` re e e e e e est fausse :

$J = $I % 2 ? printf ("impair \n") : printf ("Pair \n");

20

CHAPITRE 3. LES STRUCTURES DE CONTROLE

21

Chapitre 4

Entr e standard et sortie standard e


Compte tenu du pass Unix de Perl, on lit sur le STDIN et on ecrit sur le STDOUT. Par e d faut il sagit du clavier et de l cran, mais Perl ne sen occupe pas, cest au syst` me e e e dexploitation de lui fournir des descripteurs valides.

4.1

Lecture sur lentr e standard e

Lop rateur de lecture sur lentr e standard est <STDIN>. e e $ligne = <STDIN>; @lignes = <STDIN>; <==> on la <==> le un affecte ` la variable $ligne a ligne suivante tableau @lignes recoit lment par lignes lues e e

` Pour lire et traiter ligne a ligne on proc` de en g n ral comme suit : e e e while ($ligne = <STDIN>) { ... } Lorsque la derni`re ligne est e atteinte, <STDIN> retourne undef et la boucle while sarrte e

Perl autorise une autre forme de lecture du STDIN avec lop rateur <> qui passe au e programme tous les chiers indiqu s sur la ligne de commande (chaque argument de la e ligne de commande est alors consid r comme un nom de chier). ee

22

CHAPITRE 4. ENTREE STANDARD ET SORTIE STANDARD

4.2

Ecriture sur la sortie standard

Linstruction print ecrit une liste de chane de caract` res sur la sortie standard. e

print (@liste1, $chaine, @liste2, toto);

Il est possible de contr ler la pr sentation des impressions sur la sortie standard en utio e lisant linstruction printf qui fonctionne comme en C. Elle admet comme argument une e liste dont le premier el ment est une chane de caract` res qui contient le masque dim e ` pression des variables ainsi que des valeurs constantes a intercaler entre elles (les autres e ` el ments de la liste sont les variables a imprimer).

printf ("%s %s %5d \n",$chaine1,$chaine2,$I); %s est le masque dimpression de $chaine1 %s est le masque dimpression de $chaine2 %5d est le masque dimpression de $I \n constante qui introduit une nouvelle ligne

Si un argument de printf est une variable tableau, il convient de sp cier autant de e masques dimpression que de valeurs scalaires distinctes contenues dans le tableau. Les ` e masques dimpression indiquent les conversions a r aliser et sutilisent comme dans lexemple suivant :

%10s %.5s %3d %o %x %f %.3f %e

<==> une chane sur sa longueur relle complte e e e ventuellement par des espaces (10 maxi) e <==> les 5 premiers caract`res dune chane e <==> un entier tel que ou sur 3 caract`res sil e est infrieur ` 99 (espace ` gauche) e a a <==> un nombre en octal <==> un nombre en hxadcimal e e <==> un rel avec 6 dcimales e e <==> un rel avec 3 dcimales e e <==> un rel en reprsentation mantisse/exposant e e

23

Chapitre 5

La variable $
Perl utilise une variable scalaire fourre-tout nomm e $ ($ soulign ) comme r sultat par e e e d faut dun certain nombre dinstructions. Cest notamment le cas avec la lecture sur e lentr e standard : e

while (<STDIN>) { chop; }

<==> <==> <==> <==>

while ($_ = <STDIN>) { chop($_); }

La variable $ est egalement implicitement utilis e par les instructions foreach et print 1 , e ainsi que par les instructions qui manipulent des expressions r guli` res (cf. section 7) ou e e celles qui testent lexistence de chiers et r pertoires (cf. section 13.3). e

@liste=(1,2,3,4,5); foreach (@liste) { print ; }

<==> <==> <==> <==>

foreach $_ (@liste) { print $_; }

1. Mais printf nutilise pas la variable $ par d faut. e

24

CHAPITRE 5. LA VARIABLE $

25

Chapitre 6

Premiers exercices
6.1 Exercice num ro 1 e

#!/usr/bin/perl # TP1 # Lecture de nombres, pour chacun dentre eux on indique # sil est pair ou impair. ` lissue de la saisie (Ctrl-d A # sous Unix ou Ctrl-z sous Windows) on affiche la moyenne # des nombres entrs. e print ("Entrer un nombre \n"); $n=0; $total=0; while(<STDIN>) { # le rsultat de la saisie dans $_ e chomp(); # enl`ve le dlimiteur de fin de ligne e e if ($_ % 2) { # rend 1 si impair et 0 sinon print ("$_ est impair \n"); } else { print ("$_ est pair \n"); } $n++; $total += $_; print ("Entrer un nombre \n"); } if ($n) { print ("La moyenne est : ",$total / $n,"\n"); }

26

CHAPITRE 6. PREMIERS EXERCICES

6.2

Exercice num ro 2 e

#!/usr/bin/perl

# # # # # # #

TP2 Constituer une liste de mots entrs au clavier lun apr`s e e lautre. Trier la liste constitue par ordre croissant puis par e ordre dcroissant. e

print ("Entrer un mot \n"); while (<STDIN>) { chomp(); push (@liste, $_); print ("Entrer un mot \n"); } if (@liste) { @tri=sort(@liste); @rev=reverse(@tri); print("Par ordre croissant : \n"); print ("@tri \n"); print ("Par ordre decroissant : \n"); print ("@rev \n"); }

6.3. EXERCICE NUMERO 3

27

6.3

Exercice num ro 3 e

#!/usr/bin/perl

# # # # # #

TP3 On utilise un Hash pour grer un stock. Le nom dun e vin est utilis comme clef, une valeur saisie au clavier e vient en + ou - de lventuelle valeur deja existante. e

%Stock=(); print ("Nom du vin : \n"); while ($Vin=<STDIN>) { #Vin sera la clef du Hash de stock. chomp($Vin); # Enl`ve le car de fin de ligne. e print ("Quantit : "); e $Quant=<STDIN>; # Il faudrait vrifier quil sagit e # bien dun nombre entier relatif. chomp($Quant); unless ($Quant) {# Si lutilisateur ne saisit pas de last; # quantit, on affiche le stock. e } $Stock{$Vin} += $Quant; print ("Nom du vin : \n"); } # Parcourir le stock while (($Vin,$Quant) = each(%Stock)) { print ($Vin,"=",$Quant,"\n"); }

28

CHAPITRE 6. PREMIERS EXERCICES

29

Chapitre 7

Les expressions r guli` res e e


Perl est tr` s adapt au traitement des chanes de caract` res car il permet de sp cier e e e e des masques qui peuvent etre utilis s pour rechercher des occurrences de s quences de e e caract` res qui leurs correspondent. Les masques sont appel s expressions r guli` res, ils e e e e sont familiers des utilisateurs des commandes Unix telles que ed, sed, awk ...

7.1

Lop rateur de recherche doccurrences dexpressions r guli` res e e e

En placant une expression r guli` re entre slashs (/ expr /), on recherche son existence e e e eventuelle dans la variable $ (de la gauche vers la droite). Lop rateur de recherche retourne vrai si lexpression r guli` re trouve une correspondance (et retourne faux dans le e e cas contraire). De plus lop rateur de recherche sil retourne vrai positionne les variables e suivantes : ` $& contient le sous ensemble de $ qui correspond a lexpression r guli` re ; e e $ contient le sous ensemble de $ qui se trouve avant $& ; $ contient le sous ensemble de $ qui se trouve apr` s $&. e

$_ = "Il fait beau"; if (/fait/) { print ($&,$,$,"\n"); # <==> $& = fait, $=Il # <==> $ = beau }

30

` CHAPITRE 7. LES EXPRESSIONS REGULIERES

7.1.1

Recherche sur une variable quelconque

` Lorsque la variable a osculter nest pas $ , on utilise lop rateur = : e

$var = "Il fait beau"; if ($var = /fait/) { print ($&,$,$,"\n"); # # }

<==> $& = fait, $=Il <==> $ = beau

7.2
7.2.1

Construction des expressions r guli` res e e


Les s lecteurs de caract` res e e

Des s lecteurs de caract` res sont utilis s pour construire les expressions r guli` res. Les e e e e e plus simples recherchent lexistence dun caract` re, ils peuvent etre r p t s pour construire e e ee des expressions plus compliqu es : e

recherche nimporte quel caract`re (sauf le e changement de ligne) recherche un caract`re parmi ceux situs entre e e les accolades (classe de caract`res) e recherche un caract`re qui ne soit pas un de ceux e situs entre les accolades e recherche un caract`re dont le code ASCII est e situ entre le 1er et le 2`me caract`re cit e e e e dans cet exemple, on recherche un a, suivi dun b, suivi dun caract`re quelconque, suivi dune e lettre minuscule

[abc]

[abc]

[a-z]

ab.[a-z]

` 7.2. CONSTRUCTION DES EXPRESSIONS REGULIERES Il existe des classes de caract` res pr d nies : e e e

31

` ` (\d) correspond a un chiffre donc a [0-9] ; ` ` (\w) correspond a une lettre (plus le caract` re soulign !) donc a [a-zA-Z0-9 ] ; e e (\s) correspond aux caract` res de s paration usuels (espace, tabulation, retour e e charriot, nouvelle ligne, saut de page). Ces 3 classes de caract` res ont une construction n gative \D, \W, \S signiant respectie e vement [0-9], [a-zA-Z0-9 ] et [ \r\t\n\f].

7.2.2

Les multiplicateurs de s lecteurs e

Des multiplicateurs peuvent etre utilis s pour sp cier les expressions r guli` res : e e e e ` * indique 0 ou plus de caract` res identiques a celui plac a gauche ; e e` ` + indique 1 ou plus de caract` res identiques a celui plac a gauche ; e e` ` ? indique 0 ou 1 caract` re identique a celui plac a gauche. e e`

chane source expr. reg ============= =========== xxxF x? xxxF x* "nimporte quoi" .* abcdefg a.+d aabbbcdde a+b+ aabbbcdde a+c

V/F ===== V V V V V F

contenu de $& =============== x xxx "nimporte quoi" abcd aabbb

Il faut manipuler avec pr caution le multiplicateur * car il signie 0 ou n occurrences (0 e videmment) et de plus, comme le multiplicateur +, il est glouton, cest a dire que ` inclus e sil y a correspondance, il retournera la plus longue chane possible.

chane source ============= xxxF abcxxxF abcxxxF

expr. reg =========== x* x* abcx*

V/F ===== V V V

contenu de $& =============== xxx chane vide abcxxx

32

` CHAPITRE 7. LES EXPRESSIONS REGULIERES

Dans lexemple ci-dessus, la chane est parcourue de la gauche vers la droite, dans le premier cas lop rateur glouton retourne xxx, dans le second cas il retourne 0x (donc une e chane vide), le fonctionnement du 3` me cas est analogue au premier. e Pour inhiber le fonctionnement glouton dun multiplicateur, on le fait suivre dun ? qui signie : le nombre minimum de caract` res correspondant au s lecteur. e e

chane source ============= xxalloallo xxalloallo xyzaaaxyz xyzaaaxyz

expr. reg =========== a.*o a.*?o xyza* xyza*?

V/F ===== V V V V

contenu de $& =============== alloallo allo xyzaaa xyz

7.2.3

Mise en m moire dune s lection partielle e e

Il est possible dans une m me expression r guli` re dutiliser comme s lecteur le r sultat e e e e e dune s lection d j` effectu e, elle est mise en m moire et num rot e au pr alable par e ea e e e e e ` ee lop rateur (). Lop rateur \num ro sert a r f rencer une mise en m moire : e e e e

if (/<(.*)>.*<\/\1>/) printf ("balise : $& \n");

` Lexemple ci-dessus 1 peut servir a rechercher certaines balises dun texte HTML. Les parenth` ses autour du premier .* indiquent quil faut stocker le r sultat de la s lection, le e e e ` \1 fait r f rence a cette s lection. ee e

<H1> xxxx </H1> ou <EM> xxxxx </EM> correspondent ` lexpression rguli`re a e e donne ci-dessus, mais e <A HREF="xxxx"> ancre </A> ne le fait pas !
1. recherche nimporte quelle chane de caract` res situ e entre <> suivie dun texte ( ventuellement e e e vide), suivi entre <> de la chane trouv e initialement pr c d e dun / e e e e

` 7.2. CONSTRUCTION DES EXPRESSIONS REGULIERES

33

Lop rateur () est egalement utilis pour appliquer un multiplicateur au r sultat dune e e e s lection : e

if (/ab(cde)+/) { # vrai pour abcde, abcdecde, abcdecdecde, ... # le multiplicateur + sapplique au rsultat de e # la slection entre parenth`ses. e e }

7.2.4

La s lection alternative e

Lop rateur | est utilis pour marquer une s lection avec alternative : e e e

/abc|def/ slectionne des chanes de caract`res contenant e e conscutivement les caract`res abc ou def e e

7.2.5

Balisage des fronti` res de s lection e e

Des op rateurs particuliers permettent de sp cier des fronti` res auquelles sappliquent e e e les s lecteurs : e \b indique que le s lecteur pr c dent ne sapplique que sur une fronti` re de mot ; e e e e \B indique que le s lecteur pr c dent ne sapplique pas sur une fronti` re de mot ; e e e e marque le d but dune ligne ; e $ marque la n dune ligne.

http [http] \http xxx$ xxx\$ \bpays\b

<==> chane commencant par la squence http e <==> chane ne comportant ni h, ni t, ni t, ni p <==> chane contenant la suite de caract`res e http <==> chane terminant par xxx <==> chane contenant la suite de caract`res e xxx$ <==> chane contenant le mot pays, paysage ou paysan ne correspondent pas

34

` CHAPITRE 7. LES EXPRESSIONS REGULIERES

7.2.6

s lection dun nombre exact doccurrences e

Il est possible de s lectionner un nombre exact doccurrences en utilisant lop rateur {} : e e

/\d{1,5}/ /x{3}/ /x{3,}

` recherche un nombre compos de 1 a 5 chiffres e (au moins 1 et au plus 5) recherche exactement 3 x recherche une suite dau moins 3 x (la borne suprieure nest pas prcise) e e e

7.2.7

Priorit des op rateurs de construction dexpressions r guli` res e e e e

Comme pour r daction dexpressions arithm tiques, il peut y avoir des ambiguit s dans e e e l criture des expressions r guli` res : e e e

[a-z]|[A-Z]+

veut il dire 1 ou n occurrences dune lettre minuscule ou dune lettre majuscule ou plutt o une lettre minuscule ou 1 ou n occurrences dune lettre majuscule

Des r` gles de priorit s existent, en en tenant compte dans lexemple ci-dessus, on a proe e gramm le deuxi` me cas (le | est moins prioritaire que le plus). Pour eviter de connatre e e pr cisemment les r` gles de priorit s des op rateurs, il suft de noter que lop rateur () est e e e e e ` le plus prioritaire, pour programmer a coup s r le cas num ro 1, on pourrait ecrire : u e

([a-z]|[A-Z])+ <==> la mise entre parenth`ses de e lalternative assure quelle sera prioritaire sur le +

7.3. LOPERATEUR DE SUBSTITUTION

35

7.3

Lop rateur de substitution e

` Pour effectuer des substitutions correspondant a des expressions r guli` res, on utilise e e lop rateur s/expr-reg/chaine/, qui par d faut utilise et affecte la variable $ . e e

$_ = 123456789; s/123/abc/; $var = abctotototodef; $var = s/(to)+//;

<==> $_ = abc456789 <==> $var = abcdef

Les variables $&, $ et $ conservent le m me sens quavec lop rateur de recherche, la e e chane supprim e est contenue dans $& ... e Lorsque la chane a traiter nest pas contenue dans la variable $ , on utilise lop rateur ` e de recherche = qui combin avec lop rateur de substitution, utilise et affecte la variable e e cit e. e Lop rateur de substitution sarr te sur la premi` re occurrence de la chane correspondant e e e ` a lexpression r guli` re donn e. Pour effectuer une substitution de toutes les occurrences, e e e il convient de lindiquer en rajoutant un g (global) derri` re le dernier / de lop rateur de e e substitution :

$var = aa123aaa456aaaa789; $var = s/a+/ /g; <==> $var = 123 456 789

` Il peut etre int ressant de r f rencer la chane correspondant a une expression r guli` re e ee e e dans une op ration de substitution : e

while ($ligne = <STDIN>) { $ligne = s/(images|applet)/$1\/monprojet/g;

` Lexemple pr c dent peut servir a rajouter un r pertoire (monprojet ici) dans les r f rences e e e ee ` ` a des images ou des applets a lint rieur dun document HTML. e

36

` CHAPITRE 7. LES EXPRESSIONS REGULIERES

7.4

Ignorer la casse

Il est possible dindiquer aux op rateurs de recherche et de substitution dignorer la casse e (de traiter indiff remment les lettres majuscules et minuscules) en utilisant le symbole i e (ignore) :

s/begin/debut/i

remplace begin, Begin, BEGIN .... par la chaine "debut"

7.5

D but de ligne, n de ligne, ... e

` Les fronti` res de s lection et $ marquent le d but et la n de ligne. Si la variable a traiter e e e (par les op rateurs de recherche ou de substitution) contient plusieurs lignes (un scalaire e contenant la totalit dun chier par exemple), il convient de pr ciser si $ marquera la n e e du chier ou succ ssivement la n de chaque ligne ? On utilise pour cel` les modieurs e a m et s : ` m indique que la variable scalaire a traiter est consid r e comme multi-ligne. et ee ` $ s lectionnent un d but ou une n de ligne a nimporte quel emplacement dans la e e ` variable a traiter (et non plus le 1er et le dernier caract` re) ; e ` s indique que la variable a traiter est consid r e comme ne comportant quune seule ee ligne (un . s lectionne alors nimporte quel caract` re, le d limiteur de n de ligne e e e y compris). Cette derni` re fonctionnalit peut etre utile pour isoler une partie de e e texte comportant plusieurs lignes (cf; exemple suivant).

# Si la variable $html contient la totalit dun fichier e # HTML alors la variable $body contiendra le corps # du document : $body = $html; $body = s/(.*)<body>(.*)<\/body>/\2/s;

7.6. TRAVAILLER SUR LES CHAMPS DUNE LIGNE

37

7.6
7.6.1

Travailler sur les champs dune ligne


split

Perl traite les ux de donn es comme une suite de lignes compos es de champs s par s e e e e par les s parateurs habituels (espace, tabulation). e La fonction split d coupe une ligne en champs en utilisant comme d limiteur une exe e ` pression r guli` re, toutes les parties de la ligne qui ne correspondent pas a lexpression e e r guli` re sont stock es dans une liste. e e e

#!/usr/local/bin/perl while ($ligne=<STDIN>) { @champ = split (/:/,$ligne); printf ("User: %s Sh: %s \n",$champ[0],$champ[$#champ]); }

Le programme ci-dessus examine le contenu dun chier style /etc/passwd (dont les champs sont s par s par le caract` re :) et isole les noms dusagers (le premier champ) e e e ainsi que leurs interpr teurs de commandes favori (le dernier champ, sous Unix bien s r). e u split travaille implicitement sur la variable $ , et on aurait donc pu ecrire lexemple pr c dent sous la forme suivante : e e

#!/usr/local/bin/perl while (<STDIN>) { @champ = split (/:/); printf ("User: %s Sh: %s \n",$champ[0],$champ[$#champ]); }

Sil sagit dutiliser les espaces ou les tabulations comme d limiteur, on peut tout sime plement omettre lexpression r guli` re. Si on travaillle sur le variable $ , on peut alors e e

38 ecrire :

` CHAPITRE 7. LES EXPRESSIONS REGULIERES

while (<STDIN>) { @champ = split(); }

# ou mme @champ=split; e

7.6.2

join

join permet lop ration inverse dun split ie. recoller les morceaux. e

$ligne = join(:,@champ); <==> la variable $ligne recoit la liste @champ avec insertion dun sparateur (: ici). e

39

Chapitre 8

Exercices sur les expressions r guli` res e e


8.1 Exercice num ro 4 e

#!/usr/bin/perl # TP4 # On vrifie que des chaines saisies peuvent correspondre e # ` une immatriculation de vhicule en france. a e # On vrifie donc que la chaine saisie e # commence par un chiffre compris entre 1 et 9 # ventuellement suivi de 4 chiffres, suivi de une, deux e # ou trois lettres, suivi de # - le chiffre 0 suivi dun chiffre ou # - un chiffre suivi dun chiffre ou # - 2a ou 2b print ("Entrer une immatriculation de vhicule : \n"); e while (<STDIN>) { # chomp(); nest pas obligatoire car $ matche la fin de la ligne # ou juste avant le retour charriot sil y en a un ... if (/[1-9][0-9]{0,4}[a-zA-Z]{1,3}(0[1-9]|[1-9][0-9]|2a|2b)$/) { print ("Cest bon $& \n"); } else { print ("Cest faux $& \n");} print ("Entrer une immatriculation de vhicule : \n"); e }

40

` CHAPITRE 8. EXERCICES SUR LES EXPRESSIONS REGULIERES

8.2

Exercice num ro 5 e

#!/usr/bin/perl

# TP5 # # # # # # # Calcul dexpressions arithmtiques simples (non parenthses) e e e saisies ` la vole. a e La chaine doit commencer par un nombre suivi dun oprateur arithmtique suivi dun nombre (n fois). e e On admet que eval(expr) fait le calcul.

print ("Entrer une expression ` calculer \n"); a while (<STDIN>) { if (/\d+([+*\/-]\d+)+$/) { # si le - situ entre [] ntait pas positionn e e e # juste avant ], il faudrait le prcder dun e e # / car il serait alors pris comme dmimiteur de e # classe (cf. [a-z]). print ($_," = ",eval($_),"\n"); } else { print ("Expression arithmtique incorrecte \n"); e } print ("Entrer une expression ` calculer \n"); a }

8.3. EXERCICE NUMERO 6

41

8.3

Exercice num ro 6 e

#!/usr/bin/perl

# # # # #

TP6 On vrifie que des nombres entrs au clavier sont e e bien des entiers relatifs ou des rels. e

print ("Entrer un nombre : \n"); while (<STDIN>) { chomp(); if (/[+|-]?\d+$/) { # commence ventuellement par un + ou un e # suivi et termin par au moins un chiffre. e print ("$_ est un nombre entier relatif \n"); } elsif (/[+-]?\d+\.\d+$/) { # commence ventuellement par un + ou un e # suivi par au moins un chiffre suivi par # un . suivi et termin par au moins un e # chiffre. print ("$_ est un nombre rel \n"); e } else { print ("$_ nest pas un nombre \n"); } print ("Entrer un nombre : \n"); }

42

` CHAPITRE 8. EXERCICES SUR LES EXPRESSIONS REGULIERES

8.4

Exercice num ro 7 e

#!/usr/bin/perl # # # # # # TP7 ` On entre un texte a la vole. e Lorsque la saisie est termine, on calcule le nombre de lignes, e de mots et de caract`res du texte. e

printf ("Entrer un texte libre sur plusieurs lignes \n"); @texte=<STDIN>; chomp(@texte); $nbmots = 0; $nblig = 0; $nbcar = 0; foreach (@texte) { $nblig++; @mots=split(); $nbmots = $nbmots + @mots; foreach (@mots) { $nbcar += length(); # length($-) } } print ("Nb de lignes saisies : $nblig \n"); print ("Nb de mots saisis : $nbmots \n"); print ("Nb de caract`res saisis : $nbcar \n"); e

43

Chapitre 9

Quelques trucs utiles


9.1 Ex cuter des commandes e

` Une commande plac e entre accents graves est soumise par Perl a linterpr teur de come e mande du syst` me, le r sultat peut facilement etre r cup r dans une variable : e e e ee

@who = \usr\bin\who; foreach (@who) { @User=split(/\s+/); printf ("User : %s \n", $User[0]); }

Lexemple ci-dessus ex cute la commande Unix who et afche le nom des usagers (le e premier champ des lignes retourn es par who). Cest la sortie STDOUT qui est redirig e e e dans la variable sp ci e. Pour rediriger egalement les erreurs eventuelles, on pourrait e e ecrire (sous Unix) :

$rm = /bin/rm fichier 2>&1; if ($rm) { printf ("Erreur ---> %s \n", $rm);}

44

CHAPITRE 9. QUELQUES TRUCS UTILES

9.2

La fonction die

La fonction die arr te lex cution dun programme en afchant une liste pass e en argue e e ment.

die ("cest fini !\n");

On lutilise g n ralement avec linstruction de contr le || pour terminer lex cution dun e e o e programme si linstruction pr c dente se passe mal ( ouvertures de chiers, ...) ou si un e e probl` me survient dans la logique de d roulement : e e

($chaine) || die ("La chane ` traiter est vide \n"); a

En indiquant $! dans les param` tres pass s a la fonction die, on afche le code retour des e e ` fonctions syst` mes : e

open (FIC,"MonFichier") || die ("Pb ouverture : $! \n");

9.3

` Evaluation a la vol e e

` Perl permet d valuer a lex cution des variables contenant du code. Cette fonctionnalit e e e permet de construire dynamiquement des programmes ou morceaux de programmes. On ` utilise pour cel` linstruction eval qui va passer a Perl une chane a evaluer : a `

$var = $som = $val1 + $val2; eval $var; # <==> ` lexcution, le contenu de $var est a e pass ` Perl qui excutera son contenu e a e

` Il convient d tre prudent en utilisant eval, ne pas demander a lutilisateur de rentrer une e chane de caract` res et la faire ensuite evaluer ainsi, il pourrait par exemple avoir acc` s a e e ` linterpr teur de commandes et saisir /bin/rm * ... e

9.4. LES ARGUMENTS DE LA LIGNE DE COMMANDE

45

Perl traite les instructions trouv es dans une variable pass e a eval comme un bloc (ie. e e ` comme si elles etaient d limit es par {} ) pouvant contenir des variables locales (cf. e e section 10). Linstruction eval est egalement utilis e pour traiter les exceptions dex cution dun proe e ` evaluer doit explicitement etre ecrit gramme Perl, dans ce cas le contenu de la variable a comme un bloc complet (avec les accolades de d but et de n). e

9.4

Les arguments de la ligne de commande

Les arguments de la ligne de commande sont accessibles par linterm diaire du tableau e e @ARGV qui contient un el ment par arguments pass s au programme. Contrairement e e au langage C, le premier el ment du tableau @ARGV ne contient pas le nom de la commande, $ARGV[0] contient le premier argument pass a la commande. e`

foreach (@ARGV) { printf ("Arg = %s \n",$_); }

46

CHAPITRE 9. QUELQUES TRUCS UTILES

47

Chapitre 10

La port e des variables e


Par d faut une variable Perl est globale, elle est donc visible dans lensemble du proe ` e gramme. De plus Perl noblige pas a d clarer les variables avant de les utiliser. Ces deux propri t s sont sources de bien des probl` mes de mise au point, Perl permet donc de ee e ` d clarer des variables locales et dutiliser un m canisme obligeant le programmeur a e e d clarer les variables avant de les utiliser. e Les programmeurs utilisant les langages de programmation les plus courants sont en g n ral habitu s a un fonctionnement diff rent : les variables sont automatiquement loe e e ` e cales aux blocs de d clarations, pour les rendre globales, il est n cessaire de le pr ciser. e e e

10.1

D clarer des variables locales avec my e

Il est possible de rendre locale une variable en pr c dent sa d claration par my, elle ne e e e sera alors connue que du bloc ou de la fonction (cf. section 11) qui contient sa d claration. e 1 et, il nexiste pas de variables Les variables locales sont par d faut initialis es a undef e e ` locales statiques (celles dont la visibilit est limit e au bloc de d claration mais dont la e e e ` valeur est remanente dune entr e dans le bloc a une autre). e

1. On peut les comparer aux variables automatiques de C.

48

CHAPITRE 10. LA PORTEE DES VARIABLES

#!/usr/local/bin/perl $I = 10; { my $I = 2; { $I++; { my $I = 4; printf ("I = %d \n",$I); <==> Affiche I = 4 } printf ("I = %d \n",$I); <==> Affiche I = 3 } printf ("I = %d \n",$I); <==> Affiche I = 3 } printf ("I = %d \n",$I); <==> Affiche I = 10

10.2

Une autre mani` re de d clarer des variables locales e e

Les variables locales d clar es avec my ne sont visibles que dans leurs blocs de d clarations. e e e Perl propose une autre vari t de variables locales : celles qui en plus ont la particularit ee e d tre visibles dans toutes les fonctions (cf. section 11) appel es depuis leurs blocs de e e d clarations. e

#!/usr/local/bin/perl $I = 4; <==> cet I est global { local $I = 2; fonc(); <==> Affiche I = 2 } { my $I = 3; fonc(); <==> Affiche I = 4 } sub fonc {printf("I = %d \n", $I);}

` Les variables d clar es avec local ne contribuent pas a la lisibilit dun code, elles peuvent e e e m me etre source de confusions, il convient de ne pas les utiliser. e

10.3. USE STRICT

49

10.3

use strict

strict est un module de la biblioth` que standard de Perl, il permet de g n rer une erreur e e e ` e e a la compilation si une variable acc d e na pas et pr alablement d clar e avec my (ou e e e e compl` tement quali e, ou import e cf. section 16). e e e

#!/usr/local/bin/perl my $Compteur=10; $compteur++; # erreur de frappe print ($Compteur = ,"$Compteur \n"); # # La valeur affiche est 10, le programmeur e peut ne pas sen apercevoir.

#!/usr/local/bin/perl use strict; my $Compteur=10; $compteur++; # erreur de frappe print ($Compteur = ,"$Compteur \n"); # Un message derreur est gnr a la compilation : e e e ` # Global symbol "$compteur" requires explicit package name

Dans lexemple ci-dessus lerreur de saisie est signal e car Perl nautorise plus (use e strict) les d clarations implicites de variables globales. Toutes les variables doivent etre e d clar es a laide de my (elles sont locales au programme principal) ou d clar ees dans e e ` e e un module externe (cf. section 16). Lutilisation de use strict est donc tr` s fortement e recommand e. e

50

CHAPITRE 10. LA PORTEE DES VARIABLES

51

Chapitre 11

Les fonctions
11.1 D nition dune fonction e

Perl permet d crire des fonctions qui admettent ou pas des arguments et qui rendent ou e pas une valeur de retour. Elles sont d nies par le mot-clef sub suivi dun identicateur e et dun bloc qui va contenir le code de la fonction.

sub Ma_Fonction { instruction 1; instruction 2; }

Les fonctions peuvent etre plac es nimporte o` dans un source Perl (elles sont saut es a e u e ` lex cution), il est toutefois conseill de les placer en d but ou en n de programme. La e e e port e des fonctions est globale, il est possible denliser une fonction dans une autre mais e cel` ne restreint pas sa visibilit , cette forme d criture na donc pas de sens. a e e

sub Ma_Fonction { instruction 1; instruction 2; sub Fonction_Enlisee { ... } <==> Fonction_Enlisee est tout de mme accessible en dehors de Ma_Fonction e }

52

CHAPITRE 11. LES FONCTIONS

Si une fonction retourne une valeur elle est pr cis e par linstruction return suivi dune e e ` expression a evaluer. Les arguments dune fonction sont pass s par valeurs et r cup r s e e ee dans le tableau @ (arobas soulign ), en fonction du cas pos diverses solutions sont e e possibles pour y avoir acc` s : e

my ($var1,$var2,$var3) = @_; # ou my $var1 = $_[0]; my $var2 = $_[1]; my $var3 = $_[2]; # ou encore foreach (@_) { .... }

Dans les faits une fonction retourne toujours une valeur, cest celle de la derni` re exe pression evalu e avant la sortie. On peut donc se passer de linstruction return mais sa e ` pr sence ne nuit pas a lisibilit du code ! e e

11.2 Appel dune fonction


On appelle une fonction en indiquant son identicateur suivi entre paranth` ses des argue ` ments ( ventuellement 0). Lappel a une fonction peut etre plac dans une expression en e e fonction de sa valeur de retour :

#!/usr/local/bin/perl $I = 10; $J = 20; resultat(); <==> appel dune fonction qui ne retourne pas de valeur (ou plus exactement dont la valeur de retour est ignore ici) e sub resultat { printf ("La somme est : %d \n",som($I,$J)); } sub som { my ($a,$b) = @_; return $a + $b; }

11.3. PROTOTYPER LES FONCTIONS

53

11.3

Prototyper les fonctions

Perl permet de v rier (` la compilation) que les arguments pass s a une fonction correse a e ` ` pondent bien a ce qui est pr vu par le programmeur. On utilise pour cel` le prototypage e a ` des fonctions utilis es (qui doivent etre visibles a la compilation). Le prototypage consiste e ` a indiquer le nombre darguments attendus en pr cisant leur type. En Perl le prototype e suit la d claration du nom de la fonction (entre parenth` ses) et utilise les conventions e e suivantes : un $ indique la pr sence dun scalaire; e un @ indique la pr sence dune liste; e un % indique la pr sence dun tableau associatif; e un ; s pare les arguments obligatoires des arguments optionnels; e lorsque le caract` re \ pr c de un @ ou un % il rend obligatoire que largument e e e correspondant soit effectivement une liste ou un tableau associatif (cf. lexemple suivant).

` Il faut faire attention a lutilisation des @ et % dans les prototypes car ils mangent les caract` res suivants et forcent un contexte de liste. Lutilisation du \ devant ces caract` res e e est donc tr` s importante (cf lexemple suivant). e

54

CHAPITRE 11. LES FONCTIONS

#!/usr/bin/perl # prototypes des sub fonc1($$$); sub fonc2($$@); sub fonc3($$\@); fonctions utilises e # 3 scalaires # 2 scalaires et une liste # 2 scalaires et une variable de type liste

@liste = (1, 2, 3); print (fonc1(@liste,5,6)," ",fonc2(5,6,7), fonc3(5,6,7)); # # ici lappel de fonc1 rendra 14 car @liste dans un contexte # scalaire vaut 3 (nombre dlments). Lappel de fonc2 e e # rendra 18 car 7 est pris comme une liste de 1 lment. e e # En ltat ce programme ne compile pas car lappel ` fonc3 e a # est incorrect, le 3`me argument nest pas une variable de e # type liste. # sub fonc1($$$) { ############### my ($a, $b, $c) = @_; return($a+$b+$c); } sub fonc2($$@) { ############### my ($a, $b, @liste) = @_; my $res; foreach (@liste) { $res += $_; } return($a+$b+$res); } sub fonc3($$\@) { ############### my ($a, $b, @liste) = @_; my $res; foreach (@liste) { $res += $_; } return($a+$b+$res); }

11.4. PASSER DES ARGUMENTS PAR REFERENCES

55

11.4

Passer des arguments par r f rences ee

Les arguments dune fonction sont r cup r s dans le tableau @ , ce m canisme est e ee e ` e sufsant pour passer quelques valeurs scalaires, mais devient tr` s difcile a g rer sil est e n cessaire de passer plusieurs tableaux en param` tres (comment les d limiter entre eux?). e e e Pour r soudre ce probl` me, Perl propose dutiliser des r f rences plut t que des valeurs. e e ee o

11.4.1

Les r f rences de variables ee

On r f rence une variable Perl en pr c dant son identicateur dun \ : ee e e

$scalaire = 4; @tableau = (1,2,3,4,5,6); $refscal = \$scalaire; $reftab = \@tableau; $refhac = \%hache;

e Une ref rence est un variable de type scalaire, on peut donc corriger ce qui a et indiqu e e en section 2.1, un scalaire est un nombre, une chane de caract` re ou une r f rence. e ee Pour d r f rencer une variable contenant une r f rence, on pr c de son identicateur eee ee e e dun $,@ ou % en fonction du type de donn es quelle r f rence. e ee

$scalaire = 4; @tableau = (1,2,3,4,5,6); %hache = ("a",1,"b",2,"c",3); $refscal = \$scalaire; $reftab = \@tableau; $refhac = \%hache; $$refscal = 5; <==> $scalaire = 5; @$reftab = (7,8,9) <==> @tableau = (7,8,9); $$reftab[0] = 2; <==> $tableau[0] = 2; %$refhac = ("d",4,"e",5,"f",6); <==> %hache = ("d",4,"e",5,"f",6);

56

CHAPITRE 11. LES FONCTIONS

Pour d r f rencer une variable contenant une r f rence sur un tableau ou un tableau assoeee ee ` ciatif, on dispose dune notation ch e qui est plus confortable a utiliser que la notation e e utilisant le $$ : @tableau = (1,2,3,4,5,6,7); %hache = (bleu,1,rouge,2,vert,3); $reftab = \@tableau; $refhache = \%hache; $reftab->[1] = 10; <==> $$reftab[1] = 10; $refhache->{rouge} = 4; <==> $$refhache{rouge} = 4;

Il est egalement possible de cr er des r f rences des tableaux anonymes ou des hashes e ee anonymes. Cette forme d criture est utilis e pour manipuler des structures de donn es e e e complexes (tableaux de tableaux, tableaux de hashes ... cf. section 14). Une r f rence sur un tableau anonyme se cr e en utilisant des crochets ([]) : ee e @tableau = (1,2,3,4); $reftab = \@tableau; # peut aussi scrire e $reftab = [1,2,3,4]; # lacc`s aux lments est inchang e e e e $reftab->[1] ou $$reftab[1]

Une r f rence sur un hash anonyme se cr e en utilisant des accolades {} : ee e %hache = (bleu,1,rouge,2,vert,3); $refhache = \%hache; # peut aussi scrire e $refhache={bleu,1,rouge,2,vert,3}; # lacc`s aux lments est inchang e e e e $refhache->{rouge} = 4;

` Les r f rences anonymes en Perl sont tr` s pratiques a utiliser car le programmeur (contraiee e ` rement au langage C par exemple) na pas a se soucier de la gestion de la m moire (taille e ` demand e et lib ration). Perl g` re un compteur des r f rences a chaque valeurs, quelles e e e ee soient r f renc es directement ou pas, celles qui ne sont plus r f renc es sont d truites ee e ee e e automatiquement.

11.4. PASSER DES ARGUMENTS PAR REFERENCES

57

11.4.2

Un exemple

Dans lexemple suivant on d sire r aliser une fonction recevant deux listes en arguments e e (@tab1 et @tab2), elle va rendre une liste r sultante contenant la premi` re liste tri e suivie e e e de la seconde egalement tri e. On utilise ici un passage des arguments par r f rences car e ee on utilise deux tableaux, par valeurs la variable @ ne pourrait pas nous renseigner sur la limite du tableau @tab1. Par r f rences on peut passer un nombre tr` s important de ee e tableaux car les r f rences sont des scalaires. ee

#!/usr/bin/perl @tab1 = (7,3,2,8,9,1,2); @tab2 = (3,2,1,4); # Appel de la fonction tri avec deux arguments # qui sont des rfrences sur les tableaux. e e @ltri = tri(\@tab1, \@tab2); # Affichage du rsultat. e print (@ltri); # Fonction tri sub tri { ######### # Rcupration des arguments dans 2 variables e e # locales qui contiennent des rfrences sur e e # les tableaux @tab1 et @tab2. my ($reftab1, $reftab2) = @_; my (@tri1, @tri2); # Tri de chaque tableau, on drfrence pour e e e # pouvoir appeler la fonction sort(). @tri1=sort(@$reftab1); @tri2=sort(@$reftab2); # Retour du rsultat e push(@tri1,@tri2); return @tri1; # retour de @tri1 (par valeur) }

58

CHAPITRE 11. LES FONCTIONS

11.5

Exercice num ro 8 e

#!/usr/bin/perl # TP8 # On reprend ici le TP3 mais ` la fin de la saisie on appelle un a # fonction qui va calculer la valeur du stock. # Elle recoit en param`tre le hash du stock, un hash donnant le e # prix H.T. dune bouteille de xxxx et le taux de TVA. sub ValStock($$$); %Stock=(); %Prix = ( Bordeaux => 25, Bourgogne => 40, Bourgueil => 33, Bandol => 29); $Tva=18.6; print ("Nom du vin : \n"); while ($Vin=<STDIN>) { # $Vin sera la clef du Hash de stock chomp($Vin); # enl`ve le caract`re de fin de ligne e e print ("Quantit : "); e $Quant=<STDIN>; # Il faudrait vrifier quil sagit bien e # bien dun nombre entier relatif. chomp($Quant); unless ($Quant) { # Si lutilisateur ne saisit pas de Quantit e last; # on passe ` laffichage du stock. a } $Stock{$Vin} += $Quant; print ("Nom du vin : \n"); } # On appelle la fonction ValStock en lui passant des rfrences e e # sur les hashs (sinon le premier mangerait le second). print ("Valeur totale : ",ValStock(\%Stock, \%Prix, $Tva),"\n"); sub ValStock($$$) { ################### my ($StockPtr, $PrixPtr, $Tva) = @_; my ($Vin, $Quant, $Total); while (($Vin,$Quant) = each (%$StockPtr)) { # %$ pour drfrencer e e e $Total += ($Quant * $PrixPtr->{$Vin}); } return($Total + ($Total*$Tva/100) ); }

59

Chapitre 12

Acc` s au contenu des chiers e


` En Perl, lacc` s au contenu des chiers seffectue a travers des descripteurs de chiers e qui font le lien entre le programme et son environnement ext rieur. Comme vu en section e 4 tout programme Perl h rite de 3 descripteurs positionn s par le syst` me dexploitation : e e e STDIN (entr e standard), STDOUT (sortie standard) et STDERR (erreurs produites par e les appels au syst` me). e

12.1

Ouverture

Pour utiliser un chier (autre que STDIN, STDOUT ou STDERR) il faut dabord louvrir (effectuer lassociation entre un descripteur de chier et le nom externe du chier consid r ). On utilise linstruction open suivie dun descripteur de chier et du nom exee terne du chier cibl ( ventuellement pr c d du mode douverture) : e e e e e

open open open open open

(FIC1,monfichier); (FIC2,c:\\tmp\\truc); (FIC3,>toto); # > (FIC3,>>tutu); # >> (FIC4,+<tata); # +<

# ouverture en # pour ouverture pour ouverture pour ouverture

lecture en ecriture en ajout en lect/ecr

60

` CHAPITRE 12. ACCES AU CONTENU DES FICHIERS

open retourne vrai si louverture se passe bien, il est important de le v rier. On peut e utiliser un die conditionnel pour traiter les valeurs de retour de open :

open(FIC,MonFichier) || die("Pb douverture\n");

12.2

Lecture

Lop rateur <> permet de lire une ligne 1 dans le chier d sign par le descripteur cibl . e e e e Il rend vrai tant que la n du chier nest pas atteinte :

open (FIC,MonFic) || die ("Le fichier nexiste pas\n"); while (<FIC>) { # par dfaut chaque ligne lue (y compris le dlimiteur e e # de fin de ligne) est stocke dans $_ e }

Lop rateur <> est adapt a la lecture des chiers de textes, pour lire des chiers format s e e` e diff remment, on peut utiliser la fonction sysread() qui permet de pr ciser le nombre de e e caract` res a lire ainsi que la variable scalaire qui va contenir les caract` res lus. La fonction e ` e sysread() rend le nombre de caract` res effectivement lus : e

open (FIC,MonFic) || die ("Le fichier nexiste pas\n"); while (($nb=sysread(FIC,$enr,100) != 0) { # on a lu $nb caract`res (100 maxi) dans $enr e }

1. On peut aussi lire enti` rement un chier dans une variable de type tableau (cf. section 4). e

12.3. ECRITURE

61

12.3

Ecriture

print et printf permettent d crire des lignes dans un chier. printf (cf. section 4.2) e ` permet de pr ciser le format des variables a ecrire, print est plus rudimentaire. e

print FIC ($a,:,$b,:,$c,"\n"); printf FIC ("%.5s:%3d:%10s\n",$a,$b,$c);

print retourne 1 si l criture sest bien d roul e et 0 en cas derreur. e e e Lorsque lon ecrit un chier en Perl, il faut se poser la question de sa lecture ult rieure, e et notamment celle la d limitation des champs. Dans lexemple ci-dessus, il sera facile e dutiliser split (cf. 7.6.1) pour r cup rer les variables 2 . e e Comme pour la lecture, il est possible d crire dans un chier en pr cisant le une variable e e scalaire et le nombre de caract` res a ecrire, cest le r le de la fonction syswrite() : e ` o

$nb=syswrite(FIC,$enr,100); # ecriture du contenu de la variable $enr ` concurrence a # de 100 caract`res maximum. $nb contient le nombre de e # caract`res effectivement ecrits. e

12.4

Fermeture

` On ferme un chier en pr cisant son descripteur a laide de la fonction close. e

close(FIC);

2. ($a,$b,$c) = split (/:/);

62

` CHAPITRE 12. ACCES AU CONTENU DES FICHIERS

12.5

Exercice num ro 9 e

#!/usr/bin/perl # # # # # # TP9 Parcourir lensemble des TP raliss et rajouter un commentaire e e dans chacun dentre eux ... On choisit ici de remplacer la premi`re ligne par elle mme e e suivie dun commentaire constant.

use strict vars; my $Head = "#!/usr/bin/perl"; my $Comment= "\n#\n# Effectu en formation PERL \n#"; e my @fic = <*.pl>; # obtenir la liste des tp.

foreach $prog (@fic) { unless (open (IN,$prog)) { print ("Erreur douverture $prog ($!) \n"); } unless (open (OUT, ">${prog}.bis")) { print ("Erreur cration ${prog}.bis ($!) \n"); e } print ("Traitement de $prog ... \n"); while (<IN>) { s/($Head)$/\1$Comment/; print OUT; } close(IN); close(OUT); # Si le programme est au point, on peut dcommenter la ligne e # suivante ... # rename("${prog}.bis",$prog); }

63

Chapitre 13

Manipulations du syst` me de e gestion de chiers


13.1 Acc` s aux r pertoires e e

Perl permet dacc der au contenu des r pertoires dun syst` me de chiers en utilisant e e e la convention *, ou en appelant des fonctions qui procurent une interface dacc` s a leur e ` structure.

13.1.1

Utiliser la convention *

Une expression plac e entre les symboles < et > va solliciter le syst` me de gestion e e de chiers et obtenir une liste des chiers ou r pertoires qui lui correspondent (dans le e r pertoire de travail ou dans un r pertoire cit par lexpression elle m me) : e e e e

# acc`s aux programme c dun rpertoire e e @progc = <*.c>; # affichages du nom des fichiers slectionns e e foreach (@progc) {printf ("%s \n", $_);}

Utilis e dans un contexte scalaire la convention * va parcourir le r pertoire cibl et rendre e e e successivement les chiers qui correspondent (plus undef quand il ny a plus de corres-

` 64 CHAPITRE 13. MANIPULATIONS DU SYSTEME DE GESTION DE FICHIERS pondance). On pourrait donc ecrire lexemple pr c dent de la facon suivante : e e

while (<*.c>) {printf("%s \n",$_);}

Lutilisation de la convention * peut seffectuer en remplacant les symboles < et > par la fonction glob :

@include=</usr/local/include/*.h>; peut aussi scrire e @include=glob(/usr/local/include/*.h);

13.1.2

Utiliser une interface dacc` s e

` Il est possible de parcourir un r pertoire en utilisant la fonction readdir qui fonctionne a e partir dun descripteur de r pertoire pr alablement ouvert par opendir. Utilis e dans un e e e contexte scalaire, readdir rend successivement le noms des chiers du r pertoire (plus e undef quand il ny en a plus). Utilis e dans un contexte de liste, readdir rend la liste e de tous les chiers du r pertoire cibl . La fonction closedir ferme un descripteur de e e r pertoire ouvert par opendir. e

opendir (DIR,.) || die (Erreur Open Dir); @fic = readdir(DIR); foreach (@fic) {printf ("%s \n",$_);}

13.2

Manipulation des chiers et r pertoires e

Perl procure des fonctions pour r aliser les actions les plus usuelles sur les chiers et e r pertoires. e

13.2. MANIPULATION DES FICHIERS ET REPERTOIRES

65

13.2.1

Changer de r pertoire de travail e

La fonction chdir permet de changer le r pertoire de travail de lapplication en cours. e

chdir(c:\\windows\\system) || die ("Erreur chdir \n");

13.2.2

Cr er un r pertoire e e

La fonction mkdir permet de cr er un r pertoire en positionnant des droits dacc` s a la e e e ` 1 mode Unix

mkdir (MonRepert,0755) || die ("Err. Cr. rpertoire \n"); e

13.2.3

Supprimer un r pertoire e

Un r pertoire vide peut etre supprim par la fonction rmdir. e e

rmdir (MonRepert) || die ("Err. Sup.

rpertoire \n"); e

13.2.4

Supprimer un chier

La fonction unlink permet de supprimer une liste de chiers.

foreach (<*.old>) { unlink($_); || die ("Erreur suppression \n"); }


1. Une equivalence est faite automatiquement pour Win32.

` 66 CHAPITRE 13. MANIPULATIONS DU SYSTEME DE GESTION DE FICHIERS

13.2.5

Renommer un chier

La fonction rename permet de changer le nom dun chier.

rename("log","log-old"); || die ("Pb. logs \n");

13.2.6

Modier les droits dacc` s e

` La fonction chmod permet de positionner les droits dacc` s a un chier a la mani` re e ` e dUnix 2 en utilisant un codage octal 3 .

chmod(0755,$fic); || die ("Err. droits dacc`s \n"); e

13.3

Fonctions utiles

Il est possible dobtenir des informations sur un chier ou un r pertoire en utilisant des e expressions dont l criture est d riv e de celle de la commande Unix test. Ces expressions e e e ` s crivent a laide dun op rateur suivi dune chane de caract` res 4 qui repr sente le nom e e e e potentiel dun chier ou r pertoire 5 . Les op rateurs (sauf exceptions) rendent une valeur e e vraie ou fausse, les principaux sont les suivants :

-r -w -e -x -z -s -f -d

fichier ou rpertoire accessible en lecture e fichier ou rpertoire accessible en criture e e fichier ou rpertoire existant e fichier excutable e fichier existant mais vide fichier ou rpertoire non vide, la valeur retourne e e est la taille en octet fichier normal (rpertoire et spciaux exclus) e e rpertoire e

2. On proc` de par equivalence pour Win32. e 3. La signication du codage est document e dans le manuel Unix, voir chmod(1). e 4. Elles fonctionnent egalement sur des descripteurs de chiers. 5. En labsence de chane de caract` res et de descripteur de chier, cest la variable $ qui sera utilis e. e e

13.4. EXERCICE NUMERO 10

67

$InstallDir = "MonAppli"; (-d $InstallDir) || die ("Appli non installe \n"); e

La fonction stat permet dobtenir plus de d tails sur un chier mat rialis par une chane e e e de caract` res ou un descripteur de chier. Elle donne acc` s aux diff rents champs dune e e e ` entr e dans un syst` me de chiers 6 . On a alors acc` s a la taille dun chier, a sa date de e e e ` ` cr ation ... stat renvoie une liste de 13 valeurs dans un tableau, la 8` me correspond a la e e taille du chier. Lexemple ci-dessous utilise la fonction stat pour d terminer la taille dun chier : e

#!/usr/local/bin/perl print ("Entrez un nom de fichier : \n"); while (<STDIN>) { chomp; (-f) ? print (taille($_),"\n") : print ($_," inconnu\n"); print ("Entrez un nom de fichier : \n"); }

sub taille { my ($fic) = @_; my ($dev,$inode,$perm,$liens,$uid,$gid, $ndev,$lg,$acces,$mod,$cr,$blksize,$bl)=stat($fic); return($lg); }

13.4

Exercice num ro 10 e

6. Une inode sous Unix.

` 68 CHAPITRE 13. MANIPULATIONS DU SYSTEME DE GESTION DE FICHIERS

#!/usr/bin/perl # TP10 # Supprime le contenu dun rpertoire pass en param`tre. e e e # Lutilisation dune fonction rcursive permet de dtruire e e # les rpertoires embotes. e # On informe lutilisateur du nombre de fichiers contenus dans # le rpertoire quil souhaite dtruire. e e use strict vars; sub HowManyFiles($); # prototypes des fonctions utilises e sub DeleteDir($); # $ ==> un scalaire comme param. unless (@ARGV) { print ("Usage : tp10 rpertoire ` dtruire \n"); e a e exit(); } $_ = $ARGV[0]; if (-d) { if (/\/tmp/) { # on se limite au rpertoires temporaires. e my $nbf=HowManyFiles($_); if ($nbf) { print ("Ce rpertoire contient $nbf fichiers. \n"); e print ("Voulez vous vraiment le dtruire ? \n"); e my $nbf = <STDIN>; if ($nbf = /oui$/i) { DeleteDir($_); print ("Rpertoire supprim !"); e e } else { print ("Rpertoire non supprim !"); e e } } else { DeleteDir($_); print ("Rpertoire vide supprim !"); e e } } else { print ("Nest pas un repertoire temporaire \n"); } } else { print ("$_ nest pas un repertoire \n"); }

13.4. EXERCICE NUMERO 10

69

sub HowManyFiles ($) { ###################### # Avant de supprimer un rpertoire, on souhaite connaitre e # le nombre de fichiers quil contient. my ($Dir) = @_; my (@fichiers,$fic); my $count = 0; opendir(DIR,$Dir) || return(0); @fichiers=readdir(DIR); # le rep est lu on peut le fermer ... closedir(DIR); # @fichiers est local, cest recursable foreach $fic (@fichiers) { if (($fic ne ".") && ($fic ne "..")) { if (-d "${Dir}/$fic") { $count+=HowManyFiles("${Dir}/$fic"); } else { $count++; } } } return($count); } sub DeleteDir ($) { ################### # Suppression dun rpertoire (lutilisation rcursive permet de e e # dtruire les ventuels enbots). e e e my ($Dir) = @_; my (@fichiers,$fic); opendir(DIR,$Dir) || return(0); @fichiers=readdir(DIR); # le rep est lu on peut le fermer ... closedir(DIR); # @fichiers est local, cest recursable foreach $fic (@fichiers) { if (($fic ne ".") && ($fic ne "..")) { if (-d "${Dir}/$fic") { DeleteDir("${Dir}/$fic"); } else { unlink("${Dir}/${fic}") || die ("erreur delete"); } } } rmdir($Dir) || return(0); return(1); }

` 70 CHAPITRE 13. MANIPULATIONS DU SYSTEME DE GESTION DE FICHIERS

71

Chapitre 14

Les structures de donn es complexes e


Perl autorise de manipuler des structures de donn es plus complexes que celles accese sibles par les 3 types de base. Des r f rences sur des listes anonymes ou des hashs anoee nymes sont utilis es pour cel` . e a

14.1

Les listes de listes

@Liste = ( [toto,tutu,tata], [truc,much], [patati,patata] );

Dans lexemple ci-dessus, @Liste est une liste de r f rences sur des tableaux anonymes ee ([]). e ` Laffectation dun el ment sop` re a la mani` re dun tableau a deux dimensions. Laffece ` e tation dune liste compl` te implique lutilisation de r f rences. e ee

# remplacer truc par machin $Liste[1][0]=machin; # remplacer [patati,patata] par [bla,blabla] @AutreListe = (bla,blabla); $Liste[2] = \@AutreListe;

72

CHAPITRE 14. LES STRUCTURES DE DONNEES COMPLEXES

# Erreur ` ne pas commettre a $Liste[2] = @AutreListe; # qui charge la valeur 2 (le nombre dlments) en lieu e e # et place dune rfrence sur une liste ... e e # # # Il nest pas forcment ncessaire de dclarer une liste e e e pour assurer lopration. On utilise ci-dessous une e rfrence sur une liste anonyme ([]). e e

$Liste[2] = [bla,blabla]; # ajouter une liste push(@Liste, [en,voila,du,texte]);

e ` ` Lacc` s a un el ment seffectue a la mani` re dun tableau a deux dimensions. Lutilisation e ` e dune des listes dun tableau de listes dans une op ration daffectation n cessite un peu e e dattention :

@AutreListe = @$Liste[2];

Cette ecriture semble naturelle, $Liste[2] est une r f rence sur une liste, pour d r f rencer ee eee on la pr c` de du caract` re @. En fait, pour des raisons de priorit s entre op rateurs $Liste e e e e e sera consid r comme une r f rence (qui nexiste pas), puis on fera le d r f rencement ee ee eee e et enn on cherchera le 2` me el ment. Lutilisation de use strict (cf. section 10.3) indie ` querait dailleurs une erreur a la compilation ! Il faut donc ecrire :

@AutreListe = @{$Liste[2]}

Les { et } sont utilis s pour clairement indiquer que la r f rence est $Liste[2]. e ee

14.2. LES HASHES DE HASHES

73

14.2

Les hashes de hashes

%User = ( toto => { Homedir Passwd Email }, tutu => { Homedir Passwd Email }, tata => { Homedir Passwd Email } );

=> /Home/toto, => A1PefjWNa03H2, => toto@ici.fr

=> /Home/tutu, => 31PrfjWNa08Ha, => tutu@ici.fr

=> /Home/tata, => 41aqfjer508Ha, => tata@ici.fr

Dans lexemple ci-dessus, %User est un hash de hashs anonymes ({}) (` une clef corresa pond une r f rence sur un hash anonyme). ee

# Changer une valeur $User {tutu} {Email} = tutu@parla.fr; # Ajouter une nouvelle clef $User {titi} = {HomeDir => /home/titi, Passwd => 32drtyuoiXes, Email => titi@ici.fr}; ` # Accder a la totalit des lments e e e e foreach $util (keys %User) { foreach (keys %{$User{$util}}) { print ("$util->$_ : $User{$util}{$_} \n"); } }

Dans lexemple ci-dessus on ecrit %{$User{$util}} et non pas %$User{$util} pour les m mes raisons quindiqu es en section 14.1. e e

74

CHAPITRE 14. LES STRUCTURES DE DONNEES COMPLEXES

14.3

Autres structures de donn es e

La construction de structures de donn es ne sarr` te pas aux listes de listes ou aux hashes e e de hashes. Il est possible de g n raliser le proc d pour b tir des structures hybrides e e e e a m lant des listes et des hashes sur plusieurs niveaux. Pour bien comprendre le fonctione ` nement, il faut bien avoir a lesprit quun tableau en Perl est toujours uni-dimensionnel. ` ` Un tableau a 4 dimensions ne sera en r alit quun tableau a une dimension contenant e e des r f rences vers des tableaux contenant des r f rences vers des tableaux contenant des ee ee r f rences vers des tableaux. ee Dans lexemple suivant, on g` re un tableau (` lallure tri-dimensionnelle) de valeurs core a ` respondant a des ann es, mois et jours. On commence par installer quelques valeurs dans e le tableau avant de le parcourir enti` rement pour calculer la somme de toutes les valeurs e install es. e

#!/usr/local/bin/perl # Exemple dutilisation dun tableau ` 3 dimensions. a @Valeurs = (); # Initialisation du tableau AddValeurs(1999,12,1,150); AddValeurs(1999,12,1,250); AddValeurs(1994,12,2,100); AddValeurs(1999,12,3,500); AddValeurs(1999,11,3,500); AddValeurs(1999,11,8,500); AddValeurs(1990,11,10,500); $NbElem = @Valeurs; # $NbElem vaut 2000 [0..1999], car Perl bouche # les trous. print ("Total Annuel : ",StatAn(1999),"\n");

14.3. AUTRES STRUCTURES DE DONNEES

75

sub AddValeurs { ################ my ($an, $mois, $jour, $montant) = @_; # # On utilise ici une ecriture traditionnelle pour un tableau ` 3 dimensions. a $Valeurs [$an] [$mois] [$jour] += $montant; }

sub StatAn { ############ my ($an) = @_; my $total; foreach # # # # # # # $mois (@{$Valeurs[$an]}) {

@{$Valeurs[$an]} est une liste de rfrences e e 13 ici ([0..12]) car le plus grand mois cit e vaut 12 pour lanne 1999. e $mois contient une rfrence vers un tableau qui e e contient les valeurs associes. Il y a ici 9 e valeurs pour le 11me mois de lanne 1999 et e e 4 valeurs ([0..3]) pour le 12`me mois de 1999. e foreach $jour (@$mois) { $total += $jour; } } return($total);

` On peut maintenant compl ter lexemple de la section 14.2 pour associer a chaque utilie sateur une liste de machine sur lesquelles il est autoris a se connecter. On obtient ainsi e` un hash de hash de liste.

76

CHAPITRE 14. LES STRUCTURES DE DONNEES COMPLEXES

%User = ( toto => { Homedir Passwd Email Login }, tutu => { Homedir Passwd Email Login } );

=> => => =>

/Home/toto, A1PefjWNa03H2, toto@ici.fr, [mach1,mach2,mach3]

=> => => =>

/Home/tutu, 31PrfjWNa08Ha, tutu@ici.fr, [mach2,mach4,mach3,mach8]

# pour accder ` la liste des machines dun utilisateur e a @liste = @{$User{tutu}{Login}}; # $User{tutu}{Login} est une rfrence sur une liste, e e # on la place entre @{...} pour la drfrencer. e e e

14.4. EXERCICE NUMERO 11

77

14.4

Exercice num ro 11 e

#!/usr/bin/perl # TP11 # # Parcourir le fichier access.log (log dAPACHE) et indiquer # les URLs consultes par machines ainsi que les machines e # ayant consults par URL. e # On utilise pour cel` un hash de hash machine->URL->NbrHits a # ainsi quun hash de hash URL->machine->NbrHits use strict vars; my (@Champ1, @Champ2, @Champ3, %HostTab, %UrlTab); my ($Url, $Host); open(LOG,"access.log") || die ("Erreur douverture du log : $!"); while (<LOG>) { @Champ1 = split; # rcup`re le nom de la machine e e $Host = $Champ1[0]; @Champ2 = split(/\"/); # rcup`re la requte HTTP effectue e e e e @Champ3 = split(/ /,$Champ2[1]); $Url = $Champ3[1]; # rcup`re lURL demande e e e $HostTab{$Host}{$Url}++; # ajout dans le hash de hash des mach $UrlTab{$Url}{$Host}++; # ajout dans le hash de hash des URL } # # Impression des URL consultes par machines e # foreach $Host (keys %HostTab) { print (*** ," $Host ",***,"\n"); foreach (keys %{$HostTab{$Host}}) { print (" $_ : $HostTab{$Host}{$_} \n"); } } # # Impression des machines ayant consults par URL e # foreach $Url (keys %UrlTab) { print (### ," $Url ",###,"\n"); foreach (keys %{$UrlTab{$Url}}) { print (" $_ : $UrlTab{$Url}{$_} \n"); } }

78

CHAPITRE 14. LES STRUCTURES DE DONNEES COMPLEXES

14.5

Exercice num ro 12 e

#!/usr/bin/perl # TP12 # Prsente la liste des fichiers et rpertoires contenus dans le e e # rpertoire courant "` la windows" : e a # - les rpertoires dabord e # - dans lordre alphanumrique sans respecter la casse e use strict vars; # obtenir la liste des fichiers et rpertoires e

my(@List) = <* .*>; # Construire un hash qui pour chaque nom de fichier minusculis e # donne en correspondance la liste des vrais noms qui correspondent. my (%WithUC); foreach (@List) { push (@{$WithUC{lc($_)}},$_); } #

# Cest un hash de listes.

Construire une liste de tous les noms fichiers minusculiss. e

my ($prec, @lcased, @result); foreach (@List) { push(@lcased,lc($_)); } # # # Trier cette liste en enlevant les doublons. A partir du hash dont la clef est un nom de fichier minusculis on acc`de ` tous les e e a fichiers portant ce nom (majuscules et minuscules non confondues).

my (@sorted) = sort(@lcased); foreach (@sorted) { unless ($_ eq $prec) { push(@result,@{$WithUC{$_}}); $prec=$_; } }

14.6. EXERCICE NUMERO 13

79

# Obtenir une liste des rpertoires et une liste des fichiers. e my (@dirs, @files); foreach (@result) { if (-d) { push(@dirs,$_); } else { push(@files,$_); } } # Impression du rsultat e foreach print } foreach print } (@dirs) { ("-d $_ \n"); (@files) { ("$_ \n");

14.6

Exercice num ro 13 e

#!/usr/bin/perl # TP13 # # On souhaite rechercher lexistence dun mot pass en e # argument dans tous les fichiers du rpertoire courant. e # ` la fin on affiche le nom des fichiers qui contiennent A # le mot recherch avec en regard le nombre doccurrences e # et les numros de lignes ou il est prsent. Le rsultat e e e # est prsent par ordre dcroissant du nombre doccurrences. e e e # # # # # On utilise un tableau associatif dont la clef nom du fichier et la valeur est une rfrence e e liste contenant le nombre doccurrences ainsi rfrence sur une liste contenant les numros e e e ou le mot est prsent. e est le sur une quune de lignes

80

CHAPITRE 14. LES STRUCTURES DE DONNEES COMPLEXES

use strict vars; unless (@ARGV) { print ("Usage : tp13 mot ` rechercher \n"); a exit(); } my $mot = $ARGV[0]; my %GrepResult=(); my %Sorted=(); # # Constitution du tableau associatif (la clef est le nom des fichiers qui contiennent le mot rcherch). e

Grep(.); # # # Constitution dun hash dont la clef est le nombre doccurrences et la valeur est une liste des fichiers qui contiennent ce mot "occurrences" fois.

foreach (keys(%GrepResult)) { my @liste = @{$GrepResult{$_}}; my $nb = $liste[0]; push(@{$Sorted{$nb}}, $_); } # # Prsentation du rsultat dans lordre dcroissant. e e e # my $occur; foreach $occur (sort {$b <=> $a} (keys(%Sorted))) { foreach (@{$Sorted{$occur}}) { # $_ contient un nom de fichier qui contient le mot # $occur fois. my @liste = @{$GrepResult{$_}}; print ("$_ $liste[0] @{$liste[1]} \n"); } }

14.6. EXERCICE NUMERO 13

81

sub Grep () { ############## my ($Dir) = @_; my (@fichiers,$fic); opendir(DIR,$Dir) || return(0); @fichiers=readdir(DIR); closedir(DIR); foreach $fic (@fichiers) { if (($fic ne ".") && ($fic ne "..")) { if (-d "${Dir}/$fic") { Grep("${Dir}/$fic"); } else { unless (open(FIC,$fic)) { print ("Impossible douvrir $fic : $! \n"); next; } my $lig = 0;; while (<FIC>) { my $count = 0; $lig++; my $chaine = $_; if (/$mot/) { while ($chaine = $mot) { $count++; $chaine = $; } ${$GrepResult{$fic}}[0] += $count; push(@{${$GrepResult{$fic}}[1]},$lig); } } close(FIC); } } } }

82

CHAPITRE 14. LES STRUCTURES DE DONNEES COMPLEXES

83

Chapitre 15

Le d bogueur de Perl e
Perl propose un environnement interactif pour le d boguage des programmes. Il permet e dexaminer du code source, de poser des points darr t, de visionner l tat de la pile (voir e e la valeur des param` tres lors des appels de fonctions), de changer la valeur des variables, e ... Le d bogueur est appel en sp ciant loption -d lors de lappel de Perl, on entre alors e e e dans un mode interactif, le d bogueur attend des commandes pour d rouler le code comme e e dans lexemple suivant (o` le programme comporte au moins une erreur) : u

1 2 3 4 5 6 7 8 9

#!/usr/local/bin/perl my ($moy, $total, $nb); print ("Entrez un nombre \n"); while (<STDIN>) { $total += $_; print ("Entrez un nombre \n"); } $moy = $total / $nb; print ("la moyenne est : $moy \n");

Le programme ci-dessus provoque une division par z` ro, pour le mettre au point on ape pelle le d bogueur. Dans lexemple suivant, le texte pr c d par >> est g n r par Perl, e e e e e ee celui pr c d par << est fourni par le programmeur qui effectue la mise au point. e e e

84

CHAPITRE 15. LE DEBOGUEUR DE PERL

perl >> >> >> >> >> >> >> >> >> << >> << >> << >> >> >> >> >> >> >> >> >> >> >> >> >> >>

-d debug.pl Loading DB routines from perl5db.pl version 1.0402 Emacs support available. Enter h or h h for help. main::(debug.pl:2): my ($moy, $total, $nb); DB<1> << /\$moy/ 8: $moy = $total / $nb; DB<2> << b 8 DB<3> << c Entrez un nombre 2 Entrez un nombre 4 Entrez un nombre Ctrl-d main::(debug.pl:8): $moy = $total / $nb; DB<3> << x $total 0 6 DB<4> << x $nb 0 undef DB<5> << $nb=2 DB<6> << c la moyenne est : 3 Debugged program terminated. Use q to quit or R to restart, use O inhibit_exit to avoid stopping after program termination, h q, h R or h O to get additional info. DB<6> << q

Linvite du d bogueur est DB suivi du num ro de la requ te trait e, ici le programmeur a e e e e successivement effectu les op rations suivantes : e e recherche de la prochaine ligne de code ex cutable qui contient la chaine $moy e (/\$moy/); ` pose dun point darr t sur la ligne 8 qui correspond a la recherche effectu e (b 8); e e demande lex cution du programme jusquau prochain point darr t (c); e e rentre 2 valeurs (2 et 4) et marque la n de saisie (Ctrl-d); ` demande a consulter le contenu de la variable $total lorsque le d bogueur sarr te e e

85 sur le point darr t (x $total); e demande lafchage de la variable $nb (x $nb) et constate quelle est la source de ` lerreur (undef, cest a dire 0); ` affecte 2 a la variable $nb ($nb=2). demande la reprise du d roulement du programme qui se termine et afche le e r sultat du calcul; e quitte le d bogueur (q). e Parmi les autres commandes du d bogueur non utilis e dans lexemple pr c dent, on e e e e trouve : ` S, demander un d roulement pas a pas; e ` T, afcher la pile (et voir les param` tres transmis a une fonction); e t, afcher ou ne plus afcher les lignes de programmes ex cut es (cest une bascule e e d samorc e par d faut); e e e D, supprimer tous les points darr ts. e

86

CHAPITRE 15. LE DEBOGUEUR DE PERL

87

Chapitre 16

Ecriture et utilisation de modules


Perl autorise l criture de modules qui peuvent etre assembl s pour former une applicae e tion. Cette fonctionnalit a permis le d veloppement de nombreuses contributions, des e e e e modules ont et d velopp s pour interfacer TCP, CGI, FTP ... cest une des raisons du e succ` s de Perl. e

16.1 Inclure du code


La forme la plus simple de l criture modulaire est linclusion de code, autoris e en e e Perl par la fonction require suivie dune expression (en g n ral une chane de caract` re e e e ` repr sentant un nom de chier contenant le code a inclure). Il sagit dune fonctionnalit e e equivalente au #include du langage C, on regroupe en g n ral les inclusions en d but de e e e programme :

#!/usr/local/bin/perl require "cgi-lib.pl";

# Inclusion de la biblioth`que e # grant linterface CGI e

Les modules Perl ecrits ainsi sont souvent un peu anciens et proposent des interfaces rudimentaires :

88

CHAPITRE 16. ECRITURE ET UTILISATION DE MODULES

#!/usr/local/bin/perl # # Programme principal qui utilise le module monmodule.pl # require "monmodule.pl"; # on peut simplement appeler la fonction fonc() dfinie dans e # monmodule.pl et aussi avoir acc`s ` sa variable $I ... e a fonc(); print ("I = $I \n");

# # # #

monmodule.pl Petit module accessible simplement, les variables et fonctions sont directement accessibles ...

$I = 2; sub fonc { print (\"appel de fonc() \n\"); }

` Perl cherche les modules a inclure dans le r pertoire courant et dans les r pertoires cit s e e e dans le tableau @INC. Pour ajouter des r pertoires au tableau @INC il convient de moe dier la variable denvironnement Perl5LIB ou de modier @INC avant le require :

#!/usr/local/bin/perl unshift(@INC,"/usr/local/perl/lib/maison"); require "cgi-lib.pl"; # Inclusion de la biblioth`que e # grant linterface CGI e

Les chiers inclus par require sont charg s a lex cution du programme. Il en r sulte e ` e e une souplesse dusage li e au fait que lon peut inclure des chiers dynamiquement (en e fonction du contenu dune variable). On nest toutefois pas s r lorsquun programme u ` d marre que tout est pr t pour son bon d roulement (un chier a inclure qui nexiste pas, e e e qui comporte une erreur de syntaxe ...). Si lexpression cit e par require est num rique, il sagit du num ro de version de Perl e e e requis pour ce qui suit.

16.2. LES PACKAGES

89

16.2

Les packages

En ecrivant classiquement des modules destin s a etre inclus par require, le programmeur e ` ` doit faire attention a la visibilit des variables (cf. section 10). Une premi` re solution est e e lusage de my, Perl offre toutefois une autre solution : les packages inclus par use. Une partie de code isol e dans une d claration package est destin e a avoir une visibilit e e e ` e externe organis e, le programmeur peut indiquer explicitement quelles sont les variables, e les fonctions qui peuvent etre simplement utilis es par les consommateurs. e On peut trouver plusieurs d clarations de packages dans un chier, ce nest toutefois pas e tr` s utilis , on place g n ralement un package dans un chier dont le sufxe est .pm (Perl e e e e Module).

package essai;

# Le nom du package et du fichier .pm

use Exporter; # appel au module grant la visibilit e e @ISA=(Exporter); # hrite dExporter (non trait ici, e e # voir la section sur les objets) @EXPORT_OK=(Fonc1,Fonc2,$Var); # Le tableau @EXPORT_OK est utilis pour prciser les e e # identificateurs qui sont visibles de lextrieur du e # package. $Var = "visible"; $I = 10; sub sub sub sub Fonc1 Fonc2 Fonc3 Fonc4 { { { { ... ... ... ... } } } }

Dans lexemple ci-dessus, seulement deux fonctions (Fonc1 et Fonc2) ainsi quune va riable ($Var) peuvent etre utilis e depuis lext rieur du package. e e Pour utiliser le package essai (plac dans le chier essai.pm) il convient de proc der e e

90 comme suit :

CHAPITRE 16. ECRITURE ET UTILISATION DE MODULES

#!/usr/local/bin/perl # use est suivi du nom du package # et fonctions ` importer a use essai (Fonc1,Fonc2,$Var); Fonc1(); Fonc2(); print ("$Var \n"); # Un appel ` Fonc3 produirait une erreur a et des variables

` Il est possible dutiliser le tableau @EXPORT a la place de @EXPORT OK, dans ce cas, m me si le programmeur d clare vouloir importer seulement un sous ensemble des e e identicateurs export s, il aura une visibilit sur lensemble. Il est donc pr f rable dutie e ee liser @EXPORT OK qui evite les conits potentiels. Les identicateurs export s constituent linterface du package avec lext rieur, PERL proe e cure toutefois une autre interface avec les packages : le nommage explicite. Il est possible ` dacc der a un identicateur (export ou non) en le pr c dant du nom de son package e e e e dappartenance :

#!/usr/local/bin/perl use essai; # il ny a pas dobligation a importer

$I = 20; essai::Fonc1(); # les identificateurs exports ou non e essai::Fonc2(); # sont accessibles. essai::Fonc3(); printf ("%d \n",$essai::I); # affiche 10 (le I de essai.pm)

La d marche import/export est evidemment beaucoup plus claire et se g n ralise. e e e Les packages peuvent etre dot s de constructeurs et de destructeurs r dig s sous la forme e e e de fonctions appel es respectivement BEGIN et END. Les constructeurs sont ex cut s e e e

16.3. REMARQUES

91

d` s que possible (` la compilation) et les destructeurs le plus tard possible (lorsque le e a programme se termine normalement ou pas). package essai; BEGIN { # sub nest pas obligatoire print ("debut du package \n"); } beurk(); END { # sub nest pas obligatoire print ("fin du package \n"); }

Le package essai.pm de lexemple ci-dessus produit les sorties suivantes : debut du package Undefined subroutine &essai::beurk called at essai.pm line 7. BEGIN failed--compilation aborted at ... fin du package

16.3

Remarques

` La diff rence indiqu e ici entre use et require est ctive (elle correspond toutefois a un e e usage largement r pandu), il est en fait parfaitement possible dinclure un package en e utilisant require. Dans ce cas la routine dimport nest pas appel e mais elle peut l tre a e e ` la main, ceci permet dinclure des packages dynamiquement : if ($a) { require "moda"; moda->import(); } else { require "modb"; modb->import(); }

# Inclusion de moda.pm ou modb.pm # en fonction du contenu dune variable # Limport nest pas effectu (require) e # on le fait donc explicitement.

92

CHAPITRE 16. ECRITURE ET UTILISATION DE MODULES

16.4

Exercice num ro 15 e

# # Petit package doutils HTML pour montrer comment on exporte # des variables et des fonctions. # videmment les fonctions ci-dessous nont pas dintrt en E e e # dehors du contexte de ce TP. package html; use Exporter; @ISA=(Exporter); # Le package exporte une variable et trois fonctions.

@EXPORT=($html_Version,html_Escape,html_Title, html_Background); # variable globale au package, elle est donc exportable. $html_Version = html.pm version 1.0; use strict vars; # Lemploi de use strict rend obligatoire de manipuler # les variables globales au package en les prfixant par e # le nom du package : $html::html_Version par exemple ... sub html_Escape { ################# # On modifie les carat`res accentus les plus usuels ... e e my (@content) = @_; my @res; foreach (@content) { s//&eacute;/g; e s/`/&Egrave;/g; e s/c/&ccedil;/g; # etc etc etc .... push(@res,$_); } push(@res,"<!-- *** modifi avec $html::html_Version *** -->"); e return(@res); }

16.4. EXERCICE NUMERO 15

93

sub html_Title { ################ my ($title, @content) = @_; my (@res); # # #

On modifie le titre (sous rserve quil existe ...). e

foreach (@content) { s/<TITLE>.*<\/TITLE>/<TITLE>$title<\/TITLE>/gi; push (@res,$_); } return(@res); } sub html_Background { ##################### my ($background, @content) = @_; my (@res); # # On ajoute un attribut bgcolor ` la balise BODY a # si elle existe. # foreach (@content) { if (/.*<BODY/i) { $_ = $&." bgcolor=$background".$; } push (@res,$_); } return(@res); } # Quand on importe un package en utilisant en utilisant use # le contenu du package est pass ` eval. La derni`re expression e a e # value doit rendre vrai car sinon eval choue ... e e e return(1);

94

CHAPITRE 16. ECRITURE ET UTILISATION DE MODULES

#!/usr/bin/perl # TP15 # Utilisation du package html.pm pour modifier # un document HTML. use html; # Inclusion du package html use strict vars; my $File; # Sil nest pas donn de fichier, on traite index.html e unless (@ARGV) { $File = "index.html"; } else { $File = $ARGV[0]; } unless (open(IN,$File)) { print ("Impossible douvrir $File : $! \n"); exit(); } my @Content = <IN>; close(IN); # Appel des fonctions du package @Content = html_Escape(@Content); @Content = html_Title("nouveau titre",@Content); @Content = html_Background("#ff0000",@Content); # Mise ` jour du fichier a unless (open(OUT,">$File.new")) { print ("Impossible de rcrire $File.new : $! \n"); ee exit(); } unless (print OUT (@Content)) { print ("Impossible de rcrire $File.new : $! \n"); ee exit(); } close(OUT); unless (rename("$File.new",$File)) { print ("Impossible de mettre ` jour $File : $! \n"); a exit(); } else { print ("$File modifi ` laide de $html_Version \n"); e a }

95

Chapitre 17

Ecriture orient e objet e


17.1 Un exemple limit a lusage classique des packages e`

Si lon consid` re une classe dobjet comme une structure de donn es accompagn e de e e e proc dures qui r gissent le comportement de ses membres potentiels, alors en Perl on e e peut essayer dutiliser les packages. Dans lexemple suivant on d sire g rer des objets dune classe appel e voiture caract ris s e e e e e ` chacun par une marque et une couleur, a tout moment on souhaite connatre le nombres de voitures en cours.

#!/usr/local/bin/perl use voiture; $voit1 = voiture::nouvelle(verte,citroen); $voit2 = voiture::nouvelle(bleue,renault); $voit3 = voiture::nouvelle(rouge,citroen); printf printf printf printf (" (" (" (" %s %s %s %d \n", \n", \n", \n", voiture::couleur($voit1)); voiture::marque($voit2)); voiture::couleur($voit3)); voiture::total());

96

CHAPITRE 17. ECRITURE ORIENTEE OBJET

package voiture; BEGIN { @liste=();} sub nouvelle { my ($color,$marque) = @_; my $objptr = {}; $objptr->{couleur}=$color; $objptr->{marque}=$marque; push(@liste,$objptr); return $objptr; } sub couleur { my ($objptr) = @_; return ($objptr->{couleur}); } sub marque { my ($objptr) = @_; return ($objptr->{marque}); } sub total { return($#liste+1); } 1

Dans lexemple pr c dent, la classe voiture est un package, le constructeur de package e e ` BEGIN est utilis pour initialiser la liste des objets a vide. e La fonction nouvelle est le constructeur de la classe, elle recoit en arguments la couleur et la marque dun objet et retourne la r f rence de lobjet instanci . La r f rence de lobjet ee e ee est ici une r f rence sur un hash anonyme ($objptr = {} cf. section 11.4.1). Les foncee tions couleur et marque sont les m thodes dinstance de la classe voiture. Les fonctions e nouvelle et total sont des m thodes de classe. e ` Si le d but du code qui utilise la classe voiture sapparente a du code orient objet (ape e ` pel au constructeur notamment), lutilisation des m thodes sen eloigne. La r f rence a e ee lobjet ($voit3 par exemple) na pas de souvenir du type de lobjet r f renc et on ne peut ee e lutiliser quen citant le nom du package. Perl propose donc un type de r f rences particulier, il va permettre dappeler les m thodes ee e ` ` directement a partir de la r f rence a lobjet. Dans lexemple pr c dent on souhaite plut t ee e e o

17.2. REFERENCER UNE CLASSE ecrire $voit3->couleur() et non pas voiture::couleur($voit3).

97

17.2

R f rencer une classe ee

Dans lexemple de la classe voiture les r f rences $voit1, $voit2 et $voit3 nont pas ee connaissance de la classe dappartenance des objets quelles r f rencent. La fonction ee bless est utilis e pour cel` , on peut maintenant modier le constructeur de la classe voie a ture comme suit :

sub nouvelle { my ($classe,$color,$marque) = @_; # le nom de la classe # est le 1er argument my $objptr = {}; $objptr->{couleur}=$color; $objptr->{marque}=$marque; bless $objptr; push(@liste,$objptr); return $objptr; }

# rfrence la classe e e

Un afchage de la valeur de $objptr indique explicitement la classe de lobjet r f renc ee e (voiture=HASH(0xca454)). Le programme qui utilise la classe voiture peut maintenant etre modi de la mani` re e e suivante :

#!/usr/local/bin/perl use voiture; $voit1 = voiture->nouvelle(verte,citroen); $voit2 = voiture->nouvelle(bleue,renault); $voit3 = voiture->nouvelle(rouge,citroen); printf printf printf printf (" (" (" (" %s %s %s %d \n", \n", \n", \n", $voit1->couleur()); $voit2->marque()); $voit3->couleur()); voiture->total());

98

CHAPITRE 17. ECRITURE ORIENTEE OBJET

Il convient ici de noter la forme dappel des m thodes de classe (voiture->nouvelle()) et e la forme dappel des m thodes dinstance ($voit1->couleur()). Les m thodes de classe e e sappellent en pr c dant la m thode par le nom de la classe, et, le nom de la classe est e e e alors pass en premier argument (ce qui justie la changement intervenu dans notre classe e voiture). Les m thodes dinstance recoivent comme premier argument une r f rence dobjet, il e ee nest donc pas n cessaire de modier le code de notre classe voiture. e Comme bien souvent en Perl, il existe plusieurs notations pour un m me r sultat et, il est e e possible de faire pr c der le nom dun objet ou dune classe par le nom de la m thode. e e e Lexemple pr c dent peut donc s crire e e e

#!/usr/local/bin/perl use voiture; $voit1 = nouvelle voiture (verte,citroen); $voit2 = nouvelle voiture (bleue,renault); $voit3 = nouvelle voiture(rouge,citroen); printf printf printf printf (" (" (" (" %s %s %s %d \n", \n", \n", \n", $voit1->couleur()); $voit2->marque()); $voit3->couleur()); voiture->total());

Si on rebaptise la m thode nouvelle en new, on utilise une notation qui est famili` re au e e programmeur C++ ou Java.

17.3

H riter dune classe e

` Perl autorise de construire de nouvelles classes a partir de classes existantes en utilisant des techniques dh ritages : e ` la liste @ISA indique a un package (` une classe) quels sont les anc tres dont il a e h rite; e de mani` re a pouvoir etre h rit , le constructeur dune classe de base doit rendre e ` e e une r f rence blessee de la classe sp ci e (de la classe d riv e). ee e e e e

17.3. HERITER DUNE CLASSE

99

Pour construire une classe appel e location (g rant la location de v hicules) h ritant de e e e e notre classe voiture, on peut proc der comme suit : e

package location; use voiture; # inclure voiture.pm pour la compile @ISA = ("voiture"); # hriter des mthodes de la classe e e # voiture. sub loc { my ($classe, $couleur, $marque, $nbjour, $pu) = @_; # appel du constructeur hrit de la classe de base, il e e # rendra un objet de classe location my $locptr = $classe->nouvelle($couleur,$marque); $locptr->{pu}=$pu; $locptr->{nbjour}=$nbjour; return($locptr); } sub tarif { my ($locptr) = @_; return ($locptr->{pu} * $locptr->{nbjour}); }

Il convient de bien noter que la classe voiture doit etre modi e pour que le constructeur e nouvelle() rende un objet de la classe location et non pas un objet de la classe voiture :

sub nouvelle { my ($classe,$color,$marque) = @_; # le nom de la classe # est le 1er argument my $objptr = {}; $objptr->{couleur}=$color; $objptr->{marque}=$marque; bless $objptr,$classe; <================== push(@liste,$objptr); return $objptr; }

100

CHAPITRE 17. ECRITURE ORIENTEE OBJET

Un programme utilisant la classe location peut sutiliser comme dans lexemple ci-dessous :

#!/usr/local/bin/perl use location; $voit1 = location->loc(verte,peugeot,10,100); print $voit1; print $voit1->couleur(); print $voit1->tarif();

17.4. EXERCICE NUMERO 16

101

17.4

Exercice num ro 16 e

package champ; # # # # # # #

Une classe champ qui g`re la largeur, la longueur et e le type de culture dun champ. La classe permet de connaitre la surface dun champ ainsi que le nombre de champs et la surface cultive pour un type de e culture pass en argument. e

my @champs = (); sub new { ######### # # # #

Le constructeur recoit le nom de la classe comme premier argument.

my ($classe, $largeur, $longueur, $culture) = @_; my $champtr = {}; # pour grer les donnes dinstances. e e $champtr->{largeur} = $largeur; $champtr->{longueur} = $longueur; $champtr->{culture} = $culture; bless($champtr,champ); push(@champs, $champtr); return($champtr); } # typer la rfrence sur lobjet de e e # classe champ.

102

CHAPITRE 17. ECRITURE ORIENTEE OBJET

sub nbrchamps { ############### # # # #

Une mthode de classe, le nom de la classe est recu comme e premier argument.

my ($classe) = @_; return($#champs+1); } sub surface { ############# # # #

Une mthode dinstance de classe. Elle recoit en argument e une rfrence sur un objet de classe champ. e e my ($champtr) = @_; return($champtr->{largeur} * $champtr->{longueur});

} sub surface_cultivee { ###################### my ($classe, $culture) = @_; foreach (@champs) { if ($_->{culture} eq $culture) { $total += $_->{largeur} * $_->{longueur}; } } return($total); } 1

17.4. EXERCICE NUMERO 16

103

#!/usr/bin/perl # # # # #

TP16 utilisation de la classe champ.

use champ; use strict vars; print ("Largeur du champ : "); while (my $Largeur=<STDIN>) { # saisie des donnes dun champ. e chomp($Largeur); print ("Longueur : "); my $Longueur=<STDIN>; unless ($Longueur) { last; } chomp($Longueur); print ("Culture : "); my $Culture=<STDIN>; unless ($Culture) { last; } chomp($Culture); # cration dun objet de classe champ. e my $unchamp = new champ($Largeur,$Longueur,$Culture); # affichage de la surface du champ rentr. e printf ("La surface de ce champ est %s\n", $unchamp->surface()); print ("Largeur du champ : "); } printf ("\n Nombre de champs %s \n", champ->nbrchamps()); print ("Culture ` mesurer : "); a my $cult=<STDIN>; chomp($cult); printf ("Surface cultive en %s %s \n", e $cult, champ->surface_cultivee($cult));

104

CHAPITRE 17. ECRITURE ORIENTEE OBJET

105

Chapitre 18

L criture de scripts CGI e


18.1 Introduction

Common Gateway Interface (CGI 1 ) est une sp cication dinterface permettant dex cuter e e des proc dures externes depuis un service WWW. CGI sp cie (du c t du serveur) come e oe ment doit etre initialis e la proc dure externe et comment elle doit acc der aux informae e e ` ` tions a traiter. Les informations transmises a la proc dure externe sont : e des variables qui correspondent aux en-t tes de la requ te HTTP qui a d clench e e e e lappel de la proc dure externe (HTTP REFERER, HTTP USER AGENT, e HTTP CONNECTION, HTTP HOST, ...); des variables relatives au corps dun document transmis ou propres au contexte CGI (REQUEST METHOD, CONTENT TYPE, CONTENT LENGTH, REMOTE HOST, QUERY STRING, ...); un corps de document eventuel. CGI indique egalement que si un corps de document est transmis, il doit etre acc d e e via lentr e standard de la proc dure externe. De plus la proc dure externe (le script e e e CGI) doit toujours rendre un r sultat via sa sortie standard. La sp cication des ces deux e e m canismes impose (au serveur HTTP) un mode de cr ation assez lourd et couteux du e e script CGI (fork + redirection de lentr e et de la sortie standard + exec). Cest la raie ` son principale du manque de performance des scripts CGI, a chaque requ te, le syst` me e e dexploitation est fortement sollicit . e
1. En service depuis 1993, CGI na jamais port le status de RFC, une proposition est en cours de e r alisation cf. http://web.golux.com/coar/cgi e

106

CHAPITRE 18. LECRITURE DE SCRIPTS CGI

Dans la pratique, malgr son manque de performance, CGI reste tr` s utilis pour transe e e mettre des informations dun client WWW vers un service particulier (via un serveur HTTP). Cest notamment ainsi que fonctionnent nombre de formulaires WWW, le sy noptique des echanges entre client, serveur et script CGI est alors le suivant : un client WWW afche un formulaire ; ` lutilisateur compl` te les champs a transmettre et valide le contenu qui est transe mis. Si la m thode HTTP utilis e pour transmettre le formulaire est GET, alors les e e ` champs (linformation a transmettre) sont transmis dans lURL dappel du script CGI et lui sont pass s via la variable QUERY STRING. e Si la m hode HTTP est POST, alors les champs sont transmis dans un corps de doe cument (dont le CONTENT TYPE est application/x-www-form-urlencoded) et sont pass s au script CGI via son entr e standard. Cette derni` re facon de proc der e e e e est fortement conseill e. e Le type de document application/x-www-form-urlencoded implique que les champs du formulaire sont s par s entre eux par le caract` re &, quils sont pr c d s de leur e e e e e e nom (attribut NAME de la balise HTML <FORM>) et du signe =, que les caract` res accentu s et les espaces sont encod s comme sp ci dans le RFC1738 e e e e e sur les URL; un serveur HTTP r ceptionne la requ te et initialise le script CGI r f renc par le e e ee e formulaire WWW ; ` le script CGI effectue le traitement demand et se charge d mettre un r sultat a e e e destination du client WWW instigateur de la requ te. e En dehors de toute aide ext rieure, un programmeur de script CGI doit donc d coder le e e application/x-www-form-urlencoded pour acc der individuellement aux champs transe mis, il doit egalement prendre en charge l mission du r sultat (et donc g n rer des ene e e e t tes HTTP correctes suivies dun corps de document HTML). En Perl diverses contribue tions permettent de faciliter ces deux t ches, les plus connues sont cgi-lib.pl et CGI.pm. a

18.2

Un exemple

Dans lexemple suivant on d sire compl ter un formulaire WWW comportant deux champs e e ` (nom et pr nom), le transmettre a une proc dure CGI qui pourrait stocker les champs e e transmis dans un chier ... mais se contentera ici davertir lutilisateur de la prise en ` compte de linformation. Le code HTML du formulaire est plac dans un document a e 2 ), on v rie que la m thode HTTP utilis e est bien ` part (ext rieur a la proc dure CGI e e e e e ` POST et on montre a lutilisateur les renseignements obtenus sur lui (machine, client
2. Il est possible de placer le source du formulaire dans la proc dure, elle doit alors emettre le source du e formulaire si la m thode est GET, traiter les champs saisis si la m thode est POST. e e

18.2. UN EXEMPLE WWW, ...).

107

<HTML> <!-- Source HTML permettant dafficher le formulaire et dappeler la procdure CGI rfrence par lattribut e e e e action de la balise <FORM>. --> <HEAD> <TITLE> Test CGI </TITLE> </HEAD> <BODY> <H1> Test CGI </H1> <HR> <FORM action="http://madeo.irisa.fr/cgi-bin/tstcgi" method="POST"> Nom : <INPUT TYPE="text" NAME="nom" SIZE="25"> <BR> Prnom: <INPUT TYPE="text" NAME="prenom" SIZE="15"> <BR> e <INPUT TYPE="submit" VALUE="OK"> <INPUT TYPE="reset" VALUE="Annuler"> </FORM> <HR> </BODY> </HTML>

18.2.1

Utiliser cgi-lib.pl

e La premi` re biblioth` que qui a et diffus e pour ecrire des scripts CGI en Perl est cgie e e 3 . Elle reste aujourdhui tr` s utilis e et pr sente les caract ristiques suivantes : lib.pl e e e e permet de r cup rer les champs transmis dans un tableau associatif ; e e g` re le transfert de chiers dans le sens client serveur (upload) ; e ` globalement tr` s simple a utiliser. e Le script Perl suivant propose dutiliser cgi-lib.pl pour r aliser notre exemple, il utilise e les fonctions suivantes : Methpost() qui rend vrai si la m thode HTTP utilis e est POST; e e
3. http://cgi-lib.stanford.edu/cgi-lib/

108

CHAPITRE 18. LECRITURE DE SCRIPTS CGI ReadParse() qui prend une r f rence sur un hash et le compl` te par une associaee e tion entre le nom des champs (tel que sp ci s par lattribut NAME de la balise e e <FORM>) et leurs valeurs respectives; PrintHeader() qui indique au navigateur quil va recevoir un document HTML. ` Cette fonction prend aussi a sa charge l mission dune ligne vide pour s parer les e e en-t tes du corps de document (cf. RFC2068 sur HTTP/1.1); e ` CgiDie pour quitter la proc dure en emettant un message davertissement a lutilie sateur; ...

#!c:\perl\bin\perl.exe # TestCGI utilise cgi-lib pour acquerir les champs du # formulaire et generer le HTML resultat. On verifie # que la methode est POST, que les champs ne sont pas # vides et on informe lutilisateur du resultat. require "cgi-lib.pl"; $champs= {}; # $champs est une reference sur un hash vide if (MethPost()) { ReadParse($champs); if ($champs->{"nom"} eq "" || $champs->{"prenom"} eq "") CgiDie("Il faut remplir les champs !"); } print (PrintHeader(), HtmlTop("Resultat de votre requete"), "Nom : ", $champs->{"nom"}, "<BR>", "Prenom :", $champs->{"prenom"}, "<BR>", "vous utilisez $ENV{HTTP_USER_AGENT}", "depuis la machine $ENV{REMOTE_ADDR}", HtmlBot()); } else { CgiDie("Hum ... Que faites vous !"); }

18.2. UN EXEMPLE

109

18.2.2

Utiliser CGI.pm

CGI.pm 4 est un autre outil facilitant la r alisation de script CGI en Perl. CGI.pm peut e etre utilis de deux facons : e en important des fonctions dans lespace du script, CGI.pm est alors utilis comme e un package; en utilisant un objet de classe CGI comme dans la r alisation (ci-apr` s) de notre e e exemple.

#!c:\perl\bin\perl.exe # TestCGI utilise CGI.pm pour acquerir les champs du # formulaire et generer le HTML resultat. On verifie # que la methode est POST, que les champs ne sont pas # vides et on informe lutilisateur du resultat. use CGI; $req = new CGI; print $req->header(); print $req->start_html(Rsultat de la requte); e e if ($req->request_method() eq "POST") { if ($req->param(nom) eq " " || $req->param(prenom) eq " " ) { print $req->h1(Il faut remplir les champs); } else { print ("Nom : ", $req->param(nom), $req->br, "Prenom : ", $req->param(prenom), $req->br, " vous utilisez", $req->user_agent(), "depuis la machine ",$req->remote_addr()); } } else { print $req->h1(Hum ... Que faites vous !); } print $req->end_html;

4. http://www.wiley.com/compbooks/stein/index.html

110

CHAPITRE 18. LECRITURE DE SCRIPTS CGI

` CGI.pm peut semble run peu plus lourd a utiliser que cgi-lib.pl, il est toutefois plus elabor pour : e g n rer les en-t tes HTTP, dans notre exemple, $req->header se contente de poe e e sitionner Content-Type: text/html (suivi dune ligne vide), mais pourrait aussi indiquer une en-t te expire ($req->header(-expires=>now);) pour inhiber les caches; e g n rer du code HTML (notamment des tables, des formulaires, ...); e e etre utilis dans un contexte FastCGI (cf. 18.4) ; e mettre au point les scripts sans passer par un navigateur WWW et un serveur HTTP. CGI.pm reconnait sil est appel dans un contexte dit ofine et invite alors lutilie ` ` sateur a rentrer a la main des couples clef=valeur pour simuler la chane compl` te e dun environnement CGI.

18.3

Envoyer un chier (upload)

Il est parfois int ressant de transf rer des documents complets depuis un client WWW e e vers un serveur HTTP. CGI.pm ainsi que cgi-lib.pl offrent cette possibilit . Elle sappuie e sur le transfert dans le corps dun document (comprenant plusieurs parties), des champs eventuels dun formulaire suivi des diff rents chiers. e ` On peut compl ter notre exemple en demandant a lutilisateur de fournir deux chiers e ` qui seront transf r s sur le serveur et transmis a notre script (via cgi-lib.pl ici). Le code ee HTML peut etre modi de la facon suivante : e

<HTML> <!-- Le document est compos de plusieurs parties, donc e (ENCTYPE="multipart/form-data") + ajout de 2 champs "file". --> <HEAD> <TITLE> Test CGI </TITLE> </HEAD> <BODY> <H1> Test CGI </H1><HR> <FORM action="http://madeo.irisa.fr/cgi-bin/tfic.pl" ENCTYPE="multipart/form-data" method="POST"> Nom : <INPUT TYPE="text" NAME="nom" SIZE="25"> <BR> Prnom: <INPUT TYPE="text" NAME="prenom" SIZE="15"> <BR> e <INPUT TYPE="file" NAME="fic1" SIZE=50> <BR> <INPUT TYPE="file" NAME="fic2" SIZE=50> <BR> <INPUT TYPE="submit" VALUE="OK"> <INPUT TYPE="reset" VALUE="Annuler"> </FORM> </BODY> </HTML>

18.3. ENVOYER UN FICHIER (UPLOAD)

111

Dans le cas dun type de document multipart/form-data les arguments de la fonction ` ReadParse sont 4 r f rences a des tableaux associatifs correspondants aux champs du ee formulaire, aux nom des chiers transmis, aux Content-Type des chiers transmis et aux noms des chiers recus. Notre proc dure peut donc etre modi e de la facon suivante : e e

#!c:\perl\bin\perl.exe # # Rception des deux fichiers. e require "cgi-lib.pl"; $champs = {}; # $champs, $client_fn, $client_fn = {}; # $client_ct, $serveur_fn $client_ct = {}; # sont des rfrences sur e e $serveur_fn = {}; # des hashes vides. $cgi_lib::writefiles = "c:\tmp"; # Rpertoire dans lequel e # les fichiers transmis # seront dposs. e e if (MethPost()) { ReadParse ($champs, $client_fn, $client_ct, $serveur_fn); if ($champs->{"nom"} eq "" || $champs->{"prenom"} eq "") { CgiDie("Il faut remplir les champs !"); } print (PrintHeader(), HtnlTop("Resultat de votre requete"), "Nom : ", $champs->{"nom"}, "<BR>", "Prenom :", $champs->{"prenom"}, "<BR>", $serveur_fn->{fic1}, # nom du fichier 1 (serveur) $serveur_fn->{fic2}, # nom du fichier 2 (serveur) $client_fn->{fic1}, # nom du fichier 1 (client) $client_fn->{fic2}, # nom du fichier 2 (client) $client_ct->{fic1}, # Content-Type fichier 1 $client_ct->{fic2}, # Content-Type fichier 2 HtmlBot()); # Une procedure oprationnelle pourrait maintenant ouvrir e # les fichiers correspondants et effectuer un traitement. } else { CgiDie("Hum ... Que faites vous !"); }

Pour quune proc dure effectuant du transfert de chiers se d roule normalement, il e e convient que le serveur HTTP soit autoris a ecrire dans le r pertoire $cgi lib::writeles, e` e

112

CHAPITRE 18. LECRITURE DE SCRIPTS CGI

il faut egalement que celui-ci soit correctement dimensionn . e

18.4
18.4.1

Utiliser FastCGI
Introduction

Pour contourner le manque de performance des scripts CGI ecrits en Perl, deux solutions sont envisageables : utiliser mod perl 5 qui lie APACHE 6 et Perl et permet d viter la cr ation de proe e ` cessus a chaque appel de proc dure. Cette solution pr sente lavantage de permettre e e l criture en Perl de modules pour APACHE 7 , mais elle introduit quelques ine conv nients, notamment une tr` s forte augmentation de la taille m moire utilis e e e e e par un processus httpd; utiliser FastCGI 8 qui fait communiquer le serveur HTTP et la proc dure externe e ` e via une socket. La proc dure externe fonctionne alors comme un serveur a l coute e sur un port, elle traite les requ tes de son client (le serveur HTTP) qui lui transmet e les donn es emises par les navigateurs WWW. La proc dure externe est d marr e e e e e ` a linitialisation du serveur HTTP, elle est persistante, le gain de performance par ` rapport a CGI est tr` s signicatif. e FastCGI permet egalement de d localiser la proc dure externe (la faire se d rouler e e e sur une machine distincte de celle qui h berge le serveur HTTP), cest une fonce tionnalit tr` s int ressante, elle permet de r partir les traitements. e e e e CGI.pm permet dutiliser FastCGI comme canal de communication, en cons quence les e ` changements a apporter pour faire migrer une proc dure de CGI vers FastCGI sont tr` s e e minimes (cf. exemple ci-dessous).

18.4.2

Un exemple

` On reprend ici lexemple de la section 18.2.2, les changements a effectuer ont pour but ` dindiquer a CGI.pm de basculer dans un contexte FastCGI et de rendre la proc dure e
5. Consulter ftp://ftp.bora.net/pub/CPAN/modules/by-module/Apache/ la version actuelle est mod perl-1.18.tar.gz 6. Le serveur HTTP le plus utilis au monde, consulter http://www.apache.org e 7. Pour ajouter des fonctionnalit s au serveur HTTP de base. e 8. Consulter http://www.fastcgi.com/ et installer le module fastcgi pour APACHE ainsi que FCGI pour Perl

18.4. UTILISER FASTCGI

113

persistante (boucler sur lattente de larriv e de donn es a traiter). Pour mettre en evidence e e ` leffet de la persistance de la proc dure, on ajoute un compteur de requ tes. e e

#!/usr/local/bin/perl # TestCGI utilise CGI.pm pour acquerir les champs du # formulaire et generer le HTML resultat. On verifie # que la methode est POST, que les champs ne sont pas # vides et on informe lutilisateur du resultat. use CGI::Fast; $Cptr = 0; while ($req=new CGI::Fast) { $Cptr++; print $req->header(); print $req->start_html(Rsultat de la requte); e e if ($req->request_method() eq "POST") { if ($req->param(nom) eq " " || $req->param(prenom) eq " " ) { print $req->h1(Il faut remplir les champs); } else { print ("Requte numro : ", $Cptr, $req->br); e e print ("Nom : ", $req->param(nom), $req->br, "Prenom : ", $req->param(prenom), $req->br, " vous utilisez", $req->user_agent(), "depuis la machine ",$req->remote_addr()); } } else { print $req->h1(Hum ... Que faites vous !); } print $req->end_html; }

114

CHAPITRE 18. LECRITURE DE SCRIPTS CGI

115

Chapitre 19

La programmation dapplications r seaux e


19.1 Introduction

Perl permet le d veloppement dapplications utilisant les sockets. Il sagit de canaux de e communications utilisant un couple num ro IP/num ro de port pour mettre en rapport e e deux machines. Le num ro IP cible une machine sur le r seau, le num ro de port adresse e e e une application sur la machine r f renc e. On peut faire communiquer des processus ee e distants en utilisant des sockets TCP ou UDP. TCP assure un service de communication able entre applications (remise en ordre des paquets, demande de r emission des paquets e corrompus), UDP est beaucoup plus l ger (pas de contr les sur la validit des paquets) e o e et est utilis dans des cas bien sp ciques (transmission audios et vid os o` les contr les e e e u o sur les paquets nont pas de sens, ...). On peut egalement utiliser les sockets pour faire communiquer des processus r sidant sur e une m me machine (sockets dites Unix), pour plus de d tails, consulter le manuel des e e fonctions socket, bind, listen, accept ...

19.2

Un exemple dapplication client/serveur

Lexemple suivant permet de faire communiquer un serveur et des clients en utilisant une ` e socket TCP. Le serveur est a l coute sur le port 8888, il recoit et stocke des messages en provenance de clients distants.

116

CHAPITRE 19. LA PROGRAMMATION DAPPLICATIONS RESEAUX

` Le code qui suit nest pas a sortir du contexte de cet exemple, une v ritable application e devrait utiliser un service TCP enregistr , acquitter les messages recus, ... e

#!/usr/local/bin/perl # Serveur qui rceptionne sur le port 8888 des messages e # quil stocke dans un fichier. use Socket; my $port = 8888; my $protoc = getprotobyname(tcp); open (FICLOG,">Log") || die ("Erreur Cration Log : $!"); e # Cration de la socket TCP de reception des messages e socket (SockPerm, PF_INET, SOCK_STREAM, $protoc) || die("Erreur Creation Socket : $!"); setsockopt (SockPerm, SOL_SOCKET, SO_REUSEADDR, 1) || die ("setsockopt : $!"); bind (SockPerm, sockaddr_in($port, INADDR_ANY)) || die("Erreur bind : $!"); listen (SockPerm, SOMAXCONN); $SIG{INT}=arret; # Fermer le fichier des messages si C # Rception des messages e while(1) { $refcli = accept(SockTmp,SockPerm); my ($port, $addr) = sockaddr_in($refcli); $client=gethostbyaddr($addr, AF_INET); # # Traitement dun message # $ligne=<SockTmp>; chop($ligne); until ($ligne = /FIN/) { print FICLOG ("$client : ",$ligne,"\n"); $ligne=<SockTmp>; chop($ligne); } close(SockTmp); } sub arret { close(FICLOG); exit; }

19.2. UN EXEMPLE DAPPLICATION CLIENT/SERVEUR

117

#!/usr/local/bin/perl # # Client qui emet les messages. # use Socket; my $port = 8888; my $protoc = getprotobyname(tcp); my $adrserv = localhost; # machine locale pour les tests my $iaddr = inet_aton($adrserv); my $paddr = sockaddr_in($port,$iaddr); # # cration de la socket et connexion au serveur e # socket (SOCK, PF_INET, SOCK_STREAM, $protoc) || die ("Erreur Creation Socket: $!"); connect(SOCK, $paddr) || die ("Erreur Connect: $!"); # # Saisie et mission ligne ` ligne du message e a # while (<STDIN>) { print SOCK ("$_"); } # # Emission de la marque de fin de message # print SOCK ("FIN \n"); close(SOCK);

118

CHAPITRE 19. LA PROGRAMMATION DAPPLICATIONS RESEAUX

BIBLIOGRAPHIE

119

Bibliographie
[1] Larry WALL Tom C HRISTIANSEN et Randal L. S CHWARTZ. Programmation en Perl, 2` me edition en francais. e OREILLY, 1996. ISBN 2-84177-004-4. [2] Sriram S RINIVASAN. Advanced Perl Programming. OREILLY, 1997. ISBN 1-56592-220-4. [3] Randal L. S CHWARTZ Erik O LSON and Tom C HRISTIANSEN. Learning Perl on Win32 Systems. OREILLY, 1997. ISBN 1-56592-324-3. [4] Bruno P OULIQUEN. Introduction au langage Perl. http://www.med.univ-rennes1.fr/poulique/cours/perl/. [5] Olivier AUBERT. Introduction a perl. ` http://perso-info.enst-bretagne.fr/aubert/perl/html/perl.html.