Le langage PERL Alain FORCIOLI, aforcioli@april.org Thu Oct 19 10:32:05 WEST 2000 Perl est un langage interprété cr par Larry WALL. Perl est optimisé pour scanner des fichiers, en extraire des informations et sortir des rapports à partir de ces informations. C'est pourquoi son nom signi­ fie "Practical Extraction and Report Language". Ce document est le support de cours d'une conférence sur Perl dispensée par l'association APRIL. Nous espérons qu'il pourra aussi vous servir efficament de manuel d'introduction au langage Perl. Toute nouvelle version de ce document se trouvera sur le serveur web de l'APRIL . ______________________________________________________________________ Table of Contents 1. Introduction 2. Les types de variables de PERL 2.1 Introduction 2.2 La variable scalaire 2.2.1 Description 2.2.2 Exemples d'opérations sur les variables scalaires 2.3 La table ou liste 2.3.1 Description 2.3.2 Les fonctions utilisant les tables 2.3.2.1 push, pop, shift, unshift 2.3.2.2 sort, reverse, split, join 2.4 La table de hash 2.4.1 Introduction 2.4.2 Description 2.4.3 Fonctions usuelles 2.4.3.1 keys, values 2.4.3.2 each, delete, exists 3. Les variables spéciales 4. Les structures de contrôle 4.1 if, else, elseif 4.2 foreach, while 4.3 Présentation du code 5. Les fonctions 5.1 Présentation 5.2 Création d'une fonction 5.3 Valeur de retour d'une fonction 5.4 Arguments d'une fonction 5.5 Variables locales 6. Les expressions régulières de Perl (E.R.) 6.1 Description 6.2 Exemple: wc.pl 7. Les références 7.1 Description 7.2 Référence sur un tableau 7.3 Référence sur une table de hash 7.4 Référence sur une fonction 7.5 Extension: structure de données complexes 8. Remerciements 9. Copyright ______________________________________________________________________ 11.. IInnttrroodduuccttiioonn Larry WALL affirme que son langage regroupe les meilleures caractéristiques des langages C, sed, awk et sh. Il est proche de la vérité. Toutefois son langage manque de succès notamment à cause de la complexité de lcriture des programmes. Néanmoins, à partir de Perl 5.003 (mouture orientée objet, dotée d'un système de modules et d'un jeu d'expressions régulières très étendu) Perl a connu un vif succès auprès des webmasters qui écrivent désormais beaucoup de leur programmes CGI en Perl. 22.. LLeess ttyyppeess ddee vvaarriiaabblleess ddee PPEERRLL 22..11.. IInnttrroodduuccttiioonn (Se reporter à la section _p_e_r_l_d_a_t_a du manuel Perl.) Perl manipule quatre types de variables: 1. les variables scalaires, 2. les tableaux, 3. les tables de hash, 4. les références. 22..22.. LLaa vvaarriiaabbllee ssccaallaaiirree 22..22..11.. DDeessccrriippttiioonn C'est la variable de base. La variable scalaire se préfixe du $ (comme les variables shell). Elle peut prendre pour valeur un entier, une chaîne de caractères ou une référence. RReemmaarrqquuee:: dans un code Perl, le caractère # permet de commenter tout ce qui suit jusqu'au retour chariot. ______________________________________________________________________ $number = 1; # un entier $string = "Il fait beau"; # une chaine de caractères $reference = \$number; # une référence sur l'entier 1 ______________________________________________________________________ 22..22..22.. EExxeemmpplleess dd''ooppéérraattiioonnss ssuurr lleess vvaarriiaabblleess ssccaallaaiirreess ______________________________________________________________________ $i = "1"; # la chaine "1" $i ++ # 2 $i = "$i" # la chaine "2" ______________________________________________________________________ Perl effectue les conversions implicites des valeurs des variables scalaires pour que les opérations qui les affectent puissent être exécutées. ______________________________________________________________________ $phrase = "2*2 = 4" . "et sqrt(4) = 2" . ".\n"; # concatenation 1 ______________________________________________________________________ Le caractère . permet de concaténer des chaînes entre elles. ______________________________________________________________________ $phrase = "2*2 = ", 2*2, " et sqrt(4) = ", sqrt (4), ".\n"; # concatenation 2 ______________________________________________________________________ La virgule permet de concaténer les évaluations des routines présentes sur la ligne d'affectation. Ainsi la variable scalaire $phrase contient la chaine "2+2 = 4 et sqrt(4) = 2.". 22..33.. LLaa ttaabbllee oouu lliissttee 22..33..11.. DDeessccrriippttiioonn Préfixé du caractère @, le tableau appelé aussi table ou liste est un ensemble de variables scalaires. Donc une table peut contenir des entiers, des chaînes de caractères, des références et même des tables. Pour définir une table on utilise les parenthèses et on sépare les éléments par une virgule. ______________________________________________________________________ (a, b, c) # une table de caractères @tab = ( 1, 2, 3) # une table d'entiers @foo = ( 1, b, $var) # une table avec des éléments de # types différents ______________________________________________________________________ Une table est indexée par des entiers. Le premier indice d'une table est 0. Le premier élément de la table @tab se nomme $tab[0]. Le dernier élément de la table est $#tab. Le nombre d'éléments de la table peut donc s'écrire $#tab + 1 ______________________________________________________________________ @tab = (a, b, c); $tab[0]; # a $tab[1]; # b $#tab; # 2 $tab[ $#tab ] # c $#tab + 1 # 3 ______________________________________________________________________ 22..33..22.. LLeess ffoonnccttiioonnss uuttiilliissaanntt lleess ttaabblleess (Se reporter à la section _p_e_r_l_f_u_n_c du manuel Perl.) 22..33..22..11.. ppuusshh,, ppoopp,, sshhiifftt,, uunnsshhiifftt Ces fonctions permettent de manipuler la table comme une pile. La fonction pop retourne le dernier élément de la table et le supprime. push ajoute un élément à la fin d'une table. shift retourne le premier élément d'une table et le supprime. unshift insere un élément au début d'une table. Voici quelques exemples d'utilisation de ces fonctions. ______________________________________________________________________ @tab = ('Larry', 'WALL'); $age = '24'; push(@tab, $age); # @tab = ('Larry', 'WALL', '24') print shift(@tab); # affiche 'Larry' et # @tab = ('WALL', '24') print pop(@tab); # affiche '24' et # @tab = ('WALL') ______________________________________________________________________ 22..33..22..22.. ssoorrtt,, rreevveerrssee,, sspplliitt,, jjooiinn La commande sort trie les éléments d'une table et retourne la liste triée. ______________________________________________________________________ @tab = ('b', 'w', 'a', 't'); @tab = sort @tab; # @tab = ('a', 'b', 't', 'w') ______________________________________________________________________ La commande reverse retourne la liste des éléments dans l'ordre inversé. ______________________________________________________________________ @tab = reverse @tab; # @tab = ('w', 't', 'b', 'a') ______________________________________________________________________ split permet de découper une chaîne de caractères. C'est une fonction puissante car c'est l'utilisateur qui spécifie quel caractère ou quelle expression régulière (voir chapitre sur les expressions régulières) permet de délimiter les éléments à découper. La commande retourne une liste contenant les éléments de la chaîne découpée. ______________________________________________________________________ @tab = split(/\+/, "1 + 2 + 3"); # @tab vaut (1, 2, 3) ______________________________________________________________________ Ici le caractère de séparation est +. Si on avait voulu découper une chaîne contenant des + et des - on aurait utilisé l'expression régulière suivante : /+|-/ qui veut dire "+ ou -". join regroupe les éléments d'une table dans une chaîne de caractères en les séparant par la chaîne de caractères donnée en argument. La chaîne de caractères peut être annotée comme une expression régulière ou entre guillements. ______________________________________________________________________ print join(/ - /, @tab); # affiche '1 - 2 - 3'; print join(" - ", @tab); # idem ______________________________________________________________________ 22..44.. LLaa ttaabbllee ddee hhaasshh 22..44..11.. IInnttrroodduuccttiioonn Une fonction de hash permet de calculer une clé (unique si possible) à partir d'une chaîne de caractères. La clé de valeur entière permet d'indexer une table par la suite. Cette technique est appelée _H_a_s_h _c_o_d_i_n_g. Son avantage est qu'elle diminue considérablement le nombre de tentatives lors d'une recherche dans une table. Une table de hash est une liste dont chaque élément est un couple de la forme (nom, valeur). _n_o_m est une chaîne de caractères (ex: "123", "coucou", etc...) dont Perl extrait (par une fonction de hash) une clé. Cette fonction est invisible pour le programmeur. Donc à l'indice correspondant à la clé de nom on trouve l'élément valeur. Une table de hash est en général utilisée pour construire une structure de données. Dorénavant, et par abus de langage, je dirais que nom est la clé. RReemmaarrqquuee:: awk (gawk) fournit également ce mécanisme. 22..44..22.. DDeessccrriippttiioonn La forme générale d'une table de hash est: ______________________________________________________________________ %hash = ( cle1, val1, cle2, val2, ..., cleN, valN); %hash = (nom, WALL, prenom, Larry); ______________________________________________________________________ L'exemple montre une table avec deux éléments. La valeur associée à la clé prenom est Larry. De même la valeur associée à la clé nom est WALL. Cette notation est maintenant obsolète et peu lisible. Une nouvelle écriture permet de ne pas confondre la table de hash avec une liste. ______________________________________________________________________ %hash = ( 'nom' => 'Larry', 'prenom' => 'WALL', ); $hash{'nom'} # Larry $hash{nom} # Larry $hash{prenom} # WALL ______________________________________________________________________ On remarque que lorsque la clé est constituée d'un seul mot il n'est pas nécessaire de la mettre entre apostrophes (ou _q_u_o_t_e_s). 22..44..33.. FFoonnccttiioonnss uussuueelllleess Les exemples des fonctions que nous allons décrire seront basés sur la table de hash suivante: ______________________________________________________________________ %hash = ( 'nom' => 'FORCIOLI', 'prenom' => 'Alain', 'age' => '24', ); ______________________________________________________________________ 22..44..33..11.. kkeeyyss,, vvaalluueess keys retourne une liste (table) contenant les clés de la table de hash. ______________________________________________________________________ @k = keys %hash; # @k = ('nom', 'prenom', 'age') ______________________________________________________________________ RReemmaarrqquuee:: les clés sont des valeurs entières. Supposons que Alain et Bob soient deux noms dont les clés sont 30 et 20. On s'aperçoit que l'ordonnancement croissant des clés (20 puis 30) ne correspond pas à l'ordonnancement alphabétique des noms (Alain puis Bob). Aussi nous supposerons que la liste (nom, prenom, age) est la liste des noms (clés) retournée par keys. Sachant que keys retourne une liste, il est facile de l'avoir de manière ordonnée avec la fonction sort. ______________________________________________________________________ @k = sort keys %hash; # @k = ('age', 'nom', 'prenom') ______________________________________________________________________ values à l'inverse de keys retourne une liste de toutes les valeurs des clés. L'obtention d'une telle liste ordonnée se fait de cette manière. ______________________________________________________________________ @v = sort values %hash; # @v = ('24', 'Alain', 'FORCIOLI') ______________________________________________________________________ 22..44..33..22.. eeaacchh,, ddeelleettee,, eexxiissttss each retourne le premier couple de la table de hash sous la forme d'une liste. Le couple est ensuite supprimé de la table de hash. ______________________________________________________________________ ($nom, $val) = each %hash; # $nom = 'nom' # $val = 'FORCIOLI' # keys %hash = ('prenom', 'age') ______________________________________________________________________ delete supprime la valeur associée à la clé donnée en argument. ______________________________________________________________________ delete $hash{'age'}; # keys %hash = ('prenom') ______________________________________________________________________ exists retourne 1 (vrai) si une valeur existe pour une clé donnée. ______________________________________________________________________ print "Exists\n" if exists $hash{'prenom'}; # affiche # 'Exists\n' ______________________________________________________________________ 33.. LLeess vvaarriiaabblleess ssppéécciiaalleess (se reporter à la section _p_e_r_l_v_a_r du manuel de Perl) Perl gère un ensemble de variables globales. En voici quelques exemples. ______________________________________________________________________ $/; # Le caractère séparateur de ligne # '\n' par defaut. $_; # le contenu de l'entrée standard ou la valeur de # chaque élément d'une table dans une boucle foreach # ou while. @_; # un tableau contenant les arguments d'une fonction; %ENV; # une table de hash qui contient les variables # d'environnement du shell. # Equivalent a la commande 'env'. @ARGV; # une table des arguments du script Perl. ______________________________________________________________________ 44.. LLeess ssttrruuccttuurreess ddee ccoonnttrrôôllee Comme tout langage de programmation, Perl dispose de structures de contrôle. 44..11.. iiff,, eellssee,, eellsseeiiff ______________________________________________________________________ if(expr) { block1 } else { block2 } ______________________________________________________________________ ou ______________________________________________________________________ if(expr) { block1 } elseif(expr2) { block2 } ______________________________________________________________________ Dans les deux cas block1 est exécuté si l'évaluation de _e_x_p_r retourne une valeur positive. Dans le premier exemple, block2 est exécuté dans tous les autres cas. Dans le second, block2 est évalué seulement si _e_x_p_r_2 retourne une valeur positive. Plusieurs elseif peuvent être enchaênés. ______________________________________________________________________ if($a == "a") { print "$a\n"; } elseif($a == "b") { print "$a$a\n"; } elseif($a == "c") { print "$a$a$a\n"; } ... ______________________________________________________________________ 44..22.. ffoorreeaacchh,, wwhhiillee ______________________________________________________________________ foreach (table) { block; } while(expr) { block; } ______________________________________________________________________ La structure de contrôle foreach permet d'executer block autant de fois qu'il y a d'éléments dans table. ______________________________________________________________________ @tab = (1, 2, 3, 4, 5); $i = 0; foreach (@tab) { print "$i\n"; $i++; } ______________________________________________________________________ L'exemple ci-dessus affiche successivement les valeurs 0, 1, 2, 3 et 4. Nous avons vu dans la section Les variables speciales que la variable $_ prenait la valeur de chaque élément d'une table passée dans une boucle foreach ou while. Illustrons cette particularité en simplifiant l'exemple précédent. ______________________________________________________________________ @tab = (1, 2, 3, 4, 5); foreach (@tab) { print "$_\n"; } ______________________________________________________________________ Cette fois, l'exemple affiche 1, 2, 3, 4 et 5. $_ prend successivement chaque valeur des éléments de \@tab. Encore plus simple : ______________________________________________________________________ foreach (1 .. 5) { print "$_\n"; } ______________________________________________________________________ (1 .. 5) est un intervalle en Perl. ______________________________________________________________________ @tab = (1, 2, 3, 4, 5); while($i = shift(@tab)) { print "$i\n"; } ______________________________________________________________________ shift retourne le premier élément de la table @tab et le supprime. Ainsi $i prend successivement les valeurs 1, 2, 3, 4 et 5. La boucle s'arrête lorsque $i est vide c'est à dire lorsqu'il n'y a plus d'éléments dans @tab. 44..33.. PPrréésseennttaattiioonn dduu ccooddee Perl dispose de quelques artifices permettant de rendre plus lisible le code écrit. ______________________________________________________________________ print $value if $value; ______________________________________________________________________ Le contenu de $value est affiché si la variable est définie. Cela évite d'avoir ______________________________________________________________________ if($value) { print $value; } ______________________________________________________________________ De même: ______________________________________________________________________ print $value unless ! $value; ______________________________________________________________________ Littéralement, on affiche la valeur de $value A MOINS QUE la variable ne soit pas définie (! est l'opérateur non). Pour être encore mieux compris d'un humain, on aurait pu écrire: ______________________________________________________________________ print $value unless ! defined $value; ______________________________________________________________________ De la même manière, on peut aussi utiliser while. ______________________________________________________________________ print "/tmp/lock: exists\n" while -f "/tmp/lock"; ______________________________________________________________________ 55.. LLeess ffoonnccttiioonnss 55..11.. PPrréésseennttaattiioonn La structure générale d'une fonction est: ______________________________________________________________________ sub fonction { # block } ______________________________________________________________________ block est le corps de la fonction, c'est à dire les actions à exécuter. Chaque action est séparée d'une autre par écrit. Tout ce qui suit ce caractère jusqu'au prochain retour à la ligne n'est pas interprété. 55..22.. CCrrééaattiioonn dd''uunnee ffoonnccttiioonn ______________________________________________________________________ sub hello { print "Hello World !\n"; } hello(); # affiche 'Hello World !\n' hello; # idem &hello; # idem do hello; # idem ______________________________________________________________________ L'exemple précédent nous montre comment créer une fonction et comment l'exécuter de quatre manières différentes. 55..33.. VVaalleeuurr ddee rreettoouurr dd''uunnee ffoonnccttiioonn ______________________________________________________________________ sub true { return 1; } $t = true; # $t vaut 1; $t = true(); # idem ______________________________________________________________________ La fonction suivante est équivalente: ______________________________________________________________________ sub true { 1; } $t = true; # $t vaut 1 ______________________________________________________________________ Les deux exemples ci-dessus sont équivalents. En fait Perl retourne la valeur de la dernière expression de la fonction exécutée. Cette valeur n'est pas seulement entière. Il est possible de retourner des tables ou des tables de hash. ______________________________________________________________________ sub foo { ... ... @tab = (1, 2, 3); return @tab; # ou return (1, 2, 3); } sub bar { ... ... %hash = ( 'i' => 1, 'ii' => 2, ); %hash; } ______________________________________________________________________ Losque _r_e_t_u_r_n est manquant, la valeur de la dernière expression est retournée. 55..44.. AArrgguummeennttss dd''uunnee ffoonnccttiioonn Les arguments d'une fonction se présentent sous la forme d'une table. Elle est notée @_. Donc: ______________________________________________________________________ $_[0]; # premier argument. $_[$#_]; # dernier argument : # $#_ est le dernier indice dans le tableau ______________________________________________________________________ Bien souvent on connait à l'avance le nombre d'arguments d'une fonction. Aussi on privilégiera l'usage de @_ à $_[0], etc. ______________________________________________________________________ sub sum { $sum = 0; foreach (@_) # parcours de tous les arguments { $sum += $_; } $sum; } sum(10, 20, 30, "40"); # retourne 100 ______________________________________________________________________ RRaappppeell:: Perl fait les conversions implicitement. ______________________________________________________________________ sub hello { ($nom, $prenom) = @_; print "Hello $nom $prenom\n"; } hello("FORCIOLI", "Alain"); # affiche 'Hello FORCIOLI Alain\n' ______________________________________________________________________ Cet usage est préférable car il évite une ligne complexe du genre: ______________________________________________________________________ ($nom, $prenom) = ($_[0], $_[1]); ______________________________________________________________________ 55..55.. VVaarriiaabblleess llooccaalleess Il existe deux fonctions qui permettent de rendre locale une variable. ______________________________________________________________________ $a = "a"; { local($a) = "b"; # $a est locale au 'scope' # (par exemple: {...}) print "$a\n"; # affiche 'b\n' } print "$a\n"; # affiche 'a\n' ______________________________________________________________________ L'exemple précédent montre que les variables $a ont des valeurs différentes. La seconde déclaration (utilisant local() pour définir $a) rend $a visible uniquement à l'intérieur des crochets. Nous avons deux espaces de noms en notre présence. Dans le premier nous avons $a valant a, dans le second nous avons $a égale à b. Le manuel (section _p_e_r_l_f_u_n_c) préconise tout de même l'emploi de my(), qui apparemment donne un sens plus fort au terme _l_o_c_a_l_e. En effet dans un contexte orienté objet ou de module, une variable déclarée avec local, est connue de tout le _s_c_o_p_e (_s_c_o_p_e : espace de nommage, compris entre crochets) de module ou de la classe. Tandis qu'une variable déclarée avec my est connue uniquement à l'intérieur du scope ou elle est définie. 66.. LLeess eexxpprreessssiioonnss rréégguulliièèrreess ddee PPeerrll ((EE..RR..)) (Voir la section _p_e_r_l_r_e du manuel de Perl) 66..11.. DDeessccrriippttiioonn Les expressions régulières sont des caractères permettant de coder n'importe quelle entité écrite appartenant à un ensemble (ex: les décimales, les majuscules, les mots commencant par _z ou une minuscule, etc...). Elles sont largement utilisées par les développeurs UNIX et sont implémentées dans des commandes telles que awk, sed, ed, vi. Même le langage C dispose d'une librairie d'expressions régulières. Le principe de ces caractères est de construire un masque codant l'entité cible. Ensuite chaque séquence de caractères est comparée au masque. S'il y a correspondance, la séquence appartient à l'ensemble de l'entité. Ce mécanisme permet de faire des remplacements de chaînes de caractères dans un fichier sans savoir ou sont placées les chaînes à remplacer. Il permet d'extraire des informations sans en connaître la position dans un ou plusieurs fichiers. C'est de loin le meilleur outil d'extraction et de traitement d'informations dans un fichier et c'est pourquoi Perl l'utilise. Illustrons l'usage des expressions en codant l'ensemble de tous les mots à caractères minuscules. ______________________________________________________________________ [a-z] ______________________________________________________________________ [ ] permet de définir un ensemble de caractères. Le caractère - signifie que l'ensemble contient la lettre a, b, c, ... ou z. On aurait pu écrire: ______________________________________________________________________ [abcdefghijklmnopqrstuvwxyz] ______________________________________________________________________ _a_l_a_i_n appartient appartient à l'ensemble des mots composés de lettres minuscules. Par contre _A_l_a_i_n non, car le mot contient A. De manière générale une E.R. est préfixée et suffixée du caractère /. ______________________________________________________________________ /[a-z]/ ______________________________________________________________________ Voici une rapide description de quelques caractères d'expression régulières. ______________________________________________________________________ . # n'importe quel caractère alphanumérique et # d'espacement. + # fait correspondre au moins 1 fois ou plusieurs ce # qui précède ? # 0 ou au plus 1 caractère de ce qui précède # a? permet de faire correspondre '' ou 'a' * # 0 ou plusieurs caractères de ce qui précède # a* peut faire correspondre '', 'a', 'aa', 'aaa', etc... [] # un intervalle [^] # un complément ^ # qui commence par $ # qui finit par () # Définit un groupe de caractères réutilisable | # ou ______________________________________________________________________ Perl étend le jeu de caractères des expressions. ______________________________________________________________________ \s # n'importe quel caractère d'espacements \S # le complément de \s ______________________________________________________________________ Perl permet de modifier le traitement des chaînes par des options, en passant une ou plusieurs lettres après le / final de l'E.R : ______________________________________________________________________ i # les majuscules sont traitées comme des minuscules m # traite la chaine de caractères commes si elle était # constituée de plusieurs lignes s # traite la chaine comme si elle était sur une seule # ligne ______________________________________________________________________ Deux opérations sont principalement utilisées par les expressions régulières. La substitution et le _p_a_t_t_e_r_n _m_a_t_c_h_i_n_g (la mise en correspondance). ______________________________________________________________________ s/source/target/options ______________________________________________________________________ s signifie substitution. / est le séparateur d'expression. Si une chaîne lue correspond à _s_o_u_r_c_e elle est remplacée par _t_a_r_g_e_t. _o_p_t_i_o_n_s agit sur le nombre de substitutions. Si g est utilisé alors toutes les chaînes de la ligne lue correspondant à _s_o_u_r_c_e sont remplacées (g pour global). e permet d'évaluer _t_a_r_g_e_t. Ainsi pour convertir un fichier texte en un fichier ne comportant que des majuscules on aurait le code suivant (fichier uc.pl): ______________________________________________________________________ #! /usr/bin/perl while(<>) { s/^(.*)$/uc($1)/e; $_; } ______________________________________________________________________ On peut tester cette opération de la façon suivante: ______________________________________________________________________ $ uc.pl /etc/passwd ______________________________________________________________________ Le fichier /etc/passwd s'affiche avec uniquement des caractères majuscules. RReemmaarrqquuee:: la première ligne #! /usr/bin/perl permet de spécifier au shell quelle commande il doit lancer pour interpréter le contenu du fichier uc.pl. .pl est le suffixe standard des fichier scripts Perl. 66..22.. EExxeemmppllee:: wwcc..ppll Le programme wc.pl suivant effectue le meme travail que la commande unix, à savoir comptabiliser le nombre de caractères, de lignes et de mots d'un fichier donné en argument (fichier wc.pl): ______________________________________________________________________ #! /usr/bin/perl # Retourne le nombre de mots dans une ligne par mot on comprendra tous # ce qui n'est pas 'espace'. sub compte_mot { my($ligne) = @_; $ligne =~ s/\s+/ /g; my(@tab) = split( /\s/, $ligne); $#tab; } sub compte_ligne { my($ligne) = @_; return 1 if $ligne !~ /^\s*$/; } sub compte_char { my($ligne) = @_; $ligne =~ s/\s//g; length($ligne); } sub main { my($mots, $lignes, $chars); while() { $mots += compte_mot($_); $chars += compte_char($_); $lignes ++ if compte_ligne($_); } print "$ARGV[0]: w = $mots, l = $lignes, c = $chars\n"; } main; ______________________________________________________________________ Exemple d'utilisation : ______________________________________________________________________ $ wc.pl /etc/passwd ______________________________________________________________________ Remarque: (equivalent à <>) est le flux de l'entrée standard. et ceux de la sortie standard et d'erreur. 77.. LLeess rrééfféérreenncceess 77..11.. DDeessccrriippttiioonn La référence Perl peut être vue comme le pointeur du langage C. C'est une variable qui en référence une autre. Pour annoter la référence sur la variable scalaire contenant la valeur 1, nous écrirons: ______________________________________________________________________ $i = 1; # i est une var. scalaire et vaut 1 $scalar_ref = \$i; # scalar_ref référence i. ______________________________________________________________________ Pour accéder au contenu pointé par la référence, il faut la déréférencer. Perl utilise l'opérateur -> pour déréférencer une référence. Pour accéder à la valeur de la variable pointée il faut aussi la déréférencer. De même qu'avec le langage C, une référence peut _p_o_i_n_t_e_r une autre référence et ainsi de suite. Il faudra donc déréférencer autant de fois que nécéssaire pour obtenir la valeur. Le valeur pointée peut être modifiée en manipulant la référence. ______________________________________________________________________ int i = 3; int *ref_i = &i; *(ref_i) ++; printf("i = %d\n", i); $i = 3; $ref_i = \$i; $ref_i ++; print $i, "\n"; ______________________________________________________________________ 77..22.. RRééfféérreennccee ssuurr uunn ttaabblleeaauu La référence d'une table peut être cre de plusieurs façons: ______________________________________________________________________ @tab = (1, 2, 3); $ref = \@tab; ______________________________________________________________________ ou ______________________________________________________________________ $ref = [1, 2, 3]; ______________________________________________________________________ Pour déréférencer la table, il faut la préfixer du caractère qui désigne la table en Perl : @ ______________________________________________________________________ @tab1 = @$ref; ______________________________________________________________________ Pour parcourir les éléments de la table on peut écrire: ______________________________________________________________________ foreach (@$ref) { # $_ contient successivement 1, 2 et 3 } ______________________________________________________________________ On peut directement accéder à un élément contenu dans la table pointée. ______________________________________________________________________ $ref->[0]; # vaut 1 $ref->[1]; # vaut 2 ______________________________________________________________________ Pour obtenir le nombre d'éléments pointés : ______________________________________________________________________ $#{@$ref}; | ----- | | | retourne la table et non une référence | (1, 2, 3) | | permet d'obtenir le nombre d'éléments d'une table. ______________________________________________________________________ L'expression précédente est équivalente à: ______________________________________________________________________ $#(1, 2, 3); ______________________________________________________________________ 77..33.. RRééfféérreennccee ssuurr uunnee ttaabbllee ddee hhaasshh De même qu'avec la table il existe divers moyens de créer une référence sur une table de hash. ______________________________________________________________________ %hash = ( 'un' => 1, 'deux' => 2, 'trois' => 3, ); $ref = \%hash; ______________________________________________________________________ ou ______________________________________________________________________ $ref = { 'un' => 1, 'deux' => 2, 'trois' => 3, }; ______________________________________________________________________ Pour déréférencer la référence il faut utiliser le caractère qui désigne la table de hash : %. ______________________________________________________________________ %hash = %$ref; ______________________________________________________________________ Le parcours d'une telle référence peut se faire de la manière suivante: ______________________________________________________________________ foreach $k (sort keys %$ref) { # $k vaut 'deux', 'trois' puis 'un' } foreach $v (sort values %$ref) { # $v vaut 1, 2 et 3 } ______________________________________________________________________ On peut modifier un élément pointé comme ceci: ______________________________________________________________________ $ref->{'un'} = 'UN'; ______________________________________________________________________ On peut étendre une table de hash référencée. ______________________________________________________________________ $ref->{'quatre'} = 100; ______________________________________________________________________ On peut effacer un élément référencé: ______________________________________________________________________ delete $ref->{'un'}; ______________________________________________________________________ 77..44.. RRééfféérreennccee ssuurr uunnee ffoonnccttiioonn Cette particularité est appréciable car elle permet entre autres de faire de manière très simple de la génération de code dynamique. Une référence sur une fonction s'écrit: ______________________________________________________________________ $func = sub { # code de la fonction }; ______________________________________________________________________ Pour utiliser la fonction il faut la préfixer du caractère qui désigne (historiquement) la fonction : \&. ______________________________________________________________________ &$func(); # lance la fonction ______________________________________________________________________ 77..55.. EExxtteennssiioonn:: ssttrruuccttuurree ddee ddoonnnnééeess ccoommpplleexxeess Le référencement/déréférencement permet à Perl de pouvoir créer des structures de données complexes. ______________________________________________________________________ $a = [1, 2, 3]; $b = [ $a, { 'un'=>1, 'deux'=>2, }, ]; ______________________________________________________________________ $a référence la table (1, 2, 3). $b est une référence sur une table qui contient deux éléments: $a et une référence sur une table de hash ('un', 1, 'deux', 2). ______________________________________________________________________ $b->[0]; # vaut $a @{$b->[0]}; # vaut (1, 2, 3) ${@{$b->[0]}}[0]; # vaut 1 $b->[0]->[0]; # idem $b->[1]; # une référence sur une table de hash $b->[1]->{'un'}; # vaut 1 sort keys %{$b->[1]}; # vaut ('deux', 'un') ______________________________________________________________________ On imagine très bien les immenses possibilités d'un tel mécanisme. C'est d'ailleurs par ce biais que Perl permet de faire de la programmation orientée objet. 88.. RReemmeerrcciieemmeennttss Merci à : BBeennjjaammiinn DDRRIIEEUU < pour la mise en page du document, CChhaarrlliiee SSIIEERRRRAA <, Tony BASSETTE et Valérie GERAUX pour les diverses remarques et corrections apportées au document. 99.. CCooppyyrriigghhtt Le langage Perl Copyright © 1998 Alain FORCIOLI This document is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This work is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this work; see the file COPYING. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.