Vous êtes sur la page 1sur 1078

customer_8566

Programmation
en PERL

I l y a p l u s d u n e fa o n d e fa i re

Traduction de Philippe Bruhat, Kai Carver et Grald Sdrati

De Larry Wall, Tom Christiansen et Jon Orwant

customer_8566

A Maymak, GDGN, le philosophe de la Npalawi et Larabs


Pirate de Bard

customer_8566

Programmation en Perl

customer_8566

LARRY WALL, TOM CHRISTIANSEN et JON ORWANT

Programmation en Perl
Traduction de Philippe Bruhat, Kai Carver et Grald Sdrati

Digit Books diteur de livres numriques Brest infos@digitbooks.fr http://www.digitbooks.fr

customer_8566

Digit Books, 2009, pour la traduction franaise ISBN : 978-2-8150-0172-4 Prix : 35

OReilly Media , 2005 Ldition originale de ce livre a t publie aux tats-Unis par OReilly Media sous le titre Programming Perl, 3rd edition, ISBN 0-596-00027-.

Couverture : Yves Buraud Illustration de Ptit-Bonhomme de Jules Verne (1893) par Lon Benett.

http://www.digitbooks.fr/catalogue/9782815001724.html

Les programmes figurant dans ce livre ont pour but dillustrer les sujets traits. Il nest donn aucune garantie quant leur fonctionnement une fois compils, assembls ou interprts dans le cadre dune utilisation professionnelle ou commerciale.

Toute reprsentation ou reproduction, intgrale ou partielle, faite sans le consentement de lauteur, de ses ayants droit, ou ayants cause, est illicite (loi du 11 mars 1957, alina 1er de larticle 40). Cette reprsentation ou reproduction, par quelque procd que ce soit, constituerait une contrefaon sanctionne par les articles 425 et suivants du Code pnal. La loi du 11 mars 1957 autorise uniquement, aux termes des alinas 2 et 3 de larticle 41, les copies ou reproductions strictement rserves lusage priv du copiste et non destines une utilisation collective dune part et, dautre part, les analyses et les courtes citations dans un but dexemple et dillustration.

customer_8566

customer_8566

Table des matires

Prface ..................................................................................... xiii

I.
1.

SURVOL DE PERL ...................................................... 1


Vue densemble .................................................................... 3
Dmarrage ................................................................................................. 3 Langages naturels et artificiels ................................................................. 4 Un exemple de notation ......................................................................... 14 Handles de fichiers .................................................................................. 17 Oprateurs ................................................................................................ 19 Structures de contrle ............................................................................. 25 Expressions rgulires ............................................................................. 30 Traitement des listes ................................................................................ 36 Ce que vous ne savez pas ne vous fera pas (trop) de mal ..................... 38

II. SANCE DE DISSECTION ........................................... 39


2. Composants de Perl .......................................................... 41
Atomes ..................................................................................................... Molcules ................................................................................................. Types internes .......................................................................................... Variables ................................................................................................... Noms ........................................................................................................ Valeurs scalaires ...................................................................................... Contexte ................................................................................................... Valeur de liste et tableaux ...................................................................... Hachages .................................................................................................. 41 42 43 45 46 50 59 62 65

customer_8566

Table des matires

vi

Typeglobs et handles de fichiers ............................................................. 67 Oprateurs dentre ................................................................................. 68

3.

Oprateurs unaires et binaires ........................................ 75


Termes et oprateurs de listes (vers la gauche) ..................................... Loprateur flche ................................................................................... Auto-incrmentation et autodcrmentation ...................................... Exponentiation ........................................................................................ Oprateurs unaires idographiques ....................................................... Oprateurs de liaison .............................................................................. Oprateurs multiplicatifs ........................................................................ Oprateurs additifs .................................................................................. Oprateurs de dcalage ........................................................................... Oprateurs unaires nomms et de test de fichier ................................. Oprateurs relationnels .......................................................................... Oprateurs dgalit ................................................................................ Oprateurs sur les bits ............................................................................. Oprateurs logique de type C ( court-circuit) ..................................... Oprateur dintervalle ............................................................................. Oprateur conditionnel .......................................................................... Oprateurs daffectation ......................................................................... Oprateurs virgule ................................................................................... Oprateurs de liste (vers la droite) ......................................................... And, or, not et xor logiques .................................................................... Oprateurs C manquant en Perl ............................................................ 77 79 79 80 80 81 82 83 83 83 87 88 88 89 90 91 93 94 95 95 96

4.

Instructions et dclarations .............................................. 97


Instructions simples ................................................................................ 97 Instructions composes ........................................................................... 99 Instructions if et unless ......................................................................... 100 Instructions de boucle ........................................................................... 101 Blocs simples .......................................................................................... 108 goto ......................................................................................................... 111 Dclarations globales ............................................................................ 112 Dclarations avec porte ....................................................................... 114 Pragmas .................................................................................................. 120

5.

Recherche de motif ......................................................... 123


Bestiaire des expressions rgulires ..................................................... Oprateurs de recherche de motifs ...................................................... Mtacaractres et mtasymboles .......................................................... Classes de caractres .............................................................................. 124 126 141 148

customer_8566

Table des matires

vii

Quantificateurs ...................................................................................... Positions ................................................................................................. Capture et regroupement ..................................................................... Alternative ............................................................................................. Garder le contrle ................................................................................. Motifs tendus .......................................................................................

158 161 164 168 170 183

6.

Sous-programmes ............................................................ 197


Syntaxe ................................................................................................... Smantique ............................................................................................ Passage de rfrences ............................................................................. Prototypes .............................................................................................. Attributs de sous-programmes ............................................................. 197 199 203 205 210

7.

Formats ............................................................................ 213


Variables de format ............................................................................... 216 Pieds de page .......................................................................................... 218

8.

Rfrences ........................................................................ 221


Quest-ce quune rfrence ? ................................................................. Cration de rfrences .......................................................................... Utilisation des rfrences en dur .......................................................... Rfrences symboliques ........................................................................ Accolades, crochets et guillemets ......................................................... 221 223 229 241 242

9.

Structures de donnes ..................................................... 245


Tableaux de tableaux ............................................................................ Hachages de tableaux ............................................................................ Tableaux de hachages ............................................................................ Hachages de hachages ........................................................................... Hachages de fonctions .......................................................................... Enregistrements plus labors .............................................................. Sauvegarde de structures de donnes .................................................. 245 252 254 255 259 259 262

10. Paquetages ...................................................................... 265


Tables de symboles ................................................................................ 269 Autochargement .................................................................................... 273

11. Modules ............................................................................ 275


Utilisation des modules ........................................................................ 275 Cration de modules ............................................................................. 277 Supplanter des fonctions internes ....................................................... 281

customer_8566

Table des matires

viii

12. Objets ............................................................................... 283


Bref rappel de vocabulaire orient objet ............................................. Le systme objet de Perl ....................................................................... Invocation de mthode ......................................................................... Construction dobjet ............................................................................. Hritage de classe .................................................................................. Destructeurs dinstance ......................................................................... Gestion des donnes dinstance ........................................................... Gestion des donnes de classe .............................................................. Rsum ................................................................................................... 283 285 285 291 295 303 304 315 318

13. Surcharge ......................................................................... 319


Le pragma overload .............................................................................. Handlers de surcharge .......................................................................... Oprateurs surchargeables .................................................................... Le constructeur de copie (=) ................................................................. Lorsquun handler de surcharge fait dfaut (nomethod et fallback) Surcharge de constantes ........................................................................ Fonctions publiques de surcharge ....................................................... Hritage et surcharge ............................................................................ Surcharge lexcution ......................................................................... Surcharge de diagnostics ....................................................................... 320 320 322 328 329 330 332 332 333 333

14. Variables lies ................................................................. 335


Liaison de scalaire .................................................................................. Liaison de tableau ................................................................................. Liaison de hachage ................................................................................ Liaison de handle de fichier ................................................................. Un pige subtil du dliement ............................................................... Modules de liaison sur CPAN .............................................................. 337 344 349 355 366 368

III. TECHNIQUE PERL ................................................. 371


15. Unicode ............................................................................ 373
Construction dun caractre ................................................................. 374 Consquences de la smantique de caractre ..................................... 376 Attention au travail .............................................................................. 380

16. Communication interprocessus ...................................... 383


Signaux ................................................................................................... 384 Fichiers ................................................................................................... 390

customer_8566

Table des matires

ix

Pipes ....................................................................................................... 397 IPC System V ......................................................................................... 405 Sockets .................................................................................................... 409

17. Threads ............................................................................ 417


Le modle de processus ......................................................................... 418 Le modle de thread .............................................................................. 419

18. Compilation ..................................................................... 435


Cycle de vie dun programme Perl ...................................................... Compilation du code ............................................................................ Excution du code ................................................................................. Sorties du compilateur .......................................................................... Gnrateurs de code .............................................................................. Outils de dveloppement de code ........................................................ Compilateur davant-garde, interprteur rtro .................................. 436 437 443 446 447 449 450

19. Linterface de la ligne de commande ............................. 455


Traitement des commandes ................................................................. 455 Variables denvironnement .................................................................. 471

20. Le dbogueur Perl ........................................................... 475


Utilisation du dbogueur ..................................................................... Commandes du dbogueur .................................................................. Personnalisation du dbogueur ........................................................... Implmentation du dbogueur ........................................................... Le profileur Perl .................................................................................... 476 478 487 492 494

21. Mcanismes internes et accs externes .......................... 499


Comment fonctionne Perl ................................................................... Types de donnes internes .................................................................... tendre Perl (utiliser du C depuis du Perl) ......................................... Insrer Perl (utiliser Perl depuis C) ..................................................... Morale de lhistoire ............................................................................... 500 500 501 507 512

IV. CULTURE PERL ..................................................... 513


22. CPAN ............................................................................... 515
Le rpertoire modules de CPAN .......................................................... 516 Utilisation des modules de CPAN ....................................................... 520 Cration de modules pour CPAN ........................................................ 522

customer_8566

Table des matires

23. Scurit ............................................................................ 525


Gestion des donnes non sres ............................................................ 526 Gestion des problmes de synchronisation ......................................... 536 Gestion du code non sr ....................................................................... 543

24. Techniques couramment employes .............................. 553


tourderies courantes des dbutants ................................................... Erreurs universelles ............................................................................... Efficacit ................................................................................................. Programmation style ........................................................................... Perl avec aisance .................................................................................... Gnrer des programmes ...................................................................... 553 554 561 569 573 582

25. Portabilit ...................................................................... 587


Sauts de ligne ......................................................................................... Boutisme et taille des nombres ............................................................ Fichiers et systmes de fichiers ............................................................. Interactions avec le systme ................................................................. Communication interprocessus (IPC) ................................................. Sous-programmes externes (XS) ........................................................... Modules standard .................................................................................. Dates et heures ...................................................................................... Internationalisation .............................................................................. Style ........................................................................................................ 588 589 590 591 592 592 592 593 593 594

26. POD ................................................................................. 595


Pod en quelques mots ........................................................................... Traducteurs et modules pod ................................................................. crire vos propres outils pod ................................................................ Piges du pod ......................................................................................... Documenter vos programmes Perl ...................................................... 595 603 605 608 609

27. Culture Perl ..................................................................... 611


Lhistoire en pratique ............................................................................ 611 Posie en Perl ........................................................................................ 613

V. RFRENCES ......................................................... 617


28. Noms spciaux ................................................................. 619
Noms spciaux classs par type ............................................................ 619 Variables spciales dans lordre alphabtique .................................... 622

customer_8566

Table des matires

xi

29. Fonctions ......................................................................... 643


Fonctions Perl par catgorie ................................................................. 646 Fonctions Perl par ordre alphabtique ................................................ 647

30. La bibliothque standard Perl ....................................... 787


Bibliothquologie .................................................................................. 787 Visite guide de la bibliothque Perl ................................................... 789

31. Modules de pragmas ....................................................... 791


use attributes .......................................................................................... use autouse ............................................................................................. use base ................................................................................................... use blib ................................................................................................... use bytes ................................................................................................. use charnames ....................................................................................... use constant ........................................................................................... use diagnostics ....................................................................................... use fields ................................................................................................. use filetest ............................................................................................... use integer .............................................................................................. use less .................................................................................................... use lib ..................................................................................................... use locale ................................................................................................ use open ................................................................................................. use overload ........................................................................................... use re ...................................................................................................... use sigtrap .............................................................................................. use strict ................................................................................................. use subs ................................................................................................... use vars ................................................................................................... use warnings .......................................................................................... 792 793 794 795 795 795 796 798 800 803 803 804 804 806 807 807 808 809 812 814 814 815

32. Modules standards .......................................................... 819


Listes par type ........................................................................................ Benchmark ............................................................................................. Carp ........................................................................................................ CGI ......................................................................................................... CGI::Carp ............................................................................................... Class::Struct ............................................................................................ Config ..................................................................................................... CPAN ..................................................................................................... Cwd ......................................................................................................... Data::Dumper ........................................................................................ 819 831 833 833 834 835 836 836 837 837

customer_8566

xii

Table des matires

DB_File .................................................................................................. Dumpvalue ............................................................................................ English .................................................................................................... Errno ...................................................................................................... Exporter .................................................................................................. Fatal ........................................................................................................ Fcntl ........................................................................................................ File::Basename ....................................................................................... File::Compare ........................................................................................ File::Copy ............................................................................................... File::Find ................................................................................................ File::Glob ................................................................................................ File::Spec ................................................................................................ File::stat .................................................................................................. File::Temp .............................................................................................. FileHandle ............................................................................................. Getopt::Long .......................................................................................... Getopt::Std ............................................................................................. IO::Socket ............................................................................................... IPC::Open2 ............................................................................................. IPC::Open3 ............................................................................................. Math::BigInt ........................................................................................... Math::Complex ...................................................................................... Math::Trig .............................................................................................. Net::hostent ........................................................................................... POSIX ..................................................................................................... Safe ......................................................................................................... Socket ..................................................................................................... Symbol ................................................................................................... Sys::Hostname ....................................................................................... Sys::Syslog .............................................................................................. Term::Cap .............................................................................................. Text::Wrap ............................................................................................. Time::Local ............................................................................................ Time::localtime ...................................................................................... User::grent .............................................................................................. User::pwent ............................................................................................

838 839 840 840 841 842 842 843 843 844 845 845 848 849 849 850 853 854 854 855 856 857 857 858 858 859 861 862 863 864 864 866 866 867 868 868 869

33. Messages de diagnostic .................................................... 871 Glossaire ................................................................................... 947 Index ......................................................................................... 981

customer_8566

Prface

la poursuite du bonheur
Perl est un langage qui vous aide faire votre travail. Bien sr, si votre travail consiste programmer, vous pouvez le faire avec nimporte quel langage informatique complet , du moins en thorie. Mais nous savons par exprience que les langages informatiques ne diffrent pas tant par ce quils rendent possible que par ce quils rendent facile. Dun ct, les langages soi-disants de quatrime gnration facilitent certaines tches, mais en rendent dautres quasiment impossibles. De lautre ct, certains langages bien connus, de qualit industrielle , rendent peu prs tout difficile. Perl est diffrent. En rsum, Perl est conu pour simplifier les tches faciles, sans rendre les tches difficiles impossibles. Et quelles sont ces tches faciles qui devraient le rester ? Celles que lon rencontre tous les jours, bien sr. Il faut un langage qui facilite la manipulation des nombres, de texte, des fichiers et des rpertoires, des ordinateurs et des rseaux, et surtout des programmes. Il devrait tre facile de lancer des programmes externes et de scruter leur sortie la recherche dinformations intressantes. Il devrait tre facile denvoyer ces informations vers dautres programmes qui les manipuleront intelligemment. De mme, il devrait tre facile de dvelopper, de modifier et de mettre au point vos propres programmes. Et, bien sr, il devrait tre facile de compiler et de lancer ces programmes, de les porter facilement, ceci sur nimporte quel systme dexploitation moderne. Perl fait tout cela, et plus encore. Au dpart conu comme un langage pour administrer UNIX, Perl a t port sur la plupart des systmes dexploitation. De fait, Perl est lun des environnements de programmation les plus portables de nos jours. Pour rendre un programme C ou C++ portable, il faut y inclure ces tranges balises #ifdef diffrentes pour chaque systme cible. Pour rendre un programme Java portable, il est ncessaire de comprendre toutes les particularits de chaque nouvelle implmentation de Java. Pour porter un script shell il est n-

customer_8566

xiv

Prface

cessaire de se souvenir de la syntaxe pour chaque version du systme cible, et ceci pour chaque commande, et donc de trouver le plus petit dnominateur commun, qui avec un peu de chances fonctionnera partout. Pour porter un programme crit en Visual Basic, il faudra alors une dfinition plus souple du mot portable. :-) Perl, par on ne sait quelle magie, vite de tels problmes en retenant les cts positifs de ces langages. Cette magie a plusieurs sources : lutilit de ces mthodes, la crative communaut Perl et la f loraison du logiciel libre. Mais surtout, cette magie vient de son caractre hybride : Perl est un langage mtiss et a toujours vu cette diversit non comme une faiblesse mais comme une force. Alors, si vous avez envie de goter la libert, Perl est fait pour vous. Perl na pas de frontires. lorigine de lexplosion du langage Perl, il y a le dsir des premiers programmeurs systme Unix de ne garder que le meilleur de cet ancien monde . Pour ceux-ci, Perl est une distillation portable de la culture Unix, et une oasis dans un dsert sans issues. Ce qui est satisfaisant, cest que lon peut tout aussi bien retraverser de lautre ct : les designers de sites web sont heureux de pouvoir faire fonctionner leurs scripts Perl sans modification sur le serveur de leur socit. La raison pour laquelle Perl est si populaire parmi les programmeurs systme et les dveloppeurs de sites web, cest tout simplement parce quils lont dcouvert en premier ; mais Perl aspire une plus large audience. Depuis ses dbuts, comme simple langage traducteur dautres langages, Perl sest dvelopp comme un langage sophistiqu est trs gnral, accompagn dun systme de dveloppement complet avec dbogueur, optimiseur, rfrenceur crois, compilateur, diteur orient syntaxe et toute une bibliothque de modules en faisant ainsi un vritable langage de programmation. Mais ce qui diffrencie vraiment Perl, cest quil a toujours su garder une vision simple des choses qui lintressent. Sa puissance et son accessibilit le rendent utilisable dans tous les domaines de la connaissance, de lingnierie spatiale la biologie molculaire, des mathmatiques la linguistique, du graphisme au traitement des documents, de la gestion des bases de donnes celle des rseaux. Perl est utilis pour traiter rapidement une grande quantit dinformations, aussi bien des squences ADN que des pages web. Aussi, lune des plaisanteries de la communaut Perl, est que le prochain crack boursier sera probablement dclench par un bogue dans un script Perl. (Lavantage est que les analystes boursiers au chmage pourront toujours se reconvertir.) Il existe de nombreuses raisons au succs de Perl. Le langage Perl fut lun des premiers projets de la communaut du logiciel libre. Perl est libre et le sera toujours. Grce sa licence trs ouverte, vous pouvez lutiliser o bon vous semble : au travail ou dans des applications commerciales, sans restriction et sans redevance. Et sil survient une difficult que la communaut Perl ne peut rsoudre, vous disposez en dernier recours du code source. Elle nest pas du genre vous faire payer des mises jour. Elle ne mettra pas la cl sous la porte en laissant votre programme orphelin. Que Perl soit un langage libre la srement beaucoup aid. Mais cest aussi le cas de la plupart des logiciels libres qui prosprent. Perl autorise tous ces degrs de libert car cest un langage dont la personnalit est clate. Il sagit dun langage la fois trs simple et trs riche. Il a pris de bonnes ides presque partout, et les a implantes dans un cadre facile utiliser. Pour ceux qui laiment sans plus, Perl est le Practical Extraction and Report Language. Pour ceux qui ne jurent que par lui, Perl est le Pathologically Eclectic Rubbish

customer_8566

Prface

xv

Lister. Pour les minimalistes du lot, Perl ressemble une dmonstration de redondance inepte. Pas de problme. Le monde a besoin de quelques rductionnistes (surtout chez les physiciens). Les rductionnistes aiment isoler les choses. Nous, nous essayons de leur donner un sens. Perl est par bien des aspects un langage simple. Point nest besoin de connatre de nombreuses incantations mystrieuses pour compiler un programme Perl ; il suffit de lexcuter comme un script shell. Les types et les structures employs par Perl sont faciles utiliser et comprendre. Perl nimpose pas de limitation arbitraire vos donnes ; vos chanes et vos tableaux peuvent crotre tant quils veulent (tant quil reste de la mmoire) et ils sont conus pour sadapter leur croissance. Au lieu de vous forcer apprendre de nouvelles syntaxes et de nouveaux concepts, Perl emprunte de nombreuses notions dautres langages qui peuvent vous tre familiers (comme le C, awk, BASIC, Python, langlais et le grec). En fait, pratiquement nimporte quel programmeur peut lire un bout de code Perl bien crit et se faire une ide de son fonctionnement. Le plus important est le fait que vous navez pas besoin de tout connatre de Perl avant de pouvoir crire des programmes utiles. On peut apprendre Perl par le petit bout de la lorgnette . Vous pouvez programmer comme un enfant qui commence parler, nous vous promettons de ne pas rire. De nombreuses ides de Perl sont empruntes au langage naturel, et lune des meilleures est quil ny a aucun problme utiliser un sousensemble du langage tant quon arrive ses fins. Nimporte quel niveau de comptence technique est acceptable dans la culture Perl. Il nexiste pas de police du langage. Un script Perl est correct sil vous aide terminer votre travail avant que le patron ne vous mette dehors. Bien quil soit simple par de nombreux aspects, Perl est galement un langage riche dont il y a beaucoup apprendre. Cest le prix payer pour faciliter ce qui est difficile. Il vous faudra un certain temps pour en assimiler toutes les possibilits, mais vous serez heureux davoir accs ses remarquables capacits quand vous en aurez besoin. Nous avons fait remarquer plus haut que Perl emprunte de nombreuses aptitudes aux shells et au C, mais il possde aussi un sur-ensemble strict de celles de sed et de awk. Il existe en fait des traducteurs fournis avec Perl pour transformer les anciens scripts sed et awk en scripts Perl, et vous pouvez donc voir comment les fonctionnalits avec lesquelles vous pouvez dj tre familiers correspondent celles de Perl. En raison de cet hritage, Perl tait dj riche alors mme quil ntait quun langage de rduction de donnes, conu pour naviguer dans des fichiers, scruter de grandes quantits de texte, crer et obtenir de donnes dynamiques et afficher des rapports facilement formats se basant sur ces donnes. Mais un moment donn, Perl a commenc spanouir. Il est alors devenu un langage de manipulation de systmes de fichiers, de gestion de processus, dadministration de bases de donnes, de programmation clientserveur, de programmation scurise, de gestion dinformations bases sur le Web, et mme de programmation oriente objet et fonctionnelle. Ces possibilits nont pas t simplement colles aprs coup ; chacune fonctionne en synergie avec les autres, parce que Perl a t conu ds le dpart comme un langage dintgration. Mais Perl peut intgrer plus que ses propres capacits. Perl est conu pour tre extensible de faon modulaire. Perl vous permet de rapidement concevoir, programmer, mettre au point et dployer des applications, mais il vous permet galement dtendre aisment les fonctionnalits de ces applications quand le besoin sen fait sentir. On peut intgrer Perl dautres langages, et on peut intgrer dautres langages Perl. Le mca-

customer_8566

xvi

Prface

nisme dimportation de modules permet dutiliser ces dfinitions externes comme sil sagissait de fonctionnalits propres Perl. Les bibliothques orientes objet conservent cette proprit. Perl vous assiste en bien dautres manires. Perl compile dabord votre programme dans un code intermdiaire, alors quun langage interprt classique compile et excute une commande la fois. Il effectue diverses optimisations comme tout autre compilateur et donne des rsultats instantans concernant entre autres les erreurs de syntaxe et les problmes de liaison avec les bibliothques. Une fois que la partie en amont a valid le programme, elle passe le code intermdiaire linterprteur en aval qui lexcute (ou, si lon prfre, une autre routine de traitement capable dmettre du code C ou du langage machine). Tout ceci peut paratre compliqu, mais le compilateur et linterprteur sont assez efficaces, et la plupart dentre nous comptent le cycle compiler-lancer-dboguer en secondes. Ce cycle rapide associ une gestion douce des erreurs fait de Perl un langage idal pour le prototypage. Au fur et mesure que le programme se dveloppe, on peut resserrer les boulons et programmer avec moins de f lair mais plus de discipline. Perl vous y aide galement, quand vous le lui demandez gentiment. Perl vous permet aussi dcrire des programmes plus srs. En plus des interfaces de scurit implmentes par les autres langages, un mcanisme de traage automatique des source dinscurit, bloque toute opration dangereuse. Enfin, Perl permet de dfinir des compartiments spcialement protgs dans lesquels on peut excuter en toute scurit du code Perl dorigine douteuse, en masquant les oprations dangereuses. Mais, paradoxalement, la meilleure aide que Perl puisse vous apporter na presque rien voir avec Perl, mais tout voir avec les gens qui lutilisent. Les Perlistes comptent parmi les gens les plus utiles sur terre, vraiment. Sil existe un aspect religieux au mouvement Perl, cest celui-l. Larry a voulu que la communaut Perl fonctionne comme un bout de paradis, et il semble que son souhait se soit ralis jusqu prsent. Puissiez-vous faire de votre mieux pour que cela continue. Que vous appreniez Perl parce que vous voulez sauver le monde, ou simplement parce que vous tes curieux, ou encore parce que votre patron vous a dit de vous y mettre, ce livre vous mnera de ses bases les plus lmentaires vers ses labyrinthes les plus obscurs. Et mme si nous navons pas lintention de vous apprendre programmer, le lecteur attentif en retirera un peu de lart, et de la science, de la programmation. Nous vous encouragerons dvelopper les trois grandes vertus du programmeur : la paresse, limpatience et lorgueil. Tout au long de ce parcours, nous esprons que vous trouverez ce livre assez amusant par certains cts (et dun humour ravageur par dautres). Et si rien de tout cela ne vous suffit, souvenez-vous que lapprentissage de Perl enrichira votre curriculum vitae. Continuez donc votre lecture.

Ce qui est nouveau dans cette dition


Presque tout... Sauf des morceaux choisis de la prcdente dition (et ils taient nombreux), nous avons entirement rvis la prsente dition pour plusieurs raisons. Premirement nous avons voulu rendre le livre accessible un plus large public. Il y a trs peu de prrequis. Nous avons volontairement choisi un style vivant pour garder veills ceux qui en auraient beaucoup (des prrequis).

customer_8566

Prface

xvii

Deuximement, nous avons prsent les derniers dveloppements de Perl. Mme si ceux-ci restent ltat dexprience de laboratoire, le noyau central est solidement plant. La foule adopter pour suivre le dveloppement de certaines extensions, peut tre torride. Cest pourquoi nous vous indiquerons daller voir plutt la documentation en ligne, pour prciser certains aspects, car Perl est un langage de mcanicien et on peut confondre un boulon de 8 avec un boulon de 10. Enfin, nous avons adapt cette dition pour en faciliter la lecture, en sparant les chapitres en parties introduisant chacune un concept, dans le but de mieux saisir lensemble. Cette nouvelle dition sorganise ainsi : Partie I, Survol de Perl Le dmarrage est toujours difficile. Cette partie prsente les ides fondamentales du langage sur un ton informel et est lire au coin du feu. Il sagit plus dun marchepied que dun didacticiel complet, et elle peut ne pas correspondre aux besoins de tout le monde. Voir la section Documentation papier pour les livres qui pourraient mieux convenir. Partie II, Sance de dissection Cette partie est un dveloppement btons rompus et en profondeur des mcanismes essentiels du langage chaque niveau dabstraction, depuis les types de donnes, les variables, les expressions rgulires jusquaux routines, modules et objets. Vous y acquerrez une bonne mesure du fonctionnement de ce langage ainsi que quelques bonnes mthodes de conception de logiciels. (Et si vous navez jamais utilis un langage permettant la reconnaissance des modles, vous allez avoir un traitement de faveur.) Partie III, Technique Perl Il est possible de faire beaucoup de choses avec Perl et ce chapitre vous emmnera beaucoup plus loin. Ici, vous apprendrez comment rpondre tous les dfis lancs par votre machine, depuis le traitement des caractres Unicode, la communication entre processus, le multithreading, la compilation, le dbogage et loptimisation de Perl, jusqu lcriture de vos propres extensions en C ou C++ ou linterfaage de toute API. Perl est tout fait adapt pour communiquer avec votre PC, et si besoin avec les autres PC sur Internet. Partie IV, Culture Perl Toute culture ayant un langage, la communaut Perl a vite compris quelle devait se forger une culture. Nous verrons dans cette partie la programmation Perl dans la vie de tous les jours. Nous verrons comment reconnatre les bons des mchants, et aussi comment nous amliorer pour produire des programmes rutilisables par tout le monde. Partie V, Rfrences Nous avons regroup dans cette partie tous les termes importants de chaque chapitre, depuis les variables et fonctions spciales, aux modules et pragmas standards. Le glossaire sera particulirement utile ceux qui ne sont pas familiers avec le jargon informatique. Par exemple, si vous ignorez le sens du terme pragma , vous pouvez le dcouvrir ds maintenant.

customer_8566

xviii

Prface

Distribution standard
Aujourdhui, la grande majorit des systmes dexploitation comprennent une distribution de Perl en standard. Au moment o ces lignes sont crites, les systmes AIX, BeOS, BSDI, Debian, DG/X, DYNIX/ptx, FreeBSD, IRIX, LynxOS, Mac OS X, OpenBSD, RedHat, SINIX, Slackware, Solaris, SuSE, Mandrake et Tru64, sont tous distribus avec une version de Perl en standard. Certaines socits fournissent Perl sur un CD de distribution libre ou bien par lintermdiaire de leur service client. Des socits tierces comme ActiveState, proposent des distributions pour diffrents systmes y compris Microsoft. Mme si votre distributeur livre Perl en standard, vous aurez probablement envie de compiler et dinstaller Perl vous-mme. Vous serez ainsi certain davoir la dernire version, et de pouvoir installer o bon vous semble la documentation ainsi que les bibliothques. Vous pourrez aussi choisir parmi les diffrentes options de compilation tels que le multithreading, la gestion des grands fichiers, ou bien les options de dbogage de bas niveau disponible par le slecteur -D. (Le dbogage niveau utilisateur est toujours support.) La faon la plus simple dobtenir les sources de Perl est daller www.perl.com, o vous trouverez les informations les plus importantes, ainsi que des liens vers des distributions binaires spcifiques aux plates-formes sans compilateurs C. Vous pouvez aussi vous rendre directement sur le CPAN (Comprehensive Perl Archive Network, dcrit au chapitre 22, CPAN, ladresse http://www.Perl.com/CPAN ou bien http://www.cpan.org. Si ces adresses sont trop lentes (cest possible car elles sont trs populaires), vous pouvez choisir ainsi un miroir plus proche de chez vous. Les adresses url suivantes ont t choisies parmi les centaines de miroirs CPAN dans le monde : http://www.funet.fi/pub/languages/Perl/CPAN/ ftp://ftp.funet.fi/pub/languages/Perl/CPAN/ ftp://ftp.cs.colorado.edu/pub/Perl/CPAN/ ftp://ftp.cise.ufl.edu/pub/Perl/CPAN/ ftp://ftp.Perl.org/pub/Perl/CPAN/ http://www.Perl.com/CPAN-local http://www.cpan.org/ http://www.Perl.org/CPAN/ http://www.cs.uu.nl/mirror/CPAN/ http://CPAN.pacific.net.hk/ Les deux premires de la liste, sur le site funet.fi, pointent sur le rpertoire matre de tous les sites CPAN. Le fichier MIRRORED.BY contient la liste de tous les sites pour laisser le choix du site miroir ainsi que du protocole pour le tlchargement (FTP ou HTTP), ce qui est utile lorsque votre rseau est derrire un firewall. Le site multiplexeur http://www.Perl.com/CPAN vous aide faire cette slection. Une fois que vous avez rcupr et dcompact le code source dans un rpertoire, vous devez lire les fichiers README et INSTALL pour comprendre comment construire lexcutable Perl. Il peut aussi y avoir un fichier INSTALL.platform o platform dsigne votre plate-forme systme.

customer_8566

Prface

xix

Si votre platform est un systme Unix ou similaire, alors les commandes pour charger, configurer, construire et installer Perl seront celles qui suivent. Premirement vous devez utiliser une commande pour charger le code source. Avec ftp :
% ftp ftp://ftp.funet.fi/pub/languages/Perl/CPAN/src/latest.tar.gz

(vous pouvez substituer un miroir CPAN plus proche. Si vous habitez en Finlande cest votre miroir CPAN le plus proche.) Si vous ne pouvez utiliser ftp, alors tlcharger sur le Web avec un navigateur ou bien la ligne de commande suivante :
% wget http://www.funet.fi/pub/languages/Perl/CPAN/src/latest.tar.gz

Ensuite, il faut dcompacter, configurer, construire et installer :


% % % % tar zxf latest.tar.gz cd Perl-5.6.0 sh Configure -des make test && make install ou gunzip, et ensuite tar xf. ou 5.* pour toute version. Rponses par dfaut. En mode super-utilisateur.

Ces commandes seffectuent dans un environnement de dveloppement C conventionnel, et ncessitent donc un compilateur C. Pour connatre les diffrentes mises jour et versions de Perl pour chaque plate-forme, si vous avez besoin dune version standard ou dun portage spcial, explorez le rpertoire CPAN ports. Des liens sont disponibles pour tlcharger ses portages spciaux ou pour les systmes ne disposant pas de compilateurs C.

Documentation en ligne
Limportante documentation en ligne de Perl fait partie de la distribution standard. (Voir la section suivante pour la documentation papier.) Chaque module CPAN est accompagn de sa documentation. Quand nous faisons rfrence au manuel Perl , nous parlons de lensemble des pages en ligne du manuel Perl, sur votre PC. Le terme manuel est purement une convention indiquant un fichier contenant de la documentation (nul besoin dun programme man pour la lire. Elles peuvent mme tre au format HTML sur les systmes diffrents dUnix. Le manuel Perl en ligne a t divis en diffrentes sections, pour pouvoir facilement trouver ce que lon cherche sans avoir parcourir des centaines de pages de texte. Le manuel Perl de base se nomme perl, et on y accde avec la commande man perl1. Ce manuel vous orientera vers dautres plus spcifiques. Par exemple man perlre affichera le manuel des expressions rgulires de Perl. La commande perldoc fonctionne souvent sur les systmes ou la commande man ne fonctionne pas. Sur Mac, il faut utiliser le programme Shuck. Votre distribution peut aussi fournir le manuel Perl au format HTML, ou bien le format daide natif du systme hte.

1. Si vous obtenez une page illisible cest probablement que votre version de manuel est trop ancienne. Vrifiez votre variable denvironnement MANPATH. (Essayez la commande perldoc perl pour configurer MANPATH sur la valeur retourne par la commande perl -V:man.dir.)

customer_8566

xx

Prface

Consultation du manuel standard


lorigine du langage, en 1987, le manuel perl tait un document concis denviron vingt-quatre pages dactylographies. La section concernant les expressions rgulires noccupait que deux paragraphes. (avec la connaissance de la commande egrep cela pouvait suffire.) Dune certaine faon tout a chang depuis : de la documentation standard, les diffrents utilitaires, linformation pour le portage entre les diffrentes plates-formes et les centaines de modules standard, il y a maintenant plus de 1500 pages dactylographis de documentation rparties entre plusieurs manuels. (Sans compter les modules CPAN que vous installerez.) Dun autre ct rien na chang : le manuel de base perl existe toujours, et cest toujours le point de dpart si vous tes perdu. La diffrence est que lorsque vous y tes, vous ne pouvez vous y arrter. La documentation Perl nest plus une petite picerie mais un grand centre commercial avec des centaines de magasins o il est ncessaire de savoir o lon est pour savoir o lon va. Une fois que lon connat le plan, il est facile de sorienter. Voici quelques points de repre que vous pourrez rencontrer le :
Manuel perl perldata perlsyn perlop perlre perlvar perlsub perlfunc perlmod perlref perlobj perlipc perlrun perldebug perldiag Sujet Les diffrents manuels Perl disponibles. Les types de donnes. La syntaxe Perl. Prcdence des oprateurs. Les expressions rgulires. Les variables prdfinies. Les routines Perl. Les fonctions prdfinies. Mise en uvre des modules. Les rfrences. Les objets. La communication interprocessus. Lutilisation des commandes Perl avec slecteurs. Le dbogage. Les messages de diagnostic.

Cest juste un aperu, mais ce sont les entres essentielles : si vous voulez connatre un oprateur, perlop vous donnera la rponse, et vous cherchez une chose sur les variables prdfinies, regardez dans perlvar. Pour comprendre un message derreur, allez dans perldiag. Et ainsi de suite. Les FAQ (questions revenant frquemment) sont une partie standard du manuel Perl. Elles sont divises en neuf manuels diffrents :

customer_8566

Prface
Manuel perlfaq1 perlfaq2 perlfaq3 perlfaq4 perlfaq5 perlfaq6 perlfaq7 perlfaq8 perlfaq9 Sujet Les questions gnrales sur Perl. La rcupration et lapprentissage de Perl. Les outils de programmation. Les manipulation des donnes. Les fichiers et formats. Les expressions rgulires. Les questions dordre gnral sur le langage. Linteraction avec le systme. La connexion au rseau.

xxi

Certains manuels rassemblent des notes spcifiques certaines plates-formes :


Manuel perlamiga perlcygwin perldos perlhpux perlmachten perlos2 perlos390 perlvms perlwin32 Sujet Le portage sur Amiga. Le portage sur Cygwin. Le portage sur MS DOS. Le portage HP UX. Le portage sur Power MachTen. Le portage sur OS/2. Le portage sur OS/390. Le portage sur DEC VMS. Le portage sur MS-Windows.

(Voir aussi le chapitre 25, Portabilit, et le rpertoire des portages du CPAN dj dcrit pour toute information relative ce sujet.)

Recherche dans le manuel


Nessayez pas de lire les 1500 pages du manuel, autant chercher une aiguille dans une botte de foin. Il y a un vieux dicton qui dit quon ne peut pas grapper des arbres morts.2 Chacun des manuels Perl, dispose de son propre outil de recherche et de visualisation. Il est possible de chercher une page du manuel en indiquant la commande constitue du nom du manuel suivi dune expression rgulire comme paramtre (voir le chapitre 5, Recherche de motif) :
% % % % perlop comma perlfunc split perlvar ARGV perldiag assigned to typeglob

2. Noubliez pas le glossaire.

customer_8566

xxii

Prface

Il est possible dtendre la recherche sur un manuel entier, par exemple pour chercher dans les FAQ, utilisez la commande perlfaq (qui est aussi un manuel) :
% Perlfaq round

La commande perltoc (aussi un manuel) cherche dans le sommaire gnral de tous les manuels :
% perltoc typeglob Perl5005delta: Undefined value assigned to typeglob Perldata: Typeglobs and Filehandles Perldiag: Undefined value assigned to typeglob

Ou alors, pour trouver une chane dans toutes les ressources en ligne du manuel, incluant les en-ttes, les descriptions et exemples, utilisez la commande perlhelp :
% perlhelp CORE::GLOBAL

Voir le manuel perldoc pour les dtails.

Les autres manuels


Quand nous parlons de documentation non-Perl, comme par exemple dans getitimer(2), nous faisons rfrence aux manuels getitimer dans la section 2 du manuel Unix Programmers Manual.3 Les pages du manuel pour les appels systme tel getitimer peuvent ne pas tre prsentes sur les systmes non Unix, mais ce nest pas grave car vous ne pouvez pas les utiliser dans ce cas. Si vous en avez vraiment besoin, vous les trouverez facilement publis sur le Web une recherche rapide de "+crypt(3) +manual" avec AltaVista vous permettra den obtenir plusieurs versions. Mme si les principaux manuels Perl sont installs dans la section 1 du rpertoire standard de man, nous omettrons lindice (1) quand nous y ferons rfrence dans ce livre. Vous les reconnatrez nanmoins sans difficult car ils sont tous de la forme perlmumble .

Documentation papier
Voici quelques titres de la littrature Perl que nous vous recommandons de : Perl 5 Prcis et concis, 2e ed., de Johan Vromans (OReilly, 2000). Ce manuel au format poche est une rfrence pratique et rapide. Perl en action, par Tom Christiansen et Nathan Torkington (OReilly, 1998). Un livre pour accompagner celui-ci. Elements of Programming with Perl, Andrew L. Johnson (Manning, 1999). Pour commencer partir de 0 en utilisant Perl, pour les non programmeurs.

3. La section 2 contient les appels directs des fonctions du systme. (et sont appeles appels systmes , ne pas confondre avec les appels la fonction system, ce qui na rien voir. Cependant, les systmes diffrent quant limplmentation de ces appels systmes entre ceux qui utilisent la fonction system et ceux qui font appel aux fonctions de la bibliothque C, ce qui fait que lon peut trouver getitimer(2) dans la section 3 (Sous Programmes) au lieu de la section 2 (Appels Systmes).

customer_8566

Prface

xxiii

Introduction Perl, 2e ed., par Randal Schwartz et Tom Christiansen (OReilly, 1997). Pour les administrateurs et programmeurs du systme Unix : lutilisation de 30 % du langage dans 70 % des cas. La version sur le systme Microsoft revue par Erik Olson sappelle LearningPerl for Win32 Systems. Perl: The Programmers Companion, par Nigel Chapman (Wiley, 1997). Ce livre trs concis est destin aux ingnieurs et programmeurs en informatique et considre Perl indpendamment de la plate-forme, dune manire complte. Matrise des expressions rgulires, par Jeffrey Friedl (OReilly, 1997). Bien quil ninclut pas les derniers ajouts sur les expressions rgulires, il reste une rfrence indispensable pour quiconque cherche mieux comprendre comment celles-ci fonctionnent. Object Oriented Perl, par Damian Conway (Manning, 1999). Pour les dbutants aussi bien que les programmeurs objet avancs, ce livre tonnant dveloppe des techniques simples et exotiques dans le but dcrire des systmes objets puissants en Perl. Mastering Algorithms with Perl, par Jon Orwant, Jarkko Hietaniemi et John Macdonald (OReilly, 1999). Toutes les techniques utiles dun cours sur les algorithmes, sans les preuves ardues. Ce livre couvre les algorithmes fondamentaux dans le domaine des graphes, du traitement de texte, des ensembles et plein de bonnes choses encore. Writing Apache Modules with Perl and C, par Lincoln Stein et Doug MacEachern (OReilly, 1999). Ce guide de la programmation web enseigne comment tendre les capacits du serveur Apache en utilisant le module turbo mod_Perl pour lexcution rapide des scripts CGI ainsi que l API de ce serveur accessible Perl. The Perl Journal, dit par Jon Orwant. Ce magazine trimestriel cr par des programmeurs pour des programmeurs, dtaille des trucs et astuces, parle des dernires nouvelles et de plein dautres choses encore.

Il existe une plthore de livres et de publications sur le sujet et nous avons srement oubli des rfrences (nous avons nglig sans piti les mauvaises). En plus de ceux que nous venons de citer, nous vous recommandons les livres suivants. Ils nont pas un rapport direct avec le langage mais sont trs pratiques comme rfrence, pour la consultation et linspiration. The Art of Computer Programming, par Donald Knuth, vol. 1, Fundamental Algorithms ; vol. 2, Seminumerical Algorithms ; et vol. 3, Sorting and Searching (Addison-Wesley, 1998). Introduction to Algorithms, par Cormen, Leiserson et Rivest (MIT Press and McGrawHill, 1990). Algorithms in C: Fundamental Data Structures, Sorting, Searching, 3e ed., par Robert Sedgewick (Addison-Wesley, 1997). The Elements of Programming Style, par Kernighan et Plauger (Prentice-Hall, 1988). The Unix Programming Environment, par Kernighan et Pike (Prentice-Hall, 1984). POSIX Programmers Guide, par Donald Lewine (OReilly, 1991). Advanced Programming in the UNIX Environment, par W. Richard Stevens (AddisonWesley, 1992).

customer_8566

xxiv

Prface

TCP/IP Illustrated, vols. 13, par W. Richard Stevens, (Addison-Wesley, 19941996). Le seigneur des anneaux de J. R. R. Tolkien

Ressources supplmentaires
LInternet est une merveilleuse invention et nous dcouvrons tous les jours comment utiliser tout son potentiel. (Certains prfreront dcouvrir lInternet la manire dont Tolkien dcouvre la Terre du Milieu. )

Perl sur le web


Allez voir la page daccueil de Perl ladresse http://www.Perl.com/. On y parle des nouveauts dans le monde Perl, vous y trouvez du code source et diffrents reportages, des articles thmatiques, de la documentation, les dates des confrences et bien dautres choses encore. Allez aussi voir la page des Mongueurs ladresse http://www.Perl.org et vous pourrez constater que Perl est comme une herbe sauvage qui pousse partout dans le monde sauf au ple sud. Des groupes locaux de mongueurs se runissent rgulirement avec lesquels vous pouvez changer vos points de vue entre hackers.

Groupe de news Usenet


Les groupes de news Perl sont une source dinformations remarquable, bien que parfois confus. comp.lang.Perl.announce est un groupe modr dun faible trafic sur les annonces concernant Perl. Il sagit frquemment de nouvelles versions, de corrections de bogues, de nouvelles extensions et de nouveaux modules et de FAQ (Frequently Asked Questions, questions frquemment poses4). Le groupe comp.lang.Perl.misc traite aussi bien des problmes techniques que de la philosophie de Perl, des jeux en Perl et de la posie en Perl. Tout comme Perl lui-mme, comp.lang.Perl.misc se veut utile, et aucune question nest trop stupide.5 Le groupe comp.lang.Perl.tk discute de lutilisation du fameux module Perl/Tk. Le groupe comp.lang.Perl.modules concerne le dveloppement et lutilisation des modules Perl qui sont le meilleur moyen pour rutiliser le code. Il y a dautres groupes du type comp.lang.Perl.un_groupe qui nexistent pas au moment o nous crivons ces lignes, alors nhsitez pas naviguer. Si vous nutilisez pas un lecteur de news classique pour accder Usenet, mais plutt un navigateur web, placez devant le nom du groupe len-tte "news:" pour accder lun de ceux que vous cherchez. (Cela fonctionne seulement si vous avez un serveur de news) Vous pouvez aussi les chercher laide de AltaVista ou Deja en prcisant *Perl* comme nom du groupe dutilisateurs. Un dernier groupe dutilisateurs quil vous sera utile de consulter, au moins si vous tes
4. Ou Foire Aux Questions. 5. Il est vident que certaines questions sont trop stupides... surtout celles dont la rponse se trouve dans la FAQ.

customer_8566

Prface

xxv

programmeur CGI, est le groupe comp.infosystems.www.authoring.cgi. Mme si ce nest pas strictement parler un groupe dutilisateurs Perl, la plupart des programmes dexemples sont crits en Perl, moins que vous nutilisez le module Apache mod_Perl, auquel cas vous pouvez consulter comp.infosystems.www.servers.unix.

Rapports de bogues
Au cas improbable o vous trouviez un bogue propre Perl et non votre programme, essayez de le rduire un cas de test minimal avant de le rapporter via le programme Perlbug qui est fourni avec Perl. Voir le lien http://bugs.Perl.org pour plus dinformations.

De laide en franais
Si vous voulez en savoir plus sur Perl dans un cadre sympathique, il existe des groupes dutilisateurs francophones de Perl. Voici dailleurs un message du fondateur dun de ces groupes :
Jespre que ce livre apportera satisfaction aux lecteurs francophones qui dsirent (mieux) programmer en Perl. Ce nest pas toujours possible pour quelquun dont langlais nest pas la langue maternelle de comprendre toutes les subtilits des points techniques, ainsi que les plaisanteries et les jeux de mots qui sont lgion dans la documentation anglaise. Je crois savoir, pour avoir cout (et parfois rpondu) leurs questions, que les traducteurs de cet ouvrage nont pas failli sur les explications des subtilits techniques et aussi ont-ils fait de leur mieux pour traduire les plaisanteries. Toujours est-il que parfois, mme en lisant ce livre de manire assidue, on narrive pas comprendre comment faire marcher un module de CPAN, sil existe un module CPAN qui fait ce que lon souhaite faire, ou sil existe de meilleurs moyens pour effectuer une opration. ce moment-l, on a envie de discuter avec dautres personnes. Par la plus forte concidence, il existe des groupes dutilisateurs de Perl. J'ai fond le premier groupe franais il y a environ trois ans, Paris. Ce sont des mongers, quon pourrait traduire par marchands ; mais que je prfre crire mongueurs (mongueuses au fminin), pour rester plus fidle la prononciation anglaise. Nous avons un site web, ainsi quune liste de diffusion qui, en octobre 2001, compte environ 150 abonn(e)s. Nous avons galement fond une association, dont le but est de promouvoir lutilisation de Perl en France, en soutenant la cration de nouveaux groupes dutilisateurs ( ce jour, Toulouse et Marseille nous ont rejoint) et en organisant des confrences ou des cours consacrs Perl. Cest pourquoi je vous invite venir nous rencontrer, sur notre site web (http://www.mongueurs.net/), notre liste ou nos runions (rendez visite au groupe local prs de chez vous ou mieux, fondez-en un !), pour dcouvrir le ct humain qui se cache derrire le langage qui nous a tant apport et qui continue nous fasciner. David Landgren Prsident de lassociation Les Mongueurs de Perl Octobre 2001

customer_8566

xxvi

Prface

Conventions typographiques
Nous avons consacr une section propre pour dcrire certaines conventions telles les conventions de codage dcrites dans Programmation style au chapitre 24, Techniques couramment employes. Les conventions lexicales sont indiques dans le glossaire (notre lexique). Dans cette dition nous avons utilis les conventions typographiques suivantes : Italique Elle est utilise pour les URL, manuels, noms de fichier et programmes. Les termes nouveaux sont en italique la premire fois quils apparaissent dans le texte. La plupart sont repris plus prcisment dans le glossaire. Chasse constante Elle est utilise dans les exemples et pour indiquer du code insr dans du texte normal. Les valeurs sont crites en chasse constante entre guillemets ( ), qui bien sr ne font pas partie de la valeur. Chasse constante en gras Elle est utilise pour les options de commande, ce qui permet de distinguer entre loption avertissement -w et loprateur -w pour le test dun fichier. Elle est aussi utilise pour le texte que vous entrez littralement. Chasse constante en italique Elle est utilise pour des termes gnriques auxquels vous devez substituer vos valeurs personnelles. Nous listons beaucoup dexemples qui sont pour la plupart des bouts de code qui peuvent sintgrer dans une application plus large. Certains exemples sont des programmes complets et que vous pouvez reconnatre avec len-tte de dbut de ligne #!. Les programmes les plus importants commencent par :
#!/usr/bin/Perl

Dautres programmes doivent aussi tre entrs en ligne de commande. Nous avons utilis le symbole % pour indiquer un prompteur shell :
% Perl -e print "Hello, world.\n" Hello, world.

Ce style reprsentatif dune ligne de commande Unix o les simples guillemets reprsentent la forme la plus quote . La quotation, ainsi que les caractres gnraux (wildcards), varient dun systme lautre. Par exemple beaucoup dinterprteurs de ligne de commande sous MS DOS et VMS ncessitent la double quotation en lieu et place des simples guillemets lorsquil est ncessaire de grouper les arguments avec des espaces ou des caractres gnraux de remplacement.

Remerciements
Nous voulons remercier ici publiquement nos relecteurs pour leur patience dans ldition de cet ouvrage : Todd Miller, Sharon Hopkins Rauenzahn, Rich Rauenzahn, Paul

customer_8566

Prface

xxvii

Marquess, Paul Grassie, Nathan Torkington, Johan Vromans, Jeff Haemer, Gurusamy Sarathy, Gloria Wall, Dan Sugalski et Abigail. Nous voulons remercier tout particulirement Tim OReilly (et ses associs) dencourager les auteurs faire un effort spcial pour rendre leurs livres agrables lire.

Vos apprciations
Nous avons test et vrifi toutes les informations de ce livre du mieux que nous lavons pu, mais vous pouvez dcouvrir que certaines caractristiques ont chang (ou mme que nous avons fait des erreurs). Faites-nous part de toutes les erreurs que vous avez pu rencontrer, de mme que vos suggestions pour les ditions venir, en crivant : OReilly France 18, rue Sguier 75006 Paris Vous pouvez galement nous envoyer des messages lectroniques. Pour vous inscrire sur la liste de diffusion ou demander un catalogue, envoyez un e-mail : info@editions-oreilly.fr Nous avons un site web pour le livre o nous listons toute erreur et information relative la srie des chameaux : http://www.oreilly.fr/catalogue/pperl3.html Vous y trouverez galement le code source des exemples de ce livre.

customer_8566

customer_8566

Survol de Perl

customer_8566

customer_8566

Vue densemble

Dmarrage
Nous pensons que Perl est un langage facile apprendre et utiliser, et nous esprons vous en convaincre. Lun des aspects les plus agrables de Perl est que lon na pas besoin den crire beaucoup avant dexprimer vraiment sa pense. Dans de nombreux langages de programmation, il faut dclarer les types, les variables et les sous-programmes que lon va utiliser avant dcrire la premire instruction de code excutable. Cest une bonne approche pour des problmes complexes demandant des structures de donnes complexes ; mais pour pour beaucoup de problmes simples, que lon rencontre tous les jours, il vaut mieux un langage de programmation dans lequel il suffit dcrire :
print "Salut tout le monde!\n";

et o le programme ne fait que cela. Perl est de ce genre de langage. En fait, cet exemple est un programme complet, et si on le donne linterprteur Perl, il affiche Salut tout le monde ! lcran.1 (Le caractre \n produit un saut de ligne en sortie.) Et voil. Il ny a pas non plus grand-chose crire aprs ce que lon veut dire, dailleurs. linverse de nombreux langages, Perl estime que sarrter sans prvenir la fin du programme nest quune faon normale den sortir. On peut bien sr appeler explicitement la fonction exit si on le souhaite, de mme que lon peut dclarer certaines variables ou certains sous-programmes, ou mme se forcer dclarer toutes les variables et tous les sous-programmes. vous de voir. En Perl, vous tes libre de faire Ce Quil Faut, quelle quen soit votre dfinition. Il existe dautres raisons la facilit demploi de Perl, mais il serait inutile de toutes les numrer ici... car cest lobjet de ce livre. Le diable est dans les dtails, comme disent les Anglo-saxons, mais Perl essaie aussi de vous sortir de lenfer o vous pouvez vous retrouver plong. Cest tous les niveaux que Perl essaye de vous faire arriver vos fins avec
1. Ou un script, ou une application, ou un excutable, ou un machin. Ce quon veut.

customer_8566

Chapitre 1 Vue densemble

le minimum dennuis et le maximum de plaisir. Cest pourquoi tant de programmeurs Perl affichent un sourire bat. Ce chapitre constitue un survol de Perl, et nous nessayons pas de le prsenter la partie rationnelle de votre cerveau. Nous nessayons pas plus dtre complets ou logiques. Ce sera lobjet du prochain chapitre. Les Vulcains, les androdes ainsi que les humains de cette espce, peuvent aller directement au chapitre 29, Fonctions, pour avoir toute linformation. Ce livre prsente Perl lautre partie de votre cerveau, que vous lappeliez associative, artistique, passionne, ou simplement spongieuse. Dans ce but, nous prsenterons divers aspects de Perl qui vous en donneront une image aussi claire que celle dun lphant pour un aveugle. Allons, nous allons essayer de faire mieux. Il sagit ici dun chameau, aprs tout. Esprons quau moins un de ces aspects du langage vous mettra en selle.

Langages naturels et artificiels


Les langages ont dabord t invents par les humains, pour les humains. Ce fait a parfois t oubli dans les annales de linformatique.2 Perl ayant t conu (pour ainsi dire) par un linguiste occasionnel, il a t invent pour fonctionner aussi aisment que le langage naturel. Cela recouvre plusieurs notions, puisque le langage naturel fonctionne simultanment plusieurs niveaux. Nous pourrions numrer ici nombre de ces principes linguistiques, mais le plus important est que les choses simples doivent le rester et que les choses complexes ne doivent pas tre impossibles. Cela peut sembler vident, mais de nombreux langages informatiques ne remplissent pas ces deux conditions. Les langages naturels permettent les deux parce que les gens essayent continuellement dexprimer des choses simples et des choses complexes, ce qui fait que le langage volue pour grer les deux. Perl a t conu avant tout pour voluer, et cest ce qui sest produit. De nombreuses personnes ont contribu lvolution de Perl au cours des ans. Nous plaisantons souvent en disant que le chameau est un cheval conu par un comit, mais si lon y pense, le chameau est parfaitement adapt la vie dans le dsert. Il a volu pour devenir relativement autosuffisant. (En revanche, lvolution de lodeur du chameau est discutable. Cela vaut pour Perl.) Quand quelquun prononce le mot linguistique , on pense en gnral soit des mots, soit des phrases. Mais les mots et les phrases ne sont que deux manires pratiques de morceler la parole. Ils peuvent tous deux tre scinds en units smantiques plus petites, ou combins en units plus grandes. Et la signification de chaque unit dpend largement du contexte syntaxique, smantique et pragmatique dans lequel se trouve lunit. Le langage naturel comporte des mots de diverses sortes, des noms, des verbes, etc. Si je dis pile tout seul, il y a de fortes chances pour que vous pensiez quil sagisse dun nom. Mais je peux lemployer autrement : comme un verbe, comme un adverbe, etc., selon le contexte. Si je pile devant une pile de piles minuit pile, jai intrt disposer dune pile.3

2. Plus prcisment, ce fait a parfois d tre rappel. 3. Vous trouvez sans doute que ces considrations linguistiques manquent de sex-appeal. Le but est simplement de vous montrer en quoi Perl est diffrent dun langage informatique classique.

customer_8566

Langages naturels et artificiels

De mme, Perl value les mots de faon diffrente dans des contextes diffrents. Nous le verrons plus tard. Souvenez-vous que Perl essaie de comprendre ce que vous dites ; il est lcoute. Perl essaie vraiment daller jusquau bout. Dites ce que vous pensez, et en gnral, Perl le saisira ( moins dcrire des choses absurdes, bien sr ; lanalyseur de Perl comprend le Perl bien mieux que le Franais ou le Swahili). Mais revenons aux noms. Un nom peut dsigner un objet prcis, ou il peut nommer une classe dobjets gnrique. La plupart des langages de programmation font cette distinction, sauf que nous appelons valeur une chose prcise et variable une chose gnrique. Une valeur existe quelque part, peu importe o, mais une variable est associe une ou plusieurs valeurs durant son existence. Ce qui interprte la variable doit garder la trace de cette association. Cet interprteur peut se trouver dans votre cerveau, ou dans votre ordinateur.

Syntaxe dune variable


Une variable nest quun endroit pratique pour conserver quelque chose, un endroit qui a un nom, ce qui fait que vous pouvez retrouver vos petits quand vous y revenez plus tard. Tout comme dans la vie relle, il existe de nombreux endroits pour ranger des choses, certains privs et certains publics. Certains lieux sont temporaires et dautres sont permanents. Les informaticiens adorent parler de porte des variables, mais cest peu prs tout ce quils entendent par l. Perl connat de nombreux moyens de traiter les problmes de porte, ce que vous serez ravis dapprendre le moment venu. (Regardez lemploi des adjectifs local, my et our dans le chapitre 29, si vous tes curieux, ou bien regardez Dclarations avec porte dans le chapitre 4, Instructions et dclarations.) Mais on classifie plus efficacement les variables par le type de donnes quelles peuvent reprsenter. De mme quen franais, la premire distinction se fait entre le singulier et le pluriel. Les chanes et les nombres sont des bouts de donnes singulires, alors que les listes de chanes ou de nombres sont plurielles (et quand nous arriverons la programmation oriente objet, vous verrez quun objet peut paratre singulier de lextrieur, mais pluriel de lintrieur, de mme quune classe dlves). Nous appelons scalaire une variable singulire, et tableau une variable plurielle. Comme une chane peut tre stocke dans une variable scalaire, nous pourrons crire une version un peu plus longue (et mieux commente) de notre premier exemple comme ceci :
$phrase = "Salut tout le monde !\n"; print $phrase; # Donner une valeur une variable. # Afficher la variable.

Remarquez que nous navons pas eu prdfinir le genre de la variable $phrase. Le caractre $ dit Perl que phrase est une variable scalaire, cest--dire quelle contient une valeur singulire. Une variable tableau, en revanche, commencerait par le caractre @ (on peut remarquer que $ est un S stylis, pour scalaire, alors que @ est un a stylis pour array , tableau en anglais). Perl connat dautres types de variables aux noms bizarres comme hachage , handle et typeglob . Tout comme les scalaires et les tableaux, ces types de variables sont galement prcds par des caractres tranges. Dans un souci dexhaustivit, voici la liste de tous les caractres tranges que vous pourrez rencontrer :

customer_8566

6
Type scalaire tableau hachage sous-programme typeglob Car. $ @ % & * Exemple $cents @large %interet &comment *truc

Chapitre 1 Vue densemble


Est un nom pour Une valeur propre (nombre, chane). Une liste de valeurs, indexes par numro. Un groupe de valeurs indexes par chane. Un bout de code Perl appelable. Tout ce qui est appel truc.

Pour certains puristes des langages, ces caractres tranges sont une raison dabhorrer Perl. Cette raison est superficielle. Ces caractres procurent de nombreux avantages : les variables peuvent tre interpoles dans des chanes sans syntaxe supplmentaire. Les scripts Perl sont faciles lire (pour ceux qui ont pris la peine dapprendre Perl !) parce que les noms se distinguent des verbes, et que de nouveaux verbes peuvent tre ajouts au langage sans abmer dautres scripts (nous vous avions dit que Perl tait conu pour voluer). Et lanalogie avec les noms na rien de frivole ; il existe de nombreux prcdents dans divers langages naturels qui requirent des marqueurs de noms grammaticaux. Enfin, cest notre avis !

Singularits
Daprs notre exemple, on voit que lon peut assigner une nouvelle valeur un scalaire avec loprateur =, comme dans de nombreux autres langages informatiques. On peut affecter nimporte quelle forme de valeur scalaire une variable SCALAIRE : entier, nombre virgule f lottante, chane, et mme des choses sotriques comme des rfrences dautres variables ou des objets. Il existe de nombreuses faons de gnrer ces valeurs assigner. Comme dans le shell UNIX4, il est possible demployer diffrents mcanismes de protection (quoting) pour fabriquer diffrents types de valeurs. Les doubles apostrophes font une interpolation de variable5 et une interprtation de lantislash (Comme en transformant \t en tabulation, \n en saut de ligne, \001 en contrle-A, etc., dans la tradition de nombreux programmes UNIX, alors que les apostrophes suppriment la fois linterpolation et linterprtation. Et les apostrophes inverses excutent un programme externe et renvoient la sortie du programme, ce qui fait que lon peut capturer une ligne unique contenant toutes les lignes de la sortie.
$reponse = 42; $pi = 3.14159265; $avocats = 6.02e23; $animal = "Chameau"; $signe = "Mon $animal et moi"; # # # # # un entier un nombre "rel" notation scientifique chane chane avec interpolation

4. Nous parlons ici de tous les clones UNIX comme BSD, Linux et Unix. 5. Parfois appele substitution par les programmeurs shell, mais nous prfrons rserver ce mot pour quelque chose dautre en Perl. Il vaut donc mieux parler dinterpolation. Nous employons ce terme dans son sens textuel ( Ce passage est une interpolation gnostique ) et non dans son sens mathmatique ( Ce point du graphe est une interpolation entre deux autres points ).

customer_8566

Langages naturels et artificiels


$cout = Cela cote $100; $pourquoi = $parceque; $x = $taupes * $avocats; $exit = system("vi $x"); $cwd = `pwd`; # # # # # chane sans interpolation une autre variable une expression code de retour dune commande chane gnre par une commande

Et mme si nous navons pas encore vu les valeurs exotiques, nous devons signaler que les scalaires peuvent rfrencer dautres types de donnes incluant les sous-programmes et les objets.
$ary = \@montableau; $hsh = \%monhachage; $sub = \&monsousprog; $ary = [1,2,3,4,5]; $hsh = {Na=>19, Cl=>35}; $sub = sub { print $pays }; $fido = new Chameau "Amelia"; # rfrence un tableau nomm # rfrence un hachage nomm # rfrence un sous-programme # rfrence un tableau anonyme # rfrence un hachage anonyme # rfrence un sous-programme anonyme # rfrence un objet

Les variables non initialises se mettent exister quand le besoin sen fait sentir. Daprs le principe de moindre surprise, elles sont cres avec une valeur nulle, que ce soit "" ou 0. Selon lendroit o elles sont utilises, les variables sont automatiquement interprtes comme des chanes, des nombres ou les valeurs vrai et faux (communment appeles valeurs boolennes). Les oprateurs attendent certains types de valeurs en paramtres, et nous dirons donc que ces oprateurs fournissent ou procurent un contexte scalaire ces paramtres. Nous serons parfois plus spcifiques et dirons quil fournit un contexte numrique, un contexte de chane ou un contexte boolen ces paramtres (nous parlerons plus loin du contexte de liste, qui est linverse du contexte scalaire). Perl convertit automatiquement les donnes sous la forme requise par le contexte courant, non sans raison. Par exemple, supposons que nous ayons crit ceci :
$chameaux = 123; print $chameaux + 1, "\n";

La valeur originelle de $chameaux est une chane, mais elle est convertie en un nombre pour y ajouter 1, puis reconvertie en chane pour tre affiche : "124". Le saut de ligne, reprsent par "\n", est galement dans un contexte de chane, mais puisquil est dj une chane, aucune conversion nest ncessaire. Mais remarquez que nous avons d employer des apostrophes doubles ; les apostrophes simples () autour de \n auraient donn une chane deux caractres constitue dun antislash suivi dun n, ce qui nest en rien un saut de ligne. Dune certaine manire, les apostrophes simples et doubles reprsentent donc un autre moyen de spcifier le contexte. Linterprtation du contenu dune chane protge dpend de la forme de protection utilise. Nous verrons plus loin certains autres oprateurs qui fonctionnent comme des protections de faon syntaxique, mais qui utilisent la chane dune manire spciale comme pour la correspondance de motifs ou la substitution. Ils fonctionnent tous comme des apostrophes doubles. Le contexte dapostrophe double est le contexte interpolatif de Perl et est fourni par de nombreux oprateurs qui ne ressemblent pas des guillemets.

customer_8566

Chapitre 1 Vue densemble

De la mme manire, une rfrence se comporte comme telle lorsque vous tes dans un contexte de drfrencement , sinon elle agit comme une simple valeur scalaire. Par exemple nous cririons :
$fido = new Chameau "Amelia"; if (not $fido) { die "chameau mort"; } $fido->seller();

Ici nous crons une rfrence lobjet Chameau et la plaons dans la variable $fido. la ligne suivante nous testons $fido dans un contexte boolen, et nous levons une exception si sa valeur est fausse, ce qui dans ce cas voudrait dire que le constructeur new Chameau a chou la cration de lobjet Chameau. Mais la dernire ligne, nous utilisons $fido comme rfrence pour trouver la mthode seller() applique lobjet rfrenc par $fido, qui se trouve tre un Chameau, et donc Perl cherche la mthode seller() pour lobjet Chameau. Nous reviendrons sur ce sujet. Souvenez-vous juste pour le moment que le contexte est important en Perl, car il sert lever toute ambigut sans faire aucune dclaration, contrairement beaucoup dautres langages.

Pluralits
Certains types de variables contiennent plusieurs valeurs qui sont logiquement lies entre elles. Perl connat deux types de variables multivaleurs : les tableaux et les hashes, tables de hachage (ou hachages). Ils se comportent comme des scalaires par de nombreux aspects. Ils se mettent exister quand le besoin sen fait sentir et ne contiennent alors rien. Quand on leur assigne une valeur, ils fournissent un contexte de liste du ct droit de lassignation. On emploie un tableau quand on veut chercher quelque chose par son numro. On emploie une table de hachage quand on veut chercher quelque chose par son nom. Ces deux concepts sont complmentaires. On voit souvent des gens utiliser un tableau pour traduire les numros de mois en noms, et un hachage correspondant pour traduire les noms en numros (les hachages ne se limitent videmment pas aux seuls nombres. Par exemple, il est possible davoir un hachage qui traduise les noms de mois en nom de pierres porte-bonheur). Tableaux. Un tableau est une liste ordonne de scalaires, indice par la position du scalaire dans la liste. Celle-ci peut contenir des nombres, ou des chanes, ou un mlange des deux (elle peut aussi contenir des rfrences dautres listes ou hachages). Pour assigner une liste de valeurs un tableau, il suffit de regrouper les variables (par des parenthses) :
@maison = ("lit", "chaise", "table", "poele");

Inversement, si lon utilise @maison dans un contexte de liste, comme ce que lon trouve droite dune assignation, on obtient la mme liste qui a t entre. On peut donc assigner quatre variables depuis le tableau comme ceci :
($Procuste, $porteurs, $multiplication, $gratter) = @maison;

Cest ce que lon appelle des assignations de liste. Elles se produisent logiquement en parallle, et il est possible de permuter deux variables en crivant :
($alpha,$omega) = ($omega,$alpha);

Tout comme en C, les tableaux dmarrent zro ; quand on parle des quatre premiers

customer_8566

Langages naturels et artificiels

lments dun tableau, leur numration court de 0 3.6 Les indices de tableaux sont entours de crochets [comme ceci], et si lon veut slectionner un seul lment du tableau, on sy rfre par $maison[n], o n est lindice (un de moins que le numro de llment) que lon dsire ; voyez lexemple ci-dessous. Puisque llment considr est un scalaire, il est toujours prcd dun $. Si lon veut valoriser un seul lment de tableau la fois, on crit lassignation prcdente comme suit :
$maison[0] $maison[1] $maison[2] $maison[3] = = = = "lit"; "chaise"; "table"; "poele";

Comme les tableaux sont ordonns, il existe plusieurs oprations utiles sy rapportant, comme les oprations de pile, push et pop. Une pile nest aprs tout quune liste ordonne, avec un dbut et une fin. Surtout une fin. Perl considre que la fin de la liste est le haut dune pile (bien que la plupart des programmeurs Perl pensent quune liste est horizontale, le haut de la pile tant droite). Hachages. Un hachage (hash en anglais) est un ensemble non ordonn de scalaires index par une valeur chane associe chaque scalaire. Cest pourquoi les hachages sont souvent appels tableaux associatifs . La principale raison pour laquelle leur appellation a chang est que tableau associatif est long crire pour les paresseux, et nous en parlons tellement souvent que nous avons dcid de prendre un nom plus bref.7 Ensuite, le terme hachage souligne le fait quil sagit de tables non ordonnes. Elle sont en fait implmentes grce un systme de recherche dans une table de hachage, ce qui leur donne leur rapidit, rapidit qui reste inchange quel que soit le nombre de valeurs prsentes. On ne peut pas faire de push ou de pop sur un hachage, parce que cela na aucun sens. Un hachage na ni dbut, ni fin. Les hachages sont nammoins trs puissants et trs utiles. Tant que vous ne penserez pas en terme de hachages, vous ne penserez pas en Perl. Puisque les clefs dun tableau associatif ne sont pas ordonnes, vous devez fournir la clef aussi bien que sa valeur lorsque celui-ci est rempli. Vous pouvez aussi bien lui affecter une liste comme pour un tableau ordinaire, mais chaque paire dlments sera interprte comme la paire clef/valeur. Les tableaux associatifs utilisent le symbole % pour sidentifier. (Pour mmoire, si vous regardez attentivement le caractre %, vous pouvez voir la clef et sa valeur avec entre deux le /.) Supposons que nous voulions traduire les abrviations des noms de jours en leurs correspondants complets. Nous pourrions crire cette assignation de liste :
%longjour = ("Dim", "Dimanche", "Lun", "Lundi", "Mar", "Mardi", "Mer", "Mercredi", "Jeu", "Jeudi", "Ven", "Vendredi", "Sam", "Samedi");
6. Si cela vous semble bizarre, pensez lindice comme un offset, un dplacement, cest--dire le nombre dlments qui le prcdent. Il ny en a videmment aucun avant le premier lment, qui a donc un offset de zro. Cest ainsi que pensent les ordinateurs (cest du moins ce que nous pensons). 7. Si tant est que lon puisse qualifier de bref quoi que ce soit ayant trait aux hachages...

customer_8566

10

Chapitre 1 Vue densemble

Figure 1-1. Un tableau et un hachage Comme il est parfois difficile de lire un hachage ainsi dfini, Perl fournit la squence => (gal, suprieur) comme alternative la virgule. Cette syntaxe (associe un formatage cratif) facilite la distinction entre clefs et valeurs.
%longjour "Dim" "Lun" "Mar" "Mer" "Jeu" "Ven" "Sam" ); = ( => "Dimanche", => "Lundi", => "Mardi", => "Mercredi", => "Jeudi", => "Vendredi", => "Samedi",

Il est non seulement possible dassigner une liste un hachage, comme nous lavons fait ci-dessus, mais si lon emploie un hachage dans un contexte de liste, celui-ci convertira le hachage en une liste de paires clef/valeurs dans un ordre quelconque. La plupart du temps, on se contente dextraire une liste des seules clefs, grce la fonction (bien nomme) keys. Elle est galement non ordonne mais peut tre facilement trie au besoin grce la fonction (bien nomme) sort. On peut alors utiliser les clefs ordonnes pour accder aux valeurs dans un ordre dtermin. Les hachages ntant quune forme volue de tableau, il suffit den slectionner un lment individuel en entourant la clef par des accolades. Cest ainsi que pour trouver la

customer_8566

Langages naturels et artificiels

11

valeur associe Mer dans le hachage ci-dessus, il faut crire $longjour{"Mer"}. Remarquez encore une fois quil sagit dune valeur scalaire et quil faut donc crire $ et non %. Dun point de vue linguistique, la relation code dans un hachage est gnitive ou possessive, comme les mots de , du ou d en franais. La femme dAdam est Eve, et nous pouvons crire :
$femme{"Adam"} = "Eve";

Complexits
La famille des tableaux et des hachages permet de reprsenter des structures de donnes simples et lgantes, mais dans la ralit le problme ne se pliera pas toujours cette simplicit. Il est parfois ncessaire de construire des structures de donnes non linaires. Perl nous permet de raliser ce type de structure dune manire trs simple. Il permet en effet de manipuler de simples scalaires qui se rfrent des tableaux. Nous le faisons tous les jours dans le langage courant lorsque nous utilisons un mot par exemple aussi complexe que gouvernement pour reprsenter une entit aussi complexe et inscrutable. (Cest un exemple parmi dautres.) Pour dvelopper notre exemple prcdent, supposons que nous parlons des femmes de Jacob et Adam. Jacob a eu quatre femmes. Nous pourrions penser lcrire de cette faon :
$femme{"Jacob"} = ("La", "Rachel", "Bilha", "Zilpa"); # MAUVAIS

Mais cette reprsentation nest pas bonne car mme les parenthses ne sont pas assez puissantes pour transformer une liste en scalaire. (Les parenthses sont utilises pour le groupage syntaxique et les virgules pour la sparation syntaxique.) Il faut indiquer Perl que cette liste doit tre un scalaire. Les crochets sont parfaitement adapts cette fin :
$femme{"Jacob"} = ["La", "Rachel", "Bilha", "Zilpa"]; # ok

Cette ligne cre un tableau anonyme et affecte sa rfrence llment associatif $femme{"Jacob"}. Ainsi nous avons un tableau associatif nomm contenant un tableau anonyme. Cest comme a que Perl traite les tableaux multidimensionnels et les structures de donnes imbriques. Comme avec les types tableaux, on peut aussi affecter des lments spars comme ceci :
$femme{"Jacob"}[0] $femme{"Jacob"}[1] $femme{"Jacob"}[2] $femme{"Jacob"}[3] = = = = "La"; "Rachel"; "Bilha"; "Zilpa";

Comme vous pouvez le voir, cela ressemble beaucoup un tableau multidimensionnel avec des coordonnes de chane puis numrique. Visualisons maintenant une structure de donnes imbriques sous forme darbre o nous listons aussi tous les fils de chacune des femmes de Jacob. Dans ce cas nous voulons utiliser le tableau associatif dans un contexte scalaire. Pour cela utilisons les accolades. (La valeur de la clef est un tableau entre crochets. Maintenant nous avons un tableau lintrieur dune association, elle-mme association.)
$filsDesFemmesDe{"Jacob"} = { "La" => ["Ruben", "Simon", "Lvi", "Juda", "Issachar", "Zabulon"],

customer_8566

12
"Rachel" => ["Joseph", "Benjamin"], "Bilha" => ["Dan", "Nephtali"], "Zilpa" => ["Gad", "Aser"], };

Chapitre 1 Vue densemble

Les lignes suivantes sont quivalentes :


$fils_des_femmes_de{"Jacob"}{"La"}[0] $fils_des_femmes_de{"Jacob"}{"La"}[1] $fils_des_femmes_de{"Jacob"}{"La"}[2] $fils_des_femmes_de{"Jacob"}{"La"}[3] $fils_des_femmes_de{"Jacob"}{"La"}[4] $fils_des_femmes_de{"Jacob"}{"La"}[5] $fils_des_femmes_de{"Jacob"}{"Rachel"}[0] $fils_des_femmes_de{"Jacob"}{"Rachel"}[1] $fils_des_femmes_de{"Jacob"}{"Bilha"}[0] $fils_des_femmes_de{"Jacob"}{"Bilha"}[1] $fils_des_femmes_de{"Jacob"}{"Zilpa"}[0] $fils_des_femmes_de{"Jacob"}{"Zilpa"}[1] = = = = = = = = = = = = "Ruben"; "Simon"; "Lvi"; "Juda"; "Issachar"; "Zabulon"; "Joseph"; "Benjamin"; "Dan"; "Nephtali"; "Gad"; "Aser";

On peut constater sur cet exemple que nous avons rajout une dimension supplmentaire notre tableau. Perl nous laisse le choix, mais la reprsentation interne est identique. Le point important noter ici est que Perl nous permet de reprsenter une structure de donnes complexes comme un simple scalaire. Cette encapsulation nous permet de construire une structure oriente objet. Lorsque nous avions invoqu le constructeur de Chameau comme ceci :
$fido = new Chameau "Amelia";

nous avions cr un objet Chameau reprsent par le scalaire $fido. Mais la structure intime de lobjet Chameau est plus complique. En tant que concepteurs dobjets, nous ne sommes pas concerns par ceci, moins dtre nous-mmes les implmenteurs des mthodes de cette classe. Mais, gnralement, un objet comme celui-ci serait reprsent par un tableau associatif contenant les attributs de Chameau, tels son nom ( Amelia dans ce cas, et non pas fido ), le nombre de bosses (ce que nous navons pas spcifi, mais il vaut probablement 1, regardez la couverture du livre).

Simplicit
Si votre tte ne tourne pas aprs avoir lu cette dernire section alors vous avez une grosse tte. La plupart des humains sont rebuts par les structures compliques du type gouvernement ou du type arbre gnalogique. Pour cette raison nous disposons dans notre langage parl dartifices qui cachent cette complexit sous-jacente. La technique la plus probante est la clture du champ smantique, lexicalisation, topicalization en anglais, qui permet de saccorder sur les termes du langage utilis. La consquence immdiate est une meilleure communication. La plupart dentre nous utilisent cette technique couramment pour basculer dun contexte smantique vers un autre lorsque nous changeons simplement de sujet de conversation. Perl dispose dans sa palette de ce type doutil. Lun de ceux-ci est fourni par la simple dclaration package. Supposons que notre sujet est le Chameau de Perl. On dclenche le module Chameau par la dclaration :

customer_8566

Langages naturels et artificiels


package Chameau;

13

Tout symbole dclar ensuite sera prfix par le nom du module Chameau:: . Ainsi si on crit :
package Chameau; $fido = &fetch();

on crit en ralit $Chameau::fido et la fonction appele est &Chameau::fetch, (nous parlerons des verbes plus tard). Si dans le cours du droulement du code, linterprteur rencontre le code suivant :
package Chien; $fido = &fetch();

il ne pourra confondre les noms rels car $fido est en fait $Chien::fido, et non $Chameau::fido. En informatique cela signifie un espace de nommage. Il na pas de limite cardinale. Perl nen connat quun la fois. La simplification est le choix libre du programmeur. Une chose remarquable est que dans :
$fido = new Chameau "Amelia";

nous invoquons le verbe &new dans le package Chameau, qui a pour nom plein &Chameau::new. et par
$fido->seller();

nous invoquons la routine &Chameau::seller, car $fido pointe sur un Chameau. Cest la programmation objet en perl. La dclaration package Chameau, marque le dbut dun paquetage, ici le paquetage Chameau. Parfois il suffit dutiliser les noms et les verbes dun paquetage existant. On utilise alors la dclaration use, qui charge le module dans linterprteur. Cela doit scrire :
use Chameau;

Puis on peut utiliser nos mthodes


$fido = new Chameau "Amelia";

Perl est WYSIWYG. Sinon Perl ne connatrait pas Chameau. La chose intressante ici est quil est juste ncessaire de connatre les capacits dun Chameau. Il suffit de trouver le module sur CPAN :
use Le::Cool::Module;

Alors on peut actionner les verbes de ce module dans le champ du sujet. La lexicalisation Perl, comme dans le langage naturel, donne un nom au champ lexical. Certains modules dfinissent des ensembles lexicaux et uniquement cela, pour linterprteur lui-mme. Ces modules spciaux se nomment pragmas. On verra souvent lutilisation du pragma strict de cette manire :
use strict;

Le pragma strict permet dajouter une norme pour lvaluation des termes par Perl. Cette norme oblige prciser certains aspects comme la porte des variables du code, ce qui est utile dans le dveloppement de grands projets. En effet, Perl est optimis pour lcriture de petits modules, mais avec cette directive de compilation il devient possible

customer_8566

14

Chapitre 1 Vue densemble

de grer des projets importants. On peut en effet lajouter tout moment dans des modules lmentaires, ce qui permet de les faire interagir dans un mme champ lexical. (Et autoriser du mme coup une approche objet dans le dveloppement de lapplication elle-mme.)

Verbes
Comme tous les langages informatiques impratifs, de nombreux verbes de Perl correspondent des commandes : elles disent linterprteur de Perl de faire quelque chose. En revanche, comme dans un langage naturel, les significations des verbes de Perl tendent sparpiller dans plusieurs directions selon le contexte. Une instruction commenant par un verbe est en gnral purement imprative et value entirement pour ses effets secondaires. Nous appelons souvent ces verbes procdures, surtout quand ils sont dfinis par lutilisateur. Un verbe frquemment rencontr (que vous avez dailleurs dj vu) est la commande print :
print "La femme dAdam est ", $femme{Adam}, ".\n";

Leffet secondaire produit la sortie dsire. Mais il existe dautres modes que le mode impratif. Certains verbes permettent dinterroger linterprteur sur certaines valeurs comme dans les conditionnelles comme if. Dautres verbes traduisent leurs paramtres dentre en valeurs de retour, tout comme une recette vous indique comment transformer des ingrdients de base en un rsultat (peut-tre) comestible. Nous appelons souvent ces verbes des fonctions, par dfrence envers des gnrations de mathmaticiens qui ne savent pas ce que signifie le mot fonctionnel en langage naturel. Un exemple de fonction interne est lexponentielle :
$e = exp(1); # 2.718281828459, ou peu prs

Mais Perl ne fait pas de distinction entre les procdures et les fonctions. Les termes seront employs de faon interchangeable. Les verbes sont parfois appels sous-programmes (subroutines) quand ils sont dfinis par lutilisateur, ou oprateurs (sils sont prdfinis). Mais appelez-les comme il vous plaira ; ils renvoient tous une valeur, quelle soit ou non significative, que vous pouvez ou non choisir dignorer. Au fur et mesure que nous avanons, nous verrons dautres exemples du comportement de Perl qui le font ressembler un langage naturel. Nous avons dj insidieusement prsent certaines notions de langage mathmatique, comme laddition et les indices, sans parler de la fonction exponentielle. Perl est aussi un langage de contrle, un langage dintgration, un langage de traitement de listes et un langage orient objet. Entre autres. Mais Perl est aussi un bon vieux langage informatique. Et cest ce quoi nous allons maintenant nous intresser.

Un exemple de notation
Supposons que vous ayez un ensemble de notes pour chaque membre dune classe dlves. Vous aimeriez une liste combine de toutes les notes pour chaque tudiant, plus leur moyenne. Vous disposez dun fichier texte (appel, quelle imagination,

customer_8566

Un exemple de notation
notes ) qui ressemble ceci :
Xavier 25 Samantha 76 Herv 49 Peter 66 Olivier 92 Thierry 42 Fred 25 Samantha 12 Herv 0 Corinne 66 etc.

15

Le script ci-dessous rassemble toutes leurs notes, dtermine la moyenne de chaque tudiant et les affiche dans lordre alphabtique. Ce programme suppose, plutt navement, quil nexiste pas deux Corinne dans votre classe. Cest--dire que sil y a un deuxime lment pour Corinne, le programme supposera quil sagit dune autre note de la premire Corinne. Au fait, les numros de lignes ne font pas partie du programme, toute ressemblance avec le BASIC mise part.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: #!/usr/bin/perl open(NOTES, "notes") or die "Ouverture des notes impossible : $!\n"; while ($ligne = <NOTES>) { ($etudiant, $note) = split(/ /, $ligne); $notes\{$etudiant\} .= $note . " "; } foreach $etudiant (sort keys %notes) { $scores = 0; $total = 0; @notes = split(/ /, $notes{$etudiant}); foreach $note (@notes) { $total += $note; $scores++; } $moyenne = $total / $scores; print "$etudiant: $notes{$etudiant}\tMoyenne : $moyenne\n"; }

Ne louchez pas ainsi. Nous devons avouer que si cet exemple illustre beaucoup de ce que nous avons dcrit jusqu prsent, il comprend certaines choses que nous allons maintenant expliquer. Mais si vous regardez un peu dans le vague, vous pouvez commencer voir apparatre certains motifs intressants. Vous pouvez vous livrer toutes les suppositions imaginables, et nous vous dirons plus tard si vous aviez raison. Nous pourrions vous dire dessayer de le lancer, mais peut-tre ne savez-vous pas comment faire.

customer_8566

16

Chapitre 1 Vue densemble

Comment faire
Bien. Vous devez tre en train de vous demander comment lancer un programme Perl. La rponse la plus courte est que vous le donnez au programme interprteur de Perl, qui sappelle justement perl (notez le p minuscule). Une rponse plus complte commence comme ceci : Il Existe Plus DUne Faon De Faire.8 La premire manire dinvoquer perl (qui fonctionne sur la plupart des systmes dexploitation) est dappeler explicitement perl depuis la ligne de commande.9 Si vous vous trouvez sur une version dUNIX et que ce que vous faites est relativement simple, vous pouvez utiliser loption -e (le % de lexemple suivant reprsentant une invite standard de shell, il ne faut pas le taper) :
% perl -e print "Salut tout le monde!\n";

Sous dautres systmes dexploitation, il faudra peut-tre jouer des apostrophes. Mais le principe de base est le mme : vous essayez de rentrer tout ce que Perl doit savoir en 80 colonnes.10 Pour les scripts plus longs, vous pouvez utiliser votre diteur favori (ou un autre) pour crire vos commandes dans un fichier, puis, si le script sappelle gradation , vous entrez :
% perl gradation

Vous invoquez toujours explicitement linterprteur Perl, mais au moins, vous navez pas tout mettre sur la ligne de commande chaque fois. Et vous navez pas jouer des apostrophes pour plaire au shell. La faon la plus commode dinvoquer un script est de simplement lappeler par son nom (ou de cliquer sur son icone), et de laisser le systme dexploitation trouver linterprteur tout seul. Sous certains systmes, il peut exister un moyen dassocier certaines extensions de fichier ou certains rpertoires une application particulire. Sur les systmes UNIX qui supportent la notation #! (appele shebang), la premire ligne du script peut tre magique et dire au systme dexploitation quel programme lancer. Mettez une ligne ressemblant11 la ligne 1 de notre exemple dans votre programme :
#!/usr/bin/perl

Tout ce quil vous reste crire est maintenant :


% gradation

Ce qui ne fonctionne videmment pas parce que vous avez oubli de rendre le script ex8. Theres More Than One Way To Do It : cest le slogan de Perl, et vous allez tre fatigu de lentendre, moins que vous ne soyez lExpert Local, auquel cas vous serez fatigu de le rpter. Il est quelquefois raccourci en TMTOWTDI, que lon prononce tim-toady . Mais vous pouvez le prononcer de la faon qui vous plat. Aprs tout, TMTOWTDI. 9. En supposant que vous disposez dune ligne de commande. Si vous travaillez avec un vieux Mac, vous aurez besoin de faire une mise jour vers le systme OS X. 10. Ce genre de script est souvent appel one-liner, une-ligne . Sil vous arrive de frquenter dautres programmeurs Perl, vous dcouvrirez que certains dentre eux sont friands de une-lignes. Perl a parfois t qualifi de langage en criture seule cause de ces voyous. 11. Si Perl ne se trouve pas dans /usr/bin, vous devrez changer la ligne #!.

customer_8566

Handles de fichiers

17

cutable (voir la page de manuel de chmod(1)12 et quil nest pas dans votre PATH. Dans ce cas, vous devrez fournir un nom de chemin complet pour que votre systme dexploitation sache comment trouver votre script. Quelque chose comme :
% ../bin/gradation

Enfin, si vous avez la malchance de travailler sur un ancien systme UNIX qui ne reconnat pas la ligne magique #!, ou si le chemin vers votre interprteur est plus long que 32 caractres (une limite interne sur certains systmes), vous pourrez contourner le problme comme ceci :
#!/bin/sh -- # perl, pour arrter de boucler eval exec /usr/bin/perl -S $0 ${1+"$@"} if 0;

Certains systmes dexploitation peuvent demander une modification de ce qui prcde pour grer, /bin/sh, DCL, COMMAND.COM, ou tout ce qui vous tient lieu dinterprteur de commandes. Demandez votre Expert Local. Tout au long de ce livre, nous nous contenterons demployer #!/usr/bin/perl pour reprsenter toutes ces notions et toutes ces notations, mais vous saurez quoi vous en tenir. Une astuce : quand vous crivez un script de test, ne lappelez pas test. Les systmes UNIX ont une commande test interne, qui sera excute la place de votre script. Appelez-le plutt essai. Une autre astuce : pendant que vous apprenez Perl, et mme quand vous croyez savoir ce que vous faites, nous vous suggrons dutiliser loption -w, surtout pendant le dveloppement. Cette option active toutes sortes de messages davertissement utiles et intressants (dans le dsordre). Loption -w peut tre place sur la ligne magique , comme ceci :
#!/usr/bin/perl -w

Maintenant que vous savez lancer votre programme Perl ( ne pas confondre avec le programme perl), revenons notre exemple.

Handles de fichiers
moins quil ne sagisse dun projet dIA modlisant un philosophe solipsiste, votre programme a besoin de communiquer avec le monde extrieur. Aux lignes 3 et 4 de notre exemple de notation, on voit le mot NOTES, qui illustre un autre type de donnes de Perl, le handle de fichier. Un handle de fichier est un nom que lon donne un fichier, un priphrique, une socket ou un pipe pour que vous puissiez vous souvenir de ce dont

12. Bien que Perl ait son lot de notations bizarres, celle-ci doit tout UNIX. chmod(1) signifie que vous devez vous reporter la page de manuel de la commande chmod la section 1 de votre manuel UNIX. Si vous entrez soit man 1 chmod, soit man -s 1 chmod (selon votre type dUNIX), vous devriez trouver tout ce que sait votre systme de la commande chmod. (Bien sr, si votre type dUNIX est Pas UNIX ! , vous devrez vous rfrer la documentation de votre systme pour la commande quivalente, supposer que vous en soyez pourvu. Votre consolation tant que, si cette commande existe, elle aura un meilleur nom que chmod.)

customer_8566

18

Chapitre 1 Vue densemble

vous parlez, et pour dissimuler certaines complexits, notamment relatives au tampons. (En interne, les handles de fichiers sont similaires aux streams dun langage comme C ou C++, ou aux canaux dE/S du BASIC.) Les handles de fichiers facilitent la gestion des entres et des sorties depuis plusieurs sources et vers plusieurs destinations. Cest sa capacit communiquer avec de nombreux fichiers et de nombreux processus qui fait de Perl un bon langage dintgration.13 On cre un handle de fichier et on lattache un fichier par la fonction open. open prend deux paramtres : le handle de fichier et le nom du fichier auquel on veut lassocier. Perl vous donne aussi quelques handles de fichier prdfinis (et dj ouverts). STDIN est le canal dentre standard du programme, alors que STDOUT en est le canal de sortie standard. Et STDERR est un canal de sortie supplmentaire pour que votre programme puisse faire des remarques part pendant quil transforme (ou essaye de transformer) votre entre en sortie.14 Comme lon peut utiliser la fonction open pour crer des handles de fichiers des fins diverses (entres, sorties, pipes), vous devrez pouvoir spcifier le comportement que vous dsirez. Il suffit dajouter des caractres au nom du fichier.
open(SESAME, open(SESAME, open(SESAME, open(SESAME, open(SESAME, open(SESAME, "nomdefichier"); "<nomdefichier "); ">nomdefichier "); ">>nomdefichier "); "| sortie_de_commande"); "entre de commande |"); # lire depuis un fichier existant # (idem, explicitement) # crer un fichier et y crire # ajouter un fichier existant # mettre en place un filtre de sortie # mettre en place un filtre dentre

On voit que le nom en question est quelconque. Une fois ouvert, le handle de fichier SESAME peut tre utilis pour accder au fichier, ou au pipe, jusqu ce quil soit explicitement ferm (avec, on sen doutait, close(SESAME)), ou si le handle de fichier est attach un autre fichier par un autre open sur le mme handle.15 Une fois le handle de fichier ouvert en entre (ou si vous dsirez utiliser STDIN), vous pouvez lire une ligne grce loprateur de lecture de ligne, <>. Il est galement connu

13. Sans oublier les qualits suivantes : il travaille sur 8 bits sans problme, il est intgrable, et on peut y intgrer dautres choses via ses modules dextension. Il est concis et travaille sans problme en rseau. Il est pour ainsi dire conscient de son environnement. Il est possible de linvoquer de bien des manires (comme nous lavons dj vu). Mais surtout, le langage lui-mme est assez souple pour quil soit possible de le faire circuler autour dun problme. On revient encore ce fameux concept de TMTOWTDI. 14. Ces handles de fichier sont typiquement attachs votre terminal et vous pouvez donc entrer des donnes vers votre programme et en voir le rsultat, mais ils peuvent aussi se rattacher des fichiers (ou quivalents). Perl fournit ces handles prdfinis parce que le systme dexploitation les fournit dj, dune faon ou dune autre. Sous UNIX, les processus hritent de lentre, de la sortie et de lerreur standard de leur processus pre, typiquement un shell. Lune des tches dun shell est de mettre en place ces f lux dE/S afin que le processus fils nait pas sen proccuper. 15. Louverture dun handle de fichier dj ouvert ferme implicitement le premier fichier, le rendant ainsi inaccessible ce handle, et ouvre un fichier diffrent. Il faut faire attention ce que lon veut vraiment faire. Cela se produit parfois accidentellement, comme quand lon crit open($handle, $fichier), et que $handle contient une chane constante. Assurez-vous dassigner $handle, ou vous ne ferez quouvrir un nouveau fichier sur le handle nul.

customer_8566

Oprateurs

19

sous le nom doprateur diamant en raison de sa forme. Loprateur diamant entoure le handle de fichier <SESAME> dont on veut lire des lignes.16 Un exemple utilisant le handle de fichier STDIN pour lire une rponse fournie par lutilisateur ressemblerait ceci :
print STDOUT "Entrez un nombre : "; $nombre = <STDIN>; print STDOUT "Le nombre est $nombre\n"; # demander un nombre # entrer le nombre # afficher le nombre

Avez-vous vu ce que nous venons de vous glisser sous les pieds ? Quest-ce que ce STDOUT fait dans ces instructions print ? Cest simplement une des faons possibles dutiliser un handle de fichier. Un handle de fichier peut tre fourni comme premier argument de linstruction print et, sil est prsent, il indique o est la sortie. Dans ce cas, le handle de fichier est redondant, car la sortie aurait, de toute manire, t STDOUT. De mme que STDIN est lentre par dfaut, STDOUT est la sortie par dfaut (nous lavons enlev en ligne 18 de lexemple de notation pour viter de vous embrouiller). Nous avons fait autre chose. Si vous essayez lexemple ci-dessus, vous pouvez voir apparatre une ligne vide supplmentaire. En effet, la lecture nenlve pas automatiquement le saut de ligne de votre ligne dentre (qui serait par exemple 9\n ). Au cas o vous voudriez enlever le saut de ligne, Perl fournit les fonctions chop et chomp. chop enlve (et renvoie) le dernier caractre quon lui passe sans se poser de question, alors que chomp nenlve que le marqueur de fin denregistrement (en gnral, "\n") et renvoie le nombre de caractres enlevs. Cette expression est souvent employe pour lire une seule ligne :
chop($nombre = <STDIN>); # lire le nombre et enlever le saut de ligne # lire le nombre # enlever le saut de ligne

ce qui est identique


$number = <STDIN>; chop($number);

Oprateurs
Comme nous lavons laiss entendre plus haut, Perl est galement un langage mathmatique. Cest vrai diffrents niveaux, depuis les oprations logiques au niveau binaire jusquaux manipulations de nombres et densembles, de prdicats plus vastes diverses abstractions. Et comme nous le savons tous depuis que nous avons tudi les mathmatiques lcole, les mathmaticiens adorent les symboles tranges. Pire encore, les informaticiens ont invent leur propre version de ces symboles. Perl en connat un certain nombre, mais vous pouvez respirer car la plupart sont directement emprunts au C, au FORTRAN, sed ou awk, et seront donc familiers aux utilisateurs de ces langages. Vous pouvez vous fliciter de connatre plus de termes lexicaux, autant de point dentre vers les autres langages. Les oprateurs internes de Perl peuvent tre classs par nombre doprandes, en oprateurs unaires, binaires et ternaires. Ils peuvent tre classs par oprateurs infixes ou pr-

16. Loprateur diamant par dfaut, <>, lit des lignes depuis tous les fichiers spcifis sur la ligne de commande, ou depuis STDIN si aucun na t spcifi (ce comportement est standard pour de nombreux programmes filtres UNIX).

customer_8566

20

Chapitre 1 Vue densemble

fixes, mais aussi par le type dobjet avec lesquels ils travaillent, comme les nombres, les chanes ou les fichiers. Nous vous donnerons plus loin une table de tous les oprateurs, mais en voici quelques-uns par lesquels vous pourrez commencer.

Quelques oprateurs darithmtique binaire


Les oprateurs arithmtiques font exactement ce que lon peut attendre deux aprs les avoir tudis lcole.
Exemple $a + $b $a * $b $a % $b $a ** $b Nom Addition Multiplication Modulo Puissance Rsultat Somme de $a et de $b. Produit de $a et de $b. Reste de $a divis par $b. $a puissance $b.

Oui, nous avons bien laiss de ct la soustraction et la division. Mais vous devez pouvoir deviner comment celles-ci fonctionnent. Essayez-les et voyez si vous aviez raison (ou trichez et cherchez dans le chapitre 3, Oprateurs unaires et binaires.) Les oprateurs arithmtiques sont valus dans lordre habituel (cest--dire la puissance avant la multiplication, et la multiplication avant laddition). Les parenthses servent modifier lordre.

Oprateurs sur les chanes


Il existe galement un oprateur d addition pour les chanes, qui effectue leur concatnation. Contrairement dautres langages qui le confondent avec laddition arithmtique, Perl dfinit un oprateur distinct (.) pour cette opration.
$a = 123; $b = 456; print $a + $b; print $a . $b;

# affiche 579 # affiche 123456

Il existe aussi un oprateur de multiplication pour les chanes, galement appele rptition. Il sagit encore dun oprateur distinct (x) qui le diffrencie de la multiplication numrique :
$a = 123; $b = 3; print $a * $b; print $a x $b;

# affiche 369 # affiche 123123123

Loprateur de rptition est un peu inhabituel en ce quil prend une chane pour son argument de gauche et un nombre pour celui de droite. Remarquez galement comment Perl convertit automatiquement les nombres en chanes. Tous les nombres ci-dessus pourraient tre protgs par des apostrophes doubles avec le mme rsultat. La conversion interne se serait par contre produite dans le sens inverse (cest--dire de chanes vers des nombres).

customer_8566

Oprateurs

21

Il faut encore penser quelques dtails. La concatnation de chanes est galement implicite dans linterpolation qui se produit dans des chanes entre doubles apostrophes. Quant une liste de valeurs est affiche, les chanes de caractres sont en fait concatnes. Les trois instructions suivantes produisent donc le mme rsultat :
print $a . est gal . $b . "\n"; print $a, est gal , $b, "\n"; print "$a est gal $b\n"; # oprateur point # liste # interpolation

Le choix de celui quil convient dutiliser ne dpend que de vous. Loprateur x peut sembler relativement inutile premire vue, mais il trouve son utilit dans des cas comme celui-ci :
print "-" x $lrgecr, "\n";

Ceci trace une ligne travers lcran, supposer que sa largeur soit $lrgecr.

Oprateurs daffectation
Bien quil ne sagisse pas vraiment dun oprateur mathmatique, nous avons dj employ en de nombreuses occasions loprateur dassignation simple, =. Essayez de vous souvenir que = signifie est mis au lieu de gale (il existe aussi un oprateur dgalit mathmatique == qui signifie gale , et si vous commencez rf lchir tout de suite la diffrence entre les deux, vous aurez beaucoup moins mal la tte plus tard. Loprateur == est comme une fonction qui renvoie une valeur boolenne, alors que = est comme une procdure value dont leffet est de modifier une variable). De mme que les oprateurs prcdents, les oprateurs dassignation sont des oprateurs binaires infixes, ce qui veut dire quils ont un oprande de chaque ct de loprateur. Loprande de droite peut tre nimporte quelle expression, mais celui de gauche doit tre une lvalue correcte (ce qui, traduit en bon franais, signifie un emplacement de stockage valide, comme une variable ou un lment de tableau). Loprateur dassignation le plus courant est lassignation simple. Il dtermine la valeur de lexpression sa droite, puis met la variable sa gauche cette valeur :
$a = $b; $a = $b + 5; $a = $a * 3;

Remarquez que la dernire assignation se rfre deux fois la mme variable ; une fois pour le calcul et une autre pour lassignation. Rien dextraordinaire cela, mais cette opration est assez commune pour quelle connaisse une abrviation (emprunte au C). Si lon crit :
lvalue oprateur= expression

cela sera valu comme si ctait :


lvalue = lvalue oprateur expression

sauf que la lvalue nest pas calcule deux fois. On ne peroit de diffrence que si lvaluation de la lvalue a un effet secondaire. Mais quand il y a une diffrence, loprateur fait gnralement ce que vous vouliez. On peut, par exemple, crire :
$a *= 3;

customer_8566

22

Chapitre 1 Vue densemble

ce qui se lit multiplier $a par 3 et laffecter $a . Presque tous les oprateurs binaires de Perl le permettent, et mme certains de ceux qui ne le peuvent pas en C :
$ligne .= "\n"; # Ajouter un saut de ligne $ligne. $fill x= 80; # Rpter $fill 80 fois sur elle-mme. $val ||= "2"; # Mettre $val 2 si ce nest pas dj le cas.

La ligne 6 de notre exemple17 de notation contient deux concatnations de chanes, dont lune est un oprateur daffectation. Et la ligne 14 contient un +=. Quel que soit le type doprateur daffectation utilis, la valeur finale qui est renvoye est celle de laffectation complte18. Ceci ne surprendra pas les programmeurs C qui le savait dj en crivant
$a = $b = $c = 0;

pour initialiser 0 toutes les variables. Ce qui par contre les surprendra est que laffectation Perl retourne en lvalue la variable elle-mme, de telle sorte quil est possible en une instruction de le modifier deux fois, cest pourquoi nous pouvons crire :
($temp -= 32) *= 5/9;

pour faire la conversion en ligne Fahrenheit vers Celsius. Cest aussi pourquoi nous avons pu crire plus haut dans ce chapitre :
chop($nombre = <STDIN>);

pour que la valeur finale de $nombre soit modifie par chop. Pour rsumer, on peut utiliser cette fonctionalit chaque fois que lon veut faire une copie suivie dune modification de variable. Ce truc peut tre utilis pour faire deux choses sur la mme ligne Perl.

Oprateurs arithmtiques unaires


Comme si $variable += 1 ntait pas assez court, Perl emprunte au C un moyen encore plus concis dincrmenter une variable. Les oprateurs dautoincrmentation et dautodcrmentation ajoutent (ou soustraient) un la valeur de la variable. Ils peuvent tre placs avant ou aprs cette variable, ce qui dtermine le moment de leur valuation.
Exemple ++$a, $a++ --$a, $a-Nom Autoincrmentation Autodcrmentation Rsultat Ajouter 1 $a. Soustraire 1 de $a.

Si lon place lun des oprateurs auto avant la variable, il sagit dune variable princrmente (ou prdcrmente). Sa valeur sera modifie avant son rfrencement. Sil est

17. Vous ne lavez pas oubli ? 18. Ce qui diffre du Pascal, par exemple, o laffectation est une instruction et na pas de valeur. Nous avons dit que laffectation est comme un procdure, mais souvenez-vous quen Perl les procdures aussi ont une valeur.

customer_8566

Oprateurs

23

plac aprs la variable, il sagit dune variable post-incrmente (ou post-dcrmente) et sa valeur est modifie aprs son utilisation. Par exemple :
$a = 5; $b = ++$a; $c = $a--; # $a prend la valeur 5 # $b prend la valeur incrmente de $a, soit 6 # $c prend la valeur 6, puis $a passe 5

La ligne 15 de notre exemple de notation incrmente de un le nombre de notes, afin que nous puissions calculer la moyenne. Nous utilisons un oprateur de postincrmentation ($scores++), mais cela na pas dimportance dans ce cas puisque lexpression se trouve dans un contexte vide, ce qui nest quune faon particulire de dire que lexpression nest value que pour leffet secondaire de lincrmentation de la variable. La valeur renvoye est jete au panier.19

Oprateurs logiques
Les oprateurs logiques, que lon connat galement sous le nom doprateurs courtcircuit , permettent au programme de prendre des dcisions en fonction de critres multiples sans utiliser les conditionnelles imbriques. On les appelle court-circuit car ils arrtent lvaluation de leur argument de droite si largument de gauche suffit dterminer la valeur globale. Perl a en fait deux ensembles doprateurs logiques : lun deux, plutt poussireux, emprunt au C, et un superbe ensemble tout neuf doprateurs prcdence ultra-basse qui analysent plus comme ce quon en attend (mais ils se comportent de la mme faon une fois analyss). Perl possde deux ensembles doprateurs logiques, lun dit traditionnel emprunt au C, lautre avec une prcdence encore plus faible venant du BASIC. Lun a la prcdence la plus forte des oprateurs du langage, lautre la plus faible. Souvent les expressions sont quivalentes, cest une question de prfrences. (Pour une comparaison, voir la section And, or, not et xor logiques au chapitre 3.) Bien quils ne sont pas interchangeables, cause de la prcdence, une fois parss ils sexcutent avec le mme code. La prcdence prcise ltendue locale de arguments. Tableau 1-1. Oprateurs logiques
Exemple $a && $b $a || $b ! $a $a and $b $a or $b not $a $a xor $b Nom Et Ou Non Et Ou Non Ou exclusif Rsultat $a si $a est faux, $b sinon. $a si $a est vrai $b sinon. Vrai si $a nest pas vrai. $a si $a est faux, $b sinon. $a si $a est vrai, $b sinon. Vrai si $a nest pas vrai. Vrai si $a ou $b est vrai, mais pas les deux.

19. Et en fait, loptimisateur le remarque et optimise la post-incrmentation en princrmentation, qui est un peu plus efficace lexcution (ce que vous navez pas vraiment besoin de savoir, mais nous pensions que cela pouvait vous intresser).

customer_8566

24

Chapitre 1 Vue densemble

Puisque les oprateurs logiques court-circuitent , ils sont souvent utiliss pour excuter du code de manire conditionnelle. La ligne suivante (de notre exemple de notation) essaie douvrir le fichier notes . Si elle peut ouvrir le fichier, elle saute la ligne suivante du programme. Dans le cas contraire, elle affiche un message derreur et arrte lexcution.
open(NOTES, "notes") or die "Ouverture du fichier notes impossible: $!\n";

Littralement, Ouvrir notes ou mourir ! est encore un exemple de langage naturel, et les oprateurs de court-circuit prservent le f lux visuel. Les actions importantes sont listes en bas gauche de lcran et les actions secondaires sont caches droite. (La variable $! contient le message derreur renvoy par le systme dexploitation ; voir le chapitre 28, Noms spciaux.) Bien sr, ces oprateurs logiques peuvent aussi tre employs dans des constructions plus traditionnelles, comme les instructions if et while.

Oprateurs de comparaison
Les oprateurs de comparaison, ou relationnels, nous indiquent la relation existant entre deux valeurs scalaires (nombres ou chanes). Il existe deux ensembles doprateurs, dont lun effectue les comparaisons numriques et lautre des comparaisons de chanes. (Dans les deux cas, les arguments seront dabord transtyps, contraints , pour prendre le bon type.) Le tableau suivant suppose que $a et $b sont respectivement les arguments de gauche et de droite.
Comparaison gal Diffrent Infrieur Suprieur Infrieur ou gal Suprieur ou gal Comparaison Numrique == != < > <= >= <=> Chane eq ne lt gt le ge cmp Valeur de retour Vrai si $a est gal $b. Vrai si $a nest pas gal $b. Vrai si $a est plus petit que $b. Vrai si $a est plus grand que $b. Vrai si $a est infrieur ou gal $b. Vrai si $a est suprieur ou gal $b. 0 si gal, 1 si $a sup., -1 si $b sup.

On peut penser que les deux derniers oprateurs (<=> et cmp) sont entirement redondants. Vous avez raison. Cependant, ils sont incroyablement utiles dans les sous-programmes de tri (sort).20

20. Certains voient en la redondance le mal incarn car elle interdit un langage dtre minimaliste, ou orthogonal . Mais Perl nest pas orthogonal, il est diagonal . Nous entendons par ceci que Perl ne vous force pas tourner sans arrt angle droit. Il vaut parfois mieux suivre lhypothnuse du triangle pour aller o lon veut. Qui dit TMTOWTDI dit courts-circuits. Qui dit courts-circuits dit efficacit.

customer_8566

Structures de contrle

25

Oprateurs de tests de fichier


Les oprateurs de tests de fichier permettent de tester si certains attributs de fichier sont positionns avant de faire aveuglment nimporte quoi avec ces fichiers. Par exemple, il vaut mieux sassurer que le fichier /etc/passwd existe dj avant de louvrir en cration, effaant ainsi tout ce qui sy trouvait auparavant.
Exemple -e $a -r $a -w $a -d $a -f $a -T $a Nom Existe Lecture criture Rpertoire Fichier Fichier texte Rsultat Vrai si le fichier nomm par $a existe. Vrai si le fichier nomm par $a est accessible en lecture. Vrai si le fichier nomm par $a est accessible en criture. Vrai si le fichier nomm par $a est un rpertoire. Vrai si le fichier nomm par $a est un fichier rgulier. Vrai si le fichier nomm par $a est un fichier texte.

En voici quelques exemples :


-e "/usr/bin/perl" or warn "Perl est mal install\n"; -f "/boot" and print "Flicitations, nous devons tre sous Unix BSD\n";

Remarquez quun fichier rgulier nest pas la mme chose quun fichier texte. Les fichiers binaires comme /vmunix sont des fichiers rguliers, mais ne sont pas des fichiers texte. Les fichiers texte sont linverse des fichiers binaires, alors que les fichiers rguliers sont linverse des fichiers irrguliers comme les rpertoires et les priphriques. Il existe beaucoup doprateurs de test de fichier, dont un grand nombre nont pas t cits. La plupart sont des oprateurs boolens unaires : ils ne prennent quun seul oprande, un scalaire qui donne un fichier ou un handle de fichier, et ils renvoient une valeur vraie ou fausse. Quelques-uns renvoient une valeur plus complexe comme la taille du fichier ou son ge, mais vous pourrez les rechercher en temps utile dans la section Oprateurs unaires nomms et de test de fichier au chapitre 3.

Structures de contrle
Jusquici, et hormis notre programme de notation, tous nos exemples taient compltement linaires ; toutes les commandes taient excutes dans lordre. Nous avons vu quelques exemples dutilisation des oprateurs court-circuit permettant lexcution conditionnelle dune commande. Bien que certains programmes linaires savrent extrmement utiles (cest le cas de beaucoup de scripts CGI), on peut crire des programmes bien plus puissants grce aux expressions conditionnelles et aux mcanismes de boucles, que lon appelle structures de contrle. Perl peut donc tre considr comme un langage de contrle. Mais pour contrler le cours des choses, il faut tre en mesure de dcider, et pour dcider des choses, il faut distinguer le vrai du faux.

customer_8566

26

Chapitre 1 Vue densemble

Quest-ce que la vrit ?


Nous avons dj parl de la vrit21 et nous avons mentionn que certains oprateurs renvoient une valeur vraie ou fausse. Avant de continuer, nous devons expliquer exactement ce que nous entendons par l. Perl ne traite pas tout fait la vrit comme les autres langages informatiques, mais son comportement prend tout son sens avec un peu dhabitude. (En fait, nous esprons quil prendra tout son sens aprs avoir lu ce qui suit.) la base, Perl estime que la vrit est vidente en soi . Cest une faon un peu spcieuse de dire que lon peut valuer presque nimporte quoi pour connatre sa valeur de vrit. Perl emploie en pratique des dfinitions de la vrit qui dpendent du type de ce que lon est en train dvaluer. Il se trouve quil existe beaucoup plus de types de vrit que de types de non-vrit. La vrit en Perl est toujours value dans un contexte scalaire (sinon, aucun transtypage nest effectu). Voici donc les rgles des divers types de valeurs quun scalaire peut contenir : 1. Toute chane est vraie sauf "" et "0". 2. Tout nombre est vrai sauf 0. 3. Toute rfrence est vraie. 4. Toute valeur indfinie est fausse. En fait, les deux dernires rgles peuvent tre drives des deux premires. Toute rfrence (rgle 3) pointe vers quelque chose avec une adresse, et donne un nombre ou une chane contenant cette adresse, qui nest jamais nulle. Et toute valeur indfinie (rgle 4) donne 0 ou la chane nulle. Et dune certaine manire, il est possible de faire driver la rgle 2 de la rgle 1 si lon pose que tout est une chane. Encore une fois, aucun transtypage nest effectu pour valuer la vrit, mais mme si ctait le cas, une valeur numrique de 0 donnerait simplement la chane "0" et serait fausse. Tout autre nombre donnerait autre chose et serait vrai. Quelques exemples nous permettront de saisir un peu mieux ce que cela implique :
0 # deviendrait la chane "0", donc faux 1 # deviendrait la chane "1", donc vrai 10 - 10 # 10-10 vaut 0, deviendrait la chane "0", donc faux 0.00 # devient 0, et donc la chane "0", donc faux "0" # la chane "0", donc faux "" # une chane nulle, donc faux "0.00" # la chane "0.00", ni vide, ni vraiment "0", donc vrai "0.00" + 0 # le nombre 0 (transtyp par +), donc faux \$a # une rfrence $a, donc vrai, mme si $a est faux undef() # une fonction renvoyant la chane indfinie, donc faux

Comme nous avons dj dit que la vrit tait value dans un contexte scalaire, on peut se demander quelle serait la valeur dune liste. En fait, il nexiste pas dopration renvoyant une liste dans un contexte scalaire. Toutes renvoient une valeur scalaire et il suffit dappliquer les rgles de vrit ce scalaire. Il ny a donc pas de problme, tant que lon sait ce quun oprateur donn renvoie dans un contexte scalaire.
21. dire vrai, ce nest pas tout fait exact.

customer_8566

Structures de contrle

27

Les instructions if et unless


Nous avons vu plus haut comment un oprateur logique pouvait fonctionner comme un conditionnel. Une forme un peu plus complexe des oprateurs logiques est linstruction if. Celui-ci value une condition de vrit et excute un bloc si la condition est vraie.
if ($debug_level > 0) { # Quelque chose ne va pas. Il faut avertir lutilisateur. print "Debug: Danger, Arthur Accroc, danger!\n"; print "Debug: La rponse est 54 au lieu de 42.\n"; }

Un bloc consiste en une ou plusieurs instructions regroupes par un ensemble daccolades. Puisque linstruction if excute un bloc, les accolades sont ncessaires par dfinition. Dans un langage comme le C, on constate une certaine diffrence. Les accolades sont optionnelles sil ny a quune ligne de code, ce qui nest pas le cas en Perl. Parfois, il ne suffit pas dexcuter un bloc quand une condition est remplie. On dsire galement excuter un autre bloc quand la condition nest pas remplie. Bien que lon puisse videmment employer deux instructions if, lune tant la ngation de lautre, Perl fournit une solution plus lgante. Aprs le bloc, if peut prendre une deuxime condition optionnelle, appele else, qui nest excute que si la conditionnelle est fausse (les vtrans de linformatique nen seront pas surpris). En dautres occasions, vous pouvez mme avoir plus de deux choix possibles. En ce cas, il est possible dajouter une conditionnelle elsif pour les autre choix possibles (les vtrans de linformatique stonneront bon droit de la faon dcrire elsif , mais personne ici ne sen excusera).
if ($city eq "Lille") { print "Lille est au nord de Paris.\n"; } elsif ($city eq "Nancy") { print "Nancy est lest de Paris.\n"; } elsif ($city eq "Bayonne") { print "Bayonne est au sud-ouest de Paris. Et il y fait plus chaud!\n"; } else { print "Je ne sais pas o se trouve $city, dsol.\n"; }

Les clauses if et elsif sont calcules chacune leur tour, jusqu ce que lune dentre elles soit vraie ou que la condition else soit atteinte. Quand lune de ces conditions est vraie, son bloc est excut et toutes les branches restantes sont sautes. Parfois, on ne veut faire quelque chose que si la condition est fausse, et rien si elle est vraie. Un if vide avec un else nest pas trs propre, et la ngation dun if peut tre illisible ; il est dommage dcrire faire quelque chose si pas ceci est vrai . Dans ce cas, on peut utiliser linstruction unless.
unless ($destination eq $maison) { print "Je ne rentre pas la maison.\n"; }

Il nexiste pas de elsunless. Il sagit l dune caractristique.

customer_8566

28

Chapitre 1 Vue densemble

Constructions itratives (en boucle)


Perl possde quatre types principaux dinstructions itratives : while, until, for et foreach. Ces instructions permettent un programme Perl dexcuter de faon rptitive le mme code pour diffrentes valeurs.

Les instructions while et until


Les instructions while et until fonctionnent de la mme manire que les instructions if et unless, sauf quils rptent lexcution du bloc en bouclant. Dabord, la partie conditionnelle dune instruction est vrifie. Si la condition est remplie (si elle est vraie pour un while ou fausse pour un until), le bloc de linstruction est excut.
while ($tickets_vendus < 10000) { $dispo = 10000 - $tickets_vendus; print "$dispo tickets sont disponibles. Combien en voulez -vous: "; $achat = <STDIN>; chomp($achat); $tickets_vendus += $achat; }

Remarquez que si la condition originelle nest pas remplie, on ne rentrera jamais dans la boucle. Par exemple, si nous avons dj vendu 10 000 tickets, nous voulons que la ligne suivante du programme affiche quelque chose comme :
print "Ce spectacle est complet, revenez plus tard.\n";

Dans notre exemple de notation, on voit la ligne 4 :


while ($ligne = <NOTES>) {

ce qui assigne la ligne suivante la variable $ligne, et comme nous lavons expliqu plus haut, renvoie la valeur de $ligne afin que la condition de linstruction while puisse valuer la vrit de $ligne. On peut se demander si Perl obtient un faux \ sur les lignes vides et sort prmaturment de la boucle. La rponse est non. La raison en est simple, si vous vous reportez tout ce que nous en avons dit. Loprateur dentre de ligne laisse le saut de ligne la fin de la chane, ce qui fait quune ligne vide comporte la valeur "\n". Et vous savez que "\n" nest pas une des valeurs canoniques de fausset. La condition est donc vraie et la boucle continue mme pour les lignes vides. En revanche, quand nous atteignons la fin du fichier, loprateur dentre de ligne renvoie la valeur indfinie, qui donne toujours faux. Et la boucle se termine ainsi au moment dsir. Ce programme Perl na pas besoin dun test explicite sur la fonction eof, parce les oprateurs dentre sont conus pour fonctionner sans douleur dans un contexte conditionnel. En fait, presque tout est conu pour fonctionner sans douleur dans un contexte conditionnel. Par exemple, un tableau dans un contexte scalaire renvoie sa longueur. On voit donc frquemment ce genre de choses :
while (@ARGV) { process(shift @ARGV); }

La boucle sort automatiquement quand @ARGV est puis. Loprateur shift retire un lment de la liste argument chaque boucle et retourne cet lment. La boucle sarrte

customer_8566

Structures de contrle

29

automatiquement lorsque le tableau @ARGV est vide, donc de longueur 0 qui a pour valeur boolenne 0.22

Linstruction for
Un autre traitement itratif est la boucle for. Une boucle for tourne exactement comme la boucle while, mais parat trs diffrente (bien quelle dise quelque chose aux programmeurs C).
for ($vendu = 0; $vendu < 10000; $vendu += $achat) { $dispo = 10000 - $vendu; print "$dispo tickets sont disponibles. Combien en voulez-vous: "; $achat = <STDIN>; chomp($achat); }

La boucle for prend trois expressions entre les parenthses de la boucle : une expression pour initialiser ltat de la variable de boucle, une condition pour tester la variable et une expression pour modifier ltat de la variable. Quand la boucle commence, la variable est initialise et la condition est vrifie. Si elle est vraie, le bloc est excut. Quand le bloc se termine, lexpression de modification est excute, la condition est de nouveau vrifie et si elle est vraie, le bloc est rexcut avec les nouvelles valeurs. Tant que la condition reste vraie, le bloc et lexpression de modification continuent tre excuts. (Notez que seule la valeur de lexpression du milieu est value et mmorise, les deux autres ne sont utilises que comme effet de bord, et ne sont pas mmorises.)

Linstruction foreach
La dernire des principales instructions itratives est linstruction foreach. foreach est utilise pour excuter le mme code pour chacun des lments dun ensemble connu de scalaires, comme un tableau :
foreach $user (@users) { if (-f "$home{$user}/.nexrc") { print "$user est un type bien... il utilise un vi qui comprend Perl!\n"; } }

la diffrence des conditionnelles if et while, qui induisent un contexte scalaire dans lexpression, linstruction foreach induit un contexte de liste dans lexpression entre parenthses. Ainsi lexpression svalue en une liste (mme si cette liste ne contient quun scalaire). Chaque lment de la liste est tour tour mis dans la variable de boucle et le bloc de code est excut une fois par lment. Remarquez que la variable de boucle devient une rfrence llment lui-mme, et non une copie de llment. La modification de cette variable modifie donc le tableau originel.

22. Cest ainsi quon raisonne en Perl. Il nest pas ncessaire de comparer 0 avec 0 pour savoir que cest faux. Si certains langages vous y obligent, ne vous garez pas faire la comparaison explicite while (@ARGV != 0). Cest une perte de temps pour vous et le calculateur, aussi bien que pour la maintenance.

customer_8566

30

Chapitre 1 Vue densemble

On trouve beaucoup plus de boucles foreach dans un programme Perl typique que dans des boucles for, car il est trs facile en Perl de gnrer les listes que demande foreach. Une tournure que lon rencontre frquemment est une itration bouclant sur les clefs tries dun hachage :
foreach $clef (sort keys %hash) {

Ce qui est exactement le cas de la ligne 9 de notre exemple de notation.

Pour sen sortir : next et last


Les oprateurs next et last permettent de modifier le f lux de votre boucle. Il nest pas rare de rencontrer un cas spcial ; on peut vouloir le sauter, ou quitter la boucle quand on le rencontre. Par exemple, si lon gre des comptes UNIX, on peut vouloir sauter les comptes systme comme root ou lp. Loprateur next permet de sauter la fin de litration courante et den commencer une nouvelle. Loprateur last permet de sauter la fin du bloc comme si la condition du test avait renvoy faux, par exemple dans le cas o lon cherche un compte spcifique et que lon veut quitter aussitt quon la trouv.
foreach $user (@users) { if ($user eq "root" or $user eq "lp") { next; } if ($user eq "special") { print "Compte spcial trouv.\n"; # Traitement last; } }

Il est possible de sortir de boucles imbriques en les tiquetant et en spcifiant celles dont on veut sortir. Les modificateurs dinstruction (une autre forme de conditionnelle dont nous navons pas encore parl) associs ceci peuvent fournir des sorties de boucles trs lisibles, pour autant que le franais ou langlais soient lisibles :
LIGNE: while ($ligne = <ARTICLE>) { last LIGNE if $ligne eq "\n"; # arrt sur la premire ligne vide next LIGNE if /^#/; # sauter les lignes de commentaire # ici, votre publicit }

Vous devez vous dire, Une minute, l, quest ce que ce truc bizarre, ^#, entre ces espces de cure-dents ? Cela ne ressemble pas du langage naturel. . Vous avez mille fois raison. Il sagit dune recherche de correspondance contenant une expression rationnelle (bien quelle soit plutt simple). Et cest ce dont parle la section suivante. Perl est avant tout un langage de traitement de texte, et les expressions rationnelles sont au cur de ces fonctionnalits.

Expressions rgulires
Les expressions rgulires (aussi expressions rationnelles, regexps ou bien RE) sont utilises par la plupart des processeurs de texte du monde UNIX : grep et findstr, sed et awk,

customer_8566

Expressions rgulires

31

et les diteurs tels vi et emacs. Une expression rgulire est lcriture concise dun ensemble de chanes.23 La plupart des autres langages intgrent aussi le traitement des RE, mais aucun deux ne le fait la manire de Perl. Les expressions rationnelles sont employes de plusieurs manires dans Perl. Elles sont utilises en premier lieu dans des conditionnelles pour dterminer si une chane correspond un motif donn. Quand on voit quelque chose qui ressemble /machin/, on sait quil sagit dun oprateur de recherche de correspondance ordinaire.
if (/Windows 95/) { print "Il est temps de faire une mise jour ?\n" }

Ensuite, si lon peut retrouver des motifs dans une chane, on peut les remplacer par quelque chose dautre. Par exemple, s/machin/bidule/ demande de substituer bidule machin , si cela est possible. Nous appelons cela loprateur de substitution. Une RE peut aussi svaluer en un boolen, mais cest leffet de bord qui est utilis la plupart du temps.
s/Windows/Linux/;

Enfin, les motifs peuvent non seulement spcifier lemplacement de quelque chose, mais galement les endroits o il ne se trouve pas. Loprateur split emploie donc une expression rationnelle pour spcifier les emplacements do les donnes sont absentes. Autrement dit, lexpression rationnelle dfinit les dlimiteurs qui sparent les champs de donnes. Notre exemple de notation en comporte quelques exemples simples. Les lignes 5 et 12 clatent les chanes sur le caractre espace pour renvoyer une liste de mots. Mais split permet dclater sur tout dlimiteur spcifi par une expression rationnelle.
($bon, $brute, $truand) = split(/,/, "vi,emacs,teco");

Il existe de nombreux modificateurs utilisables dans chacun de ces contextes pour faire des choses plus exotiques comme lindiffrenciation des majuscules et des minuscules en recherchant des chanes de caractres, mais ce sont l des dtails que nous couvrirons au chapitre suivant. Lusage le plus simple des expressions rationnelles consiste rechercher une expression littrale. Dans le cas des clatements que nous venons de mentionner, nous avons recherch un simple espace. Mais si lon recherche plusieurs caractres la fois, ils doivent tous correspondre en squence. Cest--dire que le motif correspond une sous-chane, comme lon peut sy attendre. Admettons que nous dsirions montrer toutes les lignes dun fichier HTML reprsentant des liens vers dautres fichiers HTML (en excluant les liens FTP). Imaginons que nous travaillions en HTML pour la premire fois et que nous soyons donc un peu nafs. Nous savons que ces liens contiendront toujours la chane http: . Nous pouvons boucler dans le fichier comme ceci :24

23. Une bonne introduction est le livre de Jeffrey Friedl, Matrise des expressions rgulires (ditions OReilly). 24. Cela ressemble beaucoup la commande UNIX grep http: fichier. Sous MS-DOS, il est possible demployer la commande find, mais elle ne sait pas traiter dexpression plus complexe. (Cependant, le programme improprement nomm findstr de Windows NT comprend les expressions rationnelles.)

customer_8566

32
while ($ligne = <FICHIER>) { if ($ligne =~ /http:/) { print $ligne; } }

Chapitre 1 Vue densemble

Ici, le =~ (oprateur de liaison de motif) indique Perl quil doit rechercher lexpression rationnelle http: dans la variable $ligne. Sil trouve lexpression, loprateur renvoie une valeur vraie et le bloc (une commande daffichage) est excut. Au fait, si lon nutilise pas loprateur de liaison =~, Perl recherchera un motif par dfaut au lieu de $ligne. Ce motif par dfaut nest en fait quune variable spciale qui prend le nom curieux de $_. En fait, de nombreux oprateurs emploient la variable $_ et un expert de la programmation Perl peut crire ce qui prcde comme :
while (<FICHIER>) { print if /http:/; }

(Hmm, un autre modificateur dinstruction semble tre apparu ici. Insidieuses bestioles...) Tout cela est bien pratique, mais si nous voulons trouver tous les liens, et non les seuls HTTP ? Nous pouvons en donner une liste comme http: , ftp: , mailto: , etc. Mais cette liste peut tre longue, et que faire si un nouveau type de lien est ajout ?
while (<FILE>) { print if /http:/; print if /ftp:/; print if /mailto:/; # Et aprs? }

Comme les expressions rationnelles dcrivent un ensemble de chanes, nous pouvons nous contenter de dcrire ce que nous cherchons : un certain nombre de caractres alphabtiques suivis dun deux-points. Dans le dialecte des expressions rationnelles (le regexpais ?), ce serait /[a-zA-Z]+:/, o les crochets dfinissent une classe de caractres. Les a-z et A-Z reprsentent tous les caractres alphabtiques (le tiret reprsentant lintervalle de caractres entre le caractre de dbut et celui de fin, inclus). Et le + est un caractre spcial disant un ou plusieurs exemplaires du machin qui se trouve avant moi . Il sagit dun quantificateur, qui indique combien de fois quelque chose peut tre rpt. (Les barres obliques ne font pas vraiment partie de lexpression rationnelle, mais plutt de loprateur de correspondance. Elles nagissent que comme dlimiteurs de lexpression rationnelle). Certaines classes, comme la classe alphabtique, tant frquemment utilises, Perl dfinit des cas spciaux, qui comprennent :
Nom espace Caractre de mot Chiffre (digit) Dfinition ASCII [ \t\n\r\f] [a-zA-Z_0-9] [0-9] Caractre \s \w \d

customer_8566

Expressions rgulires

33

Remarquez quils ne correspondent qu des caractres simples. Un \w recherchera un unique caractre de mot et non un mot complet. (Vous souvenez-vous du quantificateur + ? On peut crire \w+ pour rechercher un mot.) Perl fournit galement la ngation de ces classes en employant le caractre en majuscule, comme \D pour un caractre qui nest pas un chiffre. (Il faut remarquer que \w nest pas toujours quivalent [a-zA-Z_0-9]. Certains locales dfinissent des caractres alphabtiques supplmentaires hors de la squence ASCII, et \w les respecte.)25 Certaines langues dfinissent des caractres alphabtiques au-del de la squence ASCII classique. Le code \w les prend en compte. Les rcentes versions de Perl connaissent aussi le codage UNICODE avec les proprits numriques et Perl traite ce codage avec les proprits en consquence. (Il considre aussi les idogrammes comme des caractres \w.) Il existe une autre classe de caractres trs spciale, que lon crit . , qui recherchera tout caractre.26 Par exemple, /a./ trouve toute chane contenant un a qui nest pas le dernier caractre de la chane. Il trouvera donc at ou am , ou mme a+ , mais non a puisquil ny a rien aprs le a qui puisse correspondre au point. Comme il cherche le motif nimporte o dans la chane, il le trouvera dans oasis et dans chameau , mais non dans sheba . Il trouvera le premier a de caravane . Il pourrait trouver le deuxime, mais il sarrte aprs la premire correspondance en cherchant de gauche droite.

Quantificateurs
Les caractres et les classes de caractres dont nous avons parl recherchent des caractres uniques. Nous avons dj mentionn que lon pouvait rechercher plusieurs caractres de mot avec \w+ pour correspondre un mot complet. Le + est un de ces quantificateurs, mais il y en a dautres (tous sont placs aprs llment quantifi). La forme la plus gnrale de quantificateur spcifie le nombre minimal et le nombre maximal de fois auquel un lment peut correspondre. Les deux nombres sont mis entre accolades, spars par une virgule. Par exemple, pour essayer de trouver les numros de tlphone dAmrique du Nord, /\d{7,11}/ rechercherait au moins 7 chiffres, mais au plus 11 chiffres. Si un seul chiffre se trouve entre les accolades, il spcifie la fois le minimum et le maximum ; cest--dire que le nombre spcifie le nombre exact de fois que llment peut tre rpt. (Si lon y rf lchit, tous les lments non quantifis ont un quantificateur implicite {1}.) Si lon met le minimum et la virgule en omettant le maximum, ce dernier passe linfini. En dautres termes, le quantificateur indique le nombre minimum de caractres, et tout ceux quil trouvera aprs cela. Par exemple, /\d{7}/ ne trouvera quun numro de tlphone local (dAmrique du Nord, sept chiffres), alors que /\d{7,}/ correspondra tous les numros de tlphones, mme les internationaux (sauf ceux qui comportent moins de 7 chiffres). Il nexiste pas de faon spcifique dcrire au plus un certain nombre de caractres. Il suffit dcrire, par exemple, /.{0,5}/ pour trouver au plus cinq caractres quelconques.
25. Ce qui est bien pratique pour rechercher les caractres accentus en franais. (N.d.T.) 26. Mais il ne trouvera pas un saut de ligne. Quand on y pense, un . ne correspond pas non plus un saut de ligne dans grep(1).

customer_8566

34

Chapitre 1 Vue densemble

Certaines combinaisons de minimum et de maximum apparaissant frquemment, Perl dfinit des quantificateurs spciaux. Nous avons dj vu +, qui est identique {1,}, cest--dire au moins une occurrence de llment qui prcde . Il existe aussi *, qui est identique {0,}, ou zro occurrence ou plus de llment qui prcde , et ?, identique {0,1}, ou zro ou une occurrence de llment qui prcde (llment qui prcde est donc optionnel). Il faut savoir deux ou trois choses concernant la quantification. Dabord, les expressions rationnelles de Perl sont, par dfaut, avides. Cela signifie quelles essayent de trouver une correspondance tant que lexpression entire correspond toujours. Par exemple, si lon compare /\d+ 1234567890 , cela correspondra la chane entire. Il faut donc spcialement surveiller lemploi de . , tout caractre. On trouve souvent une chane comme :
larry:JYHtPh0./NJTU:100:10:Larry Wall:/home/larry:/bin/tcsh

o on essaye de trouver larry avec /.+:/. Cependant, comme les expressions rationnelles sont avides, ce motif correspond tout ce qui se trouve jusqu /home/larry inclus. On peut parfois viter ce comportement en utilisant une ngation de classe de caractres, par exemple avec /[\^:]+:/, qui indique de rechercher un ou plusieurs caractres non-deux-points (autant que possible), jusquau premier deux-points. Cest le petit chapeau qui inverse le sens de la classe de caractres.27 Lautre point surveiller est que les expressions rationnelles essayent de trouver une correspondance ds que possible. Ce point est mme plus important que lavidit. Le balayage se produisant de gauche droite, cela veut dire que le motif cherchera la correspondance la plus gauche possible, mme sil existe un autre endroit permettant une correspondance plus longue (les expressions rationnelles sont avides, mais elles voient court terme). Par exemple, supposons que lon utilise la commande de substitution s/// sur la chane par dfaut ( savoir la variable $_), et que lon veuille enlever une suite de x du milieu de la chane. Si lon crit :
$_ = "fred xxxxxxx barney"; s/x*//;

cela naura aucun effet. En effet, le x* (voulant dire zro caractres x ou plus) trouvera le rien au dbut de la chane, puisque la chane nulle est large de zro caractres et que lon trouve une chane nulle juste avant le f de fred .28 Encore une chose savoir. Par dfaut, les quantificateurs sappliquent un caractre unique les prcdant, ce qui fait que /bam{2}/ correspond bamm mais pas bambam . Pour appliquer un quantificateur plus dun caractre, utilisez les parenthses. Il faut employer le motif /(bam){2}/ pour trouver bambam .

Correspondance minimale
Si lon ne voulait pas de correspondances avides dans les anciennes versions de Perl, il fallait employer la ngation dune classe de caractres (et en fait, on obtenait encore une correspondance avide, bien que restreinte).
27. Dsol, nous navons pas invent cette notation, ne nous en voulez pas. Il sagit simplement de la faon dcrire les expressions rationnelles dans la culture UNIX. 28. Mme les auteurs sy font prendre de temps en temps.

customer_8566

Expressions rgulires

35

Les versions modernes de Perl permettent de forcer une correspondance minimale par lemploi dun point dinterrogation aprs tout quantificateur. Notre recherche de nom dutilisateur serait alors /.*?:/. Ce .*? essaye alors de correspondre aussi peu de caractres que possible, au lieu dautant que possible, et il sarrte donc au premier deuxpoints au lieu du dernier.

Pour enfoncer le clou


Chaque fois que lon cherche faire correspondre un motif, celui-ci essayera partout jusqu ce quil trouve une correspondance. Une ancre permet de restreindre lespace de recherche. Une ancre est dabord quelque chose qui ne correspond rien , mais il sagit l dun rien dun type spcial qui dpend de son environnement. On peut aussi lappeler une rgle, une contrainte ou une assertion. Quelle que soit son appellation, elle essaie de faire correspondre quelque chose de longueur zro, et russit ou choue. (En cas dchec, cela veut surtout dire que le motif ne trouve pas de correspondance de cette faon. Il essaie alors dune autre manire, sil en existe.) La chane de caractres spciale \b correspond une limite de mot, qui est dfinie comme le rien entre un caractre de mot (\w) et un caractre de non-mot (\W), dans le dsordre. (Les caractres qui nexistent pas de part et dautre de la chane sont appels des caractres de non-mot). Par exemple,
/\bFred\b/

correspond Le Grand Fred et Fred le Grand , mais ne correspond pas Frederic le Grand parce que le de de Frederic ne contient pas de limite de mot. Dans une veine similaire, il existe galement des ancres pour le dbut et la fin dune chane. Sil sagit du premier caractre dun motif, le chapeau (^) correspond au rien au dbut de la chane. Le motif /^Fred/ correspondrait donc Frederic le Grand et non Le Grand Fred , alors que /Fred^/ ne correspondrait aucun des deux (et ne correspondrait dailleurs pas grand-chose). Le signe dollar ($) fonctionne comme le chapeau, mais il correspond au rien la fin de la chane au lieu du dbut.29 Vous devez maintenant tre en mesure de deviner ce que veut dire :
next LIGNE if /^#/;

Cest bien sr Aller la prochaine itration de la boucle LIGNE si cette ligne commence par un caractre # . Nous avons dit plus haut que la squence \d{7,11} concide avec un nombre de 7 11 chiffres de long ce qui est vrai mais incomplet: quand cette squence est utilise dans une expression comme /\d{7,11}/, a nexclue pas dautres chiffres aprs les 11 premiers. Donc, le plus souvent, lorsque vous utilisez des quantificateurs, vous utiliserez des ancres de chaque ct.

29. Tout ceci est un peu simpliste, car nous supposons ici que la chane ne contient quune ligne. ^ et $ sont en fait des ancres au dbut et en fin de ligne et non pas de chane. Nous essaierons de clarifier tout cela au chapitre 5, Recherche de motif (pour autant que lon puisse clarifier tout cela).

customer_8566

36

Chapitre 1 Vue densemble

Rfrences arrires
Nous avons dj mentionn que lon pouvait employer des parenthses pour grouper des caractres devant un quantificateur, mais elles peuvent aussi servir se souvenir de parties de ce qui a t trouv. Une paire de parenthses autour dune partie dexpression rationnelle permet de se souvenir de ce qui a t trouv pour une utilisation future. Cela ne change pas le motif de recherche, et /\d+ et /(\d+)/ chercheront toujours autant de chiffres que possibles, mais dans le dernier cas, ceux-ci seront mmoriss dans une variable spciale pour tre rfrencs en arrire plus tard. La faon de rfrencer la partie mmorise de la chane dpend de lendroit do on opre. Dans la mme expression rationnelle, on utilise un antislash suivi dun entier. Il correspond une paire de parenthses donne, dtermine en comptant les parenthses gauches depuis la gauche du motif, en commenant par un. Par exemple, pour rechercher quelque chose ressemblant une balise HTML (comme <B>Gras</B> ), on peut utiliser /<(.*?)>.*?<\/\1>/. On force alors les deux parties du motif correspondre exactement la mme chane de caractres, comme au B ci-dessus. Hormis lexpression rationnelle elle-mme, comme dans la partie de remplacement dune substitution, la variable spciale est utilise comme sil sagissait dune variable scalaire normale nomme par lentier. Donc, si lon veut changer les deux premiers mots dune chane, par exemple, on peut employer :
s/(\S+)\s+(\S+)/$2 $1/

Le ct droit de la substitution quivaut une sorte de chane protge par des apostrophes doubles, ce qui explique pourquoi lon peut y interpoler des variables, y compris des rfrences arrires. Ce concept est puissant : linterpolation (sous contrle) est une des raisons pour lesquelles Perl est un bon langage de traitement de texte. Entre autres raisons, on trouve bien entendu les motifs de correspondance. Les expressions rationnelles savent parfaitement extraire des lments et linterpolation sert les rassembler. Peut-tre existe-t-il enfin un espoir pour Humpty Dumpty.

Traitement des listes


Nous avons vu plus haut que Perl connat deux principaux contextes, le contexte scalaire (pour grer les singularits) et le contexte de liste (pour grer les pluralits). La plupart des oprateurs traditionnels que nous avons dcrits jusquici taient strictement scalaires dans leur opration. Ils prennent toujours des arguments singuliers (ou des paires darguments singuliers pour les oprateurs binaires), et produisent toujours un rsultat singulier, mme dans un contexte de liste. Donc, si lon crit ceci :
@tableau = (1 + 2, 3 - 4, 5 * 6, 7 / 8);

on sait que la liste de droite contient exactement quatre valeurs, car les oprateurs mathmatiques ordinaires produisent toujours des valeurs scalaires, mme dans le contexte de liste fourni par lassignation un tableau. Cependant, dautres oprateurs Perl peuvent produire soit un scalaire, soit une liste, selon le contexte. Ils savent si vous attendez deux un scalaire ou une liste. Mais comment pouvez-vous le savoir ? Cest en fait trs simple une fois que vous vous tes familiariss avec quelques concepts clefs.

customer_8566

Traitement des listes

37

Premirement, le contexte de liste doit tre fourni par quelque chose dans l environnement . Dans lexemple ci-dessus, cest lassignation de liste qui le fournit. Nous avons vu ci-avant que la liste dans linstruction de boucle foreach fournit le contexte de liste. Loprateur print aussi. Il est possible de tous les identifier dun coup. Si vous regardez les nombreuses reprsentations syntaxiques des oprateurs dans le reste de ce livre, divers oprateurs sont dfinis pour prendre une LISTE en argument. Ce sont les oprateurs qui fournissent un contexte de liste. Tout au long de ce livre, LISTE est employ comme le terme technique signifiant une construction syntaxique fournissant un contexte de liste . Par exemple, si lon regarde sort, on trouve le rsum de syntaxe suivant :
sort LISTE

Ce qui veut dire que sort procure un contexte de liste ses arguments. Deuximement, la compilation, tout oprateur qui prend une LISTE fournit un contexte de liste chaque lment syntaxique de cette LISTE. Chaque oprateur ou entit de haut niveau de la LISTE sait quil est cens fournir la meilleure liste possible. Cela signifie que si lon crit :
sort @mecs, @nanas, autres();

@mecs, @nanas et autres() savent tous quils sont censs fournir une valeur de liste. Enfin, lexcution, chacun de ces lments de LISTE fournit sa liste, puis (ceci est important) toutes les listes isoles sont rassembles, bout bout, en une liste unique. Et cette liste unique, unidimensionnelle, est ce qui est finalement donn la fonction qui voulait une LISTE. Si donc @mecs contient (Fred, Barney), @nanas contient (Wilma, Betty), et que la fonction autre() renvoie la liste un seul lment (Dino), la LISTE que voit sort devient :
(Fred,Barney,Wilma,Betty,Dino)

et sort renvoie la liste :


(Barney,Betty,Dino,Fred,Wilma)

Certains oprateurs produisent des listes (comme keys), certains les consomment (comme print) et dautres les transforment en dautres listes (comme sort). Les oprateurs de cette dernire catgorie sont considrs comme des filtres ; mais contrairement au shell, le f lux de donnes seffectue de droite vers la gauche, puisque les oprateurs de liste agissent sur les lments qui sont passs leur droite. On peut empiler plusieurs oprateurs de liste la fois :
print reverse sort map {lc} keys %hash;

Toutes les clefs de %hash sont prises et renvoyes la fonction map, qui met chacune dentre elles en minuscule par loprateur lc, et les passe la fonction sort qui les trie et les repasse la fonction reverse, qui renverse lordre des lments de la liste, qui les passe enfin la fonction print, qui les affiche. Cest, on le voit, beaucoup plus facile dcrire en Perl quen franais. Nous ne pouvons lister tous les exemples o lutilisation de la structure de liste produit un code plus naturel lire. Mais revenons sur les RE un moment. Dans un contexte de liste, toutes les concidences sont mmorises dans les lments successifs de la liste. Cherchons, par exemple, toutes les chanes de la forme 12:59:59 am . On peut le faire comme ceci :

customer_8566

38

Chapitre 1 Vue densemble


($hour, $min, $sec, $ampm) = /(\d+):(\d+):(\d+) *(\w+)/;

Ce qui est une faon pratique dinstancier plusieurs variables en mme temps. On peut aussi crire :
@hmsa = /(\d+):(\d+):(\d+) *(\w+)/;

et mettre ces 4 valeurs dans un tableau. trangement, par la sparation de laction entre les RE et les expressions Perl, le contexte de liste augmente les possibilits du langage. Nous ne le voyons pas, mais Perl est un vritable langage orthogonal en plus dtre diagonal. Allez, on fait une pause !

Ce que vous ne savez pas ne vous fera pas (trop) de mal


Enfin, permettez-nous de revenir encore une fois au concept de Perl en tant que langage naturel. Les usagers dun langage naturel ont le droit davoir des niveaux daptitude diffrents, de parler diffrents sous-ensembles de ce langage, dapprendre au fur et mesure et, en gnral, de lutiliser avant den connatre toutes les arcanes. Vous ne connaissez pas tout de Perl, tout comme vous ne connaissez pas tout du franais. Mais ceci est Officiellement OK dans la culture Perl. Vous pouvez employer utilement Perl mme si nous ne vous avons pas encore appris crire vos propres sous-programmes. Nous avons peine commenc expliquer que Perl pouvait tre vu comme un langage de gestion systme, ou comme un langage de prototypage rapide, ou comme un langage rseau, ou comme un langage orient objet. Nous pourrions crire des chapitres entiers sur ces sujets (et vrai dire, cest dj le cas). Mais au bout du compte, vous devrez crer votre propre vision de Perl. Cest votre privilge, en tant quartiste, de vous inf liger vous-mme la douleur de la crativit. Nous pouvons vous apprendre notre faon de peindre, mais nous ne pouvons pas vous apprendre votre faon. TMTOWTDI : il existe plus dune faon de faire. Amusez-vous comme il convient.

customer_8566

Sance de dissection

II

customer_8566

customer_8566

Composants de Perl

O nous tudions les lments de lensemble. Dans les prochains chapitres nous progresserons du particulier vers le gnral, approche ascendante, en commenant par dcrire les composants lmentaires qui permettront daborder les structures plus labores, un peu la manire dont les atomes forment les molcules. Linconvnient est que vous nen aurez pas ncessairement une image globale sans auparavant avoir t submerg par de nombreux dtails, mais lavantage est que vous comprendrez les exemples au fur et mesure. (si vous prfrez lapproche inverse, retournez le livre et lisez ce chapitre lenvers). Chaque chapitre est construit sur le prcdent ce qui ncessite une lecture linaire, (vous devrez donc faire attention si vous tes du genre sautiller dune page lautre). Vous tes invit utiliser les diffrentes annexes la fin du livre. (Ce qui nest pas du sautillement.) Chaque mot distingu par une police type se trouve au chapitre 29, Fonctions. Bien que nous avons essay de ne pas privilgier un systme dexploitation, si vous tes peu au courant de la terminologie Unix et si vous rencontrez un mot qui semble dire autre chose que ce que vous pensez, reportez-vous au glossaire. Si cela ne marche pas, essayez lindex.

Atomes
Le plus petit lment visible du langage est le caractre, celui que lon peut visualiser dans un diteur par exemple. Au dpart, Perl ne faisait pas la distinction entre octets et caractres ASCII, mais pour des raisons dinternationalisation, il faut bien distinguer les deux. Le code Perl peut tre crit exclusivement en ASCII, mais autorise aussi lutilisation dun codage sur 8 ou 16 bits, quil soit celui dune langue ou bien de tout autre codage dfini rgulirement, condition de le faire dans des chanes litrales uniquement. Bien sr, Perl ne vrifiera pas le contenu du texte mais saura simplement quun caractre est cod sur 16 bits.

customer_8566

42

Chapitre 2 Composants de Perl

Comme expliqu au chapitre 15, Unicode, Perl implmente Unicode.1 Cest transparent pour lutilisateur du langage qui peut en utiliser aussi bien dans des identificateurs (noms de variables, etc) que dans des chanes litrales. Pour Perl, tous les caractres ont la mme taille de rfrence, par exemple 1, quelle que soit la reprsentation interne quil en fait ensuite. En principe, il code les caractres sous forme UTF-8 et donc un caractre peut avoir une forme interne sur 1, 2, 3... octets. (LUnicode smiley U-263A est une squence de 3 octets.) Mais poursuivons lanalogie physique un peu plus avant avec les atomes. Les caractres sont atomiques de la mme faon que les atomes codent les diffrents lments. Un caractre est compos de bits et doctets mais si on le dsintgre (dans un acclrateur de caractres, sans doute), il perd toutes ses proprits propres. De la mme manire que les neutrons composent latome dUranium U-238, les octets qui composent le caractre smiley U-263A sont un dtail de son implmentation. Il faut donc bien distinguer le mot caractre du mot octet . Cest pourquoi on peut le prciser linterprteur avec la directive use bytes. (Voir le chapitre 31, Modules de pragmas). De toute manire, Perl saura par lui-mme faire le codage sur 8 bits quand il le faudra. Maintenant passons dans la prochaine dimension.

Molcules
Perl est un langage informel, ce qui ne veut pas dire quil na pas de forme, mais plutt dans le sens usuel du terme, cest--dire un langage quon peut crire avec des espaces, tabulations et caractres de nouvelle ligne partout o vous voulez sauf dans les units syntaxiques. Par dfinition, un symbole ne contient pas despace. Un symbole est une unit syntaxique avec un sens pour linterprteur, comme pour un mot dans une phrase, mais qui peut contenir dautres caractres que des lettres tant que cette unit nest pas rompue. (Ce sont de vraies molcules qui peuvent utiliser toutes sortes datomes. Par exemple, les nombres et les oprateurs mathmatiques sont des symboles. Un identificateur est un symbole qui dbute par une lettre ou un soulign et qui ne contient que des lettres, chiffres ou souligns. Un symbole ne peut contenir despace puisque le caractre espace couperait le symbole en deux nouveaux symboles, tout comme un caractre espace, en franais couperait un mot en deux nouveaux mots.2 Bien que le caractre espace soit ncessaire entre deux symboles, les espaces ne sont obligatoires quentre deux symboles qui, sinon, seraient pris pour un seul. cet effet, tous les espaces sont quivalents. Un commentaire est compt comme un espace. Les sauts de ligne ne sont diffrents des espaces quentre des dlimiteurs, dans certains formats et pour des formes orientes ligne de protection. Plus prcisment le caractre de saut de ligne ne dlimite pas une instruction comme en FORTRAN ou en Python. Les instructions en Perl se terminent par le caractre ; comme en C.
1. Aussi enthousiaste que nous soyons au sujet dUnicode, la plupart de nos exemples sont en ASCII, tant donn que tout le monde na pas ncessairement un diteur de texte Unicode. 2. Dans les chanes litrales, cest le guillemet qui dlimite lunit et non lespace, on peut donc y inclure ce caractre.

customer_8566

Types internes

43

Les caractres despace Unicode sont autoriss dans un programme Perl Unicode moyennant certaines prcautions. Si vous utilisez les caractres spciaux Unicode sparateurs de paragraphe et de ligne, dune manire diffrente que ne le fait votre diteur de texte, les messages derreur seront plus difficile interprter. Cest mieux dutiliser les caractres de saut de ligne classiques. Les symboles sont dtects dune manire large ; linterprteur Perl lit le symbole le plus long possible lors de la lecture du code. Si vous voulez quil distingue deux symboles il suffit dinsrer un espace blanc entre eux. (La tendance est dinsrer plusieurs espaces pour rendre le code plus lisible.) Un commentaire commence par le caractre # et stend jusqu la fin de la ligne. Un commentaire quivaut un espace et joue le rle de sparateur. Perl ninterprte pas une ligne place en commentaire.3 Si une ligne, et cest une autre originalit lexicale, commence par = un endroit o une instruction serait lgale, Perl ignore tout de cette ligne jusqu la prochaine contenant =cut. Le texte ignor est suppos tre du POD, ou Plain Old Documentation (des programmes Perl permettent de convertir ces commentaires au format des pages de manuel, ou en documents L, HTML et bientt XML). Dune manire complmentaire, lanalyseur lexical extrait le code Perl dun module et ignore les balises pod, ce qui permet de conserver la documentation lintrieur des modules. Voir le chapitre 26, POD, pour les dtails sur pod et la documentation multiligne. Mais seul le premier # est ncesaire, les autres ne sont que de la dcoration, bien que la plupart des codeurs lutilisent pour faire des effets visuels comme avec le langage C ou ils font une utilisation abondante du caractre *. En Perl, comme en chimie ou en linguistique, on construit des structures de plus en complexes partir dlments simples. Par exemple, une instruction est une squence de symboles sur le mode impratif. On peut combiner une srie dinstructions pour former un bloc dlimit par des accolades. Les blocs peuvent eux-mmes constituer dautres blocs. Certains blocs fonctionnels tels que les sous-programmes peuvent tre combins en modules eux-mmes combins en programmes, nous verrons tout ceci dans les prochains chapitres. Mais crons encore des symboles avec nos caractres.

Types internes
Avant de construire des types plus complexes, nous devons introduire quelques abstractions, plus prcisment trois types de donnes. Chaque langage dispose de ses propres types de donnes et la diffrence des autres, Perl en possde peu ce qui rduit les confusions possibles. Prenons par exemple le langage C qui dispose des types suivants : char, short, int, long, long long, bool, wchar_t, size_t, off_t, regex_t, uid_t, u_longlong_t, pthread_key_t, fp_exception_field_type, et ainsi de suite. Ce sont juste les types entiers! Il y a ensuite les nombres f lottants, les pointeurs et les chanes.
3. En fait ce nest pas exact. Lanalyseur lexical de Perl regarde sil existe un slecteur du type #! (voir le chapitre 19, Linterface de la ligne de commande). Il peut aussi analyser les numros de ligne produits par diffrents prpocesseurs (voir la section Gnrer du Perl dans dautres langages au chapitre 24, Techniques couramment employes).

customer_8566

44

Chapitre 2 Composants de Perl

Tous ces types compliqus nen font quun en Perl : le scalaire. (Les types simples de donnes sont suffisants pour les besoins usuels, et il est possible de crer ses propres types en utilisant la programmation objet en Perl, voir le chapitre 12, Objets.) Les trois types de base en Perl sont : les scalaires, les tableaux de scalaires et les hachages de scalaires (connus aussi sous le nom de tableaux associatifs). On peut aussi les appeler structures de donnes. Les scalaires constituent le type fondamental partir duquel les structures plus complexes peuvent tre construites. Un scalaire peut contenir une seule valeur simple, typiquement une chane ou un nombre. Les lments de ce type simple peuvent tre combins lintrieur des deux autres types composs. Un tableau est une liste ordonne de scalaires accessibles par un indice numrique (les indices dmarrent zro). Contrairement aux autres langages, Perl traite les indices ngatifs en comptant partir de la fin du type index aussi bien des chanes que des listes. Un hachage est un ensemble non ordonn de paires clef/valeur accessibles par une clef de type chane utilise pour accder la valeur scalaire associe. Les variables ont toujours lun de ces trois types. ( part les variables, Perl comprend des bidules plus ou moins confidentiels tels que des handles de fichiers et de rpertoires, des sous-programmes, des typeglobs, des formats et des tables de symboles.) Laissons la thorie et passons la pratique du langage pour en voir les possibilits. Nous allons donc crire du code et pour cela vous prsenter les termes constituant les expressions en Perl rgies par des rgles syntaxiques. Nous utilisons la terminologie terme quand nous parlerons des units syntaxiques, un peu comme dans les quations mathmatiques. La fonction des termes en Perl est de fournir des valeurs pour des oprateurs tels laddition ou la multiplication. Mais la diffrence dune quation, Perl interprte lexpression dans une action logique de la machine. Une des actions les plus courantes est la sauvegarde dune valeur en mmoire :
$x = $y;

Cest un exemple de loprateur daffectation (non pas loprateur de test dgalit des valeurs numriques, ce qui scrit == en Perl). Laffectation prend la valeur de $y et la place dans la variable $x. Notez que le terme $x nest pas utilis pour sa valeur mais pour sa fonction de mmorisation. (Lancienne valeur de $x disparat avec laffectation.) Nous disons que $x est une lvalue, parce quelle est cible dune affectation gauche dune expression. Et nous disons que $y est une rvalue car droite dans ce type dexpression. Il y a un troisime type de valeur appele temporaire quil est ncessaire de comprendre. Considrons lexpression simple suivante :
$x = $y + 1;

Perl prend la rvalue $y et lui ajoute la rvalue 1, ce qui produit une valeur temporaire qui est ensuite affecte la lvalue $x. Ces valeurs temporaires sont places dans une structure interne appele pile.4

4. Une pile fonctionne la manire de ces piles dassiettes dans les restaurants on peut empiler (push) ou bien dpiler (pop) une assiette (le push et le pop tant deux termes bien tablis dans la science informatique)

customer_8566

Variables

45

Les termes dune expression empilent des valeurs, alors que ses oprateurs (dont nous parlerons dans le prochain chapitre) dpilent des valeurs et peuvent aussi empiler des rsultats pour le prochain oprateur. Dans la pile, une expression produit autant de valeurs quelle en consomme. Nous reviendrons sur les valeurs temporaires. Certains termes sont exclusivement des rvalues comme 1, certains autres peuvent jouer les deux rles, comme la variable de lexemple prcdent nous la montr. Cest ce que nous allons voir dans la prochaine section.

Variables
Il y existe trois types de variables correspondant aux trois types abstraits mentionns plus haut. Chacun deux est prfix par un caractre spcial.5 Les variables scalaires sont toujours dfinies avec un caractre $ initial, mme si elles font rfrence des scalaires lintrieur dun tableau ou dun hachage. Ce caractre fonctionne un peu comme larticle dfini singulier (le ou la). Nous avons donc :
Construction $jours $jours[28] $jours{Fev} Signification Valeur scalaire simple $jours. 29e lment du tableau @jours. Valeur Fev du hachage %jours.

Noter que vous pouvez utiliser le mme nom pour $jours, @jours, et %jours, Perl ne les confondra pas. Il existe dautres caractres spciaux qui sappliquent sur les scalaires et sont utiliss dans des cas prcis. Ils ressemblent ceci :
Construction ${jours} $Calendrier::jours $#jours $jours->[28] $jours[0][2] $jours{2000}{Fev} $jours{2000,Fev} Signification Identique $jours en levant lambigut devant les caractres alphanumriques. Une autre variable $jours, dans le paquetage Calendrier. Dernier index du tableau @jours. 29e lment du tableau point par la rfrence $jours. Tableau multidimensionnel. Hachage multidimensionnel. mulation de hachage multidimensionnel.

Les tableaux ou les tranches de tableaux (ainsi que les tranches de hachage) dbutent par le caractre @, qui fonctionne un peu comme larticle dfini pluriel (les) :

5. Encore des termes couramment usits en informatique

customer_8566

46
Construction @jours @jours[3,4,5] @jours[3..5] @jours{jan,fev} Signification

Chapitre 2 Composants de Perl

quivaut ($jours[0], $jours[1],... $jours[n]). quivaut ($jours[3], $jours[4], $jours[5]). quivaut @jours[3,4,5]. quivaut ($jours{jan}, $jours{fev}).

Les hachages dbutent par % :


Construction %jours Signification @(jan => 31, fev => $bissextil e? 29: 28, ...) .

Chacun de ces neuf exemples peut servir de lvalue, cest--dire quils spcifient une adresse laquelle on peut, en autres choses, loger une valeur. Avec les tableaux, les hachages et les tranches de tableaux ou de hachages, la lvalue fournit un moyen simple daffecter plusieurs valeurs dun seul coup :
@days = 1 .. 7;

Noms
Nous avons parl de variables pour mmoriser des valeurs mais il faut aussi mmoriser les noms et dfinitions de ces variables. En thorie, cela sappelle des espaces de nommage. Perl dispose de deux sortes despaces de nommages : la table des symboles et les portes lexicales.6 Il peut y avoir un nombre quelconque de tables et de portes lexicales et lintersection des deux ensembles est nulle, pour chaque instance de linterprteur Perl. Nous dtaillerons chacun de ces types tout au long de cet ouvrage. Disons simplement pour le moment que les tables de symboles sont des hachages porte globale qui contiennent la table des symboles des variables globales (y compris les hachages des autres tables de symboles). A contrario, les portes lexicales sont des espaces anonymes non inclus dans une table, mais lis un bloc de code du programme courant. Ils contiennent des variables accessibles uniquement dans le bloc en cours. (Cest pourquoi on utilise le terme porte.) Le mot lexical veut dire relatif au bloc de texte courant (ce qui na rien voir avec ce quun lexicographe entend par l. Ne vous fchez pas.). Dans chaque espace de nommage, global ou lexical, chaque type de variable dispose de son propre sous-espace de nommage dtermin par le caractre spcial affect au type. Il est possible, sans risque de conf lit, dutiliser le mme nom pour une variable scalaire, un tableau ou un hachage (ou encore, pour un handle de fichier, un nom de sous-programme, un label ou votre lama familier). Cela signifie que $machin et @machin sont deux variables diffrentes. Cela veut aussi dire que $machin[1] est un lment de @machin et non une partie de $machin. Bizarre, vous avez dit bizarre ? Mais cest normal, bizarrement.
6. On les appelle plutt paquetages et pads quand il sagit de limplmentation spcifique de Perl, mais les expressions rallonge sont les termes gnriques utiliss dans lindustrie du logiciel, et nous les utiliserons donc. Dsol.

customer_8566

Noms

47

Pour lappel dun sous-programme le caractre & est facultatif. Gnralement un nom de sous-programme nest pas une lvalue, quoique dans les versions rcentes de Perl un sous-programme peut svaluer une lvalue de telle sorte que lon peut lui affecter une valeur en retour. Parfois on veut accder aux variables dun symbole donn, sym par exemple. Il suffit dutiliser le caractre spcial * o lastrisque indique tout type de variable (scalaire, tableau, hachage). On les appelle typeglobs ; ils ont plusieurs fonctions. Ils peuvent tre utiliss comme lvalues. Limportation des modules se fait par laffectation des typeglobs. Nous reviendrons sur ce thme plus tard. Perl, comme tout langage informatique, dispose dune liste de mots rservs quil reconnat comme termes spciaux. Cependant, les noms de variables commenant par un caractre spcial, il ny a pas de confusion possible avec les premiers. Dautres types de noms ne commencent pas par ces caractres : les descripteurs de fichiers et les tiquettes. Avec ceux-ci attention ne pas entrer en conf lit avec des mots rservs. Nous vous recommandons pour ces types, dutiliser des majuscules pour leurs noms. Par exemple, si vous crivez open(LOG, logfile) plutt que le regrettable open(log, "logfile"). Perl comprendra que vous ne parlez pas de la fonction log et des logarithmes,7 et prvient les futurs conf lits avec les nouvelles versions de Perl. Le nom des modules utilisateurs commence avec une majuscule alors que les modules pragmas prdfinis sont crits en minuscules. Quand nous aborderons la programmation oriente objet, vous verrez que les noms de classes sont en capitales pour la mme raison. Comme vous pouvez le dduire du prcdent paragraphe, la casse est importante dans les identificateurs TRUC, Truc, et truc sont trois noms diffrents en Perl. Un identificateur commence avec une lettre ou un soulign, il peut contenir des lettres et des chiffres, y compris les caractres Unicode, et peut avoir une longueur comprise entre 1 et 251 inclus. Les idogrammes Unicode sont des lettres mais nous vous dconseillons des les utiliser si vous ne savez pas les lire. Voir le chapitre 15. Les noms qui suivent ces caractres spciaux ne sont pas ncessairement des identificateurs. Ils peuvent commencer par un chiffre auquel cas lidentificateur ne peut contenir que des chiffres comme dans $123. Les noms qui commencent par tout autre caractre quune lettre, un chiffre ou soulign (comme $? ou $$), sont limits ce caractre et sont prdfinis en Perl. Par exemple $$ est lID du processus courant et $? est lindicateur dtat retourn par le dernier processus fils cr. Dans la version 5.6 de Perl est implmente une syntaxe extensible pour les noms de variable interne. Toute variable de la forme ${^NAME} est une variable spciale rserve par Perl. Tous ces noms spciaux sont dans la table principale de symboles. Voir le chapitre 28, Noms spciaux, pour les exemples. On pourrait penser que noms et identificateurs dsignent la mme chose, mais lorsquon parle de nom, cest du nom absolu quil sagit, cest--dire celui qui indique quelle table de symboles il appartient. De tels noms sont forms par une srie didentificateurs spars par le symbole :: :
$Doc::Aide::Perl::Classe::chameau
7. On applique ici un des principes de Perl qui prtend que des choses diffrentes doivent tre reprsentes diffremment, ce qui rend le code plus lisible ( comparer avec les langages qui obligent des choses diffrentes avoir la mme apparence, au dtriment de la lisibilit.

customer_8566

48

Chapitre 2 Composants de Perl

Ce qui fonctionne comme un nom absolu de fichier :


/Doc/Aide/Perl/Classe/chameau

En Perl, ce chemin absolu indique les tables de symboles imbriques, et le dernier identificateur est le nom de la variable elle-mme, contenu dans la dernire table imbrique. Par exemple, pour la variable de lexemple prcdent, la table de symbole se nomme Doc::Aide::Perl::Classe, et le nom de la variable dans cette table est $chameau. (la valeur de cette variable est bien entendu beige .) Une table de symboles en Perl se nomme aussi un paquetage. Donc ces variables sont aussi appeles variables de paquetage. Les variables de paquetage sont dites prives relativement leur paquetage, mais sont globales dans le sens o les paquetages sont euxmmes globaux, cest--dire quil suffit de nommer le paquetage pour y accder, ce qui est difficile faire par inadvertance. Par exemple, un programme qui rfrence $Doc::categorie demande la variable $categorie dans le paquetage Doc::, qui na rien voir avec la variable $Livre::categorie. Voir le chapitre 10, Paquetages. Les variables attaches une porte lexicale ne sont pas contenues dans un paquetage, et ne contiennent pas la squence ::. (Les variables porte lexicale sont dclares avec my.)

Recherche des noms


La question est donc comment Perl devine le chemin absolu dun nom ? Comment trouve-t-il par exemple le nom de $categorie ? Voici les tapes successives suivies par linterprteur Perl dans la phase de lecture du code, pour rsoudre les noms dans le contexte courant : 1. Premirement, Perl inspecte le bloc immdiatement contenant, pour une dclaration du type my (ou our) (Voir le chapitre 29, ainsi que la section Dclarations avec porte au chapitre 4, Instructions et dclarations). Sil trouve cette dclaration, alors la variable est porte lexicale et nexiste dans aucun elle existe uniquement dans le bloc courant. Une porte lexicale est anonyme et ne peut donc tre atteinte hors du bloc la contenant.8 2. Sil ne trouve pas, Perl cherche une variable porte lexicale dans le bloc contenant le prcdent et sil la trouve, il la marque comme appartenant ce bloc de niveau suprieur. noter que dans ce cas, sa porte comprend le bloc de la premire tape. Dans le cas inverse, il rpte cette deuxime tape jusqu la sortie du bloc racine, le plus grand contenant les prcdents. 3. Quand il ny a plus de blocs contenants, linterprteur examine lunit de compilation entire, ce qui peut tre le fichier entier ou la chane en cours de compilation dans le cas de lexpression eval CHAINE. Dans ce dernier cas, la porte lexicale est la chane elle-mme et non un bloc entre accolades. Si Perl ne trouve pas la variable
8. Si la dclaration our est utilise la place, cela revient dclarer un alias de variable de paquetage. Le code extrieur peut accder cette variable mais seulement par lintermdiaire du paquetage o la variable est dfinie. Pour le reste une dfinition our fonctionne exactement comme une dfinition my. Cest utile pour limiter lusage des globales avec la directive use strict (voir la directive strict au chapitre 31). Mais il est prfrable dutiliser my quand une variable globale nest pas ncessaire.

customer_8566

Noms

49

dans la porte lexicale de la chane, il considre quil ny a plus de bloc et retourne ltape 2 en partant de la porte lexicale du bloc eval STRING. 4. ce point, Perl na pas encore trouv de dclaration pour notre variable (ni my, ni our). Perl abandonne la recherche dune variable lexicale, et suppose que la variable recherche est une variable de paquetage. Le degr suivant de recherche est donc le paquetage. Si la directive strict est active, le compilateur provoque une erreur, (sauf si la variable est prdfinie ou importe dans le paquetage courant), car il ne peut exister de variable globale sans qualifiant. Il cherche la dclaration package toujours dans la porte lexicale, et sil la trouve, insre le nom du paquetage trouv au dbut de la variable. 5. Sil ne trouve pas de dclaration de paquetage dans la porte lexicale, Perl recherche la variable dans le paquetage main qui contient tous les autres. En labsence de dclaration contraire, $categorie veut dire $::categorie, qui veut dire $main::categorie. (main tant un paquetage dans le paquetage de plus haut niveau, cela veut aussi dire $::main::categorie ou encore $main::main::categorie et $::main::main::categorie et ainsi de suite. On en verra toute lutilit dans Tables de symboles au chapitre 10.) Il y a plusieurs consquences que nous devons souligner ici : Le fichier tant la plus grande porte lexicale, une variable porte lexicale ne peut tre vue en dehors du fichier dans lequel elle est dclare. Les portes de fichier ne sont pas imbriques. Tout code Perl compil appartient au moins une porte lexicale et exactement un paquetage. La porte obligatoire est le fichier de code lui-mme. Les blocs contenant dfinissent les portes successives. Tout code Perl est compil dans un paquetage exactement, et si la dclaration du paquetage a une porte lexicale, le paquetage nen a pas, il est global. Une variable sans qualifiant peut tre cherche dans diffrentes portes lexicales, mais dans un seul paquetage, qui est le paquetage actif (dtermin par la porte lexicale de la variable). Un nom de variable ne peut avoir quune porte. Bien que deux portes sont actives au mme moment (lexicale et paquetage), une variable ne peut exister que dans une seule la fois. Un nom de variable sans qualifiant ne peut exister que dans une place mmoire, soit dans la premire porte lexicale, soit dans le paquetage courant, mais pas les deux. La recherche sarrte ds que la place mmoire est trouve, et les autres places mmoire qui auraient t trouves si la recherche stait poursuivie, ces places mmoire donc sont nanmoins inaccessibles. La place mmoire dune variable typique peut tre compltement dtermine la compilation.

Maintenant on sait comment le compilateur Perl rsoud les noms, mais parfois on ne connat pas ce nom au moment de la compilation : par exemple dans le cas dune indirection. Dans ce cas, Perl fournit un mcanisme qui permet de remplacer une variable par une expression qui retourne une rfrence cette variable. Par exemple, au lieu de dire :

customer_8566

50
$categorie

Chapitre 2 Composants de Perl

vous diriez :
${ une_expression() }

et si la fonction une_expression() retourne une rfrence la variable $categorie (ou bien la chane "categorie"), cela fonctionne de la mme manire. Par contre, si la fonction retourne $thesaurus ce sera cette variable la place. Cette syntaxe est la plus gnrale (et la moins lisible) des formes dindirection, mais nous verrons des variantes plus pratiques au chapitre 8, Rfrences.

Valeurs scalaires
Quil soit rfrenc directement ou indirectement, dans une variable, un tableau ou bien une variable temporaire, un scalaire contient toujours une valeur simple qui peut tre un nombre, une chane ou une rfrence une autre donne. Il peut aussi navoir aucune valeur auquel cas il est dit indfini. Les scalaires sont sans type, mme sils peuvent rfrencer toutes sortes de donnes : il nest pas ncessaire de les dclarer.9 Perl mmorise les chanes comme des squences de caractres sans contrainte de longueur ni de contenu. Nul besoin de dclarer une taille lavance et tout caractre peut y tre inclus, y compris le caractre nul. Les nombres sont reprsents sous forme dentiers signs si possible, ou bien sous forme de nombres virgule f lottante en double prcision dans le format natif de la machine. Les valeurs f lottantes ne sont pas infiniment prcises, cest pourquoi certaines comparaisons de la forme (10/3 == 1/3*10) chouent mystrieusement. Perl convertit les scalaires en diffrents sous-types suivant les besoins ; le numrique peut tre trait comme du caractre et inversement, Perl faisant Ce Quil Faut. Pour convertir du caractre en numrique, Perl utilise la fonction C atof(3). Pour passer du numrique une chane de caractres, il fait lquivalent de sprintf(3) avec le format "%.14g" sur la plupart des machines. La conversion dune chane non numrique comme truc convertit le literal la valeur 0 ; sils sont actifs, les avertissements sont affichs sinon rien. Voir le chapitre 5, pour des exemples permettant didentifier le contenu dun chane. Alors que les chanes de caractres et les numriques sont interchangeables dans peu prs tous les cas, les rfrences sont dun genre diffrent. Elles sont fortement types, ce sont des pointeurs non convertibles (transtypables) comprenant des compteurs de rfrences et des invocations de destructeurs internes. Ils sont utilisables pour crer des types de donnes complexes, incluant vos propres objets. Ceci dit, les rfrences restent des scalaires, car ce qui importe nest pas tant la compexit dune structure que le fait de la considrer comme un simple scalaire. Par non convertibles, nous voulons dire que lon ne peut pas, par exemple, convertir une
9. Les versions futures de Perl permettront de dclarer les trois types int, num et str, pour lever toute ambiguit pour loptimiseur de code. Ces types seront utiliss dans du code critique qui doit sexcuter rapidement, et nous nentrerons pas dans le dtail maintenant. Le mcanisme de pseudo-hash utilise ces types optionels la manire dun langage plus fortement typ. Voir le chapitre 8 pour aller plus loin.

customer_8566

Valeurs scalaires

51

rfrence de tableau en une rfrence de hachage. Les rfrences ne sont pas convertibles en un autre type pointeur. Cependant, en utilisant une rfrence en numrique ou en caractre, on obtient une valeur numrique ou une chane de caractres, ce qui permet de se souvenir du caractre unique dune rfrence, mme si le rfrencement de la valeur est perdu au cours de la copie depuis la vraie rfrence. On peut comparer diffrentes rfrences ou tester si elles sont dfinies. Mais on ne peut en faire beaucoup plus puisquil nexiste pas de moyen de convertir du numrique ou du caractre en rfrence. En principe, si Perl noblige pas faire de larithmtique de pointeurs ou carrment linterdit , ce nest pas un problme. Voir le chapitre 8 pour en connatre plus sur les rfrences.

Littraux numriques
Les littraux numriques sont spcifis par nimporte quel format courant10 de virgule f lottante ou dentier :
$x $x $x $x $x $x $x = = = = = = = 12345; 12345.67; 6.02E23; 4_294_967_296; 0377; 0xffff; 0b1100_0000; # # # # # # # entier virgule flottante notation scientifique soulign pour la lisibilit octal hexadcimal binaire

Comme Perl utilise la virgule comme sparateur de liste, elle ne peut servir comme sparateur des milliers pour les grands nombres. Pour amliorer leur lisibilit, Perl permet dutiliser la place le caractre soulign. Celui-ci ne fonctionne quavec des constantes numriques dfinies dans le programme, et non pour les chanes de caractres traites comme du numrique ou pour les donnes externes lues par ailleurs. De mme, les caractres initiaux 0x en hexadcimal et 0 en octal marchent uniquement avec les constantes. La conversion automatique dune chane en un nombre ne reconnat pas ces prfixes vous devez faire une conversion explicite11 avec la fonction oct (qui marche aussi pour les donnes hexadcimales condition dindiquer 0x ou 0b au dbut).

Chanes littrales
Les littraux alphanumriques sont habituellement dlimits par des apostrophes simples ou doubles. Ils fonctionnent un peu comme les quotes (les dlimiteurs de protection) sous UNIX : les apostrophes doubles permettent une interpolation des antislashs et des variables, les apostrophes simples non. (\ et \\ permettent dinclure un antislash dans une chane entre apostrophes simples). Si vous voulez inclure tout autre squence
10. Courant dans la culture UNIX, nest-ce pas. Si votre culture est diffrente, bienvenue dans la ntre ! 11. On simagine parfois que Perl devrait de lui-mme convertir toutes les donnes. Mais il existe beaucoup trop de nombres dcimaux avec des zros gauche dans le monde pour que Perl puisse le faire automatiquement. Par exemple, le code postal des bureaux de OReilly & Associates Cambridge, MA, est 02140. Le facteur aurait tendance snerver si votre programme dadressage de courrier transformait 02140 en la valeur dcimale 1120.

customer_8566

52

Chapitre 2 Composants de Perl

telle que \n (saut de ligne), vous devez utiliser les apostrophes doubles. (Les squences antislashs sont des squences dchappement car elles permettent d chapper temporairement linterprtation normale des caractres.) Une chane entre apostrophes simples doit tre spare du mot prcdent par un espace car ce caractre est valide mais archaque dans un identificateur. On utilise plutt la squence :: plus visuelle: $mainvar et $main::var reprsentent la mme variable, la deuxime tant beaucoup plus lisible. Les chanes entre guillemets permettent linterpolation de diffrents types de caractres bien connus dans les autres langages. Ils sont lists au tableau 2-1. Tableau 2-1. Caractres chapps avec antislash
Code \n \r \t \f \b \a \e \033 \x7f \cC \x{263a} \N{NAME} Signification Saut de ligne (gnralement LF). Retour chariot (gnralement CR). Tabulation horizontale. Saut de page. Retour arrire. Alerte (bip). Caractre ESC. ESC en octal. DEL en hexadcimal. Control-C. Unicode (smiley). Caractre nomm.

La notation \N{NOM} est utilise avec la directive use charnames dcrite au chapitre 31. Cette notation permet dutiliser les noms symboliques comme \N{GREEK SMALL LETTER SIGMA}, \N{greek:Sigma}, ou \N{sigma} suivant la directive utilise. Voir aussi le chapitre 15. Il existe de plus des squences dchappement pour modifier la casse des caractres qui suivent. Voir le tableau 2-2. Tableau 2-2. chappements de casse
Code \u \l \U \L \Q \E Signification Force le caractre suivant en majuscule ( titlecase en Unicode). Force le caractre suivant en minuscule. Force tous les caractres suivants en majuscules. Force tous les caractres suivants en minuscules. Prfixe avec antislash tous les caractres non alphanumriques. Fin de \U, \L, ou \Q.

customer_8566

Valeurs scalaires

53

Il est aussi possible dinsrer le caractre de saut de ligne dans une chane qui peut donc stendre sur plus dune ligne. Ceci peut tre utile, mais aussi dangereux si vous oubliez un guillemet, auquel cas lerreur sera annonce la prochaine occurrence de guillemet qui peut se trouver beaucoup plus loin dans votre fichier source. Heureusement ceci provoque immdiatement une erreur de syntaxe sur la mme ligne, et Perl est suffisamment fut pour vous avertir quil sagit peut-tre dune chane qui nest pas termine au bon endroit, et de plus il vous indique la ligne o la chane a d commencer. Paralllement aux squences dchappement ci-dessus, les chanes entre doubles apostrophes permettent une interpolation des variables scalaires et des listes de valeurs. Cela signifie que les valeurs de certaines variables peuvent tre directement insres dans une chane. Cest en fait une forme pratique de concatnation de chane.12 Linterpolation ne peut tre effectue que pour des variables scalaires, la totalit dun tableau (mais pas dun hachage), des lments unitaires dun tableau ou dun hachage, ou enfin, des tranches (des slections multiples dlments) de tableaux ou de hachages. En dautres termes, seules les expressions commenant par $ ou @ peuvent tre interpoles, car ce sont les deux caractres (avec lantislash) que lanalyseur de chane recherche. lintrieur dune chane, un caractre @ ne faisant pas partie de lidentifiant dun tableau ou dun hachage doit tre inclus dans une squence dchappement avec un antislash (@), sous peine dune erreur de compilation. Bien quun hachage complet spcifi par % ne puisse tre interpol dans une chane, un lment ou une slection multiples dlments dun hachage peuvent ltre car ils commencent respectivement par les caractres $ et @. Le bout de code suivant affiche "Le prix est de $100.".
$Prix = $100; print "Le prix est de $Prix.\n"; # non interpol # interpol

Comme dans certains shells, les accolades autour dun identifiant permettent de le diffrencier des autres caractres alphanumriques : "How ${verb}able!". En fait un identifiant entre accolades est forcment interprt en chane, comme les chanes clef dun hachage. Par exemple,
$jours{fev}

peut aussi tre crit :


$jours{fev}

et les apostrophes sont censes tre automatiquement prsentes. Mais toute chose plus complexe dans lindice sera interprte comme une expression. et vous devriez les mettre entre guillemets simples :
$jours{29 Fvrier} $jours{"29 Fvrier"} $jours{ 29 Fvrier } # Ok. # Ok. "" pas besoin dinterpoler. # mauvais, provoque un erreur de lecture.

En particulier, il est ncessaire dutiliser les simples guillemets dans les tranches de tableau :
12. Avec les warnings activs, Perl peut retourner une erreur sur des valeurs indfinies interpoles dans des chanes concatnes ou jointes, mme implicitement, le compilateur les crant pour vous.

customer_8566

54
@jours{Jan,Fev} @jours{"Jan","Fev"} @jours{ Jan, Fev }

Chapitre 2 Composants de Perl


# Ok. # Ok aussi. # erreur si la directive use strict est active

Excepts les indices de tableaux interpols ou de hachages, il nexiste pas de niveaux multiples dinterpolation. En particulier, contrairement aux attentes de nombreux programmeurs shell, les apostrophes inverses ne permettent pas dinterpoler lintrieur dapostrophes doubles. De mme, les apostrophes simples ne permettent pas dempcher lvaluation de variables lintrieur dapostrophes doubles. Linterpolation est trs puissante mais dun contrle strict en Perl. Elle ne se produit que dans les guillemets et certaines oprations que nous dcrirons dans la prochaine section.
print "\n"; print \n ; # Ok, imprime un saut de ligne. # MAUVAIS, pas de contexte dinterpolation.

Choisissez vos dlimiteurs


Alors que lon ne considre souvent les dlimiteurs que comme des constantes, ils fonctionnent plus comme des oprateurs avec Perl, permettant plusieurs formes dinterpolation et de correspondance de motifs. Perl fournit des dlimiteurs spcifiques pour ces fonctions, mais offre galement le moyen de choisir un dlimiteur pour chacune. Au tableau 2-3, on peut utiliser tout caractre autre qualphanumrique ou despace comme dlimiteur la place de /. (Les caractres saut de ligne et despace ne sont plus admis dans les nouvelles versions de Perl.) Tableau 2-3. Constructions avec guillemets
Habituelle "" `` () // s/// y/// "" Gnrique q// qq// qx// qw// m// s/// tr/// qr// Signification chane littrale chane littrale excution de commande liste de mots recherche de motif substitution de motif traduction expression rationnelle Interpolation non oui oui non oui oui non oui

Certains, ci-dessus, sont uniquement des formes de sucre syntaxique ; ils vitent dalourdir une chane avec trop dantislashs, en particulier dans les expressions rgulires o slash et antislash se ctoient. Si vous utilisez les guillemets simples comme dlimiteurs, aucune interpolation de variable ne sera faite (mme si le tableau ci-dessus indique oui ). Si le dlimiteur ouvrant est un crochet, une parenthse, une accolade ou le signe infrieur, le dlimiteur fermant doit lui correspondre (les occurrences de dlimiteurs doivent correspondre par paires). Par exemple :
$simple = q!Je dis "Tu dis, Elle la dit."!; $double = qq(On ne peut pas avoir une "bonne" $variable?);

customer_8566

Valeurs scalaires
$bout_de_code = q { if ($condition) { print "Pris!"; } };

55

Le dernier exemple montre quil est possible dutiliser le caractre espace entre loprateur de protection et le dlimiteur. Pour les constructions deux lments, comme s/// et tr///, si la premire paire de dlimiteurs est une accolade, la seconde partie peut en utiliser un autre : on peut crire s<foo>(bar) ou tr(a-f)[A-F]. Les espaces sont autoriss entre les deux paires de dlimiteurs, ainsi le dernier exemple peut scrire :
tr [a-z] [A-Z];

Les caractres espace sont toutefois interdits lorsque le dlimiteur est #. q#foo# est lu comme foo, alors que q #foo# est lu comme loprateur q suivi dun commentaire. Le dlimiteur sera pris sur la ligne suivante. Les commentaires peuvent tre placs au milieu dune construction deux lments, ce qui permet dcrire :
s {foo} {bar}; # Remplacer foo # par bar.

tr [a-f] # Translittration de minuscule hexa [A-F]; # vers majuscule hexa

Ou nen mettez pas du tout


Un mot qui na pas dinterprtation dans la grammaire sera trait comme sil tait dans une chane protge. Ce sont les mots simples.13 Comme pour les handles de fichier et les labels, un mot simple entirement en minuscules risque dentrer en conf lit avec un futur mot rserv. Si vous utilisez loption -w, Perl vous avertira de ce risque. Par exemple :
@jours = (Lun,Mar,Mer,Jeu,Ven); print STDOUT Salut, , monde, "\n";

stocke dans le tableau @jours les abrviations des jours de la semaine et affiche Salut tout le monde suivi dun saut de ligne sur STDOUT. En tant le handle de fichier, Perl essaiera dinterprter Salut comme un handle de fichier avec la clef une erreur de syntaxe. Cest tellement source derreur que certains voudront dclarer hors la loi les mots simples. Les oprateurs de protection lists ci-avant ont dautres formes y compris loprateur quote words qw// qui opre sur une liste de mots spars par des espaces :
@jours = qw(Lun Mar Mer Jeu Ven); print STDOUT "Salut, tout le monde\n";

Vous pouvez aussi bannir les mots simples de votre code. Si on crit :

13. Les noms de variables, descripteurs de fichier, labels et autres, ne sont pas considrs comme des mots simples car ils ont un sens qui dpend du mot prcdent ou suivant (ou les deux). Les noms prdfinis comme les noms de sous-programme nen sont pas non plus. Un mot simple le reste tant quil ny a pas la preuve du contraire.

customer_8566

56
use strict subs;

Chapitre 2 Composants de Perl

alors tout mot simple qui nest pas interprt comme un appel un sous-programme produit la place une erreur de compilation. Cette restriction dure jusqu la fin du bloc qui la contient. Un autre bloc peut lannuler par
no strict subs;

Il faut remarquer que les identifiants dans des constructions telles que :
"${verb}able" $jours{Fv}

ne sont pas considrs comme des mots simples car ils sont autoriss par une rgle explicite plutt que par le fait de ne pas avoir dinterprtation dans la grammaire . Un nom simple avec :: en fin, tel que main:: ou bien Chameau:: est toujours considr comme un nom de paquetage. Perl transforme Chameau:: en chane Chameau au moment de la compilation, et ne sera pas rejet par la directive use strict.

Interpolation des tableaux


Les variables tableau sont interpoles dans une chane entre doubles apostrophes en runissant tous leurs lments avec le dlimiteur spcifi dans la variable $"14 lespace sera pris par dfaut. Les exemples suivants sont quivalents :
$temp = join($",@ARGV); print $temp; print "@ARGV";

lintrieur des motifs de recherche (qui comprend aussi une interpolation identique celle des doubles guillemets) il existe une ambigut dplaisante : /$machin[chose]/ est-il interprt comme /${machin}[chose]} (o [chose] est une classe de caractres pour lexpression) ou comme /${machin[chose]}/ (o [chose] est lindice du tableau @machin) ? Si @machin nexiste pas, cest bien sr une classe de caractres. Si @machin existe, Perl devinera [chose], presque toujours bon escient.15 Sil dcrypte mal, ou si vous tes paranoaque, des accolades permettent de forcer linterprtation correcte comme cidessus. Et mme si vous tes simplement prudent, ce nest pas une mauvaise ide.

Documents ici-mme
Un format de sparation orient ligne est bas sur la syntaxe des documents icimme ( here documents) du shell16 Aprs les caractres <<, on saisit une chane destine terminer la partie dlimiter, toutes les lignes suivant la ligne courante jusqu
14. $LIST_SEPARATOR si vous utilisez le module English. 15. Le devin est trop ennuyeux dcrire compltement, mais, grosso modo, il fait une moyenne pondre de ce qui ressemble une classe de caractres (a-z, \w, les caractres initiaux ^) par rapport tout ce qui ressemble des expressions (les variables et les mots rservs). 16. Il est orient ligne dans le sens o les dlimiteurs sont les lignes plutt que des caractres. Le dlimiteur initial est la ligne courante, et celui de la fin est une ligne contenant la chane spcifie.

customer_8566

Valeurs scalaires

57

la chane de terminaison tant dlimites. La chane de terminaison peut tre un identifiant (un mot) comme du texte dlimit. Dans ce cas, le type de dlimiteur utilis dtermine le traitement du texte, comme en dlimitation standard. Un identifiant non dlimit fonctionne comme des apostrophes doubles. Il ne doit pas y avoir despace entre les caractres << et lidentifiant (un espace est trait comme un identifiant nul, ce qui est valable mais pas recommand, et correspond avec la premire ligne vide ; voir le premier exemple Hourra~! plus loin). La chane de terminaison doit apparatre en tant que telle (sans dlimiteurs et non entoure despaces) sur la dernire ligne.
print <<EOF; Le prix est $Prix. EOF print <<"EOF"; Le prix est $Prix. EOF print <<EOF; # avec des apostrophes simples Tout est possible (par exemple le passage dun chameau par le chas dune aiguille), cest vrai. Mais imaginez ltat du chameau, dform en un long fil sanglant de la tte aux pieds. -- C.S. Lewis EOF print << x 10; # affiche la ligne suivante 10 fois Les chameaux dbarquent! Ho u rra! Hourra! print <<"" x 10; # La mme chose, en mieux Les chameaux dbarquent! Ho u rra! Hourra! print <<`EOC`; # excute les commandes echo comment vas-tu echo yau de pole? EOC print <<"dromadaire", <<"camelide"; # on peut les empiler Je dis bactriane. dromadaire Elle dit lama. camelide # mme exemple que prcdemment

# mme exemple quau dessus avec des apostrophes # doubles explicites

Noubliez quand mme pas de mettre un point virgule la fin pour finir la phrase, car Perl ne sait pas que vous nallez pas essayer de faire ceci :
print <<ABC 179231 ABC + 20; # affiche 179251

Si vous voulez indenter vos documents ici-mme avec votre code, il faut enlever les espaces devant chaque ligne manuellement :

customer_8566

58
($quote = <<QUOTE) =~ s/^\s+//gm; The Road goes ever on and on, down from the door where it began. QUOTE

Chapitre 2 Composants de Perl

Il est aussi possible dinstancier un tableau avec les lignes dun document ici-mme comme suit :
@sauces = <<fin_lignes =~ m/(\S.*\S)/g; tomate normale tomate pice chili vert pesto vin blanc fin_lignes

Litral V-chane
Un litral qui commence avec un v suivi dun ou plusieurs entiers spars par des points est traduit en chane dont chaque atome a pour valeur ordinale chaque entier.
$crlf = v13.10; # valeur ASCII: retour chariot, saut de ligne

Le terme v-chane est une contraction de vecteur-chane ou version de chane . Il fournit une alternative plus cohrente pour construire une chane partir des valeurs numriques de chaque caractre. Par exemple, il est plus facile dcrire v1.20.300.4000 plutt que :
"\x{1}\x{14}\x{12c}\x{fa0}" pack("U*", 1, 20, 300, 4000) chr(1) . chr(20) . chr(300) . chr(4000)

Si un tel littral est compos de deux ou trois points (au moins trois entiers), le prfixe v peut tre omis.
print v9786; print v102.111.111; print 102.111.111; use 5.6.0; $ipaddr = 204.148.40.9; # affiche le caractre UTF-8 SMILEY, "\x{263a}" # affiche "foo" # idem # ncessite au moins cette version de Perl # laddresse IP de oreilly.com

Les v-chanes sont pratiques pour reprsenter les adresses IP ou les numros de version. En particulier avec le codage de caractres sur plus dun octet qui devient courant de nos jours, on peut comparer les numros de version de toute taille avec les v-chanes. Les numros de version et les adresses IP ne sont pas trs lisibles sous la forme de v-chanes. Pour obtenir une chane affichable utilisez loption v dans un masque avec printf, comme par exemple dans "%vd", tel que dcrit au chapitre 29. Pour en savoir plus sur les chanes Unicode, voir le chapitre 15, ainsi que la directive use bytes au chapitre 31 ; pour la comparaison des versions avec les oprateurs de comparaison de chane, voir $^V au chapitre 28 ; et pour la reprsentation des adresses IPv4, voir gethostbyaddr au chapitre 29.

customer_8566

Contexte

59

Autres symboles littraux


Tout symbole prfix par deux caractres soulign et postfix de mme est rserv pour un usage spcial par Perl. Deux mots spciaux, savoir __LINE__ et __FILE__, reprsentent le numro de la ligne courante et le fichier ce stade du programme. Ils ne peuvent tre utiliss que comme des mots spars ; ils ne sont pas interpols dans les chanes. De la mme manire, __PACKAGE__ est le nom du paquetage courant de compilation. Sil nexiste pas, ce qui est le cas lorsque la directive package; est vide, __PACKAGE__ vaut undef. Le symbole __END__, ou les caractres Control-D ou ControlZ, peuvent tre utiliss pour indiquer la fin logique du script courant avant la fin physique du fichier. Tout caractre suivant est ignor par le lecteur Perl mais peut tre lu via le descripteur spcial DATA. __DATA__ fonctionne de la mme faon que __END__, mais ouvre le handle de fichier DATA lintrieur de lespace de nom du paquetage courant, ce qui fait que si vous insrez plusieurs fichiers par require, chacun peut disposer de son handle DATA personnel et louvrir sans conf lit avec les autres. Pour en savoir plus, voir DATA au chapitre 28.

Contexte
Jusqu prsent, nous avons vu un certain nombre de termes pouvant produire des valeurs scalaires. Avant den voir davantage, nous devons aborder la notion de contexte.

Contexte scalaire et contexte de liste


Chaque opration17 dun script Perl est value dans un contexte spcifique, et la faon dont lopration se comportera peut dpendre des contraintes de ce contexte. Il existe deux contextes majeurs : les scalaires et les listes. Par exemple, laffectation dune variable scalaire value la partie droite dans un contexte scalaire :
$x = fonction(); # contexte scalaire $x[1] = fonction(); # contexte scalaire $x{"ray"} = fonction(); # contexte scalaire

Mais laffectation dun tableau ou dun hachage (ou dune tranche de ceux-ci) value la partie droite dans un contexte de liste. Laffectation dune liste de scalaire se fera aussi par un contexte de liste pour la partie droite.
@x = fonction(); # contexte de liste @x[1] = fonction(); # id @x{"ray"} = fonction(); # id %x = fonction(); # id

Laffectation une liste de scalaires fournit aussi un contexte de liste en rvalue, mme sil ny a quun seul lment dans la liste produite :
($x,$y,$z) = fonction(); # contexte de liste ($x) = fonction(); # id
17. Nous utilisons ce terme la fois pour oprateur et terme. Ces deux concepts se confondent lun et lautre lorsque lon commence parler de fonctions qui agissent comme des termes mais qui ressemblent des oprateurs unaires.

customer_8566

60

Chapitre 2 Composants de Perl

Ces rgles sont inchanges quand la variable est dclare avec les termes my ou our, ainsi nous avons :
my my my my $x @x %x ($x) = = = = fonction(); fonction(); fonction(); fonction(); # # # # contexte scalaire contexte de liste id id

Vous aurez beaucoup de problmes jusquau jour o vous aurez compris la diffrence entre le contexte scalaire et le contexte de liste, car certains oprateurs (tel notre fonction imaginaire fonction()), connaissent leur contexte de retour et typent leur valeur de retour en consquence. (Ce comportement sera toujours signal quand cest le cas.) En langage informatique, on dit que les oprateurs ont leur type de retour surcharg par le contexte daffectation. Il sagit de la surcharge la plus simple base sur deux types simples, le scalaire et la liste. Si certains oprateurs rpondent suivant le contexte, cest parce que quelque chose indique son type scalaire ou liste. Laffectation se comporte comme une fonction qui fournit son oprande de droite le contexte. On a besoin de savoir quel oprateur fournit quel contexte pour ses oprandes. Toutes les fonctions avec un contexte de liste, ont le terme LISTE dans leur description. Celles qui ne lont pas ont un scalaire. Cest en gnral assez intuitif.18 Au besoin, on peut forcer un contexte scalaire au milieu dun contexte de LISTE en utilisant la pseudo-fonction scalar. (Perl ne fournit pas le moyen de forcer un contexte de liste en contexte scalaire, car partout o un contexte de liste est prvu, ceci est dj indiqu par le contexte LISTE de certaines fonctions de contrle.) Le contexte scalaire peut ensuite tre class en contexte de chanes, numriques ou contexte tolrant. la diffrence de la distinction entre scalaire et liste que nous venons de faire, les oprations ne savent jamais quel type de contexte scalaire elles ont en entre. Elles se contentent de renvoyer le type de valeur scalaire quelles dsirent et laissent Perl traduire les numriques en chane dans un contexte de chane, et les chanes en nombres dans un contexte numrique. Certains contextes scalaires se moquent de savoir si une chane ou un numrique est retourn, ce qui fait quaucune conversion ne sera effectue. (Cela arrive, par exemple, lorsquon affecte une valeur une autre variable. Celle-ci prend simplement le mme sous-type que lancienne valeur.)

Contexte boolen
Le contexte boolen est un contexte scalaire particulier. Il correspond lendroit o une expression est value pour savoir si elle est vrai ou faux. Parfois nous crivons Vrai ou Faux la place de la dfinition technique utilise par Perl : une valeur scalaire est vrai si ce nest pas une chane nulle ou le nombre 0 (ou sa chane quivalente : "0"). Les rfrences sont toujours vraies. Une rfrence est toujours vraie car cest une adresse physique jamais nulle. Une valeur indfinie, appele undef, est toujours fausse car elle vaut, suivant le contexte, "" ou 0. (Les listes nont pas de valeur boolenne car elles ne sont jamais produites dans un contexte scalaire !)
18. Remarquez cependant que le contexte LISTE peut se propager aux appels de sous-programmes ultrieurs et il nest donc pas toujours facile de savoir dun seul coup dil si une phrase va tre value dans un contexte scalaire ou de liste. Le programme peut retrouver son contexte dans un sous-programme par la fonction wantarray.

customer_8566

Contexte

61

Puisque le contexte boolen est un contexte tolrant, il nentrane aucune conversion ; noter que cest un contexte scalaire, et tout oprande pour lequel cest ncessaire sera converti en scalaire. Et pour tout oprande le ncessitant, le scalaire retourn dans un contexte scalaire est une valeur boolenne possible, ce qui signifie par exemple quun oprateur retournant une liste, peut tre utilis dans un test boolen : la fonction unlink qui opre dans un contexte de liste, peut utiliser un argument de type array :
unlink @liste_fichiers; # dtruit chaque fichier de la liste.

Maintenant, utilisons le tableau dans une condition (donc contexte boolen), alors le tableau retourne sa cardinalit car il sait que cest un contexte scalaire ; cette valeur est vraie tant quil reste des lments dans le tableau. Supposons alors que nous voulons vrifier que les fichiers ont t supprims correctement, on crirait :
while (@liste_fichiers) { my $fichier = shift @liste_fichiers; unlink $fichier or warn "Ne peut pas supprimer $fichier: $!\n"; }

Ici @liste_fichier est value dans le contexte boolen induit par la boucle while, de telle sorte que Perl value le tableau pour voir si sa valeur est vraie ou fausse. Cette valeur est vraie tant que la liste contient des lments et devient fausse ds que le dernier lment est enlev (par loprateur shift). Notez que la liste nest pas value dans un contexte scalaire. Nous indiquons au tableau quil est scalaire et lui demandons ce quil vaut dans ce contexte. Nessayez pas dutiliser defined @files pour ce faire. La fonction defined regarde si le scalaire est gal undef, et un tableau nest pas un scalaire. Un simple test boolen suffit dans ce cas.

Contexte vide
Un autre type particulier des contextes scalaires est le contexte vide. Non seulement il se moque de la valeur retourner, mais en plus il ne veut mme pas de valeur de retour. Du point de vue du fonctionnement des fonctions, il nest pas diffrent des autres contextes scalaires, mais par le switch -w de la ligne de commande, le compilateur Perl prvient de lutilisation dune expression sans effet secondaire un endroit qui ne veut pas dune valeur, comme dans une phrase qui ne renvoie pas de valeur. Par exemple, si une chane est employe comme phrase :
"Camel Lot";

on peut obtenir un avertissement tel que :


Useless use of a constant in void context in monprog line 123;

Contexte interpolatif
Nous avons dj mentionn que les apostrophes doubles autour dune chane permettent une interpolation des variables et une interprtation des antislashs, mais le contexte interpolatif (souvent appel contexte double quotes ) ne sapplique pas quaux chanes entre doubles apostrophes. Les autres constructions double quotes concernent loprateur gnral apostrophe inverse qx//, loprateur de recherche de motif m// et

customer_8566

62

Chapitre 2 Composants de Perl

loprateur de substitution s/// et loprateur dexpression rgulire qr//. En fait, loprateur de substitution fait une interpolation de sa partie gauche avant de faire la recherche de motif, puis chaque motif trouv fait une interpolation de sa partie droite. Le contexte interpolatif nintervient quentre apostrophes, ou pour des choses qui fonctionnent de la mme faon, et il nest donc peut tre pas vraiment correct de lappeler contexte au mme titre que les contextes scalaires ou les contextes de liste (ou peut-tre bien que si).

Valeur de liste et tableaux


Maintenant que nous avons parl des contextes, nous pouvons parler des listes de valeurs et de leur comportement dans les diffrents contextes. Nous avons dj vu les listes de littraux, dfinies en sparant chaque valeur par une virgule (et en encadrant la liste par une paire de parenthses). Comme il nest pas gnant (presque jamais) dajouter des parenthses supplmentaires, la forme syntaxique dune liste scrit :
(LISTE)

Nous venons de voir que la forme LISTE indique un terme qui retourne une liste son argument, mais une liste littrale simple est lexception cette rgle en ce quelle fournit un contexte de liste uniquement quand la liste elle-mme est dans un contexte de liste. La valeur dune liste litrale dans un contexte de liste est simplement les valeurs de chaque lment spares par une virgule dans lordre spcifi. Comme un terme dans une expression, une liste litrale empile simplement des valeurs temporaires sur la pile Perl, elles seront utilises ensuite par loprateur qui attend cette liste. Dans un contexte scalaire, la valeur dune liste est la valeur de son dernier lment, comme avec loprateur virgule du C qui ignore toujours la valeur gauche et renvoie celle de droite (en faisant rfrence ce que nous disions plus haut, la partie gauche de la virgule fournit un contexte vide). Loprateur virgule tant associatif gauche, une liste de valeurs spares par des virgules fournit toujours le dernier lment car la virgule oublie chaque valeur prcdente. Par exemple :
@truc = ("un", "deux", "trois");

affecte toute la liste de valeurs au tableau @truc, mais :


$truc = ("un", "deux", "trois");

naffecte que la valeur trois la variable $truc. Comme pour le tableau @liste_fichiers, loprateur virgule sait sil est dans un contexte scalaire ou de liste et adapte son comportement en consquence. Cest important de souligner quune liste est diffrente dun tableau. Une variable tableau connat aussi son contexte, et dans un contexte de liste retourne la liste de ses valeurs internes comme une liste littrale. Mais dans un contexte scalaire elle retourne simplement sa longueur. Le code suivant affecte la valeur 3 la variable $truc :
@truc = ("un", "deux", "trois"); $truc = @truc;

Si vous pensiez obtenir la valeur trois , vous avez gnralis un peu vite car en fait Perl a dtect le contexte scalaire et na empil que la longueur du tableau. Aucun terme ou oprateur nempilera des valeurs de liste dans un contexte scalaire. Il empilera une

customer_8566

Valeur de liste et tableaux

63

valeur scalaire, qui ne sera certainement pas la dernire valeur de la liste quil retournerait dans un contexte de liste, valeur scalaire qui est ici la longueur du tableau. Il faut bien comprendre cet exemple (sinon, relisez le paragraphe car cest important). Retournons aux vraies LISTE, celles qui induisent un contexte de liste. Jusqu prsent nous avons soutenu que le contexte LISTE ne contient que des littraux. Mais en fait, toute expression qui retourne une valeur peut tre utilise lintrieur dune liste. Les valeurs ainsi utilises peuvent tre des valeurs scalaires ou des listes de valeurs. Le contexte LISTE fait automatiquement une interpolation des sous-listes. Cest pourquoi, lorsquun contexte LISTE est valu, chaque lment de la liste est valu dans ce contexte et la valeur de la liste rsultante est interpole dans LISTE comme si chaque lment individuel tait un membre de LISTE. Les tableaux perdent ainsi leur identit dans LISTE. La liste :
(@machin,@chose,&sousProgramme)

contient tous les lments de @machin, suivis de tous les lments de @chose, suivis de tous les lments renvoys par le sous-programme sousProgramme lorsquil est appel dans un contexte de liste. Notez que si lun quelconque des lments est nul, son interpolation ne compte pas. La liste nulle est reprsente par (). Son interpolation dans une liste na pas deffet. Ainsi ((),(),()) est quivalent (). De mme, linterpolation dun tableau sans lment donne, ce stade, la mme chose que sil navait pas t interpol. Une consquence est que lon peut mettre une virgule optionnelle la fin de toute liste. Ceci facilitera ultrieurement les ajouts dlments.
@nombres = ( 1, 2, 3, );

Le mot qw, que nous avons mentionn plus tt, permet aussi dentrer une liste littrale. Il construit quelque chose dquivalent une chane entre apostrophes clate sur plusieurs lignes. Par exemple :
@machin = qw( pomme orange mandarine poire ); banane goyave nectarine persimmon carambole kumquat pche prune

Remarquez que ces parenthses ne sont pas ordinaires et fonctionnent comme des apostrophes. On aurait pu aussi mettre des signes infrieur-suprieur, des accolades ou des slashs (mais les parenthses cest joli). Une liste de valeurs peut aussi tre indice comme un tableau standard. Vous devez alors mettre la liste entre parenthses (des vraies) pour viter toute ambigut. Si cela sert souvent pour obtenir une valeur du tableau, cest aussi une tranche de la liste et la forme syntaxique scrit :
(LISTE)[LISTE]

Exemples :
# Stat renvoie une valeur liste.

customer_8566

64
$modification_time = (stat($fichier))[8];

Chapitre 2 Composants de Perl

# ERREUR DE SYNTAXE ICI. $modification_time = stat($fichier)[8]; # OUPS, PAS DE PARENTHESES # Trouver un chiffre hexa. $chiffrehexa = (a,b,c,d,e,f)[$chiffre-10]; # Un "oprateur virgule inverse". return (pop(@machin),pop(@machin))[0]; # Affectation de plusieurs valeurs laide dune tranche. ($jour, $mois, $annee) = (localtime)[3,4,5];

Affectation de liste
Une liste est affecte si chacun de ses lments est affect :
($a, $b, $c) = (1, 2, 3); ($map{rouge}, $map{vert}, $map{bleu}) = (0xff0000, 0x00ff00, 0x0000ff);

Il est possible daffecter undef dans une liste. Cest utile pour ignorer certaines valeurs de retour dune fonction :
($dev, $ino, undef, undef, $uid, $gid) = stat($fichier);

Llment final dune liste peut tre un tableau ou un hachage :


($a, $b, @reste) = split; my ($a, $b, %reste) = @arg_list;

Vous pouvez mettre un tableau ou un hachage dans la liste affecte en sachant que le premier de ce type rencontr absorbera les valeurs restantes et les variables restantes seront initialises undef. Ceci peut tre utile dans une initialisation de type my ou local, o on veut que les tableaux soient vides. Il est aussi possible daffecter une liste vide :
() = fonction_bidon();

De cette faon, la fonction est appele dans un contexte de liste, mais on laisse tomber les valeurs renvoyes. Si vous aviez fait lappel sans affectation, la fonction aurait t value dans un contexte vide, qui est un contexte scalaire, et se serait comporte compltement diffremment. Laffectation de liste dans un contexte scalaire retourne le nombre dlments que fournit la partie droite de laffectation :
$x = ( ($machin,$truc) = (7,7,7) );# $x contient 3, pas 2 $x = ( ($machin,$truc) = f() ); # $x contient le nombre dlments de f() $x = ( () = f() ); # idem

Cest pratique lorsquon veut faire laffectation dune liste dans un contexte boolen, car la plupart des fonctions liste retourne une liste nulle lorsquelle se termine, valeur qui affecte un scalaire produit la valeur 0 qui vaut faux dans ce contexte. Voici un exem-

customer_8566

Hachages
ple dutilisation dans une boucle while :
while (($login, $password) = getpwent) { if (crypt($login, $password) eq $password) { print "$login a un mot de passe non scuris!\n"; } }

65

Longueur dun tableau


Le nombre dlments du tableau @jours est donn par lvaluation de @jours dans un contexte scalaire :
@jours + 0; scalar(@jours) # force implicitement @jours dans un contexte scalaire # force explicitement @jours dans un contexte scalaire

Attention, cela ne fonctionne que pour les tableaux. Cela ne fonctionne pas pour les listes de valeurs en gnral. Une liste avec des virgules comme sparateur value dans un contexte scalaire retournera la dernire valeur, comme loprateur virgule en C. Mais puisquil nest presque jamais ncessaire de connatre la longueur dune liste en Perl ce nest pas un problme. $#jours est trs proche de lvaluation scalaire de @jours. Cette dernire renvoie lindice du dernier lment du tableau, ou un de moins que la longueur puisquil existe (habituellement) un lment dindice zro. Laffectation de $#jours change la longueur du tableau. Raccourcir un tableau de la sorte dtruit les valeurs intermdiaires. Vous pouvez tre plus efficace en surdimensionnant lavance un tableau destin sagrandir (pour agrandir un tableau, on peut lui affecter un lment au-del de sa fin). Un tableau peut tre tronqu par laffectation de la liste nulle (). Les deux instructions suivantes sont quivalentes :
@nimportequoi = (); $#nimportequoi = -1;

Et celle qui suit est toujours vraie :


scalar(@nimportequoi) == $#nimportequoi + 1;

La troncation dun tableau ne rcupre pas la mmoire ainsi libre. Il faut faire un undef(@nimportequoi) pour rcuprer sa mmoire dans le processus courant. Vous ne pouvez vraisemblablement pas la retouner au systme dexploitation car peu de systmes en sont capables.

Hachages
Comme nous lavons dj dit, un hachage nest quun type spcial de tableau dans lequel on retrouve les valeurs par une chane-clef au lieu dun indice numrique. En fait, on dfinit des associations entre les clefs et les valeurs, et cest pourquoi les hachages sont souvent appels tableaux associatifs par les personnes assez courageuses pour taper sur un clavier. Il nexiste pas vraiment de syntaxe particulire aux hachages en Perl, mais si une liste ordinaire est affecte un hachage, chaque paire de valeur de la liste sera prise comme

customer_8566

66
une association clef/valeur.

Chapitre 2 Composants de Perl

%map = (rouge,0xff000,vert,0x00ff00,bleu,0x0000ff);

Ce qui a le mme effet que :


%map = (); $map{rouge} = 0xff0000; $map{vert} = 0x00ff00; $map{bleu} = 0x0000ff; # dabord initialiser le hachage

Il est souvent plus lisible dutiliser loprateur => entre la clef et sa valeur. Loprateur => est synonyme de la virgule, mais il est plus clair visuellement et permet aussi une sparation d identifiant gauche (comme les identifiants entre accolades ci-dessus) ; linitialisation des variables hachages devient plus simple :
%map = ( rouge => 0xff0000, vert => 0x00fff0, bleu => 0x0000ff, );

ou pour initialiser des rfrences banalises de hachage utilises comme des enregistrements :
$rec = { NOM => John Smith GRADE => Captain MATRICULE => 951413, };

ou pour utiliser des appels complexes de fonctions par un nom :


$field = $query->radio_group( NOM => group_name, VALEURS => [eenie,meenie,minie], DEFAUT => meenie, SAUTDELIGNE => true, LABELS => %labels, );

Mais nallons pas trop vite. Revenons nos hachages. Une variable hachage (%hachage) peut tre utilise dans un contexte de liste, toutes ses paires clef/valeurs tant interpoles dans la liste. Mais ce nest pas parce que le hachage a t initialis dans un certain ordre que les valeurs sont retournes dans le mme. Les hachages sont implments au niveau interne en utilisant des tables de hachage pour une recherche rapide, ce qui signifie que lordre dans lequel les donnes sont stockes dpend du type de fonction de hachage utilise pour dterminer la place de la paire clef/valeur. Ainsi, les entres sont apparemment retournes dans un ordre quelconque (au niveau dune paire clef/valeur, les deux lments sont bien sr rendus dans le bon ordre). Pour des exemples de rordonnancement en sortie, voir la fonction keys au chapitre 29. Si un hachage est valu dans un contexte scalaire, une valeur vraie est renvoye si et seulement si le hachage contient des paires clefs/valeurs. (Sil existe plusieurs paires, la valeur renvoye est une chane contenant le nombre de cellules utilises (buckets) et le nombre

customer_8566

Typeglobs et handles de fichiers

67

de cellules alloues, spars par un slash. Ceci nest utile que pour savoir si lalgorithme rsident de Perl traite correctement ou non lensemble de donnes. Par exemple, on entre 10 000 lments dans un hachage, mais lvaluation de %HASH dans un contexte scalaire rvle 1/8 , cela signifie que seulement une des 8 cellules a t touche, et quelle contient probablement les 10 000 lments. Ce nest pas cens se produire. Pour trouver le nombre de clefs dans un hachage, utilisez la fonction keys dans un contexte scalaire : scalar(keys(%HASH)). Il est possible dmuler un tableau multidimensionnel en spcifiant plus dune clef dans les accolades spares par une virgule. Les clefs listes sont concatnes ensemble spares par le caractre $; ($SUBSCRIPT_SEPARATOR) qui a la valeur chr(28) par dfaut. La clef rsultante devient une clef du hachage. Ces deux lignes font la mme chose :
$habitants{ $pays, $dpartement } = $rsultat_recensement; $habitants{ join $; =>; $pays, $dpartement } = $rsultat_recensement;

Cette fonctionalit fut lorigine implmente pour le traducteur a2p (awk vers perl). Aujourdhui, vous utiliseriez plus justement un tableau multidimensionnel comme il est dcrit au chapitre 9, Structures de donnes. Un usage encore pratique de cet ancien style est la liaison des hachages aux fichiers DBM (voir DB_File au chapitre 32, Modules standards), qui nimplmentent pas les clefs multidimensionnelles. Ne confondez pas lmulation multidimensionnelle des hachages avec les tranches de tableaux. Lun est une valeur scalaire, lautre reprsente une liste :
$hachage{ $x, $y, $z } @hachage{ $x, $y, $z } # une valeur simple # une tranche de trois valeurs

Typeglobs et handles de fichiers


Perl utilise un type spcial appel typeglob qui contient la table des types Perl pour ce symbole. (La table des symboles *foo contient les valeurs de $foo, @foo, %foo, &foo et dautres interprtations de foo.) Le prfixe de typage dun typeglob est * car il reprsente tous les types. Les typeglobs (ou leur rfrences) sont toujours utiliss pour passer ou stocker des handles de fichier. Pour sauvegarder un handle de fichier il faut taper :
$fh = *STDOUT;

ou comme une vraie rfrence, de cette manire :


$fh = \*STDOUT;

Cest aussi le moyen de crer un handle de fichier local. Par exemple :


sub newopen { my $path = shift; local *FH; # et non my ou our! open (FH, $path) || return undef; return *FH; # et non \*FH! } $fh = newopen(/etc/passwd);

Voir la fonction open pour gnrer dautres handles de fichiers.

customer_8566

68

Chapitre 2 Composants de Perl

Cependant, la principale utilisation des typeglobs est actuellement de servir dalias entre deux entres symboliques. Cest comme un surnom. Si on crit
*machin = $truc;

tout ce qui sappelle machin , est synonyme de tout ce qui sappelle truc . Lalias peut porter sur un seul type des variables du nom en affectant une rfrence :
*machin = $truc;

$machin devient alias de $truc, mais@machin nest pas synonyme de @truc, ni %machin de %truc. Tout ceci ne concerne que les variables globales, cest--dire dfinies dans un paquetage ; les variables lexicales ne peuvent tre accdes travers la table des symboles. Le mcanisme dimport/export est entirement bas sur ce principe, lalias ne prsuppose en effet aucune appartenance un module spcifique. Cette instruction :
local *Ici::bleu = \$Ailleurs::vert;

fait de $Ici::bleu un alias pour $Ailleurs::vert, mais ne fait pas de @Ici::bleu un alias pour @Ailleurs::vert, ni %Ici::bleu un alias pour %Ailleurs;::vert. Heureusement, toutes ces manipulations compliques de typeglobs sont transparentes la plupart du temps. Voir le chapitre 8, et Tables de symboles au chapitre 10 et le chapitre 11, Modules, pour un dveloppement sur ces sujets.

Oprateurs dentre
Nous allons maintenant prsenter plusieurs oprateurs dentre qui sont analyss comme des termes. En fait, on les appelle parfois des pseudo-littraux car ils agissent, dans bien des cas, comme des chanes protges (les oprateurs de sortie comme print fonctionnent comme des oprateurs de liste et sont traits au chapitre 29.)

Oprateur dexcution de commande (Backtick)


Premirement il y a loprateur de ligne de commande, aussi appell oprateur backtick, et qui ressemble ceci :
$info = `finger $user`;

Une chane protge par des apostrophes inverses procde tout dabord une interpolation des variables comme dans une chane entre apostrophes doubles. Le rsultat est alors interprt comme une commande par le shell, et la sortie de la commande devient la valeur de lidentifiant (ceci fonctionne comme certains oprateurs similaires des shells UNIX). Dans un contexte scalaire, le rsultat est une chane simple contenant toutes les sorties de la commande. Dans un contexte de liste, une liste de valeurs est renvoye, une pour chaque ligne sortie par la commande. (On peut utiliser $/ pour avoir un autre caractre de terminaison de ligne.) La commande est interprte chaque fois que lidentifiant est valu. La valeur numrique du statut de la commande est stocke dans $? (voir le chapitre 28 pour linterprtation de $?, connu aussi sous le nom de $CHILD_ERROR). la diffrence de csh, aucune transformation nest faite sur les donnes renvoyes ; les sauts de ligne restent des sauts de ligne. linverse de tous les shells, les apostrophes simples nempchent pas linterprtation des noms de variables. Pour passer un $ au shell il faut le cacher par un anti-

customer_8566

Oprateurs dentre

69

slash. Le $user de notre exemple ci-dessus est interpol par Perl, mais non par le shell (la commande lanant un processus shell, consultez le chapitre 23, Scurit, pour les problmes de scurit). La forme gnralise pour les apostrophes inverses est qx// (pour quoted execution, excution protge), mais loprateur fonctionne exactement de la mme faon que les apostrophes inverses ordinaires. Il suffit de choisir ses caractres de protection. Comme avec les pseudo-fonctions de protection, si vous choisissez un simple guillemet comme dlimiteur, la chane de commande nest pas interpole :
$perl_info = qx(ps $$); $shell_info = qxps $$; # Variable $$ de Perl # Variable $$ du shell

Oprateur de lecture de ligne (Angle)


Loprateur de lecture de ligne est loprateur le plus utilis, aussi connu sous le nom doprateur infrieur-suprieur, ou fonction readline. Lvaluation dun handle de fichier entre infrieur-suprieur (par exemple <STDIN>) donne la ligne suivante du fichier associ. Le saut de ligne est inclus, donc en accord avec les critres de vracit de Perl, chaque ligne lue a une valeur vrai, et lorsque le programme atteint la fin du fichier, loprateur angle retourne undef, cest--dire faux. On affecte dhabitude la valeur lue une variable, mais il existe un cas o une affectation automatique se produit. Si, et seulement si, loprateur de lecture de ligne est la seule chose prsente dans le test de boucle dun while, la valeur est automatiquement affecte la variable spciale $_. La valeur affecte est alors teste pour savoir si elle est dfinie (cela peut vous paratre idiot, mais vous utiliserez cette construction dans presque tous vos scripts Perl). Bref, les lignes suivantes sont toutes quivalentes :
while (defined($_ = <STDIN>)) { print $_; } # mthode longue while ($_ = <STDIN>) { print; } # utilise $_ explicitement while (<STDIN>) { print; } # mthode courte for (;<STDIN>;) { print; } # boucle while dguise print $_ while defined($_ = <STDIN>); # instruction modifie longue print while $_ = <STDIN>; # utilise $_ print while <STDIN>; # instruction modifie courte

Souvenez-vous que cette astuce requiert une boucle while. Si vous utilisez loprateur ailleurs, vous devez affecter le rsultat explicitement pour garder la valeur.
while (<FH1> && <FH2>) {...} if (<STDIN>) { print; } if ($_ = <STDIN>) { print; } if (defined($_ = <STDIN>)) { print; } # # # # # mauvais : perd les deux entres mauvais, affiche lancienne valeur de $_ ne teste pas si $_ est dfini meilleur

Quand la variable $_ est implicitement affecte dans une boucle, cest la variable globale dont il sagit. Vous pouvez protger la valeur de $_ de la manire suivante :
while (local $_ = <STDIN>) { print; } # utilise local $_

Lancienne valeur est rtablie la sortie de la boucle. $_ peut toujours tre accde depuis la boucle. Pour viter toute confusion, il est prfrable dutiliser une variable lexicale :
while (my $ligne = <STDIN>) { print $ligne; } # variable prive

customer_8566

70

Chapitre 2 Composants de Perl

(Ces deux boucles while testent si laffectation est defined, car my et local ne changent pas son comportement habituel.) Les handles de fichiers STDIN, STDOUT et STDERR sont prdfinis et ouverts. Dautres handles peuvent tre crs avec les fonctions open ou sysopen. Voir la documentation de ces fonctions au chapitre 29 pour les dtails. Dans la boucle while ci-dessus, la ligne dentre est value dans un contexte scalaire, chaque valeur est retourne sparment. Si on lutilise dans un contexte de liste, une liste de toutes les lignes dentre restantes est retourne, chaque ligne tant un lment de liste. Un important espace de donnes peut ainsi tre cr, et il faut donc lutiliser avec prcaution :
$une_ligne = <MYFILE>; # Donne la premire ligne. @toutes_lignes = <MYFILE>; # Donne le reste des lignes.

Il nexiste pas de magie particulire pour le while associ la forme liste de loprateur dentre, car la condition dune boucle while est toujours un contexte scalaire (comme toutes les conditions). Lutilisation du handle de fichier nul lintrieur de loprateur infrieur-suprieur (ou oprateur angle) est particulire et peut tre utilise pour muler la ligne de commande de programmes standards dUNIX tels que sed et awk. Quand on lit les lignes depuis <>, toutes les lignes de tous les fichiers mentionns sur la ligne de commande sont renvoyes. Si aucun fichier ntait spcifi, cest lentre standard qui est renvoye la place et le programme peut ainsi tre facilement insr entre des processus pour former un pipe. Voici comment cela fonctionne : la premire fois que <> est valu, le tableau @ARGV est contrl, et sil est nul, $ARGV[0] est mis - , qui donne lentre standard quand on louvre. Le tableau @ARGV est trait comme une liste de noms de fichiers. La boucle
while (<>) { ... } # code pour chacune des lignes

est quivalente au pseudo-code Perl suivant :


while (@ARGV and $ARGV[0] =~ /^-/) { $_=shift; last if /^--$/; if (/^-D(.*)/) { $debug = $1 } if (/^-V/) { $verbose++ } ... # autres alternatives } while (<>) { ... # du code dans chaque ligne }

part une meilleure lisibilit, le rsultat reste identique. Le tableau @ARGV est dcal et le nom du fichier courant est stock dans la variable $ARGV. Le handle de fichier ARGV est aussi utilis en interne ; <> est simplement un synonyme de <ARGV>, qui est magique (le pseudo-code ci-dessus ne fonctionne pas parce quil traite <ARGV> comme non-magique). Il est possible de modifier @ARGV avant linstruction <> du moment que le tableau est construit avec les noms de fichier que vous attendez. Le nom de fichier - qui reprsente lentre standard, peut tre ouvert avec la fonction open, ainsi que des f lux plus

customer_8566

Oprateurs dentre

71

sotriques comme gzip -dc < file.gz| ). Les numros de ligne ($.) sincrmentent comme sil nexiste quun fichier en entre. (Mais observez lexemple ci-dessous sur eof pour voir comment on rinitialise les numros de ligne chaque fichier.) Pour affecter @ARGV une liste de fichiers, cest direct :
# par dfaut: le fichier README si aucun argument nest donn @ARGV = ("README") unless @ARGV;

Pour passer des options dans un script, on peut utiliser un des modules Getopt ou mettre une boucle initiale telle que :
while ($_ = $ARGV[0], /^-/) { shift; last if /^--$/; if (/^-D(.*)/) { $debug = $1 } if (/^-v/) { $verbose++ } ... # autres options } while (<>) { ... # code pour chacune des lignes }

Le symbole <> ne renvoie faux quune seule fois. En cas dappel ultrieur, une autre liste @ARGV est suppose tre traite, et si @ARGV nest pas initialis les lectures se font depuis STDIN. Si la chane entre loprateur angle est une variable (par exemple, <$machin>), alors celle-ci contient le nom du fichier lire ou une rfrence celui-ci. Par exemple :
$fh = \*STDIN; $ligne = <$fh>;

ou :
open($fh, "<donnees.txt>"); $line = "<$fh>";

Oprateur de globalisation des noms de fichier


Vous vous souciez peut-tre de ce qui peut arriver un oprateur de lecture de ligne si vous mettez quelque chose de bizarre entre linfrieur et le suprieur. Il est alors transform en un oprateur diffrent. Si la chane lintrieur de loprateur angle est diffrente du nom dun handle de fichier ou dune variable scalaire (mme sil agit despace), elle sera interprte comme tant un motif de fichier globaliser .19 Le motif de recherche sapplique aux fichiers du rpertoire courant (ou dans le rpertoire spcifi dans le motif glob lui-mme), et les fichiers correspondants sont retourns par loprateur. Comme pour les lectures de ligne, les noms sont renvoys un un dans un contex19. Cela na rien voir avec les typeglobs dj cits, si ce nest quils utilisent tous deux le caractre * la faon dun joker. Le caractre * prend le surnom glob lorsquil est utilis de cette manire. Avec les typeglobs, on globalise les symboles homonymes dune table de symboles. Avec un glob de nom de fichier (global), on effectue une correspondance par des jokers des fichiers dun rpertoire, comme le font de nombreux shells.

customer_8566

72

Chapitre 2 Composants de Perl

te scalaire, ou tous la fois dans un contexte de liste. Ce dernier usage est en fait prdominant. Il est courant de voir :
my @fichiers = <*.xml>;

Comme pour dautre types de pseudo-constantes, un premier niveau dinterpolation est effectu, mais on ne peut pas crire <$machin> car il sagit dun handle de fichier indirect, comme nous lavons dj vu. Dans danciennes versions de Perl, les programmeurs insraient des accolades pour forcer une interprtation de nom de fichier glob : <${machin}>. De nos jours, on considre quil est plus propre dappeler la fonction interne directement par glob($machin), ce qui aurait d tre le cas ds lorigine. On crirait donc :
@fichiers = glob("*.xml");

si vous prfrez. Que lon utilise la fonction glob ou sa forme ancienne avec loprateur dangle, loprateur de globalisation fonctionne de la mme faon dans une boucle que loprateur while en affectant le rsultat $_. (Ce fut la premire raison de surcharger cet oprateur.) Par exemple, si vous vouliez changer les autorisations de fichiers de code C, vous cririez :
while (glob "*.c") { chmod 0644, $_; }

ce qui est quivalent :


while (<*.c>) { chmod 0644, $_; }

La fonction glob tait implmente comme une commande shell dans les anciennes versions de Perl (aussi dans les anciennes versions dUnix), tait plus coteuse en ressources et ne fonctionnait pas de la mme faon sur tous les systmes. Cest aujourdhui une fonction prdfinie plus fiable et plus rapide. Voyez la description du module File::Glob au chapitre 32 pour modifier son comportement par dfaut pour, par exemple, traiter les espaces dans ces arguments, lexpansion de certains caractres (tilde ou accolade), linsensiblit la casse ou bien le classement des valeurs retournes, entre autres choses. Bien sr, la faon la plus courte et la moins lisible pour faire la commande chmod ci-dessus, est dutiliser la globalisation comme un oprateur sur liste :
chmod 0644, <*.c>;

Un glob nvalue son argument que quand il dmarre une nouvelle liste. Toutes les valeurs doivent tre lues avant son excution. Dans un contexte de liste, ce nest pas trs important, puisquon les a toutes automatiquement. Mais dans un contexte scalaire, loprateur renvoie la prochaine valeur chaque appel, ou une valeur fausse si on arrive au bout. Attention, faux nest retourn quune seule fois. Ainsi, si lon attend une valeur unique pour un glob, il vaut mieux crire :
($fichier) = <blurch*>; # contexte de liste # contexte scalaire

au lieu de :
$fichier = <blurch*>;

customer_8566

Oprateurs dentre

73

car la premire forme avale tous les noms de fichier correspondants et rinitialise loprateur, alors que ce que renvoie la seconde alterne entre un nom de fichier et faux. Pour interpoler des variables, il faut absolument utiliser loprateur glob, car lancienne syntaxe peut tre confondue avec la notation indirecte des handles de fichiers. Mais ce niveau, il devient vident que la frontire entre les termes et les oprateurs est un peu f loue.
@files = <$dir/*.[ch]>; @files = glob("$dir/*.[ch]"); @files = glob $un_motif; # viter # appelle glob en tant que fonction # appelle glob en tant quoprateur

Nous ne mettons pas les parenthses dans le second exemple pour montrer que glob peut tre utilis comme un oprateur unaire, cest--dire un oprateur prfixe avec un seul argument. Loprateur glob est un exemple doprateur unaire dfini, qui nest quun des types doprateurs dont nous parlerons dans le prochain chapitre. Ensuite nous parlerons des oprations de recherche de motif, qui ressemblent elles aussi des termes, mais fonctionnent comme des oprateurs.

customer_8566

customer_8566

Oprateurs unaires et binaires


Dans le chapitre prcdent, nous avons parl des diffrents types de termes que vous pouvez utiliser dans une expression. Mais pour tre honnte, les termes isols sont un peu ennuyeux. Beaucoup de termes sont de joyeux ftards ; ils aiment comuniquer les uns avec les autres. Un terme typique ressent une forte envie de sidentifier avec dautres termes, ou de les inf luencer de diffrentes manires. Cependant, il existe de nombreuses sortes dinteractions sociales et de nombreux niveaux dimplication. En Perl, ces relations sont exprimes laide doprateurs. Il faut bien que la sociologie serve quelque chose. Dun point de vue mathmatique, les oprateurs sont des fonctions ordinaires avec une syntaxe spciale. Dun point de vue linguistique, les oprateurs sont juste des verbes du troisime groupe. Mais comme tout linguiste vous le dira, les verbes du troisime groupe sont gnralement ceux que lon utilise le plus souvent. Cest important du point de vue de la thorie de linformation, car les verbes du troisime groupe sont gnralement plus courts et plus efficaces tant pour la production que pour la reconnaissance. Dun point de vue pratique, les oprateurs sont maniables. On distingue plusieurs varits doprateurs, en fonction de leur arit (le nombre doprandes quils prennent), leur prcdence (leur capacit prendre leurs oprandes aux oprateurs voisins), et leur associativit (agissent-ils de gauche droite ou de droite gauche quand ils sont associs des oprateurs de mme prcdence). Les oprateurs Perl se prsentent sous trois arits : unaire, binaire ou ternaire. Les oprateurs unaires sont toujours des oprateurs prfixes (excepts les oprateurs de post-incrmentation et de post-dcrmentation).1 Tous les autres sont des oprateurs infixes moins que vous ne comptiez les oprateurs de liste, qui peuvent prcder autant darguments que vous voulez. Cependant la plupart des gens prfrent voir les oprateurs de liste comme des fonctions normales autour desquelles on peut oublier de mettre des parenthses. Voici quelques exemples :
1. Bien que lon puisse galement voir les diffrents types de guillemets et de parenthses (crochets, accolades) comme des oprateurs circonfixes qui englobent et dlimitent des termes.

customer_8566

76
! $x $x * $y $x ? $y : $z print $x, $y, $z # # # # un un un un oprateur oprateur oprateur oprateur

Chapitre 3 Oprateurs unaires et binaires


unaire binaire ternaire de liste

La prcdence dun oprateur dtermine sa force dattraction. Les oprateurs de plus haute prcdence capturent les arguments qui les entourent avant les oprateurs de moindre prcdence. Lexemple typique sort tout droit des mathmatiques lmentaires, o la multiplication est prioritaire sur laddition :
2 + 3 * 4 # vaut 14, et non 20

Lordre dans lequel sont excuts deux oprateurs de mme prcdence dpend de leur associativit. Les rgles suivent en partie les conventions des mathmatiques :
2 * 3 * 4 2 ** 3 ** 4 2 != 3 != 4 # signifie (2 * 3) * 4, associatif gauche # signifie 2 ** (3 ** 4), associatif droite # illgal, car non associatif

Le tableau 3-1 liste lassociativit et larit des oprateurs Perl par ordre de prcdence dcroissante. Tableau 3-1. Prcdence des oprateurs
Associativit Non associatifs Gauche Non associatifs Droite Droite Gauche Gauche Gauche Gauche Droite Non associatifs Non associatifs Gauche Gauche Gauche Gauche Non associatifs Droite Droite Gauche Droite Droite Arit 0 2 1 2 1 2 2 2 2 0,1 2 2 2 2 2 2 2 3 2 2 0+ 1 Classe de prcdence Termes et oprateurs de liste (vers la gauche) -> ++ -** ! ~ \+ unaire et - unaire =~ !~ * / % x + - . << >> Oprateurs unaires nomms < > <= >= lt gt le ge == != <=> eq ne cmp & | ^ && || ..... ?: = += -= *= et suivants , => Oprateurs de liste (vers la droite) not

customer_8566

Termes et oprateurs de listes (vers la gauche)


Tableau 3-1. Prcdence des oprateurs (suite)
Associativit Gauche Gauche Arit 2 2 Classe de prcdence and or xor

77

Vous pourriez penser quil y a bien trop de niveaux de prcdence se souvenir. Et bien vous avez raison. Heureusement, deux choses jouent en votre faveur. Dabord les niveaux de prcdence tels quils sont dfinis sont en gnral assez intuitifs, en supposant que vous ntes pas psychotique. Ensuite, si vous tes seulement nvros, vous pouvez toujours ajouter des parenthses supplmentaires pour calmer votre angoisse. Notez galement que tous les oprateurs emprunts C conservent les mmes relations de prcdence entre eux, mme quand les rgles de prcdence de C sont lgrement biscornues. (Cela rend Perl dautant plus facile apprendre pour les personnes qui connaissent C ou C++. Peut-tre mme pour celles qui connaissent Java.) Les sections qui suivent couvrent ces oprateurs dans leur ordre de prcdence. de trs rares exceptions, ils oprent tous uniquement sur des valeurs scalaires et non sur des listes. Nous indiquerons les exceptions quand elles se prsenteront. Bien que les rfrences soient des valeurs scalaires, utiliser la plupart de ces oprateurs sur des rfrences na pas beaucoup de sens, car la valeur numrique dune rfrence na de signification que dans les profondeurs de Perl. Nanmoins, si une rfrence pointe sur un objet dune classe qui autorise la surcharge doprateurs, vous pouvez utiliser ces oprateurs sur cet objet ; si la classe a dfini une surcharge pour tel ou tel oprateur, cela dcrit comment lobjet sera trait par cet oprateur. Cest ainsi par exemple que les nombres complexes sont implments en Perl. Pour plus dinformations sur la surcharge doprateurs, voir le chapitre 13, Surcharge.

Termes et oprateurs de listes (vers la gauche)


En Perl, tout terme est de prcdence maximale. Les termes comprennent les variables, les apostrophes et les oprateurs de type quote, la plupart des expressions entre parenthses, crochets ou accolades, et toute fonction dont les arguments sont entre parenthses. En fait, si on regarde les choses ainsi, il ny a pas vraiment de fonctions, mais seulement des oprateurs de liste et des oprateurs unaires qui se comportent comme des fonctions parce que vous avez mis des parenthses autour de leurs arguments. Tout cela nempche pas le chapitre 29 de sappeler Fonctions. Maintenant lisez attentivement. Voici quelques rgles trs importantes qui simplifient grandement les choses, mais qui peuvent loccasion produire des rsultats contraires lintuition pour les imprudents. Si un oprateur de liste (comme print) ou un oprateur unaire nomm (comme chdir) est suivi dune parenthse ouvrante comme token suivant (sans tenir compte des blancs), loprateur et ses arguments entre parenthses ont la prcdence la plus haute, comme sil sagissait dun appel de fonction normal. La rgle est la suivante : si cela ressemble un appel de fonction, alors cest un appel de fonction. Vous pouvez le faire ressembler une non-fonction en prfixant les parenthses avec un plus unaire, qui ne fait absolument rien smantiquement parlant ; il ne convertit mme pas les arguments en numrique.

customer_8566

78

Chapitre 3 Oprateurs unaires et binaires

Par exemple, puisque || a une prcdence plus faible que chdir, nous aurons :
chdir $toto chdir($toto) chdir ($toto) chdir +($toto) || || || || die; die; die; die; # # # # # # # # (chdir (chdir (chdir (chdir $toto) $toto) $toto) $toto) || || || || die die die die

mais comme * a une prcdence plus grande que chdir, nous aurons :
chdir $toto * 20; chdir($toto) * 20; chdir ($toto) * 20; chdir +($toto) * 20; chdir ($toto * 20) (chdir $toto) * 20 (chdir $toto) * 20 chdir ($toto * 20)

De mme pour nimporte quel oprateur numrique qui est galement un oprateur unaire nomm, comme rand :
rand 10 * 20; rand(10) * 20; rand (10) * 20; rand +(10) * 20; # # # # rand (10 * 20) (rand 10) * 20 (rand 10) * 20 rand (10 * 20)

En labsence de parenthses, la prcdence doprateurs de liste comme print, sort, ou chmod est soit trs haute soit trs basse selon que vous regardez gauche ou droite de loprateur (cest le sens du vers la gauche dans le titre de cette section). Par exemple, dans :
@tab = (1, 3, sort 4, 2); print @tab; # imprime 1324

Les virgules droite de sort sont values avant le sort, mais les virgules sa gauche sont values aprs. En dautres termes, un oprateur de liste tend avaler tous les arguments qui le suivent, puis se comporter comme un simple terme pour lexpression qui le prcde. Il vous faut encore tre prudent avec les parenthses :
# Ces arguments sont valus avant de faire le print : print($toto, exit); # videmment pas ce que vous voulez. print $toto, exit; # Ici non plus. # Ces lignes font le (print $toto), exit; print($toto), exit; print ($toto), exit; print avant dvaluer lexit : # Cest ce que vous voulez. # Ici aussi. # Et mme ceci.

Le cas le plus simple pour se faire piger, cest quand vous utilisez des parenthses pour grouper des arguments mathmatiques, en oubliant que les parenthses servent aussi regrouper les arguments de fonctions :
print ($toto & 255) + 1, "\n"; # affiche ($toto & 255)

Cela ne fait probablement pas ce quoi vous vous attendiez au premier coup dil. Heureusement, les erreurs de cette nature provoquent des avertissements comme Useless use of addition in a void context quand les avertissements sont activs (avec loption de ligne de commande -w). Les constructions do {} et eval {} sont aussi analyses comme des termes, de mme que les appels de sous-programmes et de mthodes, les crateurs de tableaux et de hachages anonymes, [] et {}, et le crateur de sous-programme anonymes sub {}.

customer_8566

Loprateur flche

79

Loprateur f lche
Tout comme en C et en C++, loprateur binaire ->est un oprateur infixe de drfrencement. Si droite on trouve un indice de tableau entre [...], un indice de hachage entre {...} ou une liste darguments de sous-programme entre (...), alors la partie gauche de la f lche doit tre respectivement une rfrence (symbolique ou en dur) de tableau, de hachage ou de sous-programme. Dans un contexte de lvalue (o lon peut affecter une valeur), si la partie gauche nest pas une rfrence, elle doit tre capable de contenir une rfrence, auquel cas cette rfrence sera autovivifie pour vous. Pour en savoir plus ce sujet (et pour quelques avertissements sur lautovivification accidentelle), voir le chapitre 8, Rfrences.
$aref->[42] $href->{"corned beef"} $sref->(1,2,3) # un drfrencement de tableau # un drfrencement de hachage # un drfrencement de sous-programme

Sinon, cest une sorte dappel de mthode. La partie droite doit tre un nom de mthode (ou une simple variable scalaire contenant le nom de la mthode) et la partie gauche doit svaluer soit comme un objet (une rfrence consacre), soit comme un nom de classe (cest--dire un nom de paquetage) :
$yogi = Ours->new("Yogi"); $yogi->pique($piquenique); # un appel de mthode de classe # un appel de mthode sur une instance

Le nom de mthode peut tre qualifie avec un nom de paquetage pour indiquer dans quelle classe commencer chercher la mthode, ou avec le nom de paquetage spcial SUPER::, pour indiquer que la recherche doit commencer dans la classe parente. Voir le chapitre 12, Objets.

Auto-incrmentation et autodcrmentation
Les oprateurs ++ et -- fonctionnent comme en C. Cest--dire que, placs avant une variable, ils lincrmentent ou la dcrmentent avant den renvoyer la valeur. Quand ils sont placs aprs, ils lincrmentent ou la dcrmentent aprs en avoir renvoy la valeur. Par exemple, $A++2 incrmente la valeur de la variable $A et en retourne la valeur avant de raliser lincrmentation. De mme, --$b{(/(\w+)/)[0]} dcrmente llment du hachage %b index par le premier mot de la variable de recherche par dfaut ($_) et renvoie la valeur aprs la dcrmentation.3
2. N.d.T. : Pour dintressantes variations sur $A++, vous pouvez consulter http://paris.mongueurs.net/aplusplus.html. 3. Bon daccord, ce ntait pas trs sympa. Nous voulions juste tre srs que vous suiviez. Voici comment cette expression fonctionne. Dabord, la recherche de motif trouve le premier mot de $_ en utilisant lexpression rgulire \w+. Les parenthses qui lentourent permettent de retourner le mot comme valeur dans une liste un seul lment car la dtection se fait dans un contexte de liste. Le contexte de liste est fourni par loprateur de tranche de liste, (...)[0], qui retourne le premier (et unique) lment de la liste. Cette valeur est utilise comme cl pour le hachage et lentre du hachage (sa valeur) est dcrmente et retourne. En gnral, quand vous tes confront une expression complexe, analysez-la de lintrieur vers lextrieur pour voir dans quel ordre les vnements se produisent.

customer_8566

80

Chapitre 3 Oprateurs unaires et binaires

Loprateur dauto-incrmentation comporte en plus un peu de magie. Si vous incrmentez une variable qui est numrique, ou qui a t utilise un moment donn dans un contexte numrique, vous avez une incrmentation normale. Si au contraire la variable na t utilise que dans des contextes de chane depuis quelle a t affecte, que sa valeur est non nulle et correspond au motif /^[a-zA-Z]*[0-9]*$/, lincrmentation est faite sur la chane, en prservant chaque caractre dans son domaine, avec une retenue :
print print print print ++($toto ++($toto ++($toto ++($toto = = = = 99); a9); Az); zz); # # # # prints prints prints prints 100 b0 Ba aaa

lheure o nous crivons ces lignes, lauto-incrmentation magique na pas t tendue aux lettres et chiffres Unicode, mais pourrait ltre dans le futur. Loprateur dautodcrmentation nest, lui, pas magique, et il nest pas prvu que cela change.

Exponentiation
Loprateur ** binaire est loprateur dexponentiation. Notez quil lie encore plus fortement que le moins unaire ; cest pourquoi -2**4 vaut -(2**4), et non (-2)**4. Loprateur est implment grce la fonction pow(3) de C, qui fonctionne en interne avec des nombres en virgule f lottante. Les calculs sont faits grce des logarithmes, ce qui signifie quil fonctionne avec des puissances fractionnaires, mais que vous obtiendrez parfois des rsultats moins prcis quavec une simple multiplication.

Oprateurs unaires idographiques


La plupart des oprateurs portent simplement des noms (voir Oprateurs unaires nomms et de test de fichier plus loin dans ce chapitre), mais certains oprateurs sont jugs suffisament importants pour mriter leur propre reprsentation symbolique spciale. Ces oprateurs semblent tous avoir un rapport avec la ngation. Plaignez-vous auprs des mathmaticiens. Le ! unaire ralise une ngation logique, cest--dire un non . Voyez not pour une version de moindre prcdence du non logique. La valeur dun oprande ni est vraie (1) si loprande est faux (0 numrique, chane "0", chane vide ou valeur indfinie) et fausse ("") si loprande est vrai. Le - unaire effectue une ngation arithmtique si son oprande est numrique. Si loprande est un identificateur, une chane compose dun signe moins concatn lidentificateur est renvoye. Sinon, si la chane commence avec un plus ou un moins, une chane commenant avec le signe oppos est renvoye. Un des effets de ces rgles est que -motsimple est quivalent "-motsimple". Cest particulirement utile aux programmeurs Tk. Le ~ unaire ralise une ngation sur les bits, cest--dire un complment 1. Par dfinition, ce nest pas vraiment portable quand cest limit par la taille du mot-machine de votre ordinateur. Par exemple, sur une machine 32 bits ~123 vaut 4294967172, tandis

customer_8566

Oprateurs de liaison

81

que sur une machine 64 bits, cela vaut 18446744073709551492. Mais vous le saviez dj. Ce que vous ne saviez peut-tre pas, cest que si largument de ~ est une chane au lieu dun nombre, une chane de mme longueur est renvoye avec tous ses bits complments. Cest une manire rapide de basculer un grand nombre de bits dun coup, et de faon portable puisque cela ne dpend pas de la taille de votre mot-machine. Plus tard nous verrons aussi les oprateurs logiques sur les bits, qui ont eux des variantes pour les chanes. Le + na aucun effet smantique, mme sur les chanes. Son utilit est surtout syntaxique, pour sparer le nom dune fonction dune expression entre parenthses qui serait sinon interprte comme la liste complte des arguments de la fonction. (Voir les exemples dans la section Termes et oprateurs de listes (vers la gauche).) Si vous y rf lchissez dune manire un peu dtourne, le + inverse leffet quont les parenthses de changer les oprateurs prfixes en fonctions. Le \ cre une rfrence sur ce qui le suit. Utilis sur une liste, il cre une liste de rfrences. Voir la section Loprateur antislash au chapitre 8 pour plus de dtails. Attention ne pas confondre ce comportement avec celui de lantislash dans une chane, bien que les deux formes comportent la notion vaguement ngative de protection de leurs arguments contre linterprtation. Cette ressemblance nest pas purement fortuite.

Oprateurs de liaison
Le =~ binaire lie une expression scalaire un oprateur de recherche de motif, de substitution ou de translittration (ngligemment appele traduction). Ces oprations chercheraient ou modifieraient sinon la chane contenue dans $_(la variable par dfaut). La chane lier est place gauche, tandis que loprateur lui-mme est plac droite. La valeur de retour indique le succs ou lchec de lopration effectue droite, puisque loprateur de lien ne fait rien par lui-mme. Si largument de droite est une expression plutt quune recherche de motif, une substitution ou une translittration, il sera interprt comme une recherche de motif lexcution. Cest--dire que $_ =~ $pat est quivalent $_ =~ /$pat/. Cest moins efficace quune recherche explicite, puisque le motif doit tre vrifi et potentiellement recompil chaque fois que lexpression est value. Vous pouvez viter cette recompilation en prcompilant le motif original avec loprateur qr// de citation dexpression rgulire ( quote regex en anglais). Le !~ binaire est identique =~sauf que la valeur de retour est inverse logiquement. Les expressions suivantes sont fonctionnellement quivalentes :
$chaine !~ /pattern/ not $chaine =~ /pattern/

Nous avons dit que la valeur de retour indique le succs, mais il existe plusieurs sortes de succs. La substitution renvoie le nombre de substitutions russies, comme la translittration. (En fait, la translittration sert souvent compter les caractres.) Puisque nimporte quel rsultat non nul est vrai, tout fonctionne. La forme de valeur vraie la plus spectaculaire est une valeur de liste : en contexte de liste, les recherches de motif peuvent renvoyer les sous-chanes captures par les parenthses dans le motif. Conformment aux rgles de laffectation de liste, cette affectation retournera vrai si quelque

customer_8566

82

Chapitre 3 Oprateurs unaires et binaires

chose a t dtect et affect, et faux dans le cas contraire. Cest pourquoi vous voyez parfois des choses comme :
if ( ($c,$v) = $chaine =~ m/(\w+)=(\w*)/ ) { print "CLE $c VALEUR $v\n"; }

Dcomposons tout cela. Le =~ a la prcdence sur =, il se produit donc en premier. Le =~lie $chaine la recherche de motif droite. Celle-ci recherche ce qui ressemble CLE=VALEUR dans votre chane. Il se trouve en contexte de liste, car du ct droit dune affectation de liste. Si le motif est trouv, il renvoie une liste affecter $c et $v. Laffectation de liste elle-mme se trouve dans un contexte scalaire et renvoie donc 2, le nombre de valeurs droite de laffectation. Et il se trouve que 2 est vrai, puisque notre contexte scalaire est aussi un contexte boolen. Quand la recherche choue, aucune valeur nest affecte, ce qui renvoie 0, qui est faux. Voir le chapitre 5, Recherche de motif, pour en savoir plus sur le fonctionnement des motifs.

Oprateurs multiplicatifs
Perl fournit des oprateurs proches de ceux de C : * (multiplication), / (division) et % (modulo). * et / fonctionnent exactement comme vous vous y attendez, en multipliant ou divisant leurs deux oprandes. La division se fait en virgule f lottante, moins que vous nayez spcifi le pragma integer. Loprateur % convertit ses oprandes en entiers avant de calculer le reste de la division entire. (Nanmoins cette division est faite en virgule f lottante donc vos oprandes peuvent faire 15 chiffres sur la plupart des machines 32 bits.) Supposons que nos deux oprandes sappellent $a et $b. Si $b est positif, alors le rsultat de $a % $b est $a moins le plus grand multiple de $b infrieur $a (ce qui veut dire que le rsultat sera toujours dans lintervalle 0 .. $b-1). Si $b est ngatif, alors le rsultat de $a % $b est $a moins le plus petit multiple de $b suprieur $a (ce qui veut dire que le rsultat sera toujours dans lintervalle $b+1 .. 0). Quand on est porte de use integer, % vous donne directement accs loprateur modulo tel quil est implment par votre compilateur C. Cet oprateur nest pas bien dfini pour les oprandes ngatifs, mais sexcutera plus rapidement. Le x est loprateur de rptition. En ralit, il sagit de deux oprateurs. En contexte scalaire, il retourne une chane concatne compose de loprande de gauche rpt le nombre de fois spcifi par loprande de droite. (Pour assurer la compatibilit avec les versions prcdentes, il le fait galement en contexte de liste si largument de gauche nest pas entre parenthses.)
print - x 80; print "\t" x ($tab/8), x ($tab%8); # imprime une range de tirets # tabule la colonne $tab

En contexte de liste, si loprande de gauche est une liste entre parenthses, x fonctionne comme un rplicateur de liste plutt que comme un rplicateur de chane. Cela peut servir initialiser la mme valeur tous les lments dun tableau de longueur indtermine.
@ones = (1) x 80; @ones = (5) x @ones; # une liste de 80 1 # met tous les lments 5

customer_8566

Oprateurs additifs

83

De la mme manire, vous vous pouvez galement utiliser x pour initialiser des tranches de tableaux et de hachages.
@cles = qw(du Perl aux cochons); @hash{@cles} = ("") x @cles;

Si cela vous laisse perplexe, remarquez que @cles est utilis la fois comme une liste gauche de laffectation et comme une valeur scalaire (qui renvoie la longueur du tableau) droite. Lexemple prcdent a le mme effet sur %hash que :
$hash{du} $hash{Perl} $hash{aux} $hash{cochons} = = = = ""; ""; ""; "";

Oprateurs additifs
tonnament, Perl dispose des oprateurs usuels + (addition) et - (soustraction). Ces deux oprateurs convertissent leurs arguments de chane en valeurs numriques si ncessaire, et renvoient un rsultat numrique. Perl fournit galement loprateur . qui ralise la concatnation de chanes. Par exemple :
$presque = "Fred" . "Pierrafeu"; # renvoie FredPierrafeu

Remarquez que Perl najoute pas despace entre les chanes concatnes. Si vous voulez lespace ou si vous avez plus de deux chanes concatner, vous pouvez utiliser loprateur join, dcrit au chapitre 29, Fonctions. Cependant, la plupart du temps on concatne implicitement dans une chane entre doubles apostrophes :
$nomcomplet = "$prenom $nom";

Oprateurs de dcalage
Les oprateurs de dcalage de bits (<< et >>) renvoient la valeur de largument de gauche dcal gauche (<<) ou droite (>>) du nombre de bits spcifi par largument de droite. Les arguments doivent tre des entiers. Par exemple :
1 << 4; 32 >> 4; # renvoie 16 # renvoie 2

Faites attention cependant, car les rsultats sur de grands nombres (ou sur des nombres ngatifs) peuvent dpendre du nombre de bits utiliss par votre machine pour reprsenter les entiers.

Oprateurs unaires nomms et de test de fichier


Certaines des fonctions dcrites au chapitre 29 sont en fait des oprateurs unaires. Le tableau 3-2 liste tous les oprateurs unaires nomms. Les oprateurs unaires nomms ont une prcdence suprieure celle de certains oprateurs binaires. Par exemple :
sleep 4 | 3;

customer_8566

84
Tableau 3-2. Oprateurs unaires nomms
-X (tests de fichiers) alarm caller chdir chroot cos defined delete do eval exists exit gethostbyname getnetbyname getpgrp getprotobyname glob gmtime goto hex int lc lcfirst length

Chapitre 3 Oprateurs unaires et binaires

localtime lock log lstat my oct ord quotemeta rand readlink ref require

return rmdir scalar sin sleep sqrt srand stat uc ucfirst umask undef

ne dort pas pendant 7 secondes ; il dort pendant 4 secondes puis prend la valeur de retour de sleep (typiquement zro) et la combine par OU avec 3, comme si lexpression avait des parenthses comme suit :
(sleep 4) | 3;

comparer avec :
print 4 | 3;

qui prend effectivement la valeur de 4 combin par OU avec 3 avant de lafficher (7 dans ce cas), comme sil tait crit :
print (4 | 3);

En effet, print est un oprateur de liste, et non un simple oprateur unaire. Une fois que vous saurez quels oprateurs sont des oprateurs de liste, vous naurez plus de problme pour distinguer les oprateurs de liste des oprateurs unaires. En cas de doute, vous pouvez toujours utiliser des parenthses pour transformer un oprateur unaire en fonction. Souvenez-vous, si a ressemble une fonction, cest une fonction. Une autre caractristique curieuse des oprateurs unaires nomms est que beaucoup dentre eux prennent $_ comme argument par dfaut, si vous ne leur en fournissez pas dautre. Cependant, si vous omettez largument et que ce qui suit ressemble au dbut dun argument, Perl va se tromper, car il attend un terme. Quand le caractre suivant du programme est lun de ceux lists au tableau 3-3, le tokeniseur de Perl renvoie diffrents types de token selon quil attend un terme ou un oprateur. Une erreur typique est donc :
next if length < 80;

o pour lanalyseur le < ressemble au dbut du symbole <> (un terme) au lieu du infrieur (un oprateur) auquel vous pensiez. Il nexiste pas vraiment de moyen darranger les choses tout en gardant Perl pathologiquement clectique. Si vous tes paresseux au point de ne pouvoir vous rsoudre taper les deux caractres $_, lune de ces instructions devrait faire laffaire :

customer_8566

Oprateurs unaires nomms et de test de fichier


Tableau 3-3. Caractres ambigus
Caractre + * / < . ? % & next next next next Oprateur Addition Soustraction Multiplication Division Infrieur , dcalage gauche Concatnation ?: Modulo &, && if length() < 80; if (length) < 80; if 80 > length; unless length >= 80; Terme Plus unaire Moins unaire *typeglob /motif/ <HANDLE>, <<END .3333 ?motif? %assoc &sousprogramme

85

Quand un terme est attendu, un signe moins suivi dune lettre seule sera toujours interprt comme un test de fichier. Un oprateur de test de fichier est un oprateur unaire qui prend commme argument un nom ou un handle de fichier, et teste le fichier associ pour savoir si une certaine proprit est vraie son sujet. Si largument est omis, il teste $_, sauf pour -t, qui teste STDIN. Sauf si cest indiqu autrement dans la documentation, il retourne 1 pour vrai et "" pour faux, ou la valeur indfinie si le fichier nexiste pas ou nest pas accessible. Les oprateurs de test de fichier actuellement implments sont lists au tableau 3-4. Tableau 3-4. Oprateurs de test de fichier
Oprateur -r -w -x -o -R -W -X -O -e -z -s -f -d -l Signification Fichier lisible par lUID/GID effectif. Fichier en criture pour lUID/GID effectif. Fichier excutable par lUID/GID effectif. Fichier possd par lUID/GID effectif. Fichier lisible par lUID/GID rel. Fichier en criture pour lUID/GID rel. Fichier excutable par lUID/GID rel. Fichier possd par lUID/GID rel. Le fichier existe. Fichier de taille nulle. Fichier de taille non nulle (renvoie la taille) Fichier simple. Le fichier est un rpertoire. Le fichier est un lien symbolique.

customer_8566

86

Chapitre 3 Oprateurs unaires et binaires

Tableau 3-4. Oprateurs de test de fichier (suite)


Oprateur -p -S -b -c -t -u -g -k -T -B -M -A -C Signification Le fichier est un tube nomm (FIFO). Le fichier est une socket. Fichier spcial de type bloc Fichier spcial de type caractre. Handle de fichier ouvert sur un tty. Fichier avec bit setuid. Fichier avec bit setgid. Fichier avec sticky bit. Fichier texte. Fichier binaire (le contraire de -T). ge du fichier (au dmarrage) en jours depuis sa modification. ge du fichier (au dmarrage) en jours depuis le dernier accs. ge du fichier (au dmarrage) en jours depuis le changement dinode.

Remarquez que -s/a/b/ ne fait pas une substitution ngative. -exp($foo) fonctionne cependant comme prvu ; seules les lettres isoles qui suivent un signe moins sont interprtes comme des tests de fichier. Linterprtation des oprateurs de test de permissions -r, -R, -w, -W, -x et -X est fonde uniquement sur le mode du fichier et les ID dutilisateur et de groupe de lutilisateur. Il peut y avoir dautres raisons pour lesquelles vous ne pouvez effectivement pas lire, crire ou excuter le fichier, comme les listes de contrle daccs dAFS (Andrew File System).4 Notez galement que pour le super utilisateur -r, -R, -w et -W renvoient toujours 1, et que -x et -X renvoient 1 si lun des bits dexcution est 1 dans le mode. Cest pourquoi les scripts lancs par le super utilisateur peuvent ncessiter un stat afin de connatre le vritable mode du fichier, ou bien remplacer temporairement lUID par autre chose. Les autres oprateurs de test de fichier se moquent de savoir qui vous tes. Nimporte qui peut utiliser le test pour les fichiers simples :
while (<>) { chomp; next unless -f $_; ... }

# ignore les fichiers "spciaux"

Les options -T et -B fonctionnent comme suit. Le premier bloc (plus ou moins) du fichier est examin la recherche de caractres inhabituels comme des code de contrle ou des octets donc le bit de poids fort est 1 (et qui nont pas lair dtre de lUTF-8). Si on trouve plus dun tiers doctets inhabituels, cest un fichier binaire ; sinon cest un fi-

4. Vous pouvez cependant ignorer la smantique intgre avec le pragma use filetest. Voir le chapitre 31, Modules de pragmas.

customer_8566

Oprateurs relationnels

87

chier texte. De mme, tout fichier dont le premier bloc contient le caractre ASCII NUL (\0) est considr comme binaire. Si -T ou -B est utilis sur un handle de fichier, le tampon dentre standard (standard I/O ou stdio ) en cours est examin, au lieu du premier bloc du fichier. -T et -B renvoient vrai sur un fichier vide, ou sur un fichier EOF (end-of-file : fin de fichier) quand on teste un handle. Comme Perl doit lire le fichier pour faire le test -T, vous devrez viter de vous en servir sur des fichiers qui risquent de bloquer ou de vous causer des ennuis. Cest pourquoi la plupart du temps, vous devrez tester avec un -f dabord, comme dans :
next unless -f $fichier && -T $fichier;

Si lon donne lun des tests de fichier (ou lun des oprateurs stat ou lstat) le handle spcial constitu dun soulign unique, cest la structure stat du dernier test de fichier (ou de loprateur stat) qui est utilise, conomisant ainsi un appel systme. (Cela ne marche pas avec -t, et il faudra vous souvenir que lstat et -l laissent dans la structure stat les valeurs pour le lien symbolique et non pour le fichier rel. De mme, -l _ sera toujours faux aprs un stat normal.) Voici quelques exemples :
print "Fait laffaire.\n" stat($fichier); print "En lecture\n" print "En criture\n" print "Excutable\n" print "Setuid\n" print "Setgid\n" print "Sticky\n" print "Texte\n" print "Binaire\n" if -r $a || -w _ || -x _;

if if if if if if if if

-r -w -x -u -g -k -T -B

_; _; _; _; _; _; _; _;

Les ges des fichiers donns par -M, -A et -C sont en jours (avec partie fractionnaire) depuis le moment o le script a commenc tourner. Cette date est stocke dans la variable spciale $^T ($BASETIME). Donc, si le fichier a t modifi depuis que le script a dmarr, vous obtiendrez une dure ngative. Remarquez que comme la plupart des dures (86 399 sur 86 400 en moyenne) sont fractionnaires, il est gnralement illusoire de tester lgalit avec un entier sans passer par la fonction int. Exemples :
next unless -M $fichier > .5; # &nouveaufichier if -M $fichier < 0; # &avertissemnt if int(-A) == 90; # # $^T = time; fichier vieux de plus de 12 heures fichier plus rcent que le processus fichier ($_) accd il y a 90 jours aujourdhui

Pour remettre la date courante la date de dmarrage du script, crivez :

Oprateurs relationnels
Perl possde deux classes doprateurs relationnels. Lune delles opre sur les valeurs numriques et lautre sur les valeurs de chane, comme indiqu au tableau 3-5.

customer_8566

88
Tableau 3-5. Oprateurs relationnels
Numrique > >= < <= Chane gt ge lt le

Chapitre 3 Oprateurs unaires et binaires

Signification Suprieur . Suprieur ou gal . Infrieur . Infrieur ou gal .

Ces oprateurs renvoient 1 pour vrai et "" pour faux. Notez que les oprateurs relationnels sont non-associatifs, ce qui signifie que $a < $b < $c provoquera une erreur de syntaxe. En labsence de dclaration de locales, les comparaisons de chanes sappuient sur lordre lexicographique ASCII/Unicode et, contrairement certains autres langages informatiques, les espaces finaux comptent pour la comparaison. Avec une dclaration de locale, lordre lexicographique spcifi par la locale est utilis. (Les mcanismes de tri fonds sur les locales peuvent plus ou moins bien interagir avec les mcanismes Unicode actuellement en cours de dveloppement.)

Oprateurs dgalit
Les oprateurs dgalit lists au tableau 3-6 ressemblent beaucoup aux oprateurs relationnels. Tableau 3-6. Oprateurs dgalit
Numrique == != <=> Chane eq ne cmp Signification gal . Diffrent de. Comparaison, avec rsultat sign.

Les oprateurs gal et diffrent renvoient 1 pour vrai et "" pour faux (exactement comme les oprateurs relationnels). Les oprateurs <=> et cmp renvoient -1 si loprande de gauche est infrieur celui de droite, 0 sil sont gaux et +1 si loprande de gauche est suprieur celui de droite. Bien que ces oprateurs semblent trs proches des oprateurs relationnels, ils ont un niveau de prcdence plus faible, et la syntaxe de $a < $b <=> $c < $d est donc valide. Pour des raisons videntes pour quiconque a vu Star Wars, loprateur <=> est aussi connu sous le nom doprateur vaisseau spatial (spaceship operator).

Oprateurs sur les bits


Comme C, Perl dispose des oprateurs ET, OU et OU-exclusif sur les bits : &, | et ^. Vous avez bien sr remarqu, aprs votre tude attentive du tableau au dbut de ce chapitre, que le ET sur les bits possde une prcdence suprieure aux autres ; nous avons trich pour tous les inclure dans cette discussion.

customer_8566

Oprateurs logique de type C ( court-circuit)

89

Ces oprateurs fonctionnent diffremment sur les valeurs numriques et sur les chanes. (Cest lun des rares cas o Perl fait une diffrence.) Si lun des oprandes est un nombre (ou a t utilis comme un nombre), les deux oprandes sont convertis en entiers, puis lopration sur les bits est effectue. Ces entiers font au moins 32 bits de long, mais peuvent faire 64 bits sur certaines machines. Limportant est quil existe une limite arbitraire impose par larchitecture de la machine. Si les deux oprandes sont des chanes (et nont pas t utiliss comme des nombres depuis leur dernire mise jour), les oprateurs font les oprations sur les bits sur les bits correspondants des deux chanes. Dans ce cas, il ny a aucune limite arbitraire, puisque les chanes ne sont pas limites en taille. Si lune des chanes est plus longue que lautre, on considre que la plus courte dispose dun nombre suffisant de bits 0 pour complter la diffrence. Par exemple, si vous faites un ET entre deux chanes :
"123.45" & "234.56"

vous obtenez une autre chane :


"020.44"

Mais si vous faites un ET sur une chane et un nombre :


"123.45" & 234.56

La chane est dabord convertie en nombre, ce qui donne :


123.45 & 234.56

Les nombres sont ensuite convertis en entiers :


123 & 234

ce qui donne 106. Remarquez que toutes les chanes de bits sont vraies ( moins de donner la chane 0 ). Cela signifie que si vous voulez vrifier si lun des octets rsultant est non nul, vous ne devrez pas crire ceci :
if ( "fred" & "\1\2\3\4" ) { ... }

mais cela :
if ( ("fred" & "\1\2\3\4") =~ /[^\0]/ ) { ... }

Oprateurs logique de type C ( court-circuit)


Comme C, Perl propose galement les oprateurs && (ET logique) et || (OU logique). Ils sont valus de gauche droite (&& ayant une prcdence lgrement suprieure celle de ||) pendant le test de vrit de linstruction. Ces oprateurs sont appels oprateurs court-circuit car ils dterminent la vrit de linstruction en valuant le plus petit nombre doprandes possible. Par exemple, si loprande gauche dun oprateur && est faux, loprande de droite ne sera jamais valu car le rsultat de loprateur sera faux quelle que soit la valeur de loprande de droite.
Exemple $a && $b $a || $b Nom Et Ou Rsultat $a si $a est faux, sinon $b. $a si $a est vrai, sinon $b.

customer_8566

90

Chapitre 3 Oprateurs unaires et binaires

Non seulement de tels courts-circuits font gagner du temps, mais ils sont frquemment utiliss pour contrler le f lux de lvaluation. Par exemple, un idiome courant en Perl est :
open(FILE, "monfichier") || die "Impossible douvrir monfichier: $!\n";

Dans ce cas, Perl value dabord la fonction open. Si sa valeur est vraie (car monfichier a t ouvert avec succs), lexcution de la fonction die nest pas ncessaire et est donc omise. Vous pouvez littralement lire Ouvre mon fichier ou meurs ! . Les oprateurs && et ||diffrent de ceux de C en ceci quau lieu de retourner 0 ou 1, ils renvoient la dernire valeur value. Dans le cas de ||, cela a le dlicieux effet de vous permettre de choisir la premire valeur vraie dune srie. Une manire raisonnablement portable de trouver le rpertoire personnel dun utilisateur pourrait donc tre :
$home = || || || $ENV{HOME} $ENV{LOGDIR} (getpwuid($<))[7] die "Vous tes SDF !\n";

Dun autre ct, comme largument de gauche toujours valu en contexte scalaire, vous ne pouvez pas vous servir de || afin choisir entre deux aggrgats pour une affectation :
@a = @b || @c; @a = scalar(@b) || @c; @a = @b ? @b : @c; # Ceci ne fait pas ce que vous voulez # car voici ce que cela veut dire. # En revanche cela marche bien.

Perl fournit galement des oprateurs and et or de moindre prcdence, que certains trouvent plus lisibles et qui ne vous forcent pas utiliser des parenthses sur les oprateurs de liste. Ils sont aussi court-circuit. Voir le tableau 1-1 pour la liste complte.

Oprateur dintervalle
Loprateur dintervalle .. comprend en fait deux oprateurs diffrents selon le contexte. Loprateur est bi-stable, comme un f lip-f lop lectronique, et mule loprateur dintervalle de ligne (virgule) de sed, awk et dautres diteurs. Chaque oprateur .. scalaire mmorise son propre tat boolen. Il est faux tant que son oprande de gauche est faux. Une fois que loprande de gauche est vrai, loprateur reste vrai jusqu ce que loprande de droite soit vrai, aprs quoi loprateur dintervalle redevient faux. Loprateur ne devient pas faux jusqu sa prochaine valuation. Il peut tester loprande de droite et devenir faux pendant la mme valuation que celle sur laquelle il est devenu vrai (comme loprateur de awk), mais renvoie vrai au moins une fois. Si vous ne voulez pas quil teste loprande de droite avant la prochaine valuation (comme loprateur de sed) utilisez simplement trois points (...) au lieu de deux. Pour les deux oprateurs .. et ..., loprande de droite nest pas valu tant que loprateur se trouve dans ltat faux, et loprande de gauche nest pas valu tant que loprateur est dans ltat vrai. La valeur renvoye est soit la chane vide pour faux soit un numro de squence (commenant 1) pour vrai. Le numro de squence est remis zro pour chaque oprateur dintervalle rencontr. La chane E0 est accole la fin du numro de squence final dans un intervalle, ce qui naffecte pas sa valeur numrique, mais vous donne quelque

customer_8566

Oprateur conditionnel

91

chose chercher si vous voulez exclure llment final. Vous pouvez exclure le point de dpart en attendant que le numro de squence soit plus grand que 1. Si lun des oprandes de .. est un littral numrique, cet oprande est implicitement compar la variable $., qui contient le numro de ligne courant de votre fichier dentre. Exemples :
if (101 .. 200) { print; } # imprime la deuxime centaine de lignes next line if (1 .. /^$/); # passe les enttes dun message s/^/> / if (/^$/ .. eof()); # cite le corps dun message

En contexte de liste, .. renvoie une liste de valeurs comptes partir de la valeur de gauche jusqu la valeur de droite (par incrments de un). Cela sert crire des boucles for (1..10) et pour faire des tranches de tableaux :
for (101 .. 200) { print; } @foo = @foo[0 .. $#foo]; @foo = @foo[ -5 .. -1]; # affiche 101102...199200 # un no-op coteux # la tranche des 5 derniers lments

Si la valeur de gauche est suprieure celle de droite, une liste vide est renvoye. (Pour construire une liste en ordre inverse, voir loprateur reverse.) Si ses oprandes sont des chanes, loprateur dintervalle emploie lalgorithme dautoincrmentation magique vu prcdemment.5 Vous pouvez donc crire :
@alphabet = (A .. Z);

pour obtenir toutes les lettres de lalphabet (latin), ou :


$hexdigit = (0 .. 9, a .. f)[$nombre & 15];

pour obtenir un chiffre hexadcimal, ou :


@z2 = (01 .. 31); print $z2[$jour];

pour obtenir des dates avec un zro en tte. Vous pouvez galement crire :
@combis = (aa .. zz);

pour obtenir toutes les combinaisons de deux lettres minuscules. Attention cependant quelque chose comme :
@grossescombis = (aaaaaa .. zzzzzz);

car cela va ncessiter beaucoup de mmoire. Pour tre prcis, il faudra de lespace pour stocker 308 915 776 scalaires. Esprons que vous avez une grosse partition de swap. Vous devriez vous intresser une approche itrative.

Oprateur conditionnel
Loprateur ?: est le seul oprateur ternaire, comme en C. On lappelle souvent loprateur conditionnel, car il fonctionne comme un if-then-else, except quil peut tre inclus sans problme dans dautres expressions et fonctions, car cest une expression et non une instruction. En tant quoprateur ternaire, ses deux lments sparent trois expressions : COND ? EXPR_SI_VRAI : EXPR_SI_FAUX

5. Si la valeur finale spcifie nest pas dans la squence que lincrmentation magique produirait, la squence continue jusqu ce que le prochain lment soit plus long que la valeur finale.

customer_8566

92

Chapitre 3 Oprateurs unaires et binaires

Si la condition COND est vrai, seule lexpression EXPR_SI_VRAI est value, et la valeur de cette expression devient la valeur de toute lexpression. Sinon, seule lexpression EXPR_SI_FAUX est value, et sa valeur devient celle de toute lexpression. Le contexte scalaire ou de liste se propage vers le deuxime ou le troisime argument, selon celui qui est slectionn. (Le premier argument est toujours en contexte scalaire, puisque cest une condition.)
$a = $ok ? $b : $c; # donne un scalaire @a = $ok ? @b : @c; # donne un tableau $a = $ok ? @b : @c; # donne le nombre dlments dun tableau

Vous verrez souvent loprateur conditionnel inclus dans des listes de valeurs formater avec printf, car personne na envie de dupliquer une instruction complte juste pour basculer entre deux valeurs proches.
printf "Jai %d chameau%s.\n", $n, $n <= 1 ? "" : "x";

La prcdence de ?: est opportunment plus grande que celle de la virgule, mais infrieure celle de la plupart des oprateurs que vous utiliserez lintrieur (comme == dans cet exemple) ; vous naurez donc gnralement pas utiliser de parenthses. Mais vous pouvez ajouter des parenthses pour clarifier, si vous voulez. Pour les oprateurs conditionnels embots lintrieur de la partie EXPR_SI_VRAI dautres oprateurs conditionnels, nous vous suggrons de de faire des sauts de ligne et dindenter comme sil sagisait dinstruction if ordinaires :
$bissextile = $annee % 4 == 0 ? $annee % 100 == 0 ? $annee % 400 == 0 ? 1 : 0 : 1 : 0;

Pour les conditions imbriques dans des parties EXPR_SI_FAUX doprateurs conditionnels prcdents, vous pouvez faire quelque chose dquivalent :
$bissextile $annee ? : = % 4 0 $annee % 100 ? 1 : $annee % 400 ? 0 : 1;

mais il est habituellement prfrable daligner verticalement toutes les COND et les EXPR_SI_VRAI :
$bissextile $annee $annee $annee = % 4 ? 0 : % 100 ? 1 : % 400 ? 0 : 1;

customer_8566

Oprateurs daffectation

93

Mme des structures assez encombres peuvent sclaircir en alignant les points dinterrogation et les deux-points :
printf "Oui, $i18n eq $i18n eq $i18n eq jaime mon "anglais" "allemand" "japonais" livre du %s!\n", ? "camel" : ? "Kamel" : ? "\x{99F1}\x{99DD}" : "chameau"

Vous pouvez affecter loprateur conditionnel6 si le deuxime et le troisime arguments sont tous les deux des lvalueslgales (cest--dire quon peut leur affecter une valeur), et que tous deux sont soit des scalaires, soit des listes (sinon Perl ne saura pas quel contexte fournir la partie droite de laffectation) :
($a_ou_b ? $a : $b) = $c; # donne la valeur de $c soit $a, soit $b

Souvenez-vous que loprateur conditionnel lie encore plus fort que les multiples oprateurs daffectation. Cest habituellement ce que vous voulez (voir lexemple $bissextile plus haut, par exemple), mais vous ne pourrez pas obtenir leffet inverse sans parenthses. Lutilisation daffectations dans un oprateur conditionnel vous attirera des ennuis, et vous risquez mme de ne pas avoir derreur lanalyse car loprateur conditionnel peut tre analys comme une lvalue. Par exemple, vous pourriez crire ceci :
$a % 2 ? $a += 10 : $a += 2 # FAUX

Mais ce serait analys comme cela :


(($a % 2) ? ($a += 10) : $a) += 2

Oprateurs daffectation
Perl reconnat les oprateurs daffectation de C, et fournit galement les siens. Il y en a un certain nombre :
= **= += -= .= *= /= %= x= &= |= ^= <<= >>= &&= ||=

Chaque oprateur ncessite une lvalue cible (typiquement une variable ou un lment de tableau) sa gauche et une expression sa droite. Pour loprateur daffectation simple : CIBLE = EXPR La valeur de EXPR est stocke dans la variable ou lendroit dsign par CIBLE. Pour les autres oprateurs, Perl value lexpression : CIBLE OP= EXPR comme sil tait crit : CIBLE = CIBLE OP EXPR
6. Cela ne garantit pas une amlioration de la lisibilit de votre programme. Mais a peut servir construire des participations sympas pour un concours de Perl assombri (Obfuscated Perl Contest).

customer_8566

94

Chapitre 3 Oprateurs unaires et binaires

Cest un bon moyen mnmotechnique, mais il est trompeur, et de deux manires. Dabord les oprateurs daffectation sont analyss au niveau de prcdence des affectations ordinaires, quelle que soit la prcdence que loprateur OP aurait eu par lui-mme. Ensuite, CIBLE nest valu quune seule fois. Habituellement cela na aucune importance, sauf en cas deffets secondaires, comme pour une auto-incrmentation.
$var[$a++] += $valeur; $var[$a++] = $var[$a++] + $valeur; # $a is increment une fois # $a is increment deux fois

la diffrence de C, loprateur daffectation produit une lvalue valide. Modifier une affectation revient faire laffectation puis modifier la variable laquelle on vient daffecter une valeur. Cela peut servir modifier une copie de quelque chose, comme ceci :
($tmp = $global) += $constante;

qui est quivalent :


$tmp = $global + $constante;

De mme :
($a += 2) *= 3;

est quivalent :
$a += 2; $a *= 3;

Ce nest pas tellement utile, mais voici un idiome frquent :


($nouveau = $ancien) =~ s/toto/titi/g;

Dans tous les cas, la valeur de laffectation est la nouvelle valeur de la variable. Comme les oprateurs daffectations sont associatifs de droite gauche, cela peut servir affecter la mme valeur plusieurs variables, comme dans :
$a = $b = $c = 0;

qui affecte 0 $c et le rsultat de cette opration (toujours 0) $b, puis le rsultat de (toujours 0) $a. Les affectations de listes ne se font quavec loprateur daffectation simple, =. Dans un contexte de liste, une affectation de liste retourne la liste des nouvelles valeurs, tout comme laffectation scalaire. En contexte scalaire, une affectation de liste renvoie le nombre de valeurs qui taient disponibles droite de laffectation, comme indiqu au chapitre 2, Composants de Perl. Cela sert pour tester les fontions qui renvoient une liste vide quand elles chouent (ou finissent par chouer), comme dans :
while (($cle, $valeur) = each %gloss) { ... } next unless ($dev, $ino, $mode) = stat $fichier;

Oprateurs virgule
Le , binaire est loprateur virgule. En contexte scalaire, il value son argument de gauche en contexte vide, jette le rsultat, puis value son argument de droite et retourne cette valeur. Exactement comme loprateur virgule de C. Par exemple :
$a = (1, 3);

customer_8566

Oprateurs de liste (vers la droite)

95

affecte 3 $a. Attention ne pas confondre son utilisation en contexte scalaire avec son utilisation en contexte de liste. Dans un contexte de liste, une virgule est juste le sparateur des arguments de la liste et il insre ses deux arguments dans la LISTE. Il ne jette aucune valeur. Par exemple, si vous modifiez lexemple prcdent en :
@a = (1, 3);

vous construisez une liste de deux lments, tandis que :


atan2(1, 3);

appelle la fonction atan2 avec deux arguments. La plupart du temps, le digramme => est juste un synonyme pour loprateur virgule. Il sert documenter les arguments apparis. Il force galement linterprtation comme chane de tout identificateur plac sa gauche.

Oprateurs de liste (vers la droite)


La partie droite dun oprateur de liste commande tous les arguments de loprateur de liste, qui sont spars par des virgules ; donc la prcdence dun oprateur de liste est plus faible que celle de la virgule, si vous regardez vers la droite. Une fois quun oprateur de liste commence avaler des arguments spars par des virgules, les seules choses qui larrtent sont les tokens qui terminent lexpression toute entire (comme les points-virgules ou les modificateurs dinstructions) ou les tokens qui terminent la sousexpression en cours (comme les parenthses ou les crochets fermants) ou les oprateurs logiques de faible prcdence dont nous aller parler tout de suite.

And, or, not et xor logiques


Perl fournit les oprateurs and, or, et not comme alternatives de moindre prcdence &&, ||, et !. Le comportement de ces oprateurs est identique en particulier, and et or court-circuitent comme leurs alter-egos, ce qui leur donne leur utilit non seulement pour les expressions logiques, mais aussi pour le contrle du f lux dvaluation. Comme la prcdence de ces oprateurs est beaucoup plus basse que celle des oprateurs emprunts C, vous pouvez les utiliser en toute scurit aprs un oprateur de liste, sans quil soit besoin de parenthses.
unlink "alpha", "beta", "gamma" or enrage(), next LIGNE;

Avec les oprateurs issus de C, vous auriez d lcrire comme ceci :


unlink("alpha", "beta", "gamma") || (enrage(), next LIGNE);

Mais vous ne pouvez pas simplement remplacer toutes les occurences de || par or. Supposons que vous changiez ceci :
$xyz = $x || $y || $z;

en cela :
$xyz = $x or $y or $z; # FAUX

customer_8566

96

Chapitre 3 Oprateurs unaires et binaires

Cela ne ferait pas du tout la mme chose ! La prcdence de laffectation est suprieure celle de or mais plus basse que celle de ||, donc on affecterait toujours $x $xyz pour ensuite seulement faire les or. Pour obtenir le mme rsultat quavec ||, vous devrez crire :
$xyz = ( $x or $y or $z );

La morale de cette histoire, cest quil faut toujours apprendre les rgles de prcdence (ou utiliser les parenthses) quels que soient les oprateurs logiques que vous utilisez. Il existe galement un xor logique qui na pas dquivalent exact en C ou en Perl, puisque le seul autre oprateur OU-exclusif (^) travaille sur les bits. Loprateur xor ne peut pas court-circuiter, car les deux cts doivent tre valus. Le meilleur quivalent de $a xor $b est peut-tre !$a != !$b. On pourrait galement crire !$a ^ !$b ou mme $a ? !$b : !!$b, bien sr. Lessentiel est que $a et $b doivent tous les deux tre valus comme vrais ou faux dans un contexte boolen, et loprateur sur les bits existant nen fournit pas sans quon ly aide.

Oprateurs C manquant en Perl


Voici ce que C a et que Perl na pas : & unaire Loprateur adresse-de. Loprateur \ de Perl (qui fournit une rfrence) occupe la mme niche cologique :
$ref_var = \$var;

Mais les rfrences de Perl sont plus sres que les pointeurs de C. * unaire Loprateur de drfrencement dadresse. Comme Perl ne connat pas les adresses, il na pas besoin de les drfrencer. En revanche, Perl a des rfrences et ce sont donc les caractres de prfixe variable qui servent doprateurs de drfrence, tout en indiquant le type : $, @, % et &. tonnament, il existe bien un oprateur * de drfrencement, mais comme * est le drle de caractre indiquant un typeglob, vous ne lutiliserez pas ainsi. (TYPE) Loprateur de transtypage. De toute faon, personne naime se faire transtyper.

customer_8566

Instructions et dclarations
Un programme Perl consiste en une squence de dclarations et dinstuctions. Une dclaration peut-tre place partout o une instruction peut ltre, mais son effet premier se produit la compilation. Certaines dclarations jouent un double rle en tant quinstructions, mais la plupart sont totalement transparentes lexcution. Aprs la compilation, la squence dinstructions principale est excute une seule fois. Contrairement beaucoup de langages de programmation, Perl nimpose pas de dclarer explicitement les variables ; elles se mettent exister leur premire utilisation, que vous les ayez dclares ou non. Si vous essayez dutiliser la valeur dune variable laquelle aucune valeur na jamais t affecte, elle est traite silencieusement comme si elle contenait 0 si vous vouliez un nombre, comme "" si vous vouliez une chane ou simplement comme une valeur fausse si vous vouliez une valeur logique. Si vous prfrez tre averti de lutilisation de valeurs non dfinies comme si elles taient de vritables chanes ou nombres, ou mme traiter cette utilisation comme une erreur, la dclaration use warnings sen chargera ; voir la section Pragmas la fin de ce chapitre. Cependant, si vous prfrez, vous pouvez ventuellement dclarer vos variables, en utilisant soit my ou our avant le nom de variable. Vous pouvez mme faire quutiliser une variable non dclare soit une erreur. Cest bien de vouloir de la discipline, encore fautil la demander. Normalement, Perl ne sintresse pas vos habitudes de programmation ; mais avec la dclaration use strict, lutilisation de variables non dclares est dtecte la compilation. De nouveau, voir la section Pragmas.

Instructions simples
Une instruction simple est une expression value pour ses effets secondaires. Toute instruction simple doit se terminer par un point-virgule, sauf si cest la dernire instruction dun bloc. Dans ce cas, le point-virgule est optionnel Perl sait que vous en avez fini avec cette instruction, puisque vous avez fini le bloc. Mais mettez quand mme le pointvirgule sil sagit dun bloc multiligne, car vous pourriez bien ajouter une autre ligne par la suite.

customer_8566

98

Chapitre 4 Instructions et dclarations

Bien que des oprateurs comme eval {}, do {} et sub {} ressemblent des instructions composes, en fait ce nen sont pas. Certes, ils permettent davoir plusieurs instructions lintrieur, mais cela ne compte pas. Vus de lextrieur, ces oprateurs sont juste des termes dans une expression ; cest pourquoi ils ncessitent un point-virgule explicite quand ils sont utiliss comme dernier lment dune instruction. Toute instruction simple peut tre optionnellement suivi dun modificateur unique, juste avant le point-virgule final (ou la fin de bloc). Les modificateurs possibles sont :
if EXPR unless EXPR while EXPR until EXPR foreach LISTE

Les modificateurs if et unless fonctionnent comme peuvent sy attendre les anglophones :


$trash->take(out) if $you_love_me; # sors la poubelle si tu maimes shutup() unless $you_want_me_to_leave; # tais-toi, sauf si tu veux que # je men aille

Les modificateurs while et until sont valus de faon rpte. Comme notre lectorat anglophone pouvait sy attendre, un modificateur while excute lexpression tant que sa propre expression reste vraie, tandis quun modificateur until continue de sexcuter tant quelle reste fausse :
$expression++ while -e "$file$expression"; kiss(me) until $I_die; # embrasse-moi jusqu la mort

Le modificateur foreach (aussi orthographi for) est valu une fois par lment de sa LISTE, $_ tant un alias de llment courant :
s/java/perl/ for @curriculum; print "champ: $_\n" foreach split /:/, $ligne;

Les modificateurs while et until ont la smantique usuelle des boucles while (la condition est value en premier), sauf quand ils sappliquent un doBLOC (ou linstruction maintenant dprcie doSUBROUTINE), auquel cas le bloc sexcute une fois avant que la condition soit value. Cela vous permet dcrire des boucles comme :
do { $ligne = <STDIN>; ... } until $ligne eq ".\n";

Voyez aussi les trois diffrentes entres de do au chapitre 29, Fonctions. Remarquez galement que les oprateurs de contrle de boucle dcrits plus loin ne fonctionnent pas dans cette construction, car les modificateurs de boucles ne prennent pas dtiquette. Vous pouvez toujours placer un bloc supplmentaire autour pour terminer plus tt, ou lintrieur pour itrer avant la fin de la boucle, comme cela est dcrit dans la section Blocs simples. Ou bien vous pourriez crire une vraie boucle avec plusieurs commandes de contrle de boucle lintrieur. propos de vraies boucles, nous allons maintenant parler des instructions composes.

customer_8566

Instructions composes

99

Instructions composes
On appelle bloc une squence dinstructions dfinie dans une porte1. Parfois la porte stend sur un fichier tout entier, comme par exemple un fichier appel avec require ou le fichier contenant votre programme principal. Dautres fois la porte a ltendue dune chane value avec eval. Mais en gnral, un bloc est entour daccolades ({}). Quand nous parlons de porte, cela signifie nimporte laquelle de ces trois possibilits. Quand nous voudrons dire un bloc entour daccolades, nous emploierons le terme BLOC. Les instructions composes sont construites partir dexpressions et de BLOC. Les expressions sont construites partir de termes et doprateurs. Dans nos descriptions syntaxiques, nous utiliserons le mot EXPR pour indiquer un emplacement o vous pouvez utiliser nimporte quelle expression scalaire. Pour indiquer une expression value en contexte de liste, nous dirons LISTE. Les constructions suivantes peuvent tre utilises pour contrler lexcution de BLOC de faon conditionnelle ou rpte. (Ltiquette LABEL est optionnelle.)
if if if if (EXPR) (EXPR) (EXPR) (EXPR)

BLOC BLOC else BLOC BLOC elsif (EXPR) BLOC ... BLOC elsif (EXPR) BLOC ... else BLOC BLOC BLOC else BLOC BLOC elsif (EXPR) BLOC ... BLOC elsif (EXPR) BLOC ... else BLOC

unless unless unless unless

(EXPR) (EXPR) (EXPR) (EXPR)

LABEL while (EXPR) BLOC LABEL while (EXPR) BLOC continue BLOC LABEL until (EXPR) BLOC LABEL until (EXPR) BLOC continue BLOC LABEL for (EXPR; EXPR; EXPR) BLOC LABEL foreach (LISTE) BLOC LABEL foreach VAR (LISTE) BLOC LABEL foreach VAR (LISTE) BLOC continue BLOC LABEL BLOC LABEL BLOC continue BLOC Remarquez qu linverse de C et de Java, elles sont dfinies en termes de BLOC, et non dinstructions. Cela signifie que les accolades sont obligatoires ; les instructions isoles ne sont pas autorises. Si vous voulez crire des conditions sans accolades, il y a plusieurs manires de le faire. Les lignes suivantes font toutes la mme chose :
1. Les portes et les espaces de nommage sont dcrits au chapitre 2, Composants de Perl, la section Noms.

customer_8566

100
unless (open(TOTO, $toto)) if (!open(TOTO, $toto))

Chapitre 4 Instructions et dclarations


{ die "Impossible douvrir $toto: $!" } { die "Impossible douvrir $toto: $!" } unless open(TOTO, $toto); if !open(TOTO, $toto);

die "Impossible douvrir $toto: $!" die "Impossible douvrir $toto: $!" open(TOTO, $toto) open TOTO, $toto

|| die "Impossible douvrir $toto: $!"; or die "Impossible douvrir $toto: $!";

Nous avons tendance prfrer les deux dernires dans la plupart des cas. Elles sont plus lisibles que les autres, en particulier la version or die . Avec || vous devez vous habituer utiliser les parenthses religieusement, tandis quavec la version or, ce nest pas grave de les oublier. Mais la principale raison pour laquelle nous prfrons les dernires versions est quelles mettent la partie la plus importante de linstruction au dbut de la ligne, l o vous la verrez le mieux. La gestion derreur est repousse vers la droite, o vous navez pas besoin dy faire attention, sauf si vous le voulez2. Et si vous tabulez tous vos tests or die la mme position droite de chaque ligne, cest encore plus facile lire :
chdir $dir open TOTO, $fichier @lines = <TOTO> close TOTO or or or or die die die die "chdir $dir: $!"; "open $fichier: $!"; "$fichier est vide ?"; "close $fichier: $!";

Instructions if et unless
Linstruction if est simple. Comme les BLOCs sont dlimits par des accolades, il ny jamais dambigut pour savoir quel if en particulier un else ou un elsif est li. Dans une squence donne de BLOCs if/elsif/else, seul le premier dont la condition est vraie est excut. Si aucune des conditions nest vraie, alors le BLOC else, sil existe, est excut. Cest en gnral une bonne ide de mettre un else la fin dune chane de elsif, afin de se prmunir contre un cas oubli. Si vous utilisez unless la place de if, le sens du test est invers. Cest--dire que :
unless ($x == 1) ...

est quivalent :
if ($x != 1) ...

ou au plus laid :
if (!($x == 1)) ...

La porte dune variable dclare dans la condition de contrle stend de sa dclaration jusqu la fin de linstruction conditionnelle, y compris tous les elsif et lventuelle clause else finale, mais pas plus loin :
if ((my $couleur = <STDIN>) =~ /rouge/i) { $valeur = 0xff0000; }
2. Tout comme pour cette note.

customer_8566

Instructions de boucle

101

elsif ($couleur =~ /vert/i) { $valeur = 0x00ff00; } elsif ($couleur =~ /bleu/i) { $valeur = 0x0000ff; } else { warn "`$couleur : composante RGB inconnue, le noir est slectionn\n"; $valeur = 0x000000; }

Aprs le else, la variable $couleur est hors de porte. Si vous voulez que sa porte stende plus loin, dclarez la variable plus tt.

Instructions de boucle
Dans leur syntaxe formelle, toutes les instructions de boucle comportent un LABEL (ou tiquette) facultatif. (Vous pouvez mettre une telle tiquette sur nimporte quelle instruction, mais cela a une signification spciale pour les boucles.) Sil est prsent, le label consiste en un identificateur suivi de deux-points. Il est courant dcrire ltiquette en majuscules pour viter tout conf lit avec des mots rservs et les faire mieux ressortir. Bien que Perl ne se pose pas de problme si vous utilisez un label qui a dj une signification comme if ou open, vos lecteurs risquent de se tromper.

Instructions while et until


Linstruction while excute le bloc tant que EXPR est vraie. Si le mot while est remplac par until, le sens du test est invers ; cest--dire quil excute le bloc tant que EXPR est fausse. La condition est cependant toujours teste avant la premire itration. Les instructions while ou until comportent un bloc supplmentaire facultatif : le bloc continue. Ce bloc est excut chaque fois que lon achve litration, soit en sortant la fin du premier bloc, soit par un next explicite (next est un oprateur de contrle de boucle qui passe litration suivante). En pratique, le bloc continue nest pas trs utilis, mais il est prsent afin de pouvoir dfinir rigoureusement la boucle for dans la section qui suit. Contrairement la boucle for que nous allons voir dans un moment, une boucle while ne localise jamais implicitement de variables dans sa condition de test. Cela peut avoir d intressantes consquences quand des boucles while utilisent des variables globales comme variables de boucle. En particulier, consultez la section Oprateur de lecture de ligne (Angle) au chapitre 2 pour voir comment une affectation implicite la variable globale $_ peut se produire dans certaines boucles while, ainsi quun exemple de gestion de ce problme en localisant explicitement $_. Il est cependant prfrable de dclarer les autres variables de boucle avec my, comme dans lexemple suivant. Une variable dclare dans la condition de test dune instruction while ou dun until est visible seulement dans le ou les blocs pilots par ce test. Sa porte ne stend pas audel. Par exemple :
while (my $ligne = <STDIN>) {

customer_8566

102
$ligne = lc $ligne; } continue { print $ligne; # toujours visible } # $ligne maintenant hors de porte

Chapitre 4 Instructions et dclarations

Ici, la porte $ligne stend de sa dclaration dans lexpression de contrle lensemble de la boucle, y compris le bloc continue, mais pas au-del. Si vous voulez que sa porte stende plus loin, dclarez la variable avant la boucle.

Boucles for
La boucle for en trois parties comporte trois expressions spares par des points-virgules entre ses parenthses. Ces expressions sont respectivement linitialisation, la condition et la r-initialisation de la boucle. Ces trois expressions sont optionnelles (mais pas les points-virgules) ; si la condition est omise, elle est toujours vraie. La boucle for peut tre dfinie dans les termes de la boucle while correspondante. Ce qui suit :
LABEL: for (my $i = 1; $i <= 10; $i++) { ... }

est donc identique :


{ my $i = 1; LABEL: while ($i <= 10) { ... } continue { $i++; } }

sinon quil ny a pas vraiment de bloc extrieur. (Nous lavons juste mis l pour montrer les limites du my.) Si vous voulez itrer deux variables simultanment, il vous suffit de sparer les expressions parallles par des virgules :
for ($i = 0, $bit = 0; $i < 32; $i++, $bit <<= 1) { print "Le bit $i is est 1\n" if $mask & $bit; } # les valeurs de $i et $bit persistent aprs la boucle

Ou bien dclarer ces variables comme visibles seulement lintrieur de la boucle for :
for (my ($i, $bit) = (0, 1); $i < 32; $i++, $bit <<= 1) { print "Le bit $i is est 1\n" if $mask & $bit; } # les $i et $bit de la boucle sont maintenant hors de porte

customer_8566

Instructions de boucle

103

En plus des boucles habituelles sur les indices de tableaux, for a dautres applications intressantes. Il na mme pas besoin dune variable de boucle explicite. Voici un exemple permettant dviter le problme que vous rencontrez en testant explicitement la fin de fichier sur un descripteur de fichier interactif, provoquant ainsi le blocage du programme.
$sur_un_tty = -t STDIN && -t STDOUT; sub prompt { print "yes? " if $sur_un_tty } for ( prompt(); <STDIN>; prompt() ) { # fait quelque chose }

Une autre application traditionnelle pour le for en trois parties vient du fait que les trois expressions sont optionnelles et que la condition par dfaut est vraie. Si vous omettez les trois expressions, vous obtenez une boucle infinie :
for (;;) { ... }

Ce qui est exactement quivalent :


while (1) { ... }

Si la notion de boucle infinie vous inquite, nous devrions souligner que vous pouvez toujours sortir de la boucle quand vous voulez avec un oprateur de contrle explicite de boucle comme last. Bien sr, si vous crivez le code de contrle dun missile de croisire, vous naurez jamais vraiment besoin de sortir de la boucle. Elle se terminera automatiquement au moment opportun.3

Boucles foreach
La boucle foreach parcourt une liste de valeurs en affectant tour tour chaque lment de la liste la variable de contrle (VAR) :
foreach VAR (LISTE) { ... }

Le mot-cl foreach est juste un synonyme du mot-cl for, vous pouvez donc utiliser au choix for et foreach, selon lequel vous trouvez le plus lisible dans une situation donne. Si VAR est omis, la variable globale $_ est utilise. (Ne vous inquitez pas Perl distingue facilement for (@ARGV) de for ($i=0; $i<$#ARGV; $i++), car ce dernier contient des points-virgules.) Voici quelques exemples :
$somme = 0; foreach $valeur (@tableau) { $somme += $valeur } for $decompte (10,9,8,7,6,5,4,3,2,1,BOUM) { # compte rebours print "$decompte\n"; sleep(1); }
3. Cest--dire que les retombes de la boucle ont tendance se produire automatiquement.

customer_8566

104
for (reverse BOUM, 1 .. 10) { print "$_\n"; sleep(1); }

Chapitre 4 Instructions et dclarations


# pareil

for $champ (split /:/, $data) { print "Le champ contient : $champ\n"; } foreach $cle (sort keys %hash) { print "$cle => $hash{$cle}\n"; }

# toute expression de LISTE

Le dernier reprsente la manire classique dafficher les valeurs dun hachage dans lordre des cls. Consultez les entres keys et sort au chapitre 29 pour des exemples plus labors. Il nexiste aucune manire de savoir o vous en tes dans une liste avec foreach. Vous pouvez comparer des lments adjacents en vous souvenant du prcdent dans une variable, mais il faudra parfois vous contenter dcrire une boucle for en trois parties avec des indices. Aprs tout, cet autre for est justement l pour a. Si LISTE est entirement constitue dlments auxquels on peut affecter une valeur (cest--dire de variables, pas dune numration de constantes), vous pouvez modifier chacune de ces variables en modifiant VAR lintrieur de la boucle. Cela provient du fait que la variable dindice de la boucle foreach est un alias implicite de chaque lment de la liste sur laquelle vous bouclez. Vous pouvez non seulement modifier un tableau dun coup, mais galement plusieurs tableaux ou hachages dans une seule liste :
foreach $paye (@salaires) { $paye *= 1.08; } for (@noel, @paques) { s/pt/foie gras/; } s/pt/foie gras/ for @noel, @paques; # une augmentation de 8%

# change le menu

# idem

for ($scalaire, @tableau, values %hash) { s/^\s+//; # retire les espaces initiaux s/\s+$//; # retire les espaces finaux }

La variable de boucle est valide uniquement dans la porte dynamique ou lexicale de la boucle et sera implicitement lexicale si la variable a t prcdemment dclare avec my. Cela la rend invisible toute fonction dfinie en dehors de la porte lexicale de la variable, mme si elle est appele depuis cette boucle. Cependant si aucune dclaration lexicale nest porte, la variable de boucle sera une variable globale localise ( porte dynamique) ; cela permet aux fonctions appeles depuis la boucle daccder cette variable. Dans tous les cas, la valeur quavait la variable localise avant la boucle sera restaure la sortie de la boucle. Si vous prfrez, vous pouvez dclarer explicitement quel type de variable (lexicale ou globale) utiliser. Ceux qui maintiennent votre code sauront plus facilement ce qui se

customer_8566

Instructions de boucle

105

passe ; sinon, ils devront remonter la chane des portes successives la recherche dune dclaration pour deviner de quelle variable il sagit :
for my $i (1 .. 10) { ... } for our $Tick (1 .. 10) { ... } # $i toujours lexicale # $Tick toujours globale

Quand une dclaration accompagne la variable de boucle, lcriture courte for est toujours prfrable foreach, car cela se lit mieux en anglais.4 Voici comment un programmeur C ou Java pourrait dabord penser crire un algorithme donn en Perl :
for ($i = 0; $i < @tab1; $i++) { for ($j = 0; $j < @tab2; $j++) { if ($tab1[$i] > $tab2[$j]) { last; # Impossible daller la boucle externe. :-( } $tab1[$i] += $tab2[$j]; } # voici o ce last memmne }

Mais voici comment un programmeur Perl expriment pourrait lcrire :


WID: foreach $ceci (@tab1) { JET: foreach $cela (@tab2) { next WID if $ceci > $cela; $ceci += $cela; } }

Vous voyez combien ctait simple en Perl idiomatique ? Cest plus propre, plus sr et plus rapide. Cest plus propre car il y a moins de bruit. Cest plus sr car si du code est ajout par la suite entre les boucles interne et externe, ce code ne sera pas accidentellement excut, car next (expliqu plus loin) reboucle sur la boucle externe Mais vous codez comme vous prfrez. TMTOWTDI. Comme linstruction while, linstruction foreach peut aussi avoir un bloc continue. Cela vous permet dexcuter un bout de code la fin de chaque itration de boucle, que vous en soyez arriv l par le cours normal des vnements ou par un next.

Contrle de boucle
Nous avons dj mentionn que vous pouviez mettre un LABEL sur une boucle pour lui donner un nom. Ltiquette identifie la boucle pour les oprateurs de contrle de boucle next, last et redo. Le LABEL dsigne la boucle toute entire, pas seulement le dbut de celle-ci. Une commande de contrle de boucle ne va pas au LABEL lui-mme. Pour lordinateur ltiquette aurait aussi bien pu tre place la fin de la boucle. Mais il semble que les gens prfrent les tiquettes au dbut.

4. NdT : Dune manire gnrale, vous avez maintenant remarqu quil est utile davoir des notions danglais si lon veut profiter des subtilits de Perl (et de CPAN).

customer_8566

106

Chapitre 4 Instructions et dclarations

Les boucles sont typiquement nommes daprs les lments quelles manipulent chaque itration. Cela se combine bien avec les oprateurs de contrle de boucle, qui sont conus pour se lire comme de langlais quand ils sont utiliss avec une tiquette aproprie et un modificateur dinstruction. La boucle typique traite des lignes, donc ltiquette de boucle typique est LINE: ou LIGNE: et loprateur de contrle de ligne typique ressemble ceci :
next LIGNE if /^#/; last LABEL next LABEL redo LABEL # supprime les commentaires

La syntaxe des oprateurs de contrle de boucle est :

Le LABEL est optionnel ; sil est omis, loprateur se rfre la boucle englobante la plus interne. Mais si vous voulez sauter plus dun niveau, vous devez utiliser un LABEL pour dsigner la boucle sur laquelle agir. Ce LABEL na pas besoin dtre dans la mme porte lexicale que loprateur de contrle, mais cest probablement prfrable. En fait, le LABEL peut tre nimporte o dans la porte dynamique. Si cela vous force sortir dun eval ou dun sous-programme, Perl met un avertissement (sur demande). Tout comme vous pouvez avoir autant de return que vous voulez dans une fonction, vous pouvez avoir autant doprateurs de contrle de boucle que vous voulez dans une boucle. Cela na pas tre considr comme mauvais ou pas cool. Aux dbuts de la programmation structure, certaines personnes insistaient sur le fait que les boucles et les sous-programmes ne devaient avoir quune entre et quune sortie. La notion dentre unique est toujours une bonne ide, mais la notion de sortie unique a conduit lcriture de beaucoup de code artificiel. La programmation consiste principalement parcourir des arbres de dcision. Un arbre de dcision commence naturellement par une racine unique mais se termine par de nombreuses feuilles. crivez votre code avec le nombre de sorties de boucle (et de retours de fonction) qui est naturel pour le problme que vous essayez de rsoudre. Si vous avez dclar vos variables dans des portes raisonnables, tout sera automatiquement nettoy le moment venu, quelle que soit la manire dont vous quittez le bloc. Loprateur last sort immdiatement de la boucle en question. Le bloc continue, sil existe, nest pas excut. Lexemple suivant sjecte de la boucle la premire ligne blanche :
LIGNE: while (<STDIN>) { last LIGNE if /^$/; ... } # sort quand lentte de mail est fini

Loprateur next passe le reste de litration courante de la boucle et commence la suivante. Sil existe une clause continue sur la boucle, elle est excute juste avant que la condition soit r-value, exactement comme la troisime partie dune boucle for. Elle peut donc servir incrmenter une variable de boucle, mme si une itration particulire de la boucle a t interrompue par un next :
LIGNE: while (<STDIN>) { next LIGNE if /^#/; next LIGNE if /^$/; ... # ignore les commentaires # ignore les lignes blanches

customer_8566

Instructions de boucle
} continue { $compte++; }

107

Loprateur redo redmarre le bloc de boucle sans rvaluer la condition. Le bloc continue, sil existe, nest pas excut. Cet oprateur sutilise souvent pour des programmes qui veulent se cacher eux-mmes ce qui vient dtre entr. Supposons que vous traitez un fichier dont les lignes sont parfois termines par un antislash pour indiquer quelles continuent sur la ligne suivante. Voici un exemple dutilisation de redodans ce cas :
while (<>) { chomp; if (s/\\$//) { $_ .= <>; redo unless eof; # ne pas lire au-del de la fin de chaque fichier } # traitement de $_ }

qui est la version Perl usuelle du plus explicite (et laborieux) :


LIGNE: while (defined($ligne = <ARGV>)) { chomp($ligne); if ($ligne =~ s/\\$//) { $ligne .= <ARGV>; redo LIGNE unless eof(ARGV); } # traitement de $ligne }

Voici un exemple tir dun programme rel qui utilise les trois oprateurs de contrle de boucle. Bien que cette mthode soit moins courante maintenant que nous disposons des modules Getopt::* dans la distribution de Perl standard, cest toujours une illustration intressante de lutilisation des oprateurs de contrle de boucle sur des boucles nommes et imbriques :
ARG: while (@ARGV && $ARGV[0] =~ s/^-(?=.)//) { OPT: for (shift @ARGV) { m/^$/ && do { next m/^-$/ && do { last s/^d// && do { $Niveau_Debug++; redo s/^l// && do { $Genere_Listing++; redo s/^i(.*)// && do { $Sur_Place = $1 || ".bak"; next say_usage("Option inconnue : $_"); } }

ARG; ARG; OPT; OPT; ARG;

}; }; }; }; };

Encore un mot au sujet des oprateurs de contrle de boucle. Vous avez peut-tre remarqu que nous ne les appelons pas instructions . Ce ne sont en effet pas des instructions bien que comme toute expression, on puisse les utiliser comme des instructions. Vous pouvez presque les considrer comme des oprateurs unaires qui modifient le droulement du programme. En fait, vous pouvez mme vous en servir l o cela na aucun sens. On voit parfois cette erreur de codage :

customer_8566

108

Chapitre 4 Instructions et dclarations

open FICHIER, $fichier or warn "Impossible douvrir $fichier : $!\n", next FICHIER; # FAUX

Lintention est bonne, mais next FICHIER est analys comme lun des paramtres de warn, qui est un oprateur de liste. Donc le next sexcute avant que le warn ait la moindre chance dmettre son avertissement. Dans ce cas, cela se corrige facilement en changeant loprateur de liste warn en la fonction warn laide de parenthses bien places :
open FICHIER, $fichier or warn("Impossible douvrir $fichier : $!\n"), next FICHIER; # Correct

Nanmoins, vous trouverez peut-tre ceci plus facile lire :


unless (open FICHIER, $fichier) { warn "Impossible douvrir $fichier: $!\n"; next FICHIER; }

Blocs simples
Un BLOC (tiquet ou non) est en soi lquivalent smantique dune boucle qui sexcute une seule fois. Cest pourquoi vous pouvez utiliser last pour quitter un bloc ou redo pour relancer le bloc.5 Remarquez que ceci nest pas le cas des blocs lintrieur deval {}, de sub {} ou, ce qui en tonne beaucoup, de do {}. En effet, ce ne sont pas des blocs de boucle, car ce ne sont pas des blocs par eux-mmes. Le mot-cl qui les prcde fait deux les termes dexpressions qui se trouvent contenir un bloc de code. Ntant pas des blocs de boucle, ils ne peuvent tre tiquets et les contrles de boucle ne sy appliquent pas. Les contrles de boucle ne sappliquent quaux vritables boucles, tout comme return ne sutilise que dans un sous-programme (ou un eval). Les contrles de boucle ne marchent pas non plus avec un if ou un unless, puisque ce ne sont pas des boucles. Mais vous pouvez toujours ajouter une paire daccolades supplmentaires pour construire un bloc simple qui lui est une boucle :
if (/pattern/) {{ last if /alpha/; last if /beta/; last if /gamma/; # ne fait quelque chose que si on se trouve encore dans le if() }}

Voici comment utiliser un bloc pour faire fonctionner les oprateurs de contrle de boucle avec une construction do {}. Pour faire un next ou un redo sur un do, ajouter un bloc simple lintrieur :
do {{ next if $x == $y; # faire quelque chose ici }} until $x++ > $z;
5. Pour des raisons qui peuvent (ou non) paratre videntes la rf lexion, un next permet galement de sortir dun bloc. Il y a cependant une petite diffrence en ce quun next excute un bloc continue, ce qui nest pas le cas dun last.

customer_8566

Blocs simples
Vous devez tre plus subtil pour last :
{ do { last if $x = $y ** 2; # faire quelque chose ici } while $x++ <= $z; }

109

Et si vous voulez vous servir des deux contrles de boucle disponibles, vous allez devoir distinguer ces blocs avec des tiquettes :
DO_LAST: { do { DO_NEXT: { next DO_NEXT if $x == $y; last DO_LAST if $x = $y ** 2; # faire quelque chose ici } } while $x++ <= $z; }

Mais quand vous en arrivez ce point (ou mme avant), vous feriez mieux dutiliser une simple boucle infinie avec un last la fin :
for (;;) { next if $x == $y; last if $x = $y ** 2; # faire quelque chose ici last unless $x++ <= $z; }

Structures de cas
Contrairement dautres langages de programmation, Perl na pas dinstruction switch ou case officielle. Perl nen a pas besoin, puisquil y a plus dune manire de faire la mme chose. Un bloc simple est particulirement commode pour construire des structures choix multiples. En voici une :
SWITCH: { if (/^abc/) { $abc = 1; last SWITCH; } if (/^def/) { $def = 1; last SWITCH; } if (/^xyz/) { $xyz = 1; last SWITCH; } $rien = 1; }

et une autre :
SWITCH: { /^abc/ /^def/ /^xyz/ $rien = 1; } && do { $abc = 1; last SWITCH; }; && do { $def = 1; last SWITCH; }; && do { $xyz = 1; last SWITCH; };

customer_8566

110

Chapitre 4 Instructions et dclarations

ou, format pour que chaque cas ressorte mieux :


SWITCH: { /^abc/ && do { $abc = 1; last SWITCH; /^def/ }; && do { $def = 1; last SWITCH; /^xyz/ }; && do { $xyz = 1; last SWITCH; }; $rien = 1; }

ou mme, horreur :
if (/^abc/) { $abc = 1 } elsif (/^def/) { $def = 1 } elsif (/^xyz/) { $xyz = 1 } else { $rien = 1 }

Remarquez comme dans cet exemple loprateur last ignore les blocs do, qui ne sont pas des boucles, et sort de la boucle for :
for ($nom_de_variable_tres_long[$i++][$j++]->methode()) { /ce motif/ and do { push @flags, -e; last; }; /celui-l/ and do { push @flags, -h; last; }; /quelque chose dautre/ and do { last; }; die "valeur inconnue: `$_"; }

Vous pouvez trouver bizarre de boucler sur une seule valeur, puisque vous nallez traverser quune fois la boucle. mais il est commode de pouvoir utiliser les capacits dalias de for/foreach pour affecter $_ temporairement et localement. Cela rend les comparaisons multiples la mme valeur beaucoup plus faciles taper et il est donc plus difficile de se tromper. On chappe aux effets secondaires dune nouvelle valuation de lexpression. Et pour rester en rapport avec cette section, cest lun des idiomes les plus rpandus pour implmenter une structure de cas. Pour des cas simples, une cascade doprateurs ?: peut galement marcher. Ici encore, nous utilisons les capacits dalias de for afin de rendre les comparaisons multiples plus lisibles :
for ($couleur_utilisateur) { $value = /rouge/ ? 0xFF0000 : /vert/ ? 0x00FF00 : /bleu/ ? 0x0000FF : 0x000000 ; # noir sil ny a plus despoir }

Dans des situations comme celle-ci, il vaut parfois mieux vous construire un hachage et

customer_8566

goto

111

le classer rapidement pour en tirer la rponse. Contrairement aux conditions en cascade que nous avons vues, un hachage peut crotre un nombre illimit dlments sans prendre plus de temps pour trouver le premier ou le dernier lment. Linconvnient est que vous ne pourrez faire que des comparaisons exactes et pas des recherches de motif. Si vous avez un hachage comme celui-ci :
%couleur = ( azur chartreuse lavande magenta turquoise ); => => => => => 0xF0FFFF, 0x7FFF00, 0xE6E6FA, 0xFF00FF, 0x40E0D0,

alors une recherche exacte de chane tourne vite :


$valeur = $couleur{ lc $couleur_utilisateur } || 0x000000;

Mme les instructions compliques de branchement multiple (o chaque cas implique lexcution de plusieurs instructions diffrentes) peuvent se transformer en une rapide consultation. Vous avez juste besoin de vous servir dun hachage de rfrences des functions. Pour savoir comment les manipuler, voyez la section Hachages de fonctions au chapitre 9, Structures de donnes.

goto
Perl supporte aussi un oprateur goto, mais il nest pas destin aux curs sensibles. Il se prsente sous trois formes : goto LABEL, goto EXPR et goto &NOM. La forme goto LABEL trouve linstruction tiquete avec LABEL et reprend lexcution partir de l. Elle ne peut pas servir sauter lintrieur dune structure qui ncessite une initialisation, comme un sous-programme ou une boucle foreach. Elle ne peut pas non plus servir pour entrer dans une structure qui a t limine lors de loptimisation (voir le chapitre 18, Compilation). Elle peut servir pour aller peu prs nimporte o dans le bloc courant ou dans un bloc dans votre porte dynamique (cest--dire un bloc duquel vous avez t appel). Vous pouvez mme sortir dun sous-programme par goto, mais il vaut en gnral mieux utiliser une autre construction. Lauteur de Perl na jamais ressenti le besoin dutiliser cette forme de goto (en Perl ; en C, cest une autre affaire). La forme goto EXPR nest quune gnralisation de goto LABEL. Elle attend de lexpression quelle produise un nom dtiquette, dont la position doit videmment tre rsolue dynamiquement par linterprteur. Cela permet des goto calculs la FORTRAN, mais nest pas ncessairement recommand si vous cherchez optimiser la maintenabilit du code :
goto(("TOTO", "TITI", "TUTU")[$i]); @loop_label = qw/TOTO TITI TUTU/; goto $loop_label[rand @loop_label]; # en esprant que 0 <= i < 3

# tlportation au hasard

Dans presque tous les cas de ce genre, il est trs, trs largement prfrable dutiliser les mchanismes structurs de contrle de f lux de next, last ou redo au lieu davoir recours un goto. Pour certaines applications, un hachage de rfrences des fonctions

customer_8566

112

Chapitre 4 Instructions et dclarations

ou le mchanisme de capture et de gestion dexceptions sappuyant sur eval et die sont des approches prudentes. La forme goto &NAME est fortement magique et suffisamment loigne du gotousuel pour exempter ceux qui lutilisent de lopprobre qui couvre habituellement les utilisateurs de goto. Elle substitue la routine en cours dexcution un appel au sous-programme nomm. Ce fonctionnement est utilis par les routines AUTOLOAD pour charger un autre sous-programme et faire croire que cest cet autre sous-programme qui tait appel. Aprs le goto, mme caller ne pourra dire que cette routine a t appele en premier. Les modules autouse, AutoLoader et SelfLoader utilisent tous cette stratgie pour dfinir les fonctions lorsquelles sont appeles pour la premire fois puis les lancer sans que personne ne puisse jamais savoir que ces fonctions nont pas toujours t l.

Dclarations globales
Les dclarations de sous-programmes et de formats sont des dclarations globales. O que vous les placiez, ce quelles dclarent est global (cest local au paquetage, mais comme les paquetages sont globaux au programme, tout ce qui est dans un paquetage est visible de partout). Une dclaration globale peut tre place partout o lon peut mettre une instruction, mais na aucun effet sur lexcution de la squence primaire dinstructions, les dclarations prennent effet la compilation. Cela signifie que vous ne pouvez pas faire de dclaration conditionnelle de sous-programmes ou de formats et les cacher du compilateur au moyen dune condition qui ne sera prise en compte qu lexcution. Le compilateur voit les dclarations de sous-programmes et de formats (ainsi que les dclarations use et no) o quelles se produisent. Les dclarations globales sont gnralement mises au dbut ou la fin de votre programme, ou dans un autre fichier. Cependant si vous dclarez des variables porte lexicale (voir la section suivante), vous devrez vous assurer que vos dclarations de formats et de sous-programmes sont porte de vos dclarations de variables si vous esprez accder ces variables prives. Vous avez remarqu que nous sommes sournoisement passs des dclarations aux dfinitions. Sparer la dfinition de la dclaration a parfois un intrt. La seule diffrence syntaxique entre les deux est que la dfinition fournit un BLOC contenant le code excuter, et pas la dclaration. (Une dfinition de sous-programme agit comme une dclaration si aucune dclaration na t vue.) Sparer la dfinition de la dclaration vous permet de mettre la dclaration au dbut du fichier et la dfinition la fin (avec vos variables lexicales joyeusement au milieu) :
sub compte (@); # # my $x; # # $x = compte(3,2,1); # sub compte (@) { @_ } # Le compilateur compte(). Le compilateur lexicale. Le compilateur Le compilateur sait maintenant comment appeler connat maintenant la variable peut valider lappel de fonction. sait maintenant ce que fait compte().

Comme le montre cet exemple, les sous-programmes nont pas besoin dtre dfinis avant que les appels vers eux soient compils (en fait, leur dfinition peut mme tre repousse jusqu leur premire utilisation, si vous utilisez lautochargement), mais la

customer_8566

Dclarations globales

113

dclaration des sous-programmes aide le compilateur de diffrentes manires et vous donne plus de choix dans votre faon de les appeler. La dclaration dun sous-programme lui permet dtre utilis sans parenthses, comme sil sagissait dun oprateur intgr depuis ce point de la compilation. (Nous avons utilis des parenthses pour appeler compte dans lexemple prcdent, mais en fait nous nen avions pas besoin.) Vous pouvez dclarer un sous-programme sans le dfinir juste en disant :
sub monnom; $me = monnom $0 or die "Impossible de trouver mon nom";

Une dclaration simple comme celle-ci dclare la fonction comme un oprateur de liste et non comme un oprateur unaire, aussi faites attention utiliser or et non || dans ce cas. Loprateur || lie trop fortement pour tre utilis aprs des oprateurs de liste, mme si vous pouvez toujours mettre des parenthses autour des arguments de loprateur de liste pour le changer en appel de fonction. Autrement, vous pouvez utiliser le prototype ($) pour transformer la routine en oprateur unaire :
sub monnom ($); $me = monnom $0 || die "Impossible de trouver mon nom";

Cest maintenant analys comme vous vous y attendez, mais vous devriez tout de mme garder lhabitude dutiliser or dans cette situation. Pour en savoir plus sur les prototypes, voir le chapitre 6, Sous-programmes. Vous devez dfinir le sous-programme un moment donn, sinon vous obtiendrez une erreur lexcution indiquant que vous avez appel un sous-programme indfini. moins de dfinir le sous-programme vous-mme, vous pouvez rcuprer les dfinitions depuis dautres endroits de plusieurs faons. Vous pouvez charger les dfinitions depuis dautres fichiers avec une simple instruction require ; ctait la meilleure manire de charger des fichiers en Perl 4, mais elle pose deux problmes. Premirement, lautre fichier va typiquement insrer des noms de sous-programmes dans un paquetage (une table de symboles) de son choix, et non vos propres paquetages. Deuximement, un require se produit lexcution et donc arrive trop tard pour servir de dclaration dans le fichier invoquant le require. Il arrive cependant que vous cherchiez justement retarder le chargement. Une manire plus utile de charger les dclarations et les dfinitions est la dclaration use, qui fait un require du module la compilation (car use compte comme un bloc BEGIN) et vous laisse importer une partie des dclarations du module dans votre propre programme. On peut donc considrer use comme une dclaration globale en ce quelle importe les noms la compilation dans votre propre paquetage (global) comme si vous les aviez dclars vous-mme. Voir la section Tables de symboles, au chapitre 10, Paquetages au sujet du fonctionnement bas niveau de limportation entre paquetages, le chapitre 11, Modules, pour savoir comment configurer les paramtres dimportation et dexportation des modules, et le chapitre 18 pour une explication de BEGIN et de ses cousins CHECK, INIT et END, qui sont aussi des sortes de dclarations globales puisquelles sont traites la compilation et peuvent avoir un effet global.

customer_8566

114

Chapitre 4 Instructions et dclarations

Dclarations avec porte


Comme les dclarations globales, les dclarations porte lexicale ont un effet au moment de la compilation. Contrairement aux dclarations globales, les dclarations porte lexicale ne sappliquent que du point de dclaration jusqu la fin du bloc encadrant le plus interne (le premier bloc, fichier ou eval trouv). Cest pourquoi nous les appelons porte lexicale, bien que le terme porte textuelle soit peut-tre plus exact, puisque la porte lexicale na rien voir avec les lexiques. Mais les informaticiens du monde entier savent ce que signifie porte lexicale , aussi perptuons-nous cet usage ici. Perl supporte aussi les dclarations porte dynamique. Une porte dynamique stend aussi jusqu la fin du bloc encadrant le plus interne, mais encadrant dans ce cas est dfini dynamiquement lexcution, plutt que textuellement la compilation. Pour le dire autrement, les bloc sembotent dynamiquement en invoquant dautres blocs, pas en les incluant. Cet embotement de portes dynamiques peut tre corrl en quelque sorte lembotement des portes lexicales, mais les deux sont en gnral diffrents, particulirement quand des sous-programmes ont t invoqus. Nous avons mentionn que certains aspects de use pouvaient tre considrs comme des dclarations globales, mais dautres aspects de use sont porte lexicale. En particulier, use nimporte pas seulement les symboles, mais implmente galement diverses directives de compilation magiques, connues sous le nom de pragmas (ou si vous prfrez la forme classique, pragmata). La plupart des pragmas sont porte lexicale, y compris le pragma use strict vars qui vous oblige dclarer vos variables avant de vous en servir. Voir plus loin la section Pragmas. Une dclaration package, curieusement, est elle-mme porte lexicale, malgr le fait quun paquetage est une entit globale. Mais une dclaration package se contente de dclarer lidentit du paquetage par dfaut pour le reste du bloc lencadrant. Les noms de variables non dclars, non qualifis6 sont recherchs dans ce paquetage. En un sens, un paquetage nest jamais dclar du tout, mais il se met exister quand vous faites rfrence quelque chose qui appartient ce paquetage. Cest trs Perlien.

Dclarations de variables porte limite


Le reste de ce chapitre parle surtout de lutilisation de variables globales. Ou plutt, parle de la non utilisation de variables globales. Il existe plusieurs dclarations qui vous aident ne pas utiliser de variables globales ou au moins ne pas les utiliser btement. Nous avons dj mentionn la dclaration package, qui a t introduite en Perl il y a bien longtemps pour pouvoir sparer les variables globales en paquetages spars. Cela marche assez bien pour un certain type de variables. Les paquetages sont utiliss par des bibliothques, des modules et des classes pour stocker leurs donnes dinterface (et certaines de leur donnes semi-prives) pour viter les conf lits avec des variables et des

6. Et aussi les noms de sous-programmes, handles de fichiers, handles de rpertoires et formats non qualifis.

customer_8566

Dclarations avec porte

115

fonctions de mme nom dans votre programme principal ou dans dautres modules. Si vous voyez quelquun cire $Quelque::chose,7 il se sert de la variable scalaire $chose du paquetage Quelque. Voir le chapitre 10. Si ctait tout ce quil existait en la matire, les programmes Perl deviendraient de plus en plus difficiles manipuler en grossissant. Heureusement, les trois dclarations de porte de Perl permettent de crer facilement des variables compltement prives (avec my), de donner slectivement laccs aux globales (avec our) et de donner des valeurs temporaires des variables globales (avec local).
my $nose; our $House; local $TV_channel;

Si plusieurs variables sont listes, la liste doit tre place entre parenthses. Pour my et our, les lments ne peuvent tre que de simples scalaires, tableaux ou hachages. Pour local, les contraintes sont quelque peu relches : vous pouvez galement localiser des typeglobs en entier ou de simples lments, ou des tranches de tableaux ou de hachages :
my ($nose, @eyes, %teeth); our ($House, @Autos, %Kids); local (*Spouse, $phone{HOME});

Chacun de ces modificateurs propose une sorte disolation diffrente aux variables quil modifie. Pour simplifier lgrement : our confine les noms une porte, local confine les valeurs une porte, et my confine la fois les noms et les valeurs une porte. Ces constructions peuvent se voir affecter des valeurs, mais diffrent en ce quelles font rellement avec ces valeurs, puisquelles proposent des mcanismes diffrents de stockage des valeurs. Elles sont aussi quelque peu diffrentes quand vous ne leur affectez aucune valeur (comme dans notre exemple ci-dessus) : my et local font dmarrer les variables en question la valeur undef ou () approprie selon le contexte ; our au contraire ne modifie pas la valeur de la variable globale associe. Syntaxiquement, my, our et local sont simplement des modificateurs (comme des adjectifs) agissant sur une lvalue. Quand vous affectez une lvalue modifie, le modificateur ne change pas le fait que la lvalue soit vue comme un scalaire ou une liste. Pour savoir comment le modificateur va fonctionner, faites comme sil ntait pas l. Ces deux constructions fournissent donc un contexte de liste du ct droit :
my ($toto) = <STDIN>; my @tableau = <STDIN>;

Tandis que celle-ci fournit un contexte scalaire :


my $toto = <STDIN>;

Les modificateurs lient plus fort (avec une prcdence suprieure) que loprateur virgule. Lexemple suivant ne dclare quune variable au lieu de deux, car la liste qui suit le modificateur nest pas entre parenthses.

7. Ou larchaque $Quelquechose qui ne devrait probablement pas tre encourag en dehors de la posie Perl.

customer_8566

116
my $toto, $titi = 1;

Chapitre 4 Instructions et dclarations


# FAUX

Cela a le mme effet que :


my $toto; $titi = 1;

Vous serez averti de cette erreur si vous avez demand les avertissements, avec les options de ligne de commande -w ou -W, ou de prfrence avec la dclaration use warnings explique plus loin dans la section Pragmas. En gnral, il vaut mieux dclarer une variable dans la plus petite porte ncessaire. Comme les variables dclares dans des instructions de contrle de f lux ne sont visibles que dans le bloc concern par cette instruction, leur visibilit est rduite. Cela se lit galement mieux en anglais (ce qui a moins dintrt pour ceux qui codent en franais).
sub verifie_stock { for my $machin (our @Inventaire) { print "Jai un $machin en stock aujourdhui.\n"; } }

La forme de dclaration la plus frquente est my, qui dclare des variables porte lexicale dont le nom et la valeur sont stocks dans le bloc-note temporaire de la porte en cours et ne peuvent tre accds de manire globale. La dclaration our est trs proche de cela, et fait entrer un nom lexical dans la porte en cours, tout comme my, mais pointe en ralit vers une variable globale laquelle nimporte qui pourrait accder sil le voulait. En dautres termes, cest une variable globale maquille en variable lexicale. Lautre forme de porte, la porte dynamique, sapplique aux variables dclares avec local, qui malgr lemploi du mot local sont en fait des variables globales qui nont rien voir avec le bloc-notes local.

Variables porte lexicale : my


Pour vous viter le casse-tte du suivi des variables globales, Perl fournit des variables porte lexicale, appeles parfois lexicales pour faire court. Contrairement aux globales, les lexicales vous garantissent le secret de vos variables. Tant que vous ne distribuez pas des rfrences ces variables prives qui permettraient de les tripatouiller indirectement, vous pouvez tre sr que tous les accs possibles ces variables prives sont restreints au code contenu dans une section limite et aisment identifiable de de votre programme. Aprs tout, cest la raison pour laquelle nous avons choisi le mot-cl my. Une squence dinstructions peut contenir des dclarations de variables porte lexicale. De telles dclarations sont habituellement places au dbut de la squence dinstructions, mais ce nest pas une obligation. En plus de dclarer les noms de variables la compilation, les dclarations fonctionnent comme des instructions normales lexcution : chacune dentre elles est labore dans la squence dinstructions comme sil sagissait dune instruction usuelle sans le modificateur :
my $nom = "fred"; my @affaires = ("voiture", "maison", "marteau"); my ($vehicule, $domicile, $outil) = @affaires;

Ces variables lexicales sont totalement caches du monde lextrieur de la porte les

customer_8566

Dclarations avec porte

117

contenant immdiatement. Contrairement aux effets de porte dynamique de local (voir la section suivante), les lexicales sont caches tout sous-programme appel depuis leur porte. Cela reste vrai mme si le mme sous-programme est appel depuis luimme ou ailleurs chaque instance du sous-programme possde son propre blocnotes de variables lexicales. Contrairement aux portes de blocs, les portes de fichiers ne sembotent pas ; il ne se produit pas d inclusion , tout au moins pas textuellement. Si vous chargez du code dun autre fichier avec do, require ou use, le code contenu dans ce fichier ne pourra pas accder vos variables lexicales, tout comme vous ne pourrez pas accder aux siennes. Cependant toute porte lintrieur dun fichier (ou mme le fichier lui-mme) fait laffaire. Il est souvent utile davoir des portes plus larges que la dfinition de sous-programme, car cela vous permet de de partager des variables prives avec un nombre limit de routines. Cest ainsi que vous crez des variables quun programmeur C appellerait statiques :
{ my $etat = 0; sub on { $etat = 1 } sub off { $etat = 0 } sub change { $etat = !$etat } }

Loprateur eval CHAINE fonctionne aussi comme une porte embote, puisque le code lintrieur de leval peut voir les variables lexicales de lappelant (tant que leurs noms ne sont pas cachs par des dclarations identiques dans la porte dfinie par leval luimme). Les routines anonymes peuvent de mme accder nimporte quelle variable lexicale des portes les renfermant ; si elles le font, elles sont alors nommes fermetures.8 En combinant ces deux notions, si un bloc evalue une chane qui cre un sous-programme anonyme, ce sous-programme devient une fermeture avec accs complet aux lexicales de levalet du bloc, mme aprs que le leval et le bloc se sont termins. Voir la section Fermetures au chapitre 8. La variable nouvellement dclare (ou la valeur, dans le cas de local) napparat pas avant la fin de linstruction suivant linstruction contenant la dclaration. Vous pourriez donc copier une variable de cette faon :
my $x = $x;

Cela initialise le nouveau $x interne avec la valeur courante de $x, que la signification de $x soit globale ou lexicale. (Si vous ninitialisez pas la nouvelle variable, elle dmarre avec une valeur vide ou indfinie.) La dclaration dune variable lexicale dun nom donn cache toute variable lexicale du mme nom dclare prcdemment. Elle cache aussi toute variable globale non qualifie du mme nom, mais celle-ci reste toujours accessible en la qualifiant explicitement avec le nom du paquetage la contenant, par exemple $NomPaquetage::nomvar.

8. La vritable dfinition de la fermeture vient dune notion mathmatique concernant la compltude densembles de valeurs et des oprateurs sur ces valeurs.

customer_8566

118

Chapitre 4 Instructions et dclarations

Dclarations de globales porte lexicale : our


La dclaration our est une meilleure manire daccder aux globales, en particulier pour les programmes et les modules tournant avec la dclaration use strict. Cette dclaration est porte lexicale dans le sens o elle ne sapplique que jusqu la fin de la porte courante. Mais contrairement au my porte lexicale ou au local porte dynamique, our nisole rien dans la porte lexicale ou dynamique en cours. En fait, il donne accs une variable globale dans le paquetage en cours, en cachant les lexicales de mme nom qui vous auraient sinon empch de voir cette globale. cet gard, nos variables our fonctionnent tout comme mes variables my. Si vous placez une dclaration our en dehors de tout bloc dlimit par des accolades, elle dure jusqu la fin de lunit de compilation en cours. Souvent, on la place juste au dbut de la dfinition dun sous-programme pour indiquer quil accde une variable globale :
sub verifie_entrepot { our @Inventaire_Courant; my $machin; foreach $machin (@Inventaire_Courant) { print "Jai un $machin en stock aujourdhui.\n"; } }

Comme les variables globales ont une dure de vie plus longue et une visibilit plus large que les variables prives, nous prfrons utiliser pour elles des noms plus longs et plus voyants que pour les variables temporaires. Cette simple habitude, si elle est suivie consciencieusement, peut faire autant que use strict pour dcourager lemploi de variables globales, particulirement chez ceux qui ne sont pas des virtuoses du clavier. Des dclarations our rptes ne sembotent pas clairement. Chaque my embot produit une nouvelle variable, et chaque local embot produit une nouvelle valeur. Mais chaque fois que vous employez our, vous mentionnez la mme variable globale, sans notion dembotement. Quand vous affectez une variable our, les effets de cette affectation persistent une fois hors de porte de la dclaration. Cest parce que our ne cre jamais de valeur ; il donne seulement une forme daccs limit la globale qui, elle, existe pour toujours :
our $NOM_PROGRAMME = "client"; { our $NOM_PROGRAMME = "serveur"; # Le code appel dici voit "serveur". ... } # Le code excut ici voit toujours "serveur".

Comparez ceci avec ce qui arrive avec my ou local, quand la variable ou la valeur redevient visible aprs le bloc :
my $i = 10; { my $i = 99; ... }

customer_8566

Dclarations avec porte


# Le code compil ici voit la variable externe. local $NOM_PROGRAMME = "client"; { local $NOM_PROGRAMME = "serveur"; # Le code appel dici voit "serveur". ... } # Le code excut ici voit "client" de nouveau.

119

Faire une dclaration our na en gnral de sens quune seule fois, probablement tout au dbut de votre programme ou module ou, plus rarement, quand vous prfixez le our de son propre local :
{ local our @Inventaire_Courant = qw(bananes); verifie_entrepot(); # non, nous navons pas de bananes :-) }

Variables porte dynamique : local


Lutilisation de loprateur local sur une variable globale lui donne une valeur temporaire chaque fois que local est excut, mais naffecte pas la visibilit globale de cette variable. Quand le programme atteint la fin de cette porte dynamique, cette valeur temporaire est jete et la valeur prcdente restaure. Mais pendant que ce bloc sexcute, cest toujours une variable globale qui se trouve juste contenir une valeur temporaire. Si vous appelez une autre fonction pendant que votre variable globale contient la valeur temporaire et que cette fonction accde cette variable globale, elle verra la valeur temporaire et pas la valeur initiale. En dautres termes, cette autre fonction est dans votre porte dynamique, mme si elle nest probablement pas dans votre porte lexicale.9 Si vous avez un local qui ressemble ceci :
{ local $var = $nouveau; ma_fonction(); ... }

vous pouvez le voir entirement en termes daffectations lexcution :


{ $ancien = $var; local $var = $nouveau; ma_fonction(); ... }

9. Cest pourquoi on appelle parfois la porte lexicale une porte statique : pour contraster avec la porte dynamique et insister sur le fait quelle est dtermine la compilation. Ne confondez pas cette utilisation avec lemploi du mot-cl static en C ou en C++. Le terme est trs charg, cest pourquoi nous lvitons.

customer_8566

120
continue { $var = $ancien; }

Chapitre 4 Instructions et dclarations

La diffrence est quavec local, la valeur est restaure quelle que soit la manire dont vous quittez le bloc, mme si vous sortez de cette porte en faisant un returnprmatur. La variable est toujours la mme variable globale, mais la valeur qui sy trouve dpend de la porte do la fonction a t appele. Cest pourquoi on lappelle porte dynamique : parce quelle change au cours de lexcution. Comme avec my, vous pouvez initialiser un local avec une copie de la mme variable globale. Toutes les modifications faites cette variable pendant lexcution du sous-programme (et de tous les autres appels depuis celui-ci, qui peuvent bien sr voir cette globale porte dynamique) seront perdues quand la routine se terminera. Vous devriez srement commenter ce que vous faites :
# ATTENTION : les modifications sont temporaires # pour cette porte dynamique local $Ma_Globale = $Ma_Globale;

Une variable globale est donc toujours visible dans lintgralit de votre programme, quelle ait t dclare avec our, quelle ait t cre la vole ou quelle contienne une valeur locale destine tre jete une fois hors de porte. Ce nest pas compliqu pour de petits programmes. Mais vous allez rapidement ne plus retrouver o sont utilises ces variables globales dans de plus gros programmes. Si vous voulez, vous pouvez interdire lutilisation accidentelle de variables globales laide du pragma use strict vars, dcrit la section suivante. Bien que my et local confrent toutes deux un certain niveau de protection, vous devriez largement prfrer my local. Cependant, vous devrez de temps en temps utiliser localpour pouvoir modifier temporairement la valeur dune variable globale existante, comme celles dcrites au chapitre 28, Noms spciaux. Seuls les identificateurs alphanumriques peuvent avoir une porte lexicale et beaucoup de ces variables spciales ne sont pas strictement alphanumriques. Vous aurez aussi besoin de local pour faire des modifications temporaires la table des symboles dun paquetage, comme cest dcrit dans la section Tables de symboles au chapitre 10. Enfin, vous pouvez aussi utiliser local sur un lment isol ou tout une tranche dun tableau ou dun hachage. Cela fonctionne mme si le tableau ou le hachage est en fait une variable lexicale, en rajoutant la couche de comportement de porte dynamique de local au dessus de ces variables lexicales. Nous ne parlerons pas plus de la smantique de local ici. Pour plus dinformations, voir local au chapitre 29.

Pragmas
De nombreux langages de programmation vous permettent de donner des directives au compilateur. En Perl ces directives sont passes au compilateur par la dclaration use. Certains de ces pragmas sont :
use use use use use warnings; strict; integer; bytes; constant pi => ( 4 * atan2(1,1) );

customer_8566

Pragmas

121

Les pragmas de Perl sont dcrits au chapitre 31, Modules de pragmas, mais nous allons tout de suite parler des plus utiles par rapport au contenu de ce chapitre. Bien que certains soient des dclarations qui affectent les variables globales ou le paquetage en cours, la plupart des pragmas sont des dclarations porte lexicale dont les effets ne durent que jusqu la fin du bloc, du fichier ou de leval qui les contient (en fonction du premier qui se prsente). Un pragma porte lexicale peut tre annul dans une porte incluse avec une dclaration no, qui fonctionne exactement comme use, mais lenvers.

Contrle des avertissements


Pour vous montrer comment tout cela fonctionne, nous allons manipuler le pragma warnings pour dire Perl sil doit nous avertir de pratiques discutables :
use warnings; # Permet les avertissements dici la fin de fichier ... { no warnings; # Dsactive les avertissements dans le bloc ... } # Les avertissements sont automatiquement ractivs ici

Une fois les avertissements demands, Perl vous signalera les variables utilises une seule fois, les dclarations qui cachent dautres dclarations dans la mme porte, les conversions incorrectes de chanes en nombres, lutilisation de valeurs indfinies comme des nombres ou des chanes normaux, les tentatives dcriture sur des fichiers ouverts en lecture seule (ou pas ouverts du tout) et bien dautres problmes potentiels lists au chapitre 33, Messages de diagnostic. La mthode de contrle des avertissements recommande est lutilisation de use warnings. Les anciens programmes ne pouvaient utiliser que loption de ligne de commande -w ou bien modifier la variable globale $^W :
{ local $^W = 0; ... }

Il vaut beaucoup mieux utiliser les pragmas use warnings et no warnings. Un pragma vaut mieux car il se produit la compilation, parce que cest une dclaration lexicale et ne peut donc pas affecter du code quil ntait pas cens affecter, et (bien que nous ne vous layons pas montr dans ces simples exemples) quil permet un contrle plus fin sur plusieurs ensembles de classes. Pour en savoir plus sur le pragma warnings, y compris comment transformer des avertissements qui font juste un peu de bruit en erreurs fatales et comment supplanter le pragma pour activer les avertissements mme si le module ne veut pas, voir use warnings au chapitre 31.

Contrle de lutilisation des globales


Une autre dclaration communment rencontre est le pragma use strict, qui a plusieurs fonctions dont celle de contrler lutilisation des variables globales. Normalement, Perl vous laisse crer de nouvelles variables (ou trop souvent, craser danciennes

customer_8566

122

Chapitre 4 Instructions et dclarations

variables) simplement en les citant. Aucune dclaration de variable nest ncessaire (par dfaut). Sachant que lutilisation dbride de globales peut rendre les gros programmes ou les gros modules pnibles maintenir, vous pourrez vouloir dcourager leur utilisation accidentelle. Pour prvenir de tels accidents, vous pouvez crire :
use strict vars;

Cela signifie que toute variable mentionne partir dici jusqu la fin de la porte courante doit faire rfrence soit une variable lexicale, soit une variable globale explicitement autorise. Si ce nest pas le cas, une erreur de compilation se produit. Une variable globale est explicitement autorise si lune de ces propositions est vraie : Cest lune des variables spciales de Perl (voir le chapitre 28). Elle est compltement dfinie avec son nom de paquetage (voir le chapitre 10). Elle a t importe dans le paquetage courant (voir le chapitre 11). Elle se fait passer pour une variable lexicale laide dune dclaration our. (Cest la raison principale pour laquelle nous avons ajout la dclaration our Perl.)

Bien sr, il reste toujours la cinquime possibilit. Si le pragma est trop exigeant, annulez-le simplement dans un bloc intreur avec :
no strict vars

Avec ce pragma vous pouvez aussi demander une vrification stricte des drfrencements symboliques et de lutilisation des mot simples. Habituellement, les gens tapent juste :
use strict;

pour mettre en uvre les trois restrictions. Pour plus dinformations, voir lentre use strict, au chapitre 31.

customer_8566

Recherche de motif

Le support intgr de Perl pour la recherche de motif vous permet de rechercher dans de grandes quantits de donnes simplement et efficacement. Que vous fassiez tourner un norme site portail commercial balayant tous les groupes de news existants la recherche de potins intressants, un organisme public occup comprendre la dmographie humaine (ou le gnome humain), une institution scolaire dsireuse de mettre des informations dynamiques sur votre site web, Perl est loutil quil vous faut ; dune part cause de ses liens avec les bases de donnes, mais surtout cause de ses capacits de recherche de motif. Si vous prenez le mot texte dans son sens le plus large, prs de 90% de tout ce vous faites est du traitement de texte. Cest vraiment ce pour quoi Perl est fait et a toujours t fait en fait, cela fait mme partie de son nom : Practical Extraction and Report Language. Les motifs de Perl fournissent de puissants moyens pour ratisser des montagnes de donnes brutes et en extraire de linformation utile. Vous spcifiez un motif en crant une expression rationnelle (ou expression rgulire1 ou regex) et le moteur dexpressions rgulires de Perl (le Moteur , pour le reste de ce chapitre) prend cette expression et dtermine si (et comment) le motif correspond vos donnes. Alors que la plupart de vos donnes seront probablement des chanes de caractres, rien ne vous empche de vous servir des regex pour rechercher et remplacer nimporte quelle squence de bits, y compris ce que vous auriez cru tre des donnes binaires . Pour Perl, les octets sont juste des caractres qui ont une valeur ordinale infrieure 256. (Pour en savoir plus sur ce sujet, voir le chapitre 15, Unicode.) Si vous connaissiez dj les expressions rgulires avec dautres outils, nous devons vous prvenir que celles de Perl sont un peu diffrentes. Premirement elles ne sont pas vraiment rgulires (ou rationnelles ) au sens thorique du mot, ce qui signifie quelles peuvent faire beaucoup plus que les expressions rationnelles quon apprend en

1. NdT : Regular expression a deux traductions en franais : expression rationnelle , qui est un terme plutt acadmique, et expression rgulire , qui ressemble fort au terme utilis par les anglophones. Dans ce livre nous utiliserons plutt le second (et son abrviation anglaise regex ), mais il est possible quun peu de rationalit se glisse ici ou l...

customer_8566

124

Chapitre 5 Recherche de motif

cours dinformatique. Deuximement, elles sont tellement utilises en Perl, quelles ont leurs propres variables spciales et leur propres conventions de citation qui sont troitement intgres au langage, pas vaguement lies comme nimporte quelle autre librairie. Les nouveaux programmeurs Perl cherchent souvent en vain des fonctions comme :
match( $chaine, $motif ); subst( $chaine, $motif, $remplacement );

Mais la recherche et la substitution sont deux tches si fondamentales en Perl quelle mritent leurs propres oprateurs dune lettre : m/MOTIF/ et s/MOTIF/REMPLACEMENT/. Ils sont non seulement brefs syntaxiquement, mais ils sont aussi analyss comme des chanes entre apostrophes doubles plutt que comme des oprateurs ordinaires ; toutefois, ils fonctionnent comme des oprateurs, cest pourquoi nous les appelons ainsi. Tout au long de ce chapitre, vous les verrez utiliss pour comparer des motifs des chanes. Si une partie de la chane correspond au motif, nous disons que la correspondance (ou recherche) est russie. Il y a plein de trucs sympas faire avec des correspondances russies. En particulier, si vous utilisez s///, une correspondance russie provoque le remplacement de la partie correspondante dans la chane parce que vous avez spcifi comme REMPLACEMENT. Tout ce chapitre concerne la construction et lutilisation de motifs. Les expressions rgulires de Perl sont puissantes, et concentrent beaucoup de sens en peu de volume. Elles peuvent donc vous intimider si vous essayez de saisir le sens dun long motif dun seul coup. Mais si vous pouvez le dcouper en petits morceaux et que vous savez comment le Moteur interprte ces morceaux, vous pouvez comprendre nimporte quelle expression rgulire. Il nest pas rare de voir une centaine de lignes de code C ou Java exprimes en une expression rgulire dune ligne en Perl. Cette expression rgulire est peut-tre un peu plus difficile comprendre que nimporte quelle ligne du gros programme ; dun autre ct, la regex sera beaucoup plus facile comprendre que le plus long programme pris dans son ensemble. Il vous faut juste garder tout cela en perspective.

Bestiaire des expressions rgulires


Avant de nous plonger dans les rgles dinterprtation des expressions rgulires, regardons quoi certains motifs ressemblent. La plupart des caractres dune expression rgulire se correspondent eux-mmes. Si vous enchanez plusieurs caractres la suite, ils se correspondent dans lordre, comme on sy attend. Donc si vous crivez la recherche suivante :
/Frodon/

vous pouvez tre sr que le motif ne correspondra que si la chane contient quelque part la sous-chane Frodon . (Une sous-chane est juste un morceau de chane.) La correspondance peut se faire nimporte o dans la chane, tant que ces six caractres apparaissent quelque part, lun aprs lautre et dans cet ordre. Dautres caractres ne se correspondent pas eux-mmes, mais se comportent dune trange manire. Nous les appelons mtacaractres. (Tous les mtacaractres sont des coquins, mais certains sont si mauvais, quils conduisent les caractres voisins se comporter aussi mal queux.)

customer_8566

Bestiaire des expressions rgulires


Voici les sclrats :
\ | ( ) [ { ^ $ * + ? .

125

Les mtacaractres sont en fait trs utiles et ont une signification spciale lintrieur des motifs. Nous vous expliquerons toutes ces significations au fur et mesure de ce chapitre. Mais sachez dabord que vous pourrez toujours dtecter nimporte lequel de ces douze caractres en le faisant prcder dun antislash. Par exemple, comme lantislash est un mtacaractre, pour dtecter un antislash, vous devrez lantislasher : \\. Vous voyez, lantislash est le genre de caractre qui pousse les autres caractres mal se conduire. Finalement, quand vous faites mal se conduire un mtacaractre indisciplin, il se conduit bien un peu comme une double ngation. Antislasher un caractre pour le prendre littralement marche, mais seulement sur les caractres de ponctuation ; antislasher un caractre alphanumrique (qui habituellement se comporte correctement) fait le contraire : cela transforme le caractre littral en quelque chose de spcial. Ds que vous voyez une telle squence de deux caractres :
\b \D \t \3 \s

vous saurez que la squence est un mtasymbole qui correspond quelque chose dtrange. Par exemple, \b correspond une limite de mot, tandis que \t correspond un caractre de tabulation ordinaire. Remarquez quune tabulation fait un caractre de large, alors que la limite de mot a une largeur de zro caractre, puisque cest un point entre deux caractres. Nous appellerons donc \b une assertion de largeur nulle. Cependant, \t et \b se ressemblent en ce quils supposent quelque chose sur une caractristique de la chane. chaque fois que vous faites une assertion au sujet de quelque chose dans une expression rgulire, vous demandez ce que quelque chose en particulier soit vrai pour que le motif corresponde. La plupart des lments dune expression rgulire sont des assertions, y compris les caractres ordinaires qui veulent se correspondre eux-mmes. Pour tre plus prcis, ils supposent aussi que le prochain lment sera en correspondance un caractre plus loin dans la chane, cest pourquoi nous disons que la tabulation est de largeur un caractre . Certaines assertions (comme \t) consomment un peu de la chane au fur et mesure quils entrent en correspondance et dautres (comme \b) non. Mais nous rservons en gnral le terme assertion pour les assertions de largeur nulle. Pour viter les confusions, nous appellerons celles qui ont une largeur des atomes. (Si vous tes physicien, vous pouvez voir les atomes de largeur non nulle comme des particules massives, la diffrence des assertions, qui nont pas de masse comme les photons.) Vous allez voir aussi des mtacaractres qui ne sont pas des assertions ; ils sont plutt structurels (tout comme les accolades et les points-virgules dfinissent la structure du code Perl, mais ne font pas vraiment quelque chose). Ces mtacaractres structurels sont dune certaine manire les plus importants, car le premier pas dans votre apprentissage de la lecture des expressions rgulires est dhabituer votre regard reconnatre les mtacaractres structurels. Une fois que vous avez appris cela, lire des expressions rgulires est un jeu denfant2.

2. Denfant prcoce parfois, mais pas besoin dtre un futur Prix Nobel.

customer_8566

126

Chapitre 5 Recherche de motif

Lun de ces mtacaractres structurels est la barre verticale, qui indique un choix :
/Frodon|Pippin|Merry|Sam/

Cela signifie que nimporte laquelle de ces chanes peut correspondre. Ceci est trait dans la section Alternative plus loin dans ce chapitre. Dans la partie Capture et regroupement, nous vous montrerons comment utiliser les parenthses autour de morceaux de votre motif pour faire des regroupements :
/(Frodon|Drogon|Bilbon) Sacquet/

ou mme :
/(Frod|Drog|Bilb)on Sacquet/

Une autre chose que vous verrez sont les quantificateurs, qui disent combien de fois ce qui prcde doit tre trouv la queue-leu-leu. Les quantificateurs ressemblent ceci :
* + ? *? {3} {2,5}

Vous ne les verrez cependant jamais isolment. Les quantificateurs nont de sens quattachs des atomes cest--dire des assertions qui ont une largeur non nulle.3 Les quantificateurs sattachent latome prcdent seulement. Ce qui signifie en termes clairs quils ne quantifient normalement quun seul caractre. Si vous voulez une correspondance avec trois copies de bar la suite, vous devez regrouper les caractres individuels de bar dans une seule molcule avec des parenthses, comme ceci :
/(bar){3}/

Cela correspondra avec barbarbar . Si vous aviez crit /bar{3}/, cela aurait correspondu avec barrr qui aurait sonn cossais mais naurait pas constitu un barbarbarisme. Pour en savoir plus sur les quantificateurs, voir plus loin la section Quantificateurs. Maintenant que vous avez rencontr quelques-unes des bestioles qui habitent les expressions rgulires, vous tes srement impatient de commencer les apprivoiser. Cependant, avant que nous ne discutions srieusement des expressions rgulires, nous allons un petit peu rebrousser chemin et parler des oprateurs qui utilisent les expressions rgulires. (Et si vous apercevez quelques nouvelles bestioles regex en chemin, noubliez pas le guide.)

Oprateurs de recherche de motifs


Zoologiquement parlant, les oprateurs de recherche de motif de Perl fonctionnent comme une sorte de cage expressions rgulires : ils les empchent de sortir. Si nous laissions les regex errer en libert dans le langage, Perl serait une jungle complte. Le monde a besoin de jungles bien sr aprs tout, ce sont les moteurs de la diversit biologique mais les jungles devraient rester o elles sont. De mme, bien qutant le

3. Les quantificateurs sont un peu comme les modificateurs dinstructions du chapitre 4, Instructions et dclarations, qui ne peuvent sattacher qu une instruction simple. Attacher un quantificateur une assertion de largeur nulle, cela reviendrait essayer dattacher un modificateur while une dclaration ces deux actions tant aussi senses que de demander un chimiste une livre de photons. Les chimistes ne travaillent quavec des atomes.

customer_8566

Oprateurs de recherche de motifs

127

moteur de la diversit combinatoire, les expressions rgulires devraient rester lintrieur des oprateurs de recherche de motifs o est leur place. Cest une jungle, l-dedans. Comme si les expressions rgulires ntaient pas assez puissantes, les oprateurs m// et s/// leur donnent le pouvoir (lui aussi confin) de linterpolation entre apostrophes doubles. Comme les motifs sont analyss comme des chanes entre apostrophes doubles, toutes les conventions usuelles des apostrophes doubles fonctionnent, y compris linterpolation de variables ( moins que vous nutilisiez les apostrophes simples comme dlimiteurs) et les caractres spciaux indiqus par des squences dchappement avec antislash. (Voir Caractres spcifiques plus loin dans ce chapitre.) Celles-ci sont appliques avant que la chane soit interprte comme une expression rgulire. (Cest lun des quelques endroits de Perl o une chane subit un traitement en plusieurs passes.) La premire passe nest pas une interprtation entre apostrophes doubles tout fait normale, en ce quelle sait ce quelle doit interpoler et ce quelle doit passer lanalyseur dexpressions rgulires. Donc par exemple, tout $ immdiatement suivi dune barre verticale, dune parenthse fermante ou de la fin de chane ne sera pas trait comme une interpolation de variable, mais comme la traditionnelle assertion de regex qui signifie fin-de-ligne. Donc si vous crivez :
$toto = "titi"; /$toto$/;

la passe dinterpolation entre apostrophes doubles sait que ces deux $ fonctionnent diffremment. Elle fait linterpolation de $toto puis envoie ceci lanalyseur dexpressions rgulires :
/titi$/;

Une autre consquence de cette analyse en deux passes est que le tokener ordinaire de Perl trouve la fin de lexpression rgulire en premier, tout comme sil cherchait le dlimiteur final dune chane ordinaire. Cest seulement aprs avoir trouv la fin de la chane (et fait les interpolations de variables) que le motif est trait comme une expression rgulire. Entre autres choses, cela signifie que vous ne pouvez pas cacher le dlimiteur final dun motif lintrieur dun lment de regex (comme une classe de caractres ou un commentaire de regex, que nous navons pas encore couvert). Perl verra le dlimiteur o quil se trouve et terminera le motif cet endroit. Vous devez galement savoir que linterpolation de variables dans un motif ralentit lanalyseur de motif, car il se sent oblig de vrifier si la variable a t modifie, au cas o il aurait recompiler le motif (ce qui le ralentira encore plus). Voir la section Interpolation de variables plus loin dans ce chapitre. Loprateur de translittration tr/// ne fait pas dinterpolation de variables ; il nutilise mme pas dexpressions rgulires ! (En fait, il ne devrait probablement pas faire partie de ce chapitre, mais nous navons pas trouv de meilleur endroit o le mettre.) Il a cependant une caractristique commune avec m// et s/// : il se lie aux variables grce aux oprateurs =~ et !~. Les oprateurs =~ et !~, dcrits au chapitre 3, Oprateurs unaires et binaires, lient lexpression scalaire leur gauche lun des trois oprateurs de type apostrophes (ou guillemets) leur droite : m// pour rechercher un motif, s/// pour substituer une chane une sous-chane correspondant au motif et tr/// (ou son synonyme, y///) pour traduire un ensemble de caractres en un autre ensemble de caractres. (Vous pouvez crire // pour m// sans le m si les slash sont utiliss comme dlimiteurs.) Si la partie droite

customer_8566

128

Chapitre 5 Recherche de motif

de =~ ou !~ nest aucune de ces trois l, elle compte toujours comme une opration m/// de recherche, mais il ny a pas la place de mettre un seul modificateur final (voir plus loin la section Modificateurs de motif) et vous devrez grer vos propres apostrophes :
print "correspond" if $unechaine =~ $unmotif;

Vraiment, il ny a pas de raison de ne pas lcrire explicitement :


print "correspond" if $unechaine =~ m/$unmotif/;

Quand ils sont utiliss pour une recherche de correspondance, =~ et !~ se prononcent parfois respectivement correspond et ne correspond pas (bien que contient et ne contient pas puissent tre plus clair). Hormis les oprateurs m// et s///, les expressions rgulires apparaissent deux autres endroits dans Perl. Le premier argument de la fonction splitest une forme spciale de loprateur de correspondance spcifiant les parties ne pas retourner quand on dcoupe une chane en plusieurs sous-chanes. Voir la description de split et les exemples au chapitre 29, Fonctions. Loprateur qr// (quote regex) spcifie galement un motif laide dune regex, mais il nessaie pas de faire une correspondance avec quoi que ce soit (contrairement m//, qui le fait). Au lieu de cela, il retourne une forme compile de la regex pour une utilisation ultrieure. Voir Interpolation de variables pour plus dinformations. Vous appliquez lun des oprateurs m//, s/// ou tr/// une chane particulire avec loprateur de lien =~ (qui nest pas un vritable oprateur, mais plutt un indicateur du sujet de lopration). Voici quelques exemples :
$meuledefoin =~ m/aiguille/ $meuledefoin =~ /aiguille/ # cherche un motif simple # pareil

$italiano =~ s/beurre/huile dolive/ # une substitution bonne pour la sant $rotate13 =~ tr/a-zA-Z/n-za-mN-ZA-M/ # encryption simple ( casser)

Sans oprateur de lien, cest $_ qui est implicitement utilis comme "sujet" :
/nouvelles vies/ and # explore $_ et (si on trouve quelque chose) /autres civilisations/ # au mpris du danger, explore encore $_ s/sucre/aspartame/ tr/ATCG/TAGC/ # substitue un substitut dans $_ # complmente le brin dADN dans $_

Comme s/// et tr/// modifient le scalaire auquel ils sont appliqus, vous ne pouvez les utiliser quavec des lvalues valides :
"onshore" =~ s/on/off/; # FAUX : erreur la compilation

En revanche, m// fonctionne sur le rsultat de nimporte quelle expression scalaire :


if ((lc $chapeau_magique->contenu->comme_chaine) =~ /lapin/) { print "Euh, quoi dneuf, docteur ?\n"; } else { print "Ce tour ne marche jamais !\n"; }

Mais vous devez tre un petit peu prudent, car =~ et !~ ont une prcdence assez leve (dans notre exemple prcdent les parenthses sont ncessaires autour du terme de gau-

customer_8566

Oprateurs de recherche de motifs

129

che).4 Loprateur de lien !~ fonctionne comme =~, mais inverse la logique du rsultat de lopration :
if ($romance !~ /parole/) { print qq/"$romance" semble tre une romance sans parole.\n/; }

Comme m//, s/// sont des oprateurs apostrophes (ou guillemets), vous pouvez choisir vos dlimiteurs. Ils fonctionnent de la mme faon que les oprateurs de citation q//, qq//, qr//, et qw// (voir la section Choisissez vos dlimiteurs, chapitre 2, Composants de Perl).
$path =~ s#/tmp#/var/tmp/scratch#; if ($dir =~ m[/bin]) { print "Pas de rpertoires de binaires, sil vous plait.\n"; }

Quand vous utilisez des dlimiteurs apparis avec s/// ou tr///, si la premire partie utilise lune des quatre paires usuelles dencadrement (parenthses, crochets, accolades ou chevrons), vous pouvez choisir des dlimiteurs diffrents des premiers pour la seconde partie :
s(oeuf)<larve>; s{larve}{chrysalide}; s[chrysalide]/imago/;

Les blancs sont autoriss avant les dlimiteurs ouvrants :


s (oeuf) <larve>; s {larve} {chrysalide}; s [chrysalide] /imago/;

chaque fois quun motif correspond avec succs (y compris les motifs de substitution), il affecte aux variables $`, $& et $ le texte gauche de la correspondance, le texte correspondant et le texte droite de la correspondance. Cest utile pour sparer les chanes en leurs lments :
"pain print print print print au chocolat" =~ /au/; "Trouv : <$`> $& <$>\n"; "Gauche : <$`>\n"; "Correspondance : <$&>\n"; "Droite : <$>\n"; # Trouv : <pain > au < chocolat> # Gauche : <pain > # Correspondance : <au> # Droite : < chocolat>

Pour plus defficacit et de contrle, utilisez des parenthses pour capturer les portions spcifiques que vous voulez conserver. Chaque paire de parenthses capture la souschane correspondant au sous-motif entre parenthses. Les paires de parenthses sont numrotes de gauche droite par la position de chaque parenthse ouvrante. Une fois la correspondance tablie, les sous-chanes correspondantes sont disponibles dans les variables numrotes $1, $2, $3 et ainsi de suite :5

4. Sans les parenthses, le lc de moindre prcdence se serait appliqu toute la correspondance de motif plutt quau seul appel de mthode sur le chapeau de magicien. 5. Pas $0 cependant, qui contient le nom de votre programme.

customer_8566

130
$_ = "Bilbon Sacquet est n le 22 Septembre"; /(.*) est n le (.*)/; print "Personne: $1\n"; print "Date: $2\n";

Chapitre 5 Recherche de motif

$`, $&, $ et les variables numrotes sont implicitement localises dans la porte dynamique les contenant. Elles durent jusqu la prochaine recherche russie ou jusqu la fin de la porte courante, selon ce qui arrive en premier. Nous en reparlerons plus tard, dans un cadre diffrent. Une fois que Perl a dtect que vous aurez besoin de lune des variables $`, $& ou $ quelque part dans votre programme, il les fournira pour chaque correspondance. Cela va ralentir un peu votre programme. Comme Perl utilise un mcanisme semblable pour produire $1, $2et les autres, pour chaque motif contenant des parenthses de capture vous payez un peu en performance. (Voir Regroupement pour viter le cot de la capture en conservant la possibilit de regrouper.) Si vous nutilisez jamais $`, $& ou $, alors les motifs sans parenthses ne seront pas pnaliss. Si vous pouvez, il vaut donc mieux en gnral viter dutiliser $`, $& et $, en particulier dans les modules de bibliothque. Mais si vous devez les utiliser au moins une fois (et certains algorithmes apprcient vraiment leur commodit), alors utilisez-les autant que vous voulez, car vous avez dj pay le prix. $& nest pas aussi coteux que les deux autres dans les versions rcentes de Perl.

Modificateurs de motif
Nous allons discuter des diffrents oprateurs de recherche de motif dans un moment, mais nous aimerions dabord parler dun de leur points communs tous : les modificateurs. Vous pouvez placer un ou plusieurs modificateurs dune lettre immdiatement aprs le dlimiteur final, dans nimporte quel ordre. Par souci de clart, les modificateurs sont souvent appels le modificateur /o et prononcs le modificateur slash oh , mme si le modificateur final peut tre autre chose quun slash. (Certaines personnes disent drapeau ou option pour modificateur . Cest bien aussi.) Certains modificateurs changent le comportement dun seul oprateur, aussi les dcrirons-nous en dtail plus loin. Dautres changent la faon dont la regex est interprte. Les oprateurs m//, s/// et qr//6 acceptent tous les modificateurs suivants aprs le dlimiteur final :
Modificateur /i /s /m /x /o Signification Ignore les distinctions de casse des caractres (insensible la casse). Fait correspondre . avec le saut de ligne et ignore la variable obsolte $*. Fait correspondre ^ et $ ct dun \n intrieur. Ignore (la plupart) des blancs et autorise les commentaires dans le motif. Ne compile le motif quune seule fois.

6. Loprateur tr/// ne prend pas de regex, aussi ces modificateurs ne sy appliquent pas.

customer_8566

Oprateurs de recherche de motifs

131

Le modificateur /i indique de faire la correspondance la fois en majuscules et en minuscules (et en casse de titre en Unicode). Ainsi /perl/i correspondrait avec SUPERLATIF ou Perlimpinpin (entre autres choses). Le pragma use locale peut aussi avoir une inf luence sur ce qui est considr comme quivalent. (Cela peut avoir une mauvaise inf luence sur les chanes contenant de lUnicode.) Les modificateurs /s et /m nimpliquent rien de coquin. Ils affectent la manire dont Perl traite les correspondances avec des chanes contenant des sauts de ligne. Ils nindiquent pas si votre chane contient rellement des sauts de ligne ; mais plutt si Perl doit supposer que votre chane contient une seule ligne (/s) ou plusieurs lignes (/m), car certains mtacaractres fonctionnent diffremment selon quils sont censs se comporter dune manire oriente ligne ou non. Dordinaire le mtacaractre . correspond tout caractre sauf un saut de ligne, parce que sa signification traditionnelle est de correspondre aux caractres lintrieur dune ligne. Avec un /s cependant, le mtacaractre . peut aussi correspondre des sauts de ligne, car vous avez dit Perl dignorer le fait que la chane contient plusieurs sauts de ligne. (Le modificateur /s fait aussi ignorer Perl la variable obsolte $*, dont nous esprons que vous lignoriez aussi.) Le modificateur /m, de son ct, change linterprtation des mtacaractres ^ et $ en leur permettant de correspondre ct de sauts de lignes lintrieur de la chane au lieu de considrer seulement les extrmits de la chane. Voir les exemples dans la section Positions plus loin dans ce chapitre. Le modificateur /o contrle la recompilation des motifs. Sauf si les dlimiteurs sont des apostrophes simples, (mMOTIF, sMOTIFREMPLACEMENT, ou qrMOTIF), toute variable dans le motif sera interpole (et pourra provoquer la recompilation du motif) chaque fois que loprateur de motif sera valu. Si vous voulez quun motif ne soit compil quune fois et une seule, servez-vous du modificateur /o. Cela empche une recompilation coteuse lexcution ; cela peut servir quand la valeur interpole ne change pas au cours de lexcution. Cependant, utiliser /o revient faire la promesse de ne pas modifier les variables dans le motif. Si vous les modifiez, Perl ne sen rendra mme pas compte. Pour avoir un meilleur contrle de la recompilation des motifs, utilisez loprateur de citation de regex qr//. Pour plus de dtails, voir la section Interpolation de variables plus loin dans ce chapitre. Le modificateur /x est lexpressif : il vous permet dexploiter les blancs et les commentaires explicatifs pour exalter la lisibilit de votre motif, ou mme lui permettre dexplorer au-del des limites des lignes. Euh, cest--dire que /x modifie la signification des blancs (et du caractre #) : au lieu de les laisser se correspondre eux-mmes comme le font les caractres ordinaires, il les transforme en mtacaractres qui, trangement, se comportent comme les blancs (et les caractres de commentaires) devraient le faire. /x permet donc lutilisation despaces, de tabulations et de sauts de lignes pour le formatage, exactement comme le code Perl habituel. Il permet galement lutilisation du caractre #, qui nest normalement pas un caractre spcial dans un motif, pour introduire un commentaire qui stend jusquau bout de la ligne en cours lintrieur de la chane de motif.7 Si vous voulez dtecter un vritable espace (ou le caractre #), alors vous devrez le mettre dans une classe de caractres, le protger avec un antislash ou bien lencoder en octal ou en hexadcimal. (Mais les blancs sont normalement dtects avec une squence \s* ou \s+, donc la situation ne se rencontre pas souvent en pratique.)

customer_8566

132

Chapitre 5 Recherche de motif

elles toutes, ces fonctionnalits font beaucoup pour rendre les expressions rgulires plus proches dun langage lisible. Dans lesprit de TMTOWTDI, il existe donc plus dune manire dcrire une mme expression rationnelle. En fait, il y a plus de deux manires :
m/\w+:(\s+\w+)\s*\d+/; chiffres. m/\w+: (\s+ \w+) \s* \d+/x; chiffres. m{ \w+: ( \s+ \w+ ) \s* \d+ }x; # # # # # # # Dtecte un mot et un deux-points. (dbut de groupe) Dtecte un ou plusieurs blancs. Dtecte un autre mot. (fin de groupe) Dtecte zro ou plusieurs blancs. Dtecte des chiffres. # Mot, deux-points, espace, mot, espace,

# Mot, deux-points, espace, mot, espace,

Nous expliquerons ces nouveaux mtasymboles plus loin dans ce chapitre. (Cette section tait suppose dcrire les modificateurs de motifs, mais nous lavons laisser driver dans notre excitation au sujet de /x. Bref.) Voici une expression rgulire qui trouve les mots doubls dans un paragraphe, emprunt Perl en action (The Perl Cookbook). Il utilise les modificateurs /x et /i, ainsi que le modificateur /g dcrit plus loin.
# Trouve les doublons dans les paragraphes, si possible malgr les # enjambements. # Utilise /x pour les espaces et les commentaires, / pour dtecter les # deux tout dans "Tout tout va bien ?", et /g pour trouver tous les # doublons. $/ = ""; # mode "paragrep" while (<>) { while ( m{ \b # commence une limite de mot (\w\S+) # trouve un morceau de "mot" ( \s+ # spar par des blancs \1 # et ce mme morceau ) + # ad lib \b # jusqu une autre limite de mot }xig ) { print "doublon $1 au paragraphe $.\n"; } }
7. Faites attention cependant ne pas inclure le dlimiteur de motif dans le commentaire. cause de sa rgle "trouve la fin dabord", Perl na aucun moyen de savoir que vous naviez pas lintention de finir le motif cet endroit.

customer_8566

Oprateurs de recherche de motifs


Quand on lexcute sur ce chapitre, il affiche des avertissements tels que :
doublon nous au paragraphe 36

133

Bien sr, nous nous sommes aperus que dans ce cas particulier cest normal.

Loprateur m// (match)


EXPR =~ m/MOTIF/cgimosx EXPR =~ /MOTIF/cgimosx EXPR =~ ?MOTIF?cgimosx m/MOTIF/cgimosx /MOTIF/cgimosx ?MOTIF?cgimosx Loprateur m// recherche dans la chane contenue dans le scalaire EXPR le motif MOTIF. Si le dlimiteur est /ou ?, le m initial est facultatif. ? et ont tous deux une signification particulire en tant que dlimiteurs : le premier fait une dtection usage unique, le second supprime linterpolation de variables et les six squences de traduction (\U et autres, dcrits plus loin). Si lvaluation de MOTIF conduit une chane vide, soit parce que vous lavez spcifi ainsi en utilisant // ou parce quune variable interpole a donn la chane vide, la dernire expression rgulire excute avec succs sans tre cache lintrieur dun bloc inclus (ou lintrieur dun split, grep ou map) est excute la place. En contexte scalaire, loprateur renvoie vrai (1) en cas de succs, et faux ("") sinon. Cette forme se rencontre habituellement en contexte boolen :
if ($comte =~ m/Sacquet/) { ... } # recherche Sacquet dans la $comt if ($comte =~ /Sacquet/) { ... } # recherche Sacquet dans la $comt if ( m#Sacquet# ) if ( /Sacquet/ ) { ... } # cherche ici dans $_ { ... } # cherche ici dans $_

Utilis en contexte de liste, m// renvoie la liste des sous-chanes dtectes par les parenthses de capture du motif (cest--dire $1, $2, $3 et ainsi de suite), comme cela est dcrit plus loin dans la section Capture et regroupement. Les variables numrotes sont modifies malgr tout, mme si la liste est retourne. Si la recherche russit en contexte de liste mais quil ny avait pas de parenthses de capture (ni de /g), une liste consistant en (1) est retourne. Comme elle renvoie la liste vide en cas dchec, cette forme de m// peut aussi tre utilise en contexte boolen, mais seulement quand elle y participe indirectement via une affectation de liste :
if (($cle,$valeur) = /(\w+): (.*)/) { ... }

Les modificateurs valides pour m// (sous toutes ses formes) sont lists dans le tableau 5-1. Les cinq premiers modificateurs sappliquent la regex et ont t dcrits prcdemment. Les deux derniers modifient le comportement de loprateur lui-mme. Le modificateur /g indique une dtection globale cest--dire que lon recherche autant de fois quil est possible lintrieur de la chane. La faon dont cela se comporte dpend du contexte. En contexte de liste, m//g renvoie la liste de toutes les occurrences trouves. Dans lexemple suivant nous trouvons toutes les endroits o quelquun a mentionn perl , Perl , PERL , et ainsi de suite :

customer_8566

134
Tableau 5-1. Modificateurs de m//
Modificateur /i /m /s /x /o /g /cg Signification Ignore la casse des caractres.

Chapitre 5 Recherche de motif

Permet ^ et $ de fonctionner ct dun \n. Permet au . de dtecter des sauts de lignes et ignore la variable obsolte $*. Ignore (presque tous) les blancs et permet les commentaires lintrieur du motif. Compile le motif une seule fois. Recherche globale, pour dtecter toutes les occurrences. Permet de continuer la recherche aprs un chec dans /g.

if (@perls = $paragraphe =~ /perl/gi) { printf "Perl a t mentionn %d fois.\n", scalar @perls; }

Sil ny a pas de parenthses de capture dans le motif /g, alors les correspondances compltes sont renvoyes. Sil y a des parenthses de capture, seules les chanes captures sont retournes. Imaginez une chane comme celle-ci :
$chaine = "password=xyzzy verbose=9 score=0";

Imaginez galement que vous souhaitez initialiser un hachage comme ceci :


%hash = (password => "xyzzy", verbose => 9, score => 0);

Sauf videmment que vous navez pas une liste, vous avez une chane. Pour obtenir la liste correspondante, vous pouvez utiliser loprateur m//g en contexte de liste pour capturer tous les couples cl/valeur de la chane :
%hash = $chaine =~ /(\w+)=(\w+)/g;

La squence (\w+) capture un mot alphanumrique. Voir la section Capture et regroupement. Utilis en contexte scalaire, le modificateur /g indique une dtection progressive, qui reprend une nouvelle recherche sur la mme chane la position qui suit celle o la dernire sest arrte. Lassertion \G reprsente cette position dans la chane. Voir la section Positions plus loin dans ce chapitre pour une description de \G. Si vous utilisez le modificateur /c (pour continuer ) en plus de /g, alors quand le /g ne dtecte plus rien, la dtection rate ne rinitialise pas le pointeur de position. Si le dlimiteur est ?, comme dans ?MOTIF?, la recherche fonctionne comme un /MOTIF/ normal, sauf quelle ne trouve quune seule occurrence entre deux appels loprateur reset. Cela peut tre une optimisation utile, quand vous dsirez dtecter seulement la premire occurrence du motif pendant lexcution du programme, et pas toutes les occurrences. Loprateur fait la recherche chaque fois que vous lappelez, jusqu ce quil trouve finalement quelque chose, la suite de quoi il se bloque de lui-mme, renvoyant faux jusqu ce que vous le renclenchiez avec reset. Perl se souvient de ltat de la dtection pour vous. Loprateur ?? est particulirement utile quand une recherche de motif ordinaire trouverait la dernire occurrence plutt que la premire :

customer_8566

Oprateurs de recherche de motifs

135

open DICT, "/usr/dict/words_fr" or die "Impossible douvrir words_fr: $!\n"; while (<DICT>) { $premier = $1 if ?(^neur.*)?; $dernier = $1 if /(^neur.*)/; } print $premier,"\n"; # affiche "neural" print $dernier,"\n"; # affiche "neurula"

Loprateur reset ne rinitialisera que les instances de ?? qui ont t compiles dans le mme paquetage que lappel reset. m?? et ?? sont quivalents.

Loprateur s/// (substitution)


LVALUE =~ s/MOTIF/REMPLACEMENT/egimosx s/MOTIF/REMPLACEMENT/egimosx Cet oprateur recherche MOTIF dans une chane, et sil le dtecte, remplace la chane correspondante par le texte de REMPLACEMENT. (Les modificateurs sont dcrits plus loin dans cette section.)
$lotr = $hobbit; # Copie juste Bilbon le hobbit $lotr =~ s/Bilbon/Frodon/g; # et crit trs simplement une suite.

La valeur de retour dun s/// (en contexte scalaire comme en contexte de liste) est le nombre de fois quil a russit (ce qui peut tre plus dune fois sil a t utilis avec le modificateur /g dcrit plus tt). En cas dchec, il renvoie faux (""), qui est numriquement quivalent 0.
if ($lotr =~ s/Bilbon/Frodon/) { print "Suite crite avec succs." } $changements = $lotr =~ s/Bilbon/Frodon/g;

La partie de remplacement est traite comme une chane entre apostrophes doubles. Vous pouvez utiliser toutes les variables porte dynamique dcrites plus tt ($`, $&, $, $1, $2, et ainsi de suite) dans la chane de remplacement, ainsi que tous les trucs utilisables avec des apostrophes doubles. Voici un exemple qui trouve toutes les chanes revision , version , ou release , et les remplace chacune par son quivalent avec une majuscule, laide de la squence dchappement \u dans la partie de remplacement :
s/revision|version|release/\u$&/g; # Utilisez | pour dire "ou" # dans un motif

Toutes les variables scalaires sont interpoles en contexte dapostrophes doubles, et pas seulement les tranges que nous venons de voir. Supposons que vous ayez un hachage %Noms qui fasse correspondre aux numros de version des noms de projet interne ; par exemple $Noms{"3.0"} pourrait avoir le nom de code Isengard . Vous pourriez utiliser s/// pour trouver les numros de version et les remplacer par le nom des projets correspondants :
s/version ([0-9.]+)/la livraison $Noms{$1}/g;

Dans la chane de remplacement, $1 retourne ce que la premire (et unique) paire de parenthses a captur. (Vous auriez pu aussi utiliser \1 comme vous lauriez fait dans le motif, mais cet emploi est obsolte dans le remplacement. Dans une chane entre apostrophes doubles normale, \1 signifie Contrle-A.)

customer_8566

136

Chapitre 5 Recherche de motif

Si MOTIF est une chane vide, la dernire expression rgulire excute avec succs est utilise la place. MOTIF et REMPLACEMENT sont tous deux sujets linterpolation de variables. Cependant, un MOTIF est interpol chaque valuation du s/// en tant que tel, tandis que le REMPLACEMENT nest valu qu chaque fois quune correspondance est trouve. (Le MOTIF peut correspondre plusieurs fois en une valuation si vous utilisez le modificateur /g.) Comme prcdemment, les cinq modificateurs du tableau 5-2 modifient le comportement de la regex ; ce sont les mmes que pour m// et qr//. Les deux derniers affectent loprateur de substitution lui-mme. Tableau 5-2. Modificateurs de s///
Modificateur /i /m /s /x /o /g /e Signification Ignore la casse des caractres (lors de la correspondance). Permet ^ et $ de fonctionner ct dun \n. Permet au . de dtecter des sauts de ligne et ignore la variable obsolte $*. Ignore (presque tous) les blancs et permet les commentaires lintrieur du motif. Compile le motif une seule fois. Replacement global, cest--dire de toutes les occurrences. value la partie droite comme une expression.

Le modificateur /g est utilis avec s/// pour remplacer chaque occurrence de MOTIF par la valeur REMPLACEMENT, et pas seulement la premire rencontre. Un oprateur s///g agit comme un rechercher-remplacer global, en faisant toutes les modifications en une seule fois. Tout comme un m//g en contexte de liste, sauf que m//g ne change rien. (Et que s///g ne fait pas de dtection progressive comme le faisait un m//g en contexte scalaire.) Le modificateur /e traite le REMPLACEMENT comme sil sagissait dun bout de code Perl plutt que dune chane interpole. Le rsultat de lexcution de ce code est utilis comme chane de remplacement. Par exemple, s/([0-9]+)/sprintf("%#x", $1)/ge remplacerait 2581 par 0xb23. Ou supposez que dans notre exemple prcdent, vous nayez pas t sr de disposer dun nom pour toutes les versions et que vous ayez voulu laisser inchanges les versions sans nom. Avec un formatage un peu cratif de /x, vous auriez pu crire :
s{ version \s+ ( [0-9.]+ ) }{ $Noms{$1} ? "la livraison $Names{$1}" : $& }xge;

customer_8566

Oprateurs de recherche de motifs

137

La partie droite de votre s///e (ou dans ce cas, la partie basse) est vrifie syntaxiquement et compile en mme temps que le reste de votre programme. Toute erreur de syntaxe est dtecte la compilation, et les exceptions dynamiques ne sont pas releves. Chaque nouveau /e ajout la suite du premier (comme /ee, /eee et ainsi de suite) revient appeler eval CHAINE sur le rsultat du code, une fois par /e supplmentaire. Ceci value le rsultat du code dans lexpression et capture les exceptions dans la variable spciale $@. Voir la section Motifs programmatiques plus loin dans ce chapitre pour plus de dtails.

Modifier les chanes en passant


Parfois vous voulez une nouvelle chane, modifie sans altrer celle sur laquelle elle est base. Au lieu dcrire :
$lotr = $hobbit; $lotr =~ s/Bilbon/Frodon/g;

vous pouvez combiner ces deux instructions en une seule. cause de la prcdence, des parenthses sont requises autour de laffectation, tout comme dans la plupart des combinaisons appliquant =~ une expression.
($lotr = $hobbit) =~ s/Bilbon/Frodon/g;

Sans les parenthses autour de laffectation, vous nauriez fait que changer $hobbit et rcuprer le nombre de modifications dans $lotr, ce qui nous aurait donn une suite fort peu intressante. Vous ne pouvez pas utiliser un oprateur s/// directement sur un tableau. Pour cela, vous aurez besoin dune boucle. Par une heureuse concidence, lidiome Perl standard pour rechercher et modifier sur chaque lment dun tableau sobtient grce au systme dalias de for/foreach, combin avec lutilisation de $_ comme variable par dfaut de la boucle :
for (@chapitres) { s/Bilbon/Frodon/g } # Fait les substitutions chapitre # par chapitre. s/Bilbon/Frodon/g for @chapitres; # Pareil.

Comme avec les variables scalaires, vous pouvez galement combiner substitution et affectation si vous dsirez conserver une copie de loriginal :
@anciens = (oiseau bleu, bleu roi, bleu nuit, bleu de travail); for (@nouveaux = @anciens) { s/bleu/rouge/ } print "@nouveaux\n"; # affiche : oiseau rouge rouge roi rouge # nuit rouge de travail

La manire idiomatique dappliquer des substitutions rptes sur une mme variable est dutiliser une boucle un seul tour. Par exemple, voici comment normaliser les blancs dans une variable :
for ($chaine) { s/^\s+//; s/\s+$//; s/\s+/ /g; } # supprime les blancs au dbut # supprime les blancs la fin # minimise les blancs internes

customer_8566

138
ce qui produit exactement le mme rsultat que :
$chaine = join(" ", split " ", $chaine);

Chapitre 5 Recherche de motif

Vous pouvez galement utiliser une telle boucle dans une affectation, comme nous lavons fait dans le cas du tableau :
for ($nouveau = $ancien) { s/Fred/Homer/g; s/Wilma/Marge/g; s/Pebbles/Lisa/g; s/Dino/Bart/g; }

Quand une substitution globale nest pas assez globale


De temps en temps, vous ne pouvez tout simplement pas utiliser un /g pour que tous les changements soient faits, soit parce que les substitutions se produisent de droite gauche, soit parce que la longueur de $` doit changer entre deux occurrences. En gnral, vous pouvez faire cela en appelant s/// rptition. Mais vous voulez tout de mme que la boucle sarrte quand le s/// finit par chouer, ce qui ne laisse rien faire dans la partie principale de la boucle. Alors nous crivons un simple 1, qui est une chose plutt ennuyeuse faire, mais souvent le mieux que vous pouvez esprer. Voici quelques exemples qui utilisent quelques unes des ces tranges bestioles que sont les regex :
# met des points aux bons endroits dans un entier 1 while s/(\d)(\d\d\d)(?!\d)/$1.$2/; # change les tabulations pour des espacements sur 8 colonnes 1 while s/\t+/ x (length($&)*8 - length($`)%8)/e; # supprime les parenthses (imbriques (ou mme trs imbriques (comme a))) 1 while s/\([^()]*\)//g; # supprime les doublons (et les triplons (et les quadruplons...)) 1 while s/\b(\w+) \1\b/$1/gi;

Cette dernire ncessite une boucle car sinon elle transformerait ceci :
Paris AU AU AU AU printemps.

en cela :
Paris AU AU printemps.

Loprateur tr/// (translittration)


LVALUE =~ tr/LISTEDERECHERCHE/LISTEDEREMPLACEMENT/cds tr/LISTEDERECHERCHE/LISTEDEREMPLACEMENT/cds Pour les fans de sed, y/// est fourni comme synonyme de tr///. Cest la raison pour laquelle vous ne pouvez pas plus appeler une fonction y que vous ne pouvez lappeler q ou m. Hormis cela, y/// est exactement identique tr/// et nous ne le mentionnerons plus.

customer_8566

Oprateurs de recherche de motifs

139

Cet oprateur naurait pas vraiment de raison dapparatre dans un chapitre consacr la dtection de motif, puisquil nutilise pas de motif. Cet oprateur balaie une chane caractre par caractre, et remplace chaque occurrence dun caractre de LISTEDERECHERCHE (qui nest pas une expression rgulire) par le caractre correspondant dans LISTEDEREMPLACEMENT (qui nest pas une chane de remplacement). Cependant, il ressemble un peu m// et s///, et vous pouvez mme utiliser les oprateurs de lien =~ et !~ dessus. Cest pourquoi nous le dcrivons ici. (qr// et split sont des oprateurs de recherche de motif, mais on ne peut pas utiliser les oprateurs de lien dessus, cest pourquoi ils sont ailleurs dans ce livre. Allez comprendre.) La translittration retourne le nombre de caractres remplacs ou effacs. Si aucune chane nest spcfie par les oprateurs =~ ou !~, cest la chane $_ qui est modifie. LISTEDERECHERCHE et LISTEDEREMPLACEMENT peuvent dfinir des intervalles de caractres successifs laide dun tiret :
$message =~ tr/A-Za-z/N-ZA-Mn-za-m/; # cryptage rot13.

Remarquez quun intervalle comme A-Z suppose un ensemble de caractres linaire comme lest la table ASCII. Mais chaque ensemble de caractres a son propre point de vue concernant lordre de ses caractres, et donc de quels caractres font partie dun intervalle particulier. Un principe sain est dutiliser des intervalles qui commencent et finissent sur des caractres de la mme casse (a-e, A-E) ou des chiffres (0-4). Tout le reste est suspect. En cas de doute, dcrivez lensemble qui vous intresse en entier : ABCDE. LISTEDERECHERCHE et LISTEDEREMPLACEMENT ne subissent pas dinterpolation de variable comme des chanes entre apostrophes doubles ; vous pouvez cependant utiliser les squences avec antislash qui correspondent des caractres spcifiques, comme \n ou \015. Le tableau tableau 5-3 donne la liste des modificateurs qui sappliquent loprateur tr///. Ils sont compltement diffrents de ceux que vous appliquez m//, s/// ou qr//, mme si certains dentre eux y ressemblent. Si le modificateur /c est spcifi, le jeu de caractres dans LISTEDERECHERCHE est complment ; cest--dire que la liste de recherche effective comprend tous les caractres qui ne se trouvent pas dans LISTEDERECHERCHE. Dans le cas de lUnicode, cela peut reprsenter un grand nombre de caractres, mais comme ils sont stocks logiquement et non physiquement, vous navez pas vous inquiter dun ventuel manque de mmoire. Tableau 5-3. Modificateurs de tr///
Modificateur /c /d /s Signification Complmente la LISTEDERECHERCHE. Supprime les caractres trouvs mais non remplacs. Concentre les caractres dupliqus remplacs.

Le modificateur /d transforme tr/// en ce quon pourrait appeler loprateur de transoblitration : tout caractre spcifi par LISTEDERECHERCHE mais qui na pas de caractre de remplacement dans LISTEDEREMPLACEMENT est effac. (Cest un peu plus souple que le comportement de certains tr(1), qui effacent tout ce quils trouvent dans LISTEDERECHERCHE, point.)

customer_8566

140

Chapitre 5 Recherche de motif

Si le modificateur /s est spcifi, les suites de caractres qui sont convertis en un caractre identique sont rduites un seul exemplaire de ce caractre. Si le modificateur /d est utilis, LISTEDEREMPLACEMENT est toujours interprte comme elle est spcifie. Sinon, si LISTEDEREMPLACEMENT est plus courte que LISTEDERECHERCHE, le dernier caractre est rpliqu jusqu ce quelle soit assez longue. Si LISTEDEREMPLACEMENT est vide, la LISTEDERECHERCHE est rplique, ce qui est tonnamment utile si vous voulez juste compter les caractres, et non les modifier. Cest aussi utile pour compacter les squences de caractres. avec /s.
tr/aeiou/!/; tr{/\\\r\n\b\f. }{_}; tr/A-Z/a-z/ for @ARGV; # change toutes les voyelles en ! # change les caractres bizarres en souligns # normalise en minuscules ASCII

$compte = ($para =~ tr/\n//); # compte les sauts de lignes dans $para $compte = tr/0-9//; # compte les chiffres dans $_ $mot =~ tr/a-zA-Z//s; tr/@$%*//d; tr#A-Za-z0-9+/##cd; # illettrisme -> iletrisme # supprime tous ceux l # supprime les caractres hors base64

# change en passant ($HOTE = $hote) =~ tr/a-z/A-Z/; $pathname =~ tr/a-zA-Z/_/cs; # change les caractres ASCII non # alphabtiques en un seul soulign tr [\200-\377] [\000-\177];

# supprime le 8e bit de chaque octet

Si le mme caractre apparat plusieurs fois dans la LISTEDERECHERCHE, seul le premier est utilis. Ainsi, ceci :
tr/AAA/XYZ/

changera tout A en X (dans $_). Bien que les variables ne soient pas interpoles par tr///, vous pouvez obtenir le mme effet en utilisant eval EXPR :
$compte = eval "tr/$ancien/$nouveau/"; die if $@; # propage lexception due un contenu de eval incorrect

Encore un mot : si vous voulez passer votre texte en majuscules ou en minuscules, nutilisez pas tr///. Utilisez plutt les squences \U ou \L dans des chanes entre apostrophes doubles (lquivalent des fonctions ucet lc) car elles seront attentives aux informations de locales et lUnicode, alors que tr/a-z/A-Z ne le sera pas. De plus, dans les chanes Unicode, la squence \u et la fonction correspondante ucfirst comprennent la notion de casse de titre, ce qui pour certaines langues peut tre diffrent de simplement convertir en majuscules.

customer_8566

Mtacaractres et mtasymboles

141

Mtacaractres et mtasymboles
Maintenant que nous avons admir les jolies cages, nous pouvons de nouveau nous intresser aux bestioles dans ces cages, les tranges caractres que vous mettez dans les motifs. Maintenant vous avez compris que ces symboles ne sont pas du code Perl normal comme les appels de fonction ou les oprateurs arithmtiques. Les expressions rgulires ont leur propre petit langage inclus dans Perl. (Chacun a son jardin et sa jungle secrte.) Malgr leur puissance et leur expressivit, les motifs de Perl reconnaissent les mmes 12 caractres traditionnels (les Douze salopards , sil en est) quon trouve dans de nombreux autres modules dexpressions rgulires.
\ | ( ) [ { ^ $ * + ? .

Certains dentre eux changent les rgles, rendant spciaux les caractres normaux qui les suivent. Nous naimons pas appeler les squences de plus dun caractre des caractres , cest pourquoi nous les appelerons mtasymboles (ou mme seulement symboles ). Mais au plus haut niveau, ces douze mtacaractres sont tout ce dont vous (et Perl) avez vous inquiter. Tout le reste procde de l. Certains mtacaractres simples fonctionnent par eux-mmes, comme ., ^ et $. Ils naffectent directement rien de ce qui les entoure. Certains mtacaractres fonctionnent commes des oprateurs prfixes, contrlant ce qui les suit, comme \. Dautres fonctionnent comme des oprateurs postfixes, et contrlent ce qui les prcde immdiatement, comme *, + et ?. Un mtacaractre, |, fonctionne comme un oprateur infixe, en se tenant entre les deux oprandes quil affecte. Il existe mme des mtacaractres de parenthsage, qui fonctionnent comme des oprateurs circonfixes , et rgissent ce quils contiennent, comme (...) et [...]. Les parenthses sont particulirement importantes, car elles dfinissent les limites de | lintrieur, et celles de *, + et ? lextrieur. Si vous napprenez quun seul des douze mtacaractres, choisissez lantislash. (Euh... et les parenthses.) Cest parce que lantislash invalide les autres. Quand un antislash prcde un caractre non alphanumrique dans un motif Perl, il en fait toujours un caractre littral. Si vous avez besoin de faire une correspondance littrale avec lun des douze mtacaractres, vous navez qu lcrire prcde dun antislash. Ainsi, \. est un vrai point, \$ un vrai dollar, \\ un vrai antislash, et ainsi de suite. On appelle cela protger le mtacaractre, ou simplement l antislasher . (Bien sr, vous savez dj que lantislash sert supprimer linterpolation de variable dans les chanes entre apostrophes doubles.) Bien quun antislash transforme un mtacaractre en caractre littral, il a leffet inverse sur un caractre alphanumrique le suivant. Il prend ce qui tait normal et le rend spcial. Cest--dire qu eux deux, ils forment un mtasymbole. Une liste alphabtique de ces mtasymboles se trouve juste en dessous dans le tableau 5-7.

Tables de mtasymboles
Dans les tableaux qui suivent, la colonne Atomique indique Oui si le mtasymbole correspondant est quantifiable (cest--dire sil peut correspondre quelque chose qui a une largeur, plus ou moins). Nous avons galement utilis ... pour reprsenter

customer_8566

142

Chapitre 5 Recherche de motif

quelque chose dautre . (Consultez la discussion qui suit pour savoir ce que ... signifie, si le commentaire du tableau nest pas suffisant.) Le tableau 5-4 liste les mtasymboles traditionnels de base. Les quatre premiers sont les mtasymboles structurels dj mentionns, tandis que les trois suivants sont de simples mtacaractres. Le mtacaractre . est un exemple datome car il correspond quelque chose qui a une largeur (la largeur dun caractre, dans ce cas) ; ^ et $ sont des exemples dassertions, car ils correspondent quelque chose de largeur nulle et ne sont valus que pour savoir sils sont vrais ou faux. Tableau 5-4. Mtacaractres usuels de regex
Symbole \... ...|... (...) [...] ^ . $ Atomique Variable Non Oui Oui Non Oui Non Signification Rend le caractre non alphanumrique suivant littral, rend le caractre alphanumrique suivant mta (peut-tre). Alternative (correspond lun ou lautre). Regroupement (traite comme une unit). Classe de caractres (correspond un caractre dun ensemble). Vrai au dbut dune chane (ou aprs toute nouvelle ligne, ventuellement). Correspond un caractre (sauf le saut de ligne, normalement). Vrai en fin de chane (ou avant toute nouvelle ligne, ventuellement).

Les quantificateurs, dcrits plus loin dans leur propre section, indiquent combien de fois latome qui les prcde (caractre simple ou regroupement) doit correspondre. Ils sont lists dans le tableau 5-5. Tableau 5-5. Quantificateurs de regex
Quantificateur Atomique * + ? {COMPTE} {MIN,} {MIN,MAX} *? +? ?? {MIN,}? {MIN,MAX}? Non Non Non Non No No Non Non Non Non Non Signification Correspond 0 fois ou plus (maximal). Correspond 1 fois ou plus (maximal). Correspond 0 ou 1 fois (maximal). Correspond exactement COMPTE fois. Correspond au moins MIN fois (maximal). Correspond au moins MIN fois, mais pas plus de MAX fois (maximal). Correspond 0 fois ou plus (minimal). Correspond 1 fois ou plus (minimal). Correspond 0 ou 1 fois (minimal). Correspond au moins MIN fois (minimal). Correspond au moins MIN fois, mais pas plus de MAX fois (minimal).

customer_8566

Mtacaractres et mtasymboles

143

Un quantificateur minimal essaie de correspondre aussi peu que possible dans lintervalle autoris. Un quantificateur maximal essaie de correspondre le plus possible, dans lintervalle autoris. Par exemple, .+ est sr de correspondre au moins un des caractres de la chane, mais correspondra tous sil en a loccasion. Ces occasions seront dcrites plus loin dans Le petit Moteur qui /(ne )?pouvait( pas)?/ . Vous remarquerez quun quantificateur ne peut jamais tre quantifi. Nous voulions fournir une syntaxe extensible pour pouvoir introduire de nouveaux types de mtasymboles. tant donn que nous navions quune douzaine de mtacaractres notre disposition, nous avons choisi dutiliser une squence de regex anciennement incorrecte pour ces extensions syntaxiques arbitraires. Ces mtasymboles sont tous de la forme (?CLE...) ; cest--dire une parenthse (quilibre) suivie dun point dinterrogration, suivie par une CLE et le reste du sous-motif. Le caractre CLE indique de quelle extension de regex il sagit. Voyez le tableau 5-6 pour en avoir la liste. La plupart dentre eux se comportent bien structurellement, car ils sont bass sur des parenthses, mais ont galement une signification supplmentaire. De nouveau, seuls les atomes peuvent tre quantifis, car ils reprsentent quelque chose qui est vraiment l (potentiellement). Tableau 5-6. Squences de regex tendues
Extension (?#...) (?:...) (?imsx-imsx) (?imsx-imsx:...) (?=...) (?!...) (?<=...) (?<!...) (?>>...) (?{...}) (??{...}) (?(...)...|...) (?(...)...) Atomique Non Oui No Oui Non Non Non Non Yes Non Oui Oui Oui Signification Commentaire, ignor. Parenthses de regroupement seul, sans capture. Active/dsactive les modificateurs de motif. Parenthses de regroupement, et modificateurs. Vrai si lassertion de pr-vision est un succs. Vrai si lassertion de pr-vision est un chec. Vrai si lassertion de rtro-vision est un succs. Vrai si lassertion de rtro-vision est un chec. Correspond au motif sans retour arrire. Excute le code Perl inclus. Fait correspondre la regex du code Perl inclus. Correspond avec un motif si-alors-sinon. Correspond avec un motif si-alors.

Enfin, tableau 5-7 donne la liste de tous les mtasymboles alphanumriques usuels. (Les symboles qui sont traits durant la passe dinterpolation de variables sont indiqus avec un tiret dans la colonne Atomique, car le Moteur ne les voit jamais.) Les accolades sont facultatives pour \p et \P si le nom de la proprit fait un seul caractre. Les accolades sont facultatives pour \x si le nombre hexadcimal fait deux chiffres ou moins. Les accolades ne sont jamais facultatives pour \N.

customer_8566

144
Tableau 5-7. Mtasymboles alphanumriques de regex
Symbole \0 \NNN \n \a \A \b \b \B \cX \C \d \D \e \E \f \G \l \L \n \N{NAME} \p{PROP} \P{PROP} \Q \r \s \S \t \u \U \w Atomique Oui Oui Oui Oui Non Oui Non Non Oui Oui Oui Oui Oui Oui Non Oui Oui Oui Oui Oui Oui Oui Oui Oui Signification

Chapitre 5 Recherche de motif

Correspond au caractre nul (ASCII NUL). Correspond au caractre donn en octal, jusqu \377. Correspond la nime chane capture (en dcimal). Correspond au caractre alarme (BEL). Vrai au dbut dune chane. Correspond au caractre espace arrire (BS). Vrai une limite de mot. Vrai hors dune limite de mot. Correspond au caractre de contrle Contrle-X (\cZ, \c[, etc.). Correspond un octet (un char en C), mme en utf8 (dangereux). Correspond tout caractre numrique. Correspond tout caractre non numrique. Correspond au caractre dchappement (ASCII ESC, pas lantislash). Termine la traduction de casse (\L, \U) ou la citation de mtacaractres. Correspond au caractre de fin de page (FF). Vrai la position de fin de recherche du m//g prcdent. Passe le prochain caractre seulement en minuscules. Minuscules jusquau prochain \E. Correspond au caractre de saut de ligne (en gnral NL, mais CR sur les Mac). Correspond au caractre nomm (\N{greek:Sigma}). Correspond tout caractre ayant la proprit cite. Correspond tout caractre nayant pas la proprit cite. Cite les mtacaractres (dsactive leur ct mta) jusquau prochain \E. Correspond au caractre de retour chariot (CR en gnral, mais NL sur les Mac). Correspond tout caractre blanc. Correspond tout caractre non blanc. Correspond au caractre de tabulation (HT). Passe le prochain caractre seulement en grandes initiales. Passe en majuscules (et non en grandes initiales) jusquau prochain \E. Correspond tout caractre de mot (alphanumriques et _ ).

customer_8566

Mtacaractres et mtasymboles
Tableau 5-7. Mtasymboles alphanumriques de regex (suite)
Symbole \W \x{abcd} \X \z \Z Atomique Oui Oui Oui Non Non Signification Correspond tout caractre non mot . Correspond au caractre donn en hexadcimal.

145

Correspond une squence de caractres Unicode combins . Vrai seulement en fin de chane. Vrai en fin de chane ou avant un ventuel saut de ligne.

Seuls les mtasymboles dont la description est Correspond ... peuvent tre utiliss dans une classe de caractres. Cest--dire que les classes de caractres ne peuvent contenir que des ensembles spcifiques de caractres, et vous ne pouvez donc utiliser lintrieur que des mtasymboles qui dcrivent dautres ensembles spcifiques de caractres ou qui dcrivent des caractres individuels. Bien sr, ces mtasymboles peuvent aussi tre utiliss en dehors des classes de caractres, avec les autres mtasymboles (qui ne peuvent tre utiliss quhors classe). Remarquez cependat que \b est en fait deux bestioles compltement diffrentes : cest un espace arrire dans une classe de caractres, mais une assertion de limite de mot en dehors. Il y a un certain chevauchement entre les caractres auxquels un motif peut correspondre et les caractres quune chane entre apostrophes doubles peut interpoler. Comme les regex subissent deux passes, il est parfois ambigu de savoir quelle passe doit traiter quel caractre. Quand il y a une ambigut, la passe dinterpolation de variable dfre linterprtation de ces caractres lanalyseur dexpressions rgulires. Mais la passe dinterpolation de variable ne peut dfrer lanalyseur de regex que quand elle sait quelle est en train danalyser une regex. Vous pouvez spcifier des expressions rgulires comme des chanes entre apostrophes doubles ordinaires, mais vous devez alors suivre les rgles normales des apostrophes doubles. Chacun des mtasymboles prcdents qui correspond un caractre existant continuera de marcher, mme sil nest pas dfr lanalyseur de regex. Mais vous ne pourrez utiliser aucun des autres mtasymboles entre des apostrophes doubles ordinaires (ou dans toute construction analogue comme `...`, qq(...), qx(...) ou les documents ici-mme quivalents). Si vous voulez que votre chane soit analyse comme une expression rgulire sans faire de correspondance, vous devriez utiliser loprateur qr// (quote regex). Notez que les squences dchappement de casse et de mtacitation (\U et compagnie) doivent tre traits durant la passe dinterpolation, car leur rle est de modifier la faon dont les variables sont interpoles. Si vous supprimez linterpolation de variable avec des apostrophes simples, vous naurez pas non plus les squences dchappement. Ni les variables ni les squences dchappement (\U, etc.) ne sont tendues dans les chanes entre apostrophes simples, ni dans les oprateurs m... ou qr... avec apostrophes simples. Et mme si vous faites une interpolation, ces squences dchappement sont ignores si elles apparaissent dans le rsultat de linterpolation de variable, car ce moment-l il est trop tard pour inf luencer linterpolation de variable. Bien que loprateur de translittration ne prenne pas dexpression rgulire, tout mtasymbole prcdemment discut qui correspond un caractre spcifique simple mar-

customer_8566

146

Chapitre 5 Recherche de motif

che aussi dans une opration tr///. Les autres ne marchent pas (sauf bien sr lantislash qui continue toujours fonctionner sa manire bien lui).

Caractres spcifiques
Comme mentionn prcdemment, tout ce qui nest pas spcial dans un motif se correspond lui-mme. Cela signifie quun /a/ correspond un a , un /=/ correspond un = , et ainsi de suite. Certains caractres ne sont cependant pas trs faciles taper au clavier ou, mme si vous y arrivez ne safficheront pas lisiblement ; les caractres de contrle sont connus pour cela. Dans une expression rgulire, Perl reconnat les alias dapostrophes doubles suivants :
chappement \0 \a \e \f \n \r \t Signification Caractre nul (ASCII NUL) Alarme (BEL) chappement (ESC) Fin de page (FF) Saut de ligne (NL, CR sur Mac) Retour chariot (CR, NL sur Mac) Tabulation (HT)

Tout comme dans les chanes entre apostrophes doubles, Perl reconnat galement les quatre mtasymboles suivants dans les motifs : \cX Un caractre de contrle nomm, comme \cC pour Contrle-C, \cZ pour ContrleZ, \c[ pour ESC, et \c? pour DEL. \NNN Un caractre spcifi en utilisant son code octal deux ou trois chiffres. Le 0 initial est facultatif, sauf pour les valeurs infrieures 010 (8 en dcimal), car (contrairement aux chanes entre apostrophes doubles) les versions un seul chiffre sont toujours considres comme des rfrences arrires des chanes captures dans un motif. Les versions plusieurs chiffres sont interprtes comme la nime rfrence arrire si vous avez captur au moins n sous-chanes plus tt dans le motif (avec n considr comme un nombre dcimal). Sinon, elle est interprte comme un caractre octal. \x{HEXLONG} \xHEX Un caractre spcifi par son numro un ou deux chiffres hexadcimaux ([0-9afA-F]), comme \x1B. La forme un seul chiffre est utilisable quand le caractre suivant nest pas un chiffre hexadcimal. Si vous utilisez des accolades, vous pouvez mettre autant de chiffres que vous voulez, ce qui peut conduire un caractre Unicode. Par exemple, \x{262f} correspond un YIN YANG Unicode.

customer_8566

Mtacaractres et mtasymboles
\N{NOM}

147

Un caractre nomm, comme \N{GREEK SMALL LETTER EPSILON}, \N{greek:epsilon}, ou \N{epsilon}. Ceci requiert lutilisation du pragma use charnames dcrit au chapitre 31, Modules de pragmas, et qui dtermine aussi lequel de ces noms vous pouvez utiliser (":long", ":full", ":short" qui correspondent respectivement aux trois styles que nous venons de citer). Vous trouverez une liste de tous les noms de caractres Unicode dans vos documents de standard Unicode prfrs ou dans le fichier PATH_TO_PERLLIB/unicode/Names.txt.

Mtasymboles jokers
Trois mtasymboles spciaux sont utiliss comme des jokers gnriques, chacun dentre eux correspondant tout caractre (pour certaines valeurs de tout ). Ce sont le point ("."), \C et \X. Aucun dentre eux ne peut tre utilis dans une classe de caractres. Vous ne pouvez pas y utiliser le point car il correspondrait (presque) tout caractre existant. Cest donc dj une sorte de classe de caractres universelle par lui-mme. Si vous voulez tout inclure ou tout exclure, il ny a pas grand intrt utiliser une classe de caractres. Les jokers spciaux \C et \X ont une signification structurelle spcifique qui ne saccorde pas bien avec lide de choisir un seul caractre Unicode, ce qui est le niveau auquel fonctionne une classe de caractres. Le mtacaractre point correspond tout caractre autre que le saut de ligne. (Et avec le modificateur /s, il lui correspond aussi.) Comme chacun des autres caractres spciaux dans un motif, pour correspondre un point littral, vous devez le protger avec un antislash. Par exemple, ceci vrifie si un nom de fichier se termine par un point suivi dune extension un caractre :
if ($chemin =~ /\.(.)\z/s) { print "Se termine par $1\n"; }

Le premier point, celui qui est protg, est un caractre littral, tandis que le second dit correspond tout caractre . Le \z demande de ne correspondre qu la fin de la chane, et le modificateur /s permet au point de correspondre galement un saut de ligne. (Certes, utiliser un saut de ligne comme extension nest Pas Trs Gentil, mais cela ne veut pas dire que cela ne peut pas se produire.) Le mtacaractre point est le plus souvent utilis avec un quantificateur. Un .* correspond un nombre maximal de caractres, tandis quun .*? correspond un nombre minimal de caractres. Mais il est aussi utilis parfois sans quantificateur pour sa propre largeur : /(..):(..):(..)/ correspond trois champs spars par des deux-points, chacun faisant deux caractres de large. Si vous utilisez un point dans un motif compil sous le pragma porte lexicale use utf8, alors il correspondra tout caractre Unicode. (Vous ntes pas suppos avoir besoin de use utf8 pour cela, mais il y a toujours des accidents. Le pragma peut ne plus tre utile dici ce que vous lisiez ces lignes.)
use utf8; use charnames qw/:full/;

customer_8566

148

Chapitre 5 Recherche de motif

$BWV[887] = "G\N{MUSIC SHARP SIGN} minor"; # partition anglaise ($note, $noire, $mode) = $BWV[887] =~ /^([A-G])(.)\s+(\S+)/; eq chr(9839); print "Cest en dise !\n" if $n

Le mtasymbole \X correspond un caractre Unicode dans un sens plus tendu. Il correspond en fait une chane dun ou plusieurs caractres Unicode connue sous le nom de squence de caractres combins . Une telle squence consiste en un caractre de base suivi par lun des caractres de marquage (signe diacritique comme une cdille ou un trma) qui se combine avec le caractre de base pour former une unit logique. \X est exactement quivalent (?:\PM\pM*). Cela permet de correspondre un seul caractre logique, mme si celui est en fait constitu de plusieurs caractres distincts. La longueur de la correspondance de /\X/ peut excder un caractre si celui-ci a trouv des caractres combins. (Et nous parlons ici de la longueur en caractres, qui na pas grand chose voir avec la longueur en octets.) Si vous utilisez Unicode et que vous voulez vraiment travailler sur un seul octet plutt que sur un seul caractre, vous pouvez utiliser le mtasymbole \C. Ceci correspondra toujours un seul octet (spcifiquement, un seul lment de type char de C), mme si cela vous dsynchronise de votre f lux de caractres Unicode. Rfrez-vous aux avertissements relatifs cela au chapitre 15.

Classes de caractres
Dans une recherche de motif, vous pouvez tablir une correspondance avec tout caractre qui a ou na pas une proprit particulire. Il existe quatre manires de spcifier les classes de caractres. Vous pouvez spcifier une classe de caractres de la manire traditionnelle en utilisant des crochets et en numrant les caractres possibles, ou en utilisant lun des trois raccourcis mnmotechniques : les classes Perl habituelles, les nouvelles proprits Unicode de Perl ou les classes POSIX standard. Chacun de ces raccourcis correspond un seul caractre de son ensemble. Quantifiez-les si vous voulez faire une correspondance avec un plus grand nombre dentre eux, comme \d+ pour correspondre plusieurs chiffres. (Une erreur facile faire est de croire que \w correspond un mot. Utilisez \w+ pour trouver un mot.)

Classes de caractres personnalises


Une liste de caractres numre entre crochets est appele une classe de caractre et correspond tout caractre dans la liste. Par exemple, [aeiouy] correspond une voyelle (non accentue). Pour correspondre un crochet fermant, antislashez-le ou bien placezle en premier dans la liste. Des intervalles de caractres peuvent tre indiqus en utilisant un tiret et la notation az. Plusieurs intervalles peuvent tre combins ; par exemple [0-9a-fA-F]correspond un chiffre hexadcimal. Vous pouvez utiliser un antislash pour protger un tiret qui serait sinon interprt comme un dlimiteur dintervalle, ou simplement le placer en dbut de liste (une pratique probablement moins lisible mais plus traditionnelle). Un chapeau (ou accent circonf lexe, ou f lche vers le haut) au dbut de la classe de caractre linverse, la faisant correspondre tout caractre ne se trouvant pas dans la liste. (Pour correspondre un chapeau, ou bien ne le mettez pas au dbut, ou mieux, prot-

customer_8566

Classes de caractres

149

gez-le avec un antislash.) Par exemple, [^aeiouy] correspond tout caractre qui nest pas une voyelle (non accentue). Cependant soyez prudent avec la ngation de classe, car lunivers des caractres est en expansion. Par exemple, cette classe de caractre correspond aux consonnes et aussi aux espaces, aux sauts de ligne, et tout (y compris les voyelles) en cyrillique, en grec ou tout autre alphabet, sans compter tous les idogrammes chinois, japonais et corens. Et un jour aussi le cirth, le tengwar et le klingon. (Mais dj le linaire B et ltrusque.) Il vaut donc peut-tre mieux spcifier vos consonnes explicitement, comme [bcdfghjklmnpqrstvwxyz], ou [b-df-hj-np-tv-z] pour faire plus court. (Cela rsout aussi le problme du y qui devrait tre deux endroits la fois, ce quinterdit lutilisation de lensemble complmentaire.) Les mtasymboles caractres normaux, comme \n, \t, \cX, \NNN et \N{NOM} sont utilisables dans une classe de caractres (voir la section Caractres spcifiques). De plus, vous pouvez utiliser \b dans une classe de caractres pour signifier un espace arrire, exactement comme dans une chane entre apostrophes doubles. Normalement, dans une recherche de motif, il reprsente une limite de mot. Mais les assertions de largeur nulle nont aucun sens dans une classe de caractres, cest pourquoi \b retrouve la signification quil a dans les chanes. Vous pouvez galement utiliser les classes de caractres prdfinies qui sont dcrites plus loin dans ce chapitre (classique, Unicode ou POSIX), mais nessayez pas de les utiliser comme point initial ou final dun intervalle cela nayant pas de sens, le - sera interprt comme un caractre littral. Tous les autres mtasymboles perdent leur signification spciale quand ils sont entre crochets. En particulier, vous ne pouvez utiliser aucun des trois jokers gnriques : . , \Xou \C. Le premier surprend souvent, mais cela na pas grand sens dutiliser la classe de caractre universelle lintrieur dune classe plus restrictive, et de plus vous avez souvent besoin de faire une correspondance avec un point littral dans une classe de caractre quand vous travaillez sur des noms de fichier, par exemple. Cela na pas grand sens non plus de spcifier des quantificateurs, des assertions ou des alternatives dans une classe de caractres, puisque les caractres sont interprts individuellement. Par exemple, [fee|fie|foe|foo] a exactement la mme signification que [feio|].

Raccourcis de classes de caractres classiques Perl


Depuis lorigine, Perl a fourni un certain nombre de raccourcis pour les classes de caractres. La liste est fournie dans le tableau 5-8. Tous sont des mtasymboles alphabtiques antislashs, et dans chaque cas, la version en majuscule est la ngation de la version en minuscules. Leur signification est nest pas aussi rigide que vous pourriez le croire : leur sens peut tre inf luenc par les dfinitions de locales. Mme si vous nutilisez pas les locales, leur signification peut changer chaque fois quun nouveau standard Unicode sortira, ajoutant de nouveaux scripts avec de nouveaux chiffres et de nouvelles lettres. (Pour conserver lancienne signification par octets, vous pouvez toujours utiliser use bytes. Voir Proprits Unicode un peu plus loin dans ce chapitre pour des explications sur les correspondances utf8. Dans tous les cas, les correspondances utf8 sont un surensemble des correspondances sur les octets.) (Oui, nous savons que la plupart des mots ne comportent ni chiffres ni souligns mais parfois des accents ; \w sert trouver des mots au sens des tokens dans un langage de programmation usuel. Ou en Perl.)

customer_8566

150
Tableau 5-8. classe de caractres classiques
Symbole \d \D \s \S \w \W Signification Chiffre Non chiffre Blanc Non blanc Caractre de mot Non-(caractre mot) En octets [0-9] [^0-9]

Chapitre 5 Recherche de motif

En utf8 \p{IsDigit} \P{IsDigit} \p{IsSpace} \P{IsSpace} \p{IsWord} \P{IsWord}

[ \t\n\r\f] [^ \t\n\r\f] [a-zA-Z0-9_] [^a-zA-Z0-9_]

Ces mtacaractres peuvent tre utiliss lextrieur ou lintrieur de crochets, cest-dire soit par eux-mmes ou comme lment dune classe de caractres :
if ($var =~ /\D/) { warn "contient des non-chiffres" } if ($var =~ /[^\w\s.]/) { warn "contient des non-(mot, espace, point)" }

Proprits Unicode
Les proprits Unicode sont disponibles en utilisant \p{PROP} et son ensemble complmentaire \P{PROP}. Pour les rares proprits qui ont un nom en un seul caractre, les accolades sont facultatives, comme dans \pN pour indiquer un caractre numrique (pas ncessairement dcimal les chiffres romains sont aussi des caractres numriques). Ces classes de proprits peuvent tre utilises par elles-mmes ou combines dans une classe de caractres :
if ($var =~ /^\p{IsAlpha}+$/) { print "tout alphabtique" } if ($var =~ s/[\p{Zl}\p{Zp}]/\n/g) { print "saut de lignes" }

Certaines proprits sont directement dfinies dans le standard Unicode, et dautres sont des composes dfinies par Perl, en sappuyant sur les proprits standard. Zl et Zp sont des proprits Unicode standard qui reprsentent les sparateurs de lignes et de paragraphes, tandis quIsAlpha est dfinie par Perl comme une classe regroupant les proprits standard Ll, Lu, Lt et Lo (cest--dire les lettres qui sont en majuscules, en minuscules, en casse de titre ou autre). partir de la version 5.6.0 de Perl, vous avez besoin de use utf8 pour que ces proprits fonctionnent. Cette restriction sera assouplie dans le futur. Il y a un grand nombre de proprits. Nous allons lister celles que nous connaissons, mais la liste sera forcment incomplte. De nouvelles proprits sont susceptibles dapparatre dans les nouvelles versions dUnicode, et vous pouvez mme dfinir vos propres proprits. Nous verrons cela plus loin. Le Consortium Unicode produit les informations que lon retrouve dans les nombreux fichiers que Perl utilise dans son implmentation dUnicode. Pour plus dinformations sur ces fichiers, voyez le chapitre 15. Vous pouvez lire un bon rsum de ce quest Unicode dans le document PATH_TO_PERLLIB/unicode/Unicode3.html o PATH_TO_PERLLIB est ce qui est affich par :
perl -MConfig -le print $Config{privlib}

La plupart des proprits Unicode sont de la forme \p{IsPROP}. Le Is est facultatif, mais vous pouvez le laisser pour des raisons de lisibilit.

customer_8566

Classes de caractres

151

Proprits Unicode de Perl


Le tableau 5-9 donne la liste des proprits composites de Perl. Elles sont dfinies de faon tre raisonnablement proches des dfinitions POSIX standard pour les classes de caractres. Tableau 5-9. Proprits Unicode composites
Proprt IsASCII IsAlnum IsAlpha IsCntrl IsDigit IsGraph IsLower IsPrint IsPunct IsSpace IsUpper IsWord IsXDigit quivalent [\x00-\x7f] [\p{IsLl}\p{IsLu}\p{IsLt}\p{IsLo}\p{IsNd}] [\p{IsLl}\p{IsLu}\p{IsLt}\p{IsLo}] \p{IsC} \p{Nd} [^\pC\p{IsSpace}] \p{IsLl} \P{IsC} \p{IsP} [\t\n\f\r\p{IsZ}] [\p{IsLu}\p{IsLt}] [_\p{IsLl}\p{IsLu}\p{IsLt}\p{IsLo}\p{IsNd}] [0-9a-fA-F]

Perl fournit galement les composites suivants pour chacune des principales catgories des proprits Unicode standard (voir la section suivante) :
Proprit IsC IsL IsM IsN IsP IsS IsZ Signification Codes de contrle et quivalents Lettres Marqueurs Nombres Ponctuation Symboles Sparateurs (Zparateurs?) Normative Oui Partiellement Oui Oui Non Non Oui

Proprits Unicode standard


Le tableau 5-10 donne la liste des proprits Unicode standard les plus basiques, qui drivent de la catgorie de chaque caractre. Aucun caractre nest membre de plus dune catgorie. Certaines proprits sont normatives ; dautres sont simplement informatives. Reportez-vous au standard Unicode pour savoir combien linformation normative est normative, et combien linformation informative ne lest pas.

customer_8566

152
Tableau 5-10. Proprits Unicode standard
Proprit IsCc IsCf IsCn IsCo IsCs IsLl IsLm IsLo IsLt IsLu IsMc IsMe IsMn IsNd IsNl IsNo IsPc IsPd IsPe IsPf IsPi IsPo IsPs IsSc IsSk IsSm IsSo IsZl IsZp IsZs Signification Autre, contrle Autre, format Autre, non affect Autre, usage priv Autre, substitut Lettre, minuscule Lettre, modificateur Lettre, autre Lettre, casse de titre Lettre, majuscule Marque, combinante Marque, entourant Marque, non-espacement Nombre, chiffre dcimal Nombre, lettre Nombre, autre Ponctuation, connecteur Ponctuation, tiret Ponctuation, fermeture Ponctuation, guillemet fermant Ponctuation, guillemet ouvrant Ponctuation, autre Ponctuation, ouvert Symbole, monnaie Symbole, modificateur Symbole, math Symbole, autre Sparateur, de ligne Sparateur, de paragraphe Sparateur, espace

Chapitre 5 Recherche de motif

Normative Oui Oui Oui Oui Oui Oui Non Non Oui Oui Oui Oui Oui Oui Oui Oui Non Non Non Non Non Non Non Non Non Non Non Oui Oui Oui

Un autre ensemble de proprits utiles est li au fait quun caractre peut tre dcompos (de faon canonique ou compatible) en dautres caractres plus simples. La dcomposition canonique ne perd aucune information de formatage. La dcomposition compatible peut perdre des informations de formatage, comme le fait de savoir si le caractre est en exposant.

customer_8566

Classes de caractres
Proprit IsDecoCanon IsDecoCompat IsDCcircle IsDCfinal IsDCfont IsDCfraction IsDCinitial IsDCisolated IsDCmedial IsDCnarrow IsDCnoBreak IsDCsmall IsDCsquare IsDCsub IsDCsuper IsDCvertical IsDCwide IsDCcompat Information perdue Rien Quelque chose (parmi les suivants) Cercle autour du caractre Prfrence de position finale (Arabe) Prfrence de variante de fonte Caractristique de fraction ordinaire Prfrence de position initiale (Arabe) Prfrence de position isole (Arabe) Prfrence de position mdiane (Arabe) Caractristique dtroitesse Prfrence de non-coupure sur un espace ou un tiret Caractristique de petite taille Carr autour dun caractre CJK Position dindice Position dexposant Rotation (dhorizontal vertical) Caractristique de largeur Identit (variable)

153

Voici quelques proprits qui intressent les personnes faisant du rendu bidirectionnel :
Proprit IsBidiL IsBidiLRE IsBidiLRO IsBidiR IsBidiAL IsBidiRLE IsBidiRLO IsBidiPDF IsBidiEN IsBidiES IsBidiET IsBidiAN IsBidiCS IsBidiNSM IsBidiBN IsBidiB Signification Gauche droite (Arabe, Hbreu) Inclusion de gauche droite Force de gauche droite Droite gauche Droite gauche arabe Inclusion de droite-gauche Force de droite gauche Dpile le format directionnel Nombre europen Sparateur de nombre europen Terminateur de nombre europen Nombre arabe Sparateur de nombres communs Marque de non-espacement Limite neutre Sparateur de paragraphe

customer_8566

154
Proprit IsBidiS IsBidiWS IsBidiON IsMirrored Signification Sparateur de segment Blanc Autres neutres

Chapitre 5 Recherche de motif

Image miroir quand utilis de droite gauche

Les proprits suivantes classent diffrents syllabaires selon les sonorits des voyelles :
IsSylA IsSylAA IsSylAAI IsSylAI IsSylC IsSylE IsSylEE IsSylI IsSylII IsSylN IsSylO IsSylOO IsSylU IsSylV IsSylWA IsSylWAA IsSylWC IsSylWE IsSylWEE IsSylWI IsSylWII IsSylWO IsSylWOO IsSylWU IsSylWV

Par exemple, \p{IsSylA} correspondrait \N{KATAKANA LETTER KA} mais pas \N{KATAKANA LETTER KU}. Maintenant que nous vous avons parl de toutes ces proprits Unicode 3.0, nous devons tout de mme lister quelques unes des plus sotriques qui ne sont pas implmentes dans Perl 5.6.0, car cette implmentation tait base en partie sur Unicode 2.0, et que des choses comme lalgorithme bidirectionnel taient encore sur le mtier. Cependant, comme dici ce que vous lisiez ceci, les proprits manquantes pourraient bien avoir t implmentes, nous les avons listes quand mme.

Proprits de bloc Unicode


Certaines proprits Unicode sont de la forme \p{InSCRIPT}. (Remarquez la distinction entre Is et In.) Les proprits In servent tester lappartenance des blocs dun SCRIPT unique. Si vous avez un caractre et que vous vous demandez sil est crit en criture hbraque, vous pouvez le tester avec :
print "Pour moi cest de lHbreu!\n" if chr(1488) =~ /\p{InHebrew}/;

Cela fonctionne en vrifiant si un caractre est dans lintervalle valide de ce type dcriture. Cela peut tre invers avec \P{InSCRIPT} pour savoir si quelque chose nest pas dans un bloc de script particulier, comme \P{InDingbats} pour savoir si une chane contient un caractre non dingbat. Dans les proprits de bloc on trouve les lments suivants :
InArabic InArmenian InArrows InBasicLatin InBengali InBopomofo InBoxDrawing InCherokee InCyrillic InDevanagari InDingbats InEthiopic InGeorgian InGreek InGujarati InGurmukhi InHangulJamo InHebrew InHiragana InKanbun InKannada InKatakana InKhmer InLao InMalayalam InMongolian InMyanmar InOgham InOriya InRunic InSinhala InSpecials InSyriac InTamil InTelugu InThaana InThai InTibetan InYiRadicals InYiSyllables

Sans oublier les impressionnants :


InAlphabeticPresentationForms InArabicPresentationForms-A InArabicPresentationForms-B InHalfwidthandFullwidthForms InHangulCompatibilityJamo InHangulSyllables

customer_8566

Classes de caractres
InBlockElements InBopomofoExtended InBraillePatterns InCJKCompatibility InCJKCompatibilityForms InCJKCompatibilityIdeographs InCJKRadicalsSupplement InCJKSymbolsandPunctuation InCJKUnifiedIdeographs InCJKUnifiedIdeographsExtensionA InCombiningDiacriticalMarks InCombiningHalfMarks InCombiningMarksforSymbols InControlPictures InCurrencySymbols InEnclosedAlphanumerics InEnclosedCJKLettersandMonths InGeneralPunctuation InGeometricShapes InGreekExtended

155
InHighPrivateUseSurrogates InHighSurrogates InIdeographicDescriptionCharacters InIPAExtensions InKangxiRadicals InLatin-1Supplement InLatinExtended-A InLatinExtended-B InLatinExtendedAdditional InLetterlikeSymbols InLowSurrogates InMathematicalOperators InMiscellaneousSymbols InMiscellaneousTechnical InNumberForms InOpticalCharacterRecognition InPrivateUse InSuperscriptsandSubscripts InSmallFormVariants InSpacingModifierLetters

Et le mot le plus long :


InUnifiedCanadianAboriginalSyllabics

Pas mieux. Consultez PATH_TO_PERLLIB/unicode/In/*.pl pour obtenir une liste jour de toutes ces proprits de blocs de caractres. Remarquez que les proprits In ne font que vrifier si le caractre est dans lintervalle allou pour ce script. Rien ne vous garantit que tous les caractres dans cet intervalle sont dfinis ; vous devrez galement tester lune des proprits Is discutes prcdemment pour vrifier si le caractre est dfini. Rien ne vous garantit non plus quune langue particulire nutilise pas des caractres en dehors de lintervalle qui lui est affect. En particulier, de nombreuses langues europennes mlangent les caractres latins tendus avec des caractres Latin-1. Mais bon, si vous avez besoin dune proprit particulire qui nest pas fournie, ce nest pas un gros problme. Continuez lire.

Dfinir vos propres proprits de caractres


Pour dfinir vos propres proprits, vous devrez crire un sous-programme portant le nom de la proprit que vous voulez (voir chapitre 6, Sous-programmes). Le sous-programme doit tre dfini dans le paquetage qui a besoin de la proprit, ce qui signifie que si vous dsirez lutiliser dans plusieurs paquetages, vous devrez soit limporter dun autre module (voir chapitre 11, Modules), ou lhriter comme mthode de classe depuis le paquetage dans lequel il est dfini (voir chapitre 12, Objets). Une fois que cela est fait, le sous-programme doit renvoyer des donnes dans le mme format que les fichiers du rpertoire PATH_TO_PERLLIB/unicode/Is. Cest--dire que vous devez juste retourner une liste de caractres ou des intervalles de caractres en hexadcimal, un par ligne. Sil y a un intervalle, les deux nombres sont spars par une tabulation. Supposons que vous vouliez crer une proprit qui serait vraie si votre caractre

customer_8566

156

Chapitre 5 Recherche de motif

est dans lintervalle de lun des deux syllabaires japonais, nomms hiragana et katakana. (Ensemble on les appelle simplement kana.) Vous pouvez juste mettre les deux intervalles comme suit :
sub InKana { return <<END; 3040 309F 30A0 30FF END }

Vous pourriez galement le dfinir laide de noms de proprits existantes :


sub InKana { return <<END; +utf8::InHiragana +utf8::InKatakana END }

Vous pouvez aussi faire une soustraction en utilisant un prfixe - . Supposons que vous ne vouliez que les vritables caractres, et pas seulement les blocs de caractres. Vous pouvez retirer tous les caractres indfinis comme ceci :
sub IsKana { return <<END; +utf8::InHiragana +utf8::InKatakana -utf8::IsCn END }

Vous pouvez aussi dmarrer avec le complment dun ensemble de caractres en utilisant le prfixe ! :
sub IsNotKana { return <<END; !utf8::InHiragana -utf8::InKatakana +utf8::IsCn END }

Perl lui-mme utilise les mmes trucs pour dfinir la signification de ses propres classes de caractres classiques (comme \w) quand vous les incluez dans vos classes de caractres personnalises (comme [-.\w\s]). Vous pourriez penser que plus les rgles deviennent compliques, plus lentement cela tournera ; mais en fait, une fois que Perl a calcul le motif de bits pour le bloc de 64 bits de votre proprit, il le mmorise pour navoir jamais le recalculer. (Cela est fait dans des blocs de 64 bits pour ne mme pas avoir dcoder votre utf8 pour faire les recherches.) Ainsi, toutes les classes de caractres, internes ou personnalises, tournent toutes peu prs la mme vitesse (rapide) une fois mises en route.

customer_8566

Classes de caractres

157

Classes de caractres de style POSIX


Contrairement aux autres raccourcis de classes de caractres, la notation de style POSIX, [:CLASSE:], nest utilisable que pour la construction dautres classes de caractres, cest-dire lintrieur dune autre paire de crochets. Par exemple, /[.,[:alpha:][:digit:]]/ va chercher un caractre qui est soit un point (littral, car dans une classe de caractres), une virgule, ou un caractre alphabtique ou un nombre. Les classes POSIX disponibles partir de la version 5.6 de Perl sont listes dans le tableau 5-11. Tableau 5-11. Classes de caractres POSIX
Classe alnum alpha ascii cntrl Signification Tout alphanumrique, cest--dire un alpha ou un digit. Toute lettre. (Cela fait beaucoup plus de lettres que vous pensez, sauf si vous pensez en Unicode, auquel cas cela fait quand mme beaucoup.) Tout caractre avec une valeur numrique comprise entre 0 et 127. Tout caractre de contrle. En gnral ce sont des caractres qui ne produisent pas daffichage par eux-mmes, mais contrlent le terminal dune faon ou dune autre. Par exemple, les caractres de nouvelle ligne, de fin de page ou despace arrire sont des caractres de contrle. Les caractres ayant une valeur numrique infrieure 32 sont le plus souvent considrs comme des caractres de contrle. Un caractre reprsentant un chiffre dcimal, comme ceux entre 0 et 9. (Cela comprend dautres caractres en Unicode.) quivalent \d. Tout caractre alphanumrique ou de ponctuation. Une lettre minuscule. Tout caractre alphanumrique, de ponctuation ou despacement. Tout caractre de ponctuation. Tout caractre despacement. Cela inclut tabulation, nouvelle ligne, saut de page et retour chariot (et encore beaucoup plus en Unicode). quivalent \s. Tout caractre en majuscule (ou casse de titre). Tout caractre didentificateur, soit un alnum ou un soulign. Tout chiffre hexadcimal. Bien que cela semble un peu bte ([0-9a-fA-F] marche trs bien), cest inclus pour tre complet.

digit graph lower print punct space

upper word xdigit

Vous pouvez inverser la classe de caractres POSIX en prfixant le nom de la classe par un ^ aprs le [:. (Cest une extension apporte par Perl.) Par exemple :
POSIX [:^digit:] [:^space:] [:^word:] Classique \D \S \W

customer_8566

158

Chapitre 5 Recherche de motif

Si le pragma use utf8 nest pas demand, mais que le pragma use locale lest, la classe correspond directement avec les fonctions quivalentes de linterface isalpha(3) de la librairie C (except word, qui est une extension Perl correspondant \w). Si le pragma utf8 est utilis, les classes de caractres POSIX sont exactement quivalentes aux proprits Is listes dans le tableau 5-9. Par exemple, [:lower:] et \p{Lower} sont quivalentes, sauf que les classes POSIX ne peuvent tre utilises que dans les classes de caractres construites, tandis que les proprits Unicode ne sont pas soumises de telles restrictions et peuvent tre utilises dans des motifs partout o les raccourcis Perl comme \s et \w peuvent ltre. Les crochets font partie de la construction de style POSIX [::] et pas de la classe de caractres. Ce qui nous amne crire des motifs tels que /^[[:lower:][:digit:]]+$/ pour correspondre une chane consistant entirement de lettres minuscules ou de chiffres (avec un saut de ligne final facultatif). En particulier, ceci ne fonctionne pas :
42 =~ /^[:digit:]+$/ # FAUX

Cela est d au fait quon nest pas dans une classe de caractres. Ou plutt, cest une classe de caractres, celle qui reprsente les caractres : , i , t , g et d . Perl se moque du fait que vous ayez utilis deux : (et deux i ). Voici ce dont vous avez en fait besoin :
42 =~ /^[[:digit:]]+$/

Les classes de caractres POSIX [.cc.] et [=cc=] sont reconnues, mais produisent une erreur indiquant quelles ne sont pas utilisables. Lutilisation de nimporte quelle classe de caractres POSIX dans une version de Perl plus ancienne ne marchera pas, et de faon probablement silencieuse. Si vous comptez utiliser les classes de caractres POSIX, il est prfrable dimposer lutilisation dune nouvelle version de Perl en crivant :
use 5.6.0;

Quantificateurs
moins que vous nen dcidiez autrement, chaque lment dune expression rgulire ne correspond quune fois quelque chose. Avec un motif comme /nop/, chacun de ces caractres doit correspondre, lun la suite de lautre. Les mots comme panoplie ou xnophobie marchent bien, car o la correspondance se fait na aucune importance. Si vous vouliez trouver la fois xnophobie et Snoopy , vous ne pourriez pas utiliser le motif /nop/, puisque cela requiert quil ny ait quun seul o entre le n et le p , et que Snoopy en a deux. Cest ici que les quantificateurs montrent leur utilit : ils indiquent combien de fois quelque chose peut correspondre, au lieu de une fois par dfaut. Les quantificateurs dans une expression rgulire sont comme les boucles dans un programme ; en fait, si vous regardez une expression rgulire comme un programme, alors ce sont des boucles. Certaines boucles sont exactes, comme rpte cette correspondance cinq fois seulement ({5}). Dautres vous donnent la fois la limite infrieure et la limite suprieure du nombre de correspondances, comme rpte ceci au moins deux fois, mais pas plus de quatre ({2,4}). Dautres nont pas de limite suprieure du tout, comme trouve ceci au moins deux fois, mais ensuite autant de fois que tu veux ({2,}).

customer_8566

Quantificateurs
Le tableau 5-12 liste les quantificateurs que Perl reconnat dans un motif. Tableau 5-12. Comparaison des quantificateurs de motifs
Maximum {MIN,MAX} {MIN,} {COMPTE} * + ? Minimum {MIN,MAX}? {MIN,}? {COMPTE}? *? +? ?? Plage autorise

159

Doit apparatre au moins MIN fois mais pas plus de MAX fois Doit apparatre au moins MIN fois Doit apparatre exactement COMPTE fois 0 ou plus (comme {0,}) 1 fois ou plus (comme {1,}) 0 ou 1 fois (comme {0,1})

Quelque chose suivi dune * ou dun ? nest pas oblig de correspondre tout prix. Cest parce que cela peut correspondre 0 fois et toujours tre considr comme un succs. Un + est souvent un meilleur choix, car llment recherch doit tre prsent au moins une fois. Ne vous laissez pas embrouiller par lemploi de exactement dans le tableau prcdent. Il ne fait rfrence quau nombre de rptitions, et pas la chane complte. Par exemple, $n =~ /\d{3}/ ne dit pas est-ce que cette chane fait exactement trois chiffres de long ? . En fait le motif se proccupe de savoir sil existe une position dans $n laquelle trois chiffres apparaissent les uns la suite des autres. Des chanes comme 101 rue de la Rpublique correspondent, tout comme des chanes telles que 75019 ou 0 825 827 829 . Toutes contiennent trois chiffres la suite un ou plusieurs endroits, ce qui est tout ce que vous demandiez. Voir dans la section Positions lutilisation des assertions de position (comme dans /^\d{3}$/) pour prciser votre recherche. Si on leur donne la possibilit de correspondre un nombre variable de fois, les quantificateurs maximaux vont essayer de maximiser le nombre de rptitions. Cest pourquoi quand nous disons autant de fois que tu veux , les quantificateurs gourmands le comprennent comme le plus de fois que tu le peux , la seule condition que cela nempche pas des spcifications plus loin dans lexpression de correspondre. Si un motif contient deux quantificateurs ouverts, les deux ne peuvent videmment pas consommer lintgralit de la chane : les caractres utiliss par la premire partie de lexpression ne sont plus disponibles pour la partie qui suit. Chaque quantificateur est gourmand aux dpens de ceux qui le suivent, en lisant le motif de gauche droite. Cest du moins le comportement traditionnel des quantificateurs dans les expressions rgulires. Cependant Perl vous permet de modifier le comportement de ses quantificateurs : en mettant un ?aprs un quantificateur, vous le transformez de maximal en minimal. Cela ne signifie pas quun quantificateur minimal va toujours correspondre au nombre minimum de rptitions permises par ses spcifications, pas plus quun quantificateur maximal correspond toujours au plus grand nombre dfini dans ses spcifications. La correspondance globale doit toujours se faire, et le quantificateur minimal prendra juste ce quil faut pour que ce soit un succs, et pas plus. (Les quantificateurs minimaux prfrent la satisfaction la gourmandise.) Par exemple dans la correspondance :
"exigence" =~ /e(.*)e/ # $1 vaut maintenant "xigenc"

customer_8566

160

Chapitre 5 Recherche de motif

le .* correspond xigenc , la plus longue chane possible laquelle il peut correspondre. (Il stocke galement cette valeur dans $1, comme cela est expliqu dans la section Capture et regroupement plus loin dans ce chapitre.) Bien quune correspondance plus courte fut possible, un quantificateur gourmand sen moque. Sil a le choix entre deux possibilits partir de la mme position, il retournera toujours la plus longue des deux. Comparez ceci avec cela :
"exigence" =~ /e(.*?)e/ # $1 vaut maintenant "xig"

Ici, cest la version minimale, .*?, qui est utilise. Lajout du ? l* fait que *? a un comportement oppos : ayant le choix entre deux possibilits partir du mme point, il prend toujours la plus courte des deux. Bien que vous puissiez lire *? comme une injonction correspondre zro ou plus de quelque chose en prfrant zro, cela ne veut pas dire quil correspondra toujours zro caractre. Si ctait le cas ici, par exemple, et quil laissait $1 la valeur "", alors le second e ne serait pas trouv, puisquil ne suit pas immdiatement le premier. Vous pourriez aussi vous demander pourquoi, alors quil cherchait une correspondance minimale avec /e(.*?)e/, Perl na pas plutt mis nc dans $1. Aprs tout, nc se trouve lui aussi entre deux e et est plus court que xig . En Perl, le choix minimal/maximal se fait seulement lorsquon recherche la plus courte ou la plus longue parmi plusieurs correspondances ayant toutes le mme point de dpart. Si plusieurs correspondances possibles existent, mais commencent des endroits diffrents dans la chane, alors leurs longueurs nont aucune importance pas plus que le fait que vous ayez utilis un quantificateur minimal ou maximal. La premire de plusieurs correspondances possibles est toujours prpondrante devant celles qui la suivent. Cest seulement lorsque plusieurs correspondances possibles dmarrent du mme point dans la chane que le ct minimal ou maximal de la correspondance sert les dpartager. Si les points de dpart sont diffrents, il ny a rien dpartager. Les correspondances de Perl sont normalement de type la plus gauche la plus longue ; avec une correspondance minimale, cela devient la plus gauche la plus courte. Mais la partie la plus gauche ne change pas et reste le critre dominant.8 Il y a deux manires de passer lorientation gauche du dtecteur de motif. Premirement vous pouvez utiliser un quantificateur gourmand au dbut (typiquement .*) pour essayer de consommer le dbut de la chane. En cherchant la correspondance pour un quantificateur gourmand, il essaie dabord la correspondance la plus longue ce qui provoque effectivement une recherche de droite gauche dans le reste de la chane :
"exigence" =~ /.*e(.*?)e/ # $1 vaut maintenant "nc"

Mais faites attention avec cette mthode, car la correspondance complte contient maintenant toute la chane jusqu ce point.

8. Tous les moteurs de regex ne fonctionnent pas comme cela. Certains croient plutt en la gourmandise globale, o la correspondance la plus longue gagne toujours, mme si elle apparat plus tard dans la chane. Perl ne fonctionne pas comme cela. Vous pourriez dire que lardeur prime sur la gourmandise (ou le rationnement). Pour une discussion plus formelle de ce principe et de beaucoup dautres, voir la section Le petit Moteur qui /(ne )?pouvait( pas)?/ .

customer_8566

Positions

161

La seconde manire de dfaire cette inclination gauche est dutiliser les assertions de position, qui sont discutes dans la section suivante.

Positions
Certaines constructions de regex reprsentent des positions dans la chane traiter, qui est juste un emplacement gauche ou droite dun vritable caractre. Ces mtasymboles sont des exemples dassertions de largeur nulle. Nous les appellerons souvent simplement assertions . (On les connait aussi sous le nom d ancres , car elles lient une partie du motif une position particulire.) Vous pouvez toujours manipuler les positions dans une chane sans utiliser de motif. La fonction intgre substr vous permet dextraire et daffecter des sous-chanes, calcules partir du dbut de la chane, de la fin de la chane ou partir dune position numrique particulire. Cest juste ce dont vous avez besoin si vous travaillez avec des enregistrements de longueur fixe. Les motifs deviennent ncessaires quand un dcalage numrique nest plus suffisant. Et la plupart du temps, les dcalages ne sont pas suffisants disons pas suffisament commodes, par rapport aux motifs.

Les dbuts : assertions \A et ^


Lassertion \A correspond seulement au dbut de la chane, quelles que soient les circonstances. Cependant lassertion ^ est lassertion traditionnelle de dbut de ligne, ainsi que celle de dbut de chane. Cest pourquoi si le motif utilise le modificateur /m9 et que la chane contient des sauts de ligne, ^ correspond galement nimporte o dans la chane immdiatement aprs un caractre de saut de ligne :
/\Abar/ /^bar/ /^bar/m # Correspond "bar" et "barbecue" # Correspond "bar" et "barbecue" # Correspond "bar" et "barbecue" et "zinc\nbar"

Utilise en mme temps que /g, le modificateur /m permet ^ de correspondre plusieurs fois dans la mme chane :
s/^\s+//gm; $total++ while /^./mg; # Supprime les blancs en tte de chaque ligne # Compte les lignes qui ne sont pas vides

Fins : assertions \z, \Z et $


Le mtasymbole \z correspond la fin de la chane, quoi quil y ait lintrieur. \Z correspond juste avant le saut de ligne en fin de chane sil y en a un, ou la fin sil ny en a pas. Le mtacaractre $ signifie en gnral la mme chose que \Z. Cependant, si le modificateur /m a t spcifi et que la chane contient des sauts de ligne, alors $ peut aussi correspondre nimporte o dans la chane, juste avant un saut de ligne :
/bot\z/ /bot\Z/ # Correspond avec "robot" # Correspond avec "robot" et "poulbot\n"

9. Ou si vous avez mis la variable obsolte $* 1 et que vous nignorez pas $* avec le modificateur /s.

customer_8566

162
/bot$/ /bot$/m

Chapitre 5 Recherche de motif


# Correspond avec "robot" et "poulbot\n" # Correspond avec "robot" et "poulbot\n" et "robot\nmnager" et "robot\n" et "robot\n" et "ce\nrobot\n" et "robot\n" uniquement -- mais pourquoi ne

/^robot$/ # Correspond avec "robot" /^robot$/m # Correspond avec "robot" /\Arobot\Z/ # Correspond avec "robot" /\Arobot\z/ # Correspond avec "robot" #pas avoir utilis eq ?

Tout comme avec ^, le modificateur /mpermet $ de correspondre plusieurs fois dans la mme chane quand il est utilis avec /g. (Ces exemples supposent que vous avez lu un enregistrement multiligne dans $_, par exemple en mettant $/ "" avant la lecture.)
s/\s*$//gm; # Supprime les blancs en fin de chaque ligne du paragraphe

while (/^([^:]+):\s*(.*)/gm ) { # obtient les en-ttes de mail $headers{$1} = $2; }

Plus loin dans ce chapitre, la section Interpolation de variables, nous discuterons de la faon dont vous pouvez interpoler des variables dans des motifs : si $toto vaut bc , alors /a$toto/ est quivalent /abc/. Ici, le $ ne correspond pas la fin de la chane. Pour quun $ corresponde la fin de la chane, il doit tre la fin du motif ou tre immdiatement suivi dune barre verticale ou dune parenthse fermante.

Limites : assertions \b et \B
Lassertion \b correspond toute limite de mot, celle-ci tant dfinie comme la position entre un caractre \w et un caractre \W, dans nimporte quel ordre. Si lordre est \W\w cest la limite en dbut de mot, et si lordre est \w\W cest la limite en fin de mot. (Une extrmit de chane compte comme un caractre \W ici.) Lassertion \B correspond toute position qui nest pas une limite de mot, cest--dire au milieu de \w\w ou de \W\W.
/\best\b/ /\Best\B/ /\best\B/ /\Best\b/ # # # # correspond correspond correspond correspond "ce quil est" et " lest dEden" "zeste" et "intestin" "estival" et "il testime" et "ouest puis nord" "al

Comme \W comprend tous les caractres de ponctuation, (sauf le soulign), il y a des limites \b au milieu de chanes comme aujourdhui , booktech@oreilly.com , S.N.C.F. et cl/valeur . lintrieur dune classe de caractres ([\b]), un \b reprsente un caractre espace arrire plutt quune limite de mot.

Reconnaissance progressive
Utilise avec le modificateur /g, la fonction pos vous permet de connatre ou de modifier la position partir de laquelle la prochaine comparaison progressive commencera :
$voleur = "Bilbon Baggins"; while ($voleur =~ /b/gi) { printf "Trouv un B en %d\n", pos($voleur)-1; }

customer_8566

Positions

163

(Nous retirons un de la position car cest la longueur de la chane que nous voulions, alors que pos renvoie toujours la position juste aprs la fin de la reconnaissance prcdente.) Le code ci-dessus affiche :
Trouv un B en 0 Trouv un B en 3 Trouv un B en 7

Aprs un chec, la position de reconnaissance est normalement remise zro. Si vous utilisez le modificateur /c (pour continue ), alors quand le /g se termine, lchec de la reconnaissance ne rinitialise pas le pointeur de position. Cela vous permet de continuer votre recherche au-del de ce point, sans recommencer partir du dbut.
$voleur = "Bilbon Baggins"; while ($voleur =~ /b/gci) { # AJOUT DE /c printf "Trouv un B en %d\n", pos($voleur)-1; } while ($voleur =~ /i/gi) { printf "Trouv un I en %d\n", pos($voleur)-1; }

En plus des trois B trouvs prcdemment, Perl indique maintenant quil a trouv un i la position 11. Sans le /c, la seconde boucle de reconnaissance aurait recommenc depuis le dbut de la chane et dabord trouv un autre i la position 1.

L o vous en tiez : assertion \G


Ds que vous commencez rf lchir en termes de la fonction pos, il est tentant de commencer creuser dans votre chane coups de substr, mais cest rarement la bonne chose faire. La plupart du temps, si vous avez commenc avec une recherche de motif, vous devriez continuer avec une recherche de motif. Cependant, si vous recherchez une assertion de position, cest probablement \G quil vous faut. Lassertion \G reprsente lintrieur du motif le mme point que pos reprsente lextrieur. Quand vous faites une recherche progressive avec le modificateur /g (ou que vous avez utilis la fonction pos pour slectionner directement le point de dpart), vous pouvez utiliser \G pour spcifier la position qui suit la fin de la reconnaissance prcdente. Cest--dire quil reconnat la position immdiatement avant le caractre qui serait identifi par pos. Cela vous permet de vous souvenir o vous en tiez :
($recette = <<DISH) =~ s/^\s+//gm; # Anchois sauce Roswel Prchauffer le four 451 deg. fahrenheit. Mlanger 1 ml. de dilithium avec 3 oz. de NaCl et y plonger 4 anchois. Glacer avec 1 gr. de mercure. Faire cuire 4 heures et laisser refroidir 3 secondes. Pour 10 martiens. DISH $recette =~ /\d+ /g; $recette =~ /\G(\w+)/;

# $1 vaut "deg"

customer_8566

164
$recette $recette $recette $recette =~ =~ =~ =~ /\d+ /g; /\G(\w+)/; /\d+ /g; /\G(\w+)/;

Chapitre 5 Recherche de motif

# $1 vaut "ml" # $1 vaut "gr"

Le mtasymbole \G est souvent utilis dans une boucle, comme nous allons le monrer dans notre prochain exemple. Nous faisons une pause aprs chaque suite de chiffres, et cette position, nous testons sil y a une abrviation. Si oui, nous rcuprons les deux mots qui suivent. Sinon, nous rcuprons seulement le mot suivant :
pos($recette) = 0; # Par scurit, initialise \G 0 while ( $recette =~ /(\d+) /g ) { my $quantite = $1; if ($recette =~ / \G (\w{0,3}) \. \s+ de \s+ (\w+) /x) { # abrv. + mot print "$quantite $1 de $2\n"; } else { $recette =~ / \G (\w+) /x; # juste un mot print "$quantite $1\n"; } }

Ce qui donne :
451 deg 1 ml de dilithium 3 oz de NaCl 4 anchois 1 gr de mercure 4 heures 3 secondes 10 martiens

Capture et regroupement
Les motifs vous permettent de regrouper des portions de votre motif dans des sous-motifs et de vous souvenir des chanes reconnues par ces sous-motifs. Nous appellerons le premier comportement regroupement et le second capture.

Capture
Pour capturer une sous-chane pour une utilisation ultrieure, mettez des parenthses autour du motif qui la reconnat. La premire paire de parenthses stocke sa sous-chane dans $1, la deuxime paire dans $2 et ainsi de suite. Vous pouvez utilisez autant de parenthses que vous voulez ; Perl continuera dfinir des variables numrotes pour que vous puissiez reprsenter ces chanes captures. Quelques exemples :
/(\d)(\d)/ # Trouve deux chiffres, qui sont capturs dans $1 et $2 /(\d+)/ # Trouve un ou plusieurs chiffres, capturs ensemble dans $1 /(\d)+/ # Trouve un chiffre une fois ou plus, et capture le dernier dans $1

Remarquez la diffrence entre le deuxime et le troisime motifs. La deuxime forme

customer_8566

Capture et regroupement

165

est en gnral ce que vous voulez. La troisime forme ne cre pas plusieurs variables pour plusieurs chiffres. Les parenthses sont numrotes quand le motif est compil, pas quand il est utilis. Les chanes captures sont souvent appeles rfrences arrires car elles font rfrence des parties du texte situes en arrire par rapport la position courante. Il existe en fait deux manires dutiliser ces rfrences arrires. Les variables numrotes que vous avez vues donnent accs en dehors du motif aux rfrences arrires, mais lintrieur du motif, cela ne marche pas. Vous devez utiliser \1, \2, etc.10 Pour trouver les mots doubls comme le le ou est est , vous pourriez utilisez ce motif :
/\b(\w+) \1\b/i

Mais la plupart du temps, vous utiliserez la forme $1, car en gnral on applique un motif, pour ensuite faire quelque chose des sous-chanes. Supposons que vous ayez du texte (des en-ttes de mail) qui ressemble a :
From: gnat@perl.com To: camelot@oreilly.com Date: Mon, 17 Jul 2000 09:00:00 -1000 Subject: Eye of the needle

et que vous vouliez construire un hachage qui fasse le lien entre le texte avant les deuxpoints et celui aprs. Si vous boucliez sur ce texte ligne ligne (par exemple parce que vous lisez un fichier), vous pourriez faire comme suit :
while (<>) { /^(.*?): (.*)$/; $champs{$1} = $2; } # Texte avant les deux-points dans $1, aprs dans $2

Comme $`, $& et $, ces variables numrotes sont porte dynamique jusqu la fin du bloc ou de la chane eval englobant, ou jusqu la prochaine recherche de motif russie, selon lequel se produit le premier. Vous pouvez galement les utiliser dans la partie droite (la zone de remplacement) dune substitution :
s/^(\S+) (\S+)/$2 $1/; # Intervertit les deux premiers mots

Les regroupements peuvent semboter, et quand ils le font, les groupes sont compts par lordre de leurs parenthses ouvrantes. Donc, si on donne la chane Primula Brandebouc au motif :
/^((\w+) (\w+))$/

il capturerait Primula Brandebouc dans $1, Primula dans $2, et Brandebouc dans $3. Cela est dcrit la figure 5-1.

10. Vous ne pouvez pas utiliser $1 pour une rfrence arrire lintrieur dun motif, car il aurait dj t interpol au moment o la regex a t compile. Cest pourquoi nous utilisons la notation traditionnelle \1 pour les rfrences arrires lintrieur dun motif. Pour les rfrences deux ou trois chiffres, il y a une ambigut avec la notation octale des caractres, mais cest finement rsolu en regardant combien de motifs capturs sont disponibles. Par exemple, si Perl voit un mtasymbole \11, cest quivalent $11 seulement sil y a au moins 11 sous-chanes capturs plus tt dans le motif. Sinon cest quivalent \011, cest--dire un caractre de tabulation.

customer_8566

166

Chapitre 5 Recherche de motif

Figure 5-1. Cration de rfrences arrires avec des parenthses Les motifs avec capture sont souvent utiliss en contexte de liste pour remplir une liste de valeurs, car le motif est assez malin pour retourner les sous-chanes comme une liste :
($premier, $dernier) = /^(\w+) (\w+)$/; ($tout, $premier, $dernier) = /^((\w+) (\w+))$/;

Avec le modificateur /g, un motif peut renvoyer plusieurs sous-chanes issues de plusieurs correspondances, le tout dans une seule liste. Supposons que vous ayez len-tte que nous avons vu prcdemment dans une seule chane (disons dans $_). Vous pourriez faire la mme chose que notre boucle ligne ligne avec une seule instruction :
%champs = /^(.*?): (.*)$/gm;

Le motif russit quatre fois, et chaque fois il trouve deux sous-chanes. La recherche /gm retourne lensemble comme une liste plate de huit chanes, que laffectation de liste %champs interprtera comme quatre couples cl/valeur, ramenant ainsi lharmonie dans lunivers. Plusieurs autres variables spciales traitent du texte captur dans des recherches de motif. $& contient la chane trouve dans son ensemble, $` tout ce qui est gauche de la correspondance, $ tout ce qui est droite. $+ garde le contenu de la dernire rfrence arrire.
$_ = "Parlez, <EM>ami</EM>, et entrez."; m[ (<.*?>) (.*?) (</.*?>) ]x; # Une balise, du texte, et une balise de fin print "prematch: $`\n"; # Parlez, print "match: $&\n"; # <EM>ami</EM> print "postmatch: $\n"; # , et entrez. print "lastmatch: $+\n"; # </EM>

Pour plus dexplication sur ces variables elfiques magiques (et pour savoir comment les crire en anglais), voir le chapitre 28, Noms spciaux. Le tableau @- (@LAST_MATCH_START) contient les positions des dbuts de chacunes des correspondances, et @+ (@LAST_MATCH_END) contient les positions de leurs fins :
#!/usr/bin/perl $alphabet = "abcdefghijklmnopqrstuvwxyz"; $alphabet =~ /(hi).*(stu)/; print "La recherche complte a commenc en $-[0] et sest termine en $+[0]\n";

customer_8566

Capture et regroupement
print "La premire recherche a commenc en $-[1] et sest termine en $+[1]\n"; print "La deuxime recherche a commenc en $-[2] et sest termine en $+[2]\n";

167

Si vous voulez trouver une parenthse littrale plutt que de linterprter comme un mtacaractre, antislashez-la :
/\(p.e., .*?\)/

Ceci trouve un exemple entre parenthses (p.e., celui-ci). Mais comme le point est un joker, cela trouve aussi toute phrase entre parenthses dont la premire lettre est un p et la troisime un e (pied, par exemple).

Regroupement
Les parenthses simples regroupent et capturent la fois. Mais parfois vous nen demandez pas tant. Parfois vous voulez juste regrouper des portions du motif sans crer de rfrence arrire. Vous pouvez utiliser une forme tendue de parenthses pour supprimer la capture : la notation (?:PATTERN) va regrouper sans capturer. Il y a au moins trois raisons pour lesquelles vous voudrez regrouper sans capturer : 1. Pour quantifier quelque chose. 2. Pour limiter la porte dune alternative ; par exemple, /^chat|chien|vache$/ aura besoin dtre crit /^(?:chat|chien|vache)$ si vous ne voulez pas que le chat file avec le ^. 3. Pour limiter la porte dun modificateur de motif un sous-motif spcifique, comme dans /toto(?-i:Attention_A_La_Casse)titi/i. (Voir la section suivante, Modificateurs clotrs.) De plus, il est plus efficace de supprimer la capture de quelque chose que vous nallez pas utiliser. En revanche, la notation est un peu moins lisible. Dans un motif, une parenthse ouvrante immdiatement suivie dun point dinterrogation indique une extension de regex. Le bestiaire actuel des expressions rgulires est relativement fix nous nosons pas crer un nouveau mtacaractre, de peur de casser danciens programmes Perl. Au lieu de cela, la syntaxe dextension permet dajouter de nouvelles fonctionnalits au bestiaire. Dans le reste du chapitre, nous allons voir beaucoup dautres extensions de regex, lesquelles feront toutes du regroupement sans capture, avec quelque chose dautre. Lextension (?:MOTIF) est spciale en ce quelle ne fait rien dautre. Donc si vous crivez :
@champs = split(/\b(?:a|b|c)\b/)

cest comme :
@champs = split(/\b(a|b|c)\b/)

sauf que cela ne renvoie pas de champs supplmentaires. (Loprateur split est un peu comme m//g en ce quil retournera des champs supplmentaires pour chaque chane capture dans le motif. Dordinaire, split ne retourne que ce qui na pas t trouv. Pour en savoir plus sur split, voir le chapitre 29.)

customer_8566

168

Chapitre 5 Recherche de motif

Modificateurs clotrs
Vous pouvez clotrer les modificateurs /i, /m, /s et /x dans une portion de votre motif en les insrant (sans le slash) entre le ? et le : de la notation de regroupement. Si vous crivez :
/Harry (?i:s) Truman/

cela correspondra la fois Harry S Truman et Harry s Truman , tandis que :


/Harry (?x: [A-Z] \.? \s )?Truman/

correspondra la fois Harry S Truman et Harry S. Truman , aussi bien qu Harry Truman , et :
/Harry (?ix: [A-Z] \.? \s )?Truman/

trouvera les cinq, en combinant les modificateurs /i et /x dans le clotre. Vous pouvez galement soustraire des modificateurs dun clotre avec un signe moins :
/Harry (?x-i: [A-Z] \.? \s )?Truman/i

Ceci trouve le nom dans toutes les combinaisons de majuscules et minuscules mais si linitiale centrale est fournie, elle doit tre en majuscules, car le /i appliqu au motif dans son ensemble est suspendu lintrieur du clotre. En omettant les deux-points et le MOTIF, vous pouvez exporter les rglages des modificateurs un regroupement extrieur, en le transformant en clotre. Cest--dire que vous pouvez slectivement activer ou dsactiver les modificateurs pour le regroupement qui se trouve un niveau lextrieur des parenthses du modificateur, comme ceci :
/(?i)toto/ /toto((?-i)titi)/i /toto((?x-i) titi)/ # quivalent /toto/i # "titi" doit tre en minuscules # Active /x et dsactive /i pour "titi"

Remarquez que le deuxime et le troisime exemples crent des rfrences arrires. Si ce ntait pas ce que vous vouliez, alors vous auriez d utiliser respectivement (?-i:titi) et (?x-i: titi). Activer les modificateurs sur une partie de votre motif est particulirement utile quand vous voulez que . corresponde des sauts de ligne dans une partie de votre motif, mais pas dans le reste. Activer /s sur tout le motif ne vous sera daucune utilit dans ce cas.

Alternative
lintrieur dun motif ou dun sous-motif, utilisez le mtacaractre | pour spcifier un ensemble de possibilits dont chacune peut correspondre. Par exemple :
/Gandalf|Saroumane|Radagaste/

correspond Gandalf, Saroumane ou Radagaste. Lalternative stend seulement jusquaux parenthses qui lentourent les plus proches (quelles capturent ou non) :
/perc|l|s|tes/ /per(c|l|s|t)es/ /per(?:c|l|s|t)es/ # Trouve perc, l, s ou tes # Trouve perces, perles, perses ou pertes # Trouve perces, perles, perses ou pertes

customer_8566

Alternative

169

La deuxime et la troisime formes correspondent aux mmes chanes, mais la deuxime capture le caractre changeant, tandis que la troisime ne le fait pas. Dans toutes les positions, le Moteur essaie de trouver le premier lment de lalternative, puis le deuxime, et ainsi de suite. La longueur de chaque lment na pas dimportance, ce qui signifie que dans ce motif :
/(Sam|Samsagace)/

$1 ne vaudra jamais Samsagace, quelle que soit la chane sur laquelle on lutilise, car Sam sera toujours trouv en premier. Quand vous avez des recherches qui se superposent comme ceci, mettez les plus longues au dbut. Mais lordre des lments de lalternative na dimportance qu une position donne. La boucle externe du Moteur fait une recherche de gauche droite, cest pourquoi ce qui suit trouve toujours le premier Sam :
"Sam je suis, dit Samsagace" =~ /(Samsagace|Sam)/; # $1 eq "Sam"

Mais vous pouvez forcer une recherche de droite gauche en utilisant les quantificateurs gourmands, comme nous lavons vu prcdemment dans Quantificateurs :
"Sam je suis, dit Samsagace" =~ /.*(Samsagace|Sam)/; # $1 eq "Samsagace"

Vous pouvez dfaire toute recherche gauche droite (ou de droite gauche) en incluant nimporte laquelle des assertions de position vues prcdemment, comme \G, ^ et $. Ici nous ancrons le motif la fin de la chane :
"Sam je suis, dit Samsagace" =~ /(Samsagace|Sam)$/; # $1 eq "Samsagace"

Cet exemple met le $ en facteur en dehors de lalternative (car nous avions dj une paire de parenthses en dehors de laquelle le mettre), mais en labsence de parenthses vous pouvez galement distribuer les assertions sur tout ou partie des lments de lalternative, selon comment vous voulez quils trouvent. Ce petit programme affiche les lignes qui commencent par un token __DATA__ ou __END__ :
#!/usr/bin/perl while (<>) { print if /^__DATA__|^__END__/; }

Mais faites attention avec cela. Souvenez-vous que le premier et le dernier lments de lalternative (avant le premier | et aprs le dernier) ont tendance avaler les autres de chaque ct, sauf sil y a des parenthses autour. Une erreur courante est de demander :
/^chat|chien|vache$/

quand vous voulez en fait :


/^(chat|chien|vache)$/

La premire trouve chat au dbut de la chane, ou chien nimporte o, ou bien vache en fin de chane. La deuxime trouve nimporte quelle chane consistant simplement de chat , chien ou vache . Elle capture galement $1, ce qui nest pas forcment ce que vous voulez. Vous pouvez galement crire :
/^chat$|^chien$|^vache$/

Nous vous montrerons une autre solution plus loin. Un lment de lalternative peut tre vide, auquel cas il russit toujours.

customer_8566

170

Chapitre 5 Recherche de motif

/com(posite|)/; # Trouve "composite" ou "com" /com(posite(s|)|)/; # Trouve "composites", "composite" ou "com"

Cela revient utiliser le quantificateur ?, qui trouve 0 ou 1 fois :


/com(posite)?/; # Trouve "composite" ou "com" /com(posite(s?))?/; # Trouve "composites", "composite" ou "com" /com(posites?)?/; # Pareil, mais nutilise pas $2

Il y a cependant une diffrence. Quand vous appliquez le ? un sous-motif qui fait une capture dans une variable numrote, cette variable sera indfinie sil ny a pas de chane y mettre. Si vous avez mis llment vide dans lalternative, elle serait toujours fausse, mais ce serait en fait une chane vide dfinie.

Garder le contrle
Comme le sait tout bon chef dquipe, cela ne sert rien dtre toujours sur le dos de vos employs. Dites-leur simplement ce que vous voulez, et laissez-les trouver la meilleure manire de le faire. De mme, la meilleure manire de voir une expression rgulire, cest comme une spcification : Voil ce que je veux ; trouve-moi une chane qui correspond . Dun autre ct, les meilleurs chefs dquipe comprennent ce que leurs employs essayent de faire. Cest galement vrai pour les expressions rgulires en Perl. Mieux vous comprenez comment Perl sacquitte de la tche de trouver un motif particulier, plus vous serez capable dutiliser les capacits de recherche de motif de Perl en connaissance de cause. Une des choses les plus importantes comprendre propos de la recherche de motif en Perl, cest quand ne pas lutiliser.

Laisser Perl faire le boulot


Quand certaines personnes apprennent les expressions rgulires, elles sont souvent tentes de voir tout problme comme un problme de recherche de motif. Et quand bien mme ce serait vrai en gnral, la recherche de motif est plus que la simple valuation dexpressions rgulires. Cest aussi comme rechercher vos cls de voiture o vous les avez fait tomber, et pas seulement sous le rverbre, l o vous y voyez le mieux. Dans le monde rel, nous savons tous quil est plus efficace de chercher aux bons endroits quaux mauvais. De mme, vous devriez utiliser le contrle de f lux de Perl pour dcider quels motifs excuter et lesquels ignorer. Une expression rgulire est plutt maligne, mais pas plus quun cheval. Elle peut tre distraite si elle voit trop de choses la fois. Cest pourquoi il vous faut parfois lui mettre des illres. Par exemple, souvenez-vous de notre prcdent exemple dalternative :
/Gandalf|Saroumane|Radagaste/

Cela marche comme prvu, mais pas aussi bien que possible, car elle cherche chaque nom chaque position dans la chane avant de passer la suivante. Les lecteurs attentifs du Seigneur des anneaux se souviendront que, des trois magiciens mentionns ci-dessus, Gandalf est mentionn plus souvent que Saroumane, et que Saroumane est mentionn

customer_8566

Garder le contrle

171

plus souvent que Radagaste. Il est donc en gnral plus efficace dutiliser les oprateurs logiques de Perl pour raliser lalternative :
/Gandalf/ || /Saroumane/ || /Radagaste/

Cest galement une autre manire de passer outre la recherche oriente gauche du Moteur. Il ne recherche Saroumane que si Gandalf est introuvable. Et il ne cherche Radagaste que si Saroumane est galement absent. Non seulement cela change lordre de recherche des diffrents termes, but cela permet galement loptimiseur dexpressions rgulires de mieux fonctionner. Il est en gnral plus simple doptimiser la recherche pour une seule chane que pour plusieurs la fois. De mme, les recherches ancres peuvent souvent tre optimises si elles ne sont pas trop compliques. Vous navez pas vous limiter loprateur || pour le contrle de f lux. Vous pouvez souvent contrler les choses au niveau des instructions. Vous devriez toujours penser vous dbarrasser des cas les plus courants en premier. Supposons que vous criviez une boucle pour traiter un fichier de configuration. La plupart des fichiers de configuration sont composs principalement de commentaires. Cest souvent mieux de supprimer les commentaires et les lignes blanches avant de sattaquer aux lourds traitements, mme si les lourds traitements supprimeraient galement les commentaires et lignes blanches en cours de route :
while (<CONF>) { next if /^#/; next if /^\s*(#|$)/; chomp; meugneumeugneu($_); }

Mme si vous nessayez pas dtre efficace, vous avez souvent besoin dalterner entre les expressions Perl normales et les expressions rgulires, simplement parce que vous voulez faire quelque chose qui nest pas possible (ou qui est trs difficile) lintrieur dune expression rgulire, comme afficher quelque chose. Voici un classificateur de nombres bien utile :
warn warn warn warn warn warn warn "contient des non-chiffres" if /\D/; "pas un nombre naturel" unless /^\d+$/; # rejette -3 "pas un entier" unless /^-?\d+$/; # rejette +3 "pas un entier" unless /^[+-]?\d+$/; "pas un nombre dcimal" unless /^-?\d+\.?\d*$/; # rejette .2 "pas un nombre dcimal" unless /^-?(?:\d+(?:\.\d*)?|\.\d+)$/; "pas un flottant de C" unless /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/;

Nous pourrions encore beaucoup allonger cette section, mais ceci est vraiment le sujet de tout le livre. Vous verrez encore beaucoup dexemples mlant du code Perl et des recherches de motif au long du livre. En particulier, reportez-vous la section suivante Motifs programmatiques. (Mais vous pouvez quand mme commencer par lire ce qui suit, bien sr.)

customer_8566

172

Chapitre 5 Recherche de motif

Interpolation de variables
Lutilisation des mcanismes de contrle de f lux de Perl pour contrler les expressions rgulires a ses limites. La difficult principale est quil sagit dune approche tout ou rien ; soit vous faites tourner le motif, soit vous ne le faites pas tourner. Parfois vous savez vaguement ce que vous cherchez, mais vous aimeriez avoir la possibilit de le paramtrer. Linterpolation de variables fournit cette capacit, tout comme le paramtrage des sous-programmes vous permet davoir une plus grande inf luence sur leur comportement que simplement de choisir entre les appeler ou non. (Vous en verrez plus sur les sous-programmes au chapitre suivant.) Un des intrts de linterpolation est de fournir un peu dabstraction, ainsi quun peu de lisibilit. Avec des expressions rgulires, il est certes possible dcrire les choses de faon concise :
if ($num =~ /^[-+]?\d+\.?\d*$/) { ... }

Mais ce que vous voulez dire est plus comprhensible ainsi :


$signe = [-+]?; $chiffres = \d+; $point_decimal = \.?; $encore_des_chiffres = \d*; $nombre = "$signe$chiffres$point_decimal$encore_des_chiffres"; ... if ($num =~ /^$nombre$/o) { ... }

Nous couvrirons un peu plus cette utilisation de linterpolation dans la section Motifs gnrs, plus loin dans ce chapitre. Notez juste que nous avons utilis le modificateur /o pour supprimer la recompilation du motif, car nous ne nous attendons pas ce que $nombre change de valeur au cours du programme. Un autre truc sympa est de renverser vos tests et de vous servir de la chane variable comme motif vis--vis dun ensemble de chanes connues :
chomp($reponse if ("SEND" elsif ("STOP" elsif ("ABORT" elsif ("LIST" elsif ("EDIT" = <STDIN>); =~ /^\Q$reponse/i) =~ /^\Q$reponse/i) =~ /^\Q$reponse/i) =~ /^\Q$reponse/i) =~ /^\Q$reponse/i) { { { { { print print print print print "Action "Action "Action "Action "Action : : : : : send\n" stop\n" abort\n" list\n" edit\n" } } } } }

Ceci permet lutilisateur de lancer laction send en tapant S, SE, SEN ou SEND (dans nimporte quel mlange de majuscules et minuscules). Pour faire stop , il lui faudra au moins taper ST (ou St, sT ou st).

Retour de lantislash
Quand vous pensez linterpolation entre apostrophes doubles, vous pensez gnralement linterpolation des variables et des antislashs. Mais comme nous lavons indiqu prcdemment, il y a deux passes pour les expressions rgulires, et la passe dinterpolation laisse la plupart du travail dinterprtation des antislashs lanalyseur dexpressions rgulires (dont nous parlerons plus tard). Dordinaire, vous ne remarquerez pas de diffrence, car Perl fait bien attention les masquer. (Une squence qui est videm-

customer_8566

Garder le contrle

173

ment diffrente est le mtasymbole \b, qui se transforme en assertion de limite en dehors des classes de caractres, en tout cas. lintrieur dune classe de caractres, o les assertions nont aucun sens, il redevient un espace arrire, comme dhabitude.) Il est en fait assez important que lanalyseur de regex gre les antislashs. Imaginons que vous cherchiez les caractres de tabulation avec un motif sous le modificateur /x :
($col1, $col2) = /(.*?) \t+ (.*?)/x;

Si Perl ne laissait pas linterpolation de \t lanalyseur de regex, le \t se serait transform en un blanc que lanalyseur de regex aurait btement ignor cause du /x. Mais Perl nest ni si ignoble, ni si pigeant. Vous pouvez cependant vous piger tout seul. Imaginons que vous ayez un peu virtualis le sparateur de colonne, comme ceci :
$sepcol = "\t+"; # (apostrophes doubles) ($col1, $col2) = /(.*?) $sepcol (.*?)/x;

Et maintenant vous voil fait comme un rat, car le \t se transforme en vritable tabulation avant datteindre lanalyseur de regex, qui croira que vous avez crit /(.*?)+(.*?)/ une fois les blancs supprims. Oups. Pour corriger cela, vitez /x ou bien utilisez des apostrophes simples. Ou mieux, utilisez qr//. (Voir la section suivante.) Les seules squences dchappement entre apostrophes doubles qui sont traites comme telles sont les six squences de traduction : \U, \u, \L, \l, \Q et \E. Si jamais vous vous plongez un jour dans le fonctionnement interne du compilateur dexpressions rgulires, vous y trouverez du code destin grer les squences dchappement comme \t pour la tabulation, \n pour le saut de ligne, et ainsi de suite. Mais vous ny trouverez pas de code pour ces six squences de traduction. (Nous avons listes dans le tableau 5-7 uniquement car cest l quon sattend les trouver.) Si vous vous dbrouillez pour les inclure dans le motif sans passer par lvaluation entre apostrophes doubles, elles ne seront pas reconnues. Comment ont-elles pu sy glisser ? Vous pouvez contrecarrer linterpolation en utilisant des apostrophes simples comme dlimiteurs de motifs. Les apostrophes simples suppriment linterpolation de variables et le traitement des squences de traduction dans m..., qr... et s......, comme ils le feraient dans une chane entre apostrophes simples. crire m\ufrodon ne trouvera pas une version en majuscules de ce pauvre frodon. Cependant, comme les antislash normaux ne sont pas vraiment traits ce niveau, m\t\d trouvera toujours une vraie tabulation suivie dun chiffre quelconque. Une autre manire de contrecarrer linterpolation est de passer par linterpolation ellemme. Si vous crivez :
$var = \U; /${var}frodon/;

ce pauvre frodon reste en minuscules. Perl ne refera pas la passe dinterpolation pour vous simplement parce que vous avez interpol quelque chose qui a lair de vouloir tre interpol. Vous ne pouvez pas plus esprer que cela soit interpol que vous ne pourriez attendre que cette double interpolation marche :
$hobbit = Frodon; $var = $hobbit; /$var/; # (apostrophes simples) # signifie m$hobbit, et pas mFrodon.

customer_8566

174

Chapitre 5 Recherche de motif

Voici un autre exemple qui montre comment les antislashs sont interprts par lanalyseur de regex et pas par linterpolation de variables. Imaginons que vous ayez un petit utilitaire simple la grep :11
#!/usr/bin/perl $motif = shift; while (<>) { print if /$motif/o; }

Si vous appelez ce programme pgrep et linvoquez comme suit :


% pgrep \t\d *.c

alors vous dcouvrirez quil affiche toutes les lignes de tous vos fichiers source C dans lesquelles un chiffre suit une tabulation. Vous navez rien eu faire de spcial pour que Perl se rende compte que \t tait une tabulation. Si les motifs de Perl taient simplement interpols en contexte dapostrophes doubles, vous auriez d faire quelque chose ; heureusement ils ne le sont pas. Ils sont directement reconnus par lanalyseur de regex. Le vrai programme grep a une option -i qui rend la recherche insensible la casse. Vous navez pas besoin dajouter une telle option votre programme pgrep ; il peut dj le faire sans modification. Il suffit de lui passer un motif un peu plus labor, avec un modificateur /i inclus :
% pgrep (?i)anneau LotR*.pod

On cherche maintenant Anneau , anneau , ANNEAU et ainsi de suite. Vous ne verrez pas beaucoup cette fonctionnalit dans les motifs littraux, puisque vous pouvez simplement crire /anneau/i. Mais pour les motifs passs sur la ligne de commande, dans les formulaires web ou inclus dans les fichiers de configuration, cela peut savrer primordial.

Loprateur qr// de citation de regex


Les variables qui sont interpoles en motifs le sont ncessairement lexcution et non la compilation. Ceci ralentit lexcution, car Perl doit vrifier que vous navez pas chang le contenu de la variable ; si cest le cas, il faut alors recompiler lexpression rgulire. Comme mentionn dans Oprateurs de recherche de motifs, si vous promettez de ne jamais modifier le motif, vous pouvez utiliser loption /o pour interpoler et compiler une seule fois :
print if /$pattern/o;

Bien que cela fonctionne correctement dans notre programme pgrep, ce nest pas le cas en gnral. Imaginez que vous ayez une f loppe de motifs et que vous vouliez tous les tester dans une boucle, peut-tre comme ceci :
foreach $elem (@donnees) { foreach $motif (@motifs) {
11. Si vous ne saviez pas ce quest un programme comme grep, vous le saurez. Il ne devrait pas y avoir de systme sans grep nous pensons que grep est le plus utile des petits programmes jamais invents. (Ce qui logiquement indique que nous ne croyons pas que Perl soit un petit programme.)

customer_8566

Garder le contrle
if ($elem =~ /$motif/) { ... } } }

175

Vous ne pourriez pas crire /$motif/o, car la signification de $motif change chaque tour de la boucle interne. Ce problme est rsolu par loprateur qr/MOTIF/imosx. Cet oprateur cite et compile son MOTIF comme une expression rgulire. MOTIF est interpol de la mme faon que dans m/MOTIF/. Si est utilis comme dlimiteur, aucune interpolation de variable (ni des squences de traduction) nest faite. Loprateur renvoie une valeur Perl qui peut tre utilise la place de la chane littrale quivalente dans la recherche ou la substitution correspondante. Par exemple :
$regex = qr/ma.CHAINE/is; s/$regex/quelque chose dautre/;

est quivalent :
s/ma.CHAINE/quelque chose dautre/is;

Pour rsoudre notre problme prcdent de boucles embotes, vous pouvez donc dabord traiter le motif dans une boucle spare :
@regexes = (); foreach $motif (@motifs) { push @regexes, qr/$motif/; }

Ou bien dun seul coup en utilisant loprateur map de Perl :


@regexes = map { qr/$_/ } @motifs;

Puis modifier la boucle pour utiliser ces regex prcompiles :


foreach $elem (@donnees) { foreach $re (@regexes) { if ($elem =~ /$re/) { ... } } }

Dsormais quand vous faites tourner la recherche, Perl nest plus oblig de crer une expression rgulire compile chaque test if, car il se rend compte quil en possde dj une. Le rsultat dun qr// peut mme tre interpol dans un motif plus grand, comme sil sagissait dune simple chane :
$regex = qr/$motif/; $chaine =~ /toto${regex}titi/; # interpolation dans un motif plus grand

Cette fois Perl recompile le motif, mais vous pourriez chaner plusieurs oprateurs qr// en un seul. La raison pour laquelle cela fonctionne est que loprateur qr// retourne un objet spcial pour lequel la conversion en chane est surcharge comme dcrit au chapitre 13, Surcharge. Si vous affichez la valeur de retour, vous verrez la chane quivalente :
$re = qr/ma.CHAINE/is; print $re; # affiche (?si-xm:ma.CHAINE)

customer_8566

176

Chapitre 5 Recherche de motif

Les modificateurs /i et /s ont t activs dans le motif car ils ont t fournis qr//. De mme, /x et /m sont dsactivs car ils nont pas t fournis. chaque fois que vous interpolez des chanes de provenance inconnue dans un motif, vous devriez tre prt traiter les exceptions renvoyes par le compilateur de regex, dans le cas o lon vous aurait pass une chane contenant des bestioles indomptables :
$re = qr/$motif/is; # peut schapper et vous mordre $re = eval { qr/$motif/is } || warn ... # pris dans une cage extrieure

Pour en savoir plus sur loprateur eval, voir le chapitre 29.

Le compilateur de regex
Aprs que la passe dinterpolation de variable est passe sur la chane, lanalyseur de regex a enfin une occasion dessayer de comprendre votre expression rgulire. ce niveau-l, il ny a plus grand chose qui peut mal se passer, sinon embrouiller les parenthses ou utiliser une squence de mtacaractres qui na aucun sens. Lanalyseur fait une analyse rcursive descendante de votre expression rgulire et si elle est correcte, la met sous une forme interprtable par le Moteur (voir la section suivante). La plupart des choses intressantes qui se passent dans lanalyseur sont lies loptimisation de votre expression rgulire afin quelle soit excute le plus rapidement possible. Nous ne chercherons pas expliquer cette partie-l. Cest un secret de fabrication. (Ne croyez pas les rumeurs qui disent que regarder le code li aux expressions rgulires vous rendra fou ; elles sont trs exagres. Esprons-le.) Mais vous pourriez avoir envie de savoir ce que lanalyseur a vraiment pens de votre expression rgulire. Si vous lui demandez poliment, il vous le dira. En utilisant use re "debug";, vous pouvez examiner le traitement de votre motif par lanalyseur. (Vous pouvez galement obtenir la mme information en utilisant loption de ligne de commande -Dr. Celle-ci est disponible si votre Perl a t compil avec loption -DDEBUGGING lintallation.)
#!/usr/bin/perl use re "debug"; "Smeagol" =~ /^Sm(.*)g[aeiou]l$/;

La sortie suit. Vous pouvez voir quavant lexcution Perl compile la regex et donne une signification aux composantes du motif : BOL pour le dbut de ligne (^ ou Beginning Of Line), REG_ANY pour le point, et ainsi de suite :
Compiling REx `^Sm(.*)g[aeiou]l$ size 24 first at 2 rarest char l at 0 rarest char S at 0 1: BOL(2) 2: EXACT <Sm>(4) 4: OPEN1(6) 6: STAR(8) 7: REG_ANY(0) 8: CLOSE1(10) 10: EXACT <g>(12) 12: ANYOF[aeiou](21)

customer_8566

Garder le contrle
21: EXACT <l>(23) 23: EOL(24) 24: END(0) anchored `Sm at 0 floating `l$ at 4..2147483647 (checking anchored) anchored(BOL) minlen 5

177

Certaines de ces lignes rsument les conclusions de loptimiseur de regex. Il sait que la chane doit commencer par Sm et quil ny a donc aucune raison de faire lhabituelle recherche de gauche droite. Il sait que la chane doit se terminer par un l et peut donc rejeter directement celles qui ne le sont pas. Il sait que la chane doit faire au moins cinq caractres de long, et peut donc ignorer toute chane plus courte que cela sans autre forme de procs. Il sait galement quels sont les caractres les moins courants dans chaque sous-chane constante, ce qui peut aider avec les chanes tudies par study. (Voir study au chapitre 29.) Ensuite il liste la faon dont le motif est excut :
Guessing start of match, REx `^Sm(.*)g[aeiou]l$ against `Smeagol... Guessed: match at offset 0 Matching REx `^Sm(.*)g[aeiou]l$ against `Smeagol Setting an EVAL scope, savestack=3 0 <> <Smeagol> | 1: BOL 0 <> <Smeagol> | 2: EXACT <Sm> 2 <Sm> <eagol> | 4: OPEN1 2 <Sm> <eagol> | 6: STAR REG_ANY can match 5 times out of 32767... Setting an EVAL scope, savestack=3 7 <Smeagol> <> | 8: CLOSE1 7 <Smeagol> <> | 10: EXACT <g> failed... 6 <Smeago> <l> | 8: CLOSE1 6 <Smeago> <l> | 10: EXACT <g> failed... 5 <Smeag> <ol> | 8: CLOSE1 5 <Smeag> <ol> | 10: EXACT <g> failed... 4 <Smea> <gol> | 8: CLOSE1 4 <Smea> <gol> | 10: EXACT <g> 5 <Smeag> <ol> | 12: ANYOF[aeiou] 6 <Smeago> <l> | 21: EXACT <l> 7 <Smeagol> <> | 23: EOL 7 <Smeagol> <> | 24: END Match successful! Freeing REx: `^Sm(.*)g[aeiou]l$

Si vous suivez le blanc au milieu de Smeagol, vous pouvez voir le Moteur aller au plus loin pour que le .* soit aussi gourmand que possible, puis revient en arrire jusqu trouver une faon pour le reste du motif de russir. Mais cest justement le sujet de la section suivante.

customer_8566

178

Chapitre 5 Recherche de motif

Le petit Moteur qui /(ne )?pouvait( pas)?/


Et maintenant nous aimerions vous raconter lhistoire du petit Moteur de Regex qui dit Je crois que jpeux. Je crois que jpeux. Je crois que jpeux. .12 Dans cette section, nous allons prsenter les rgles que le Moteur utilise pour effectuer les recherches de correspondance de motifs. Le Moteur est extrmement persvrant et travailleur. Il est tout fait capable de continuer travailler alors que vous croyiez quil aurait dj abandonn. Le Moteur nabandonne pas tant quil nest pas absolument sr quil ny a aucun moyen pour lui de trouver une correspondance entre le motif et la chane. Les rgles ci-dessous expliquent comment le Moteur croit quil peut aussi longtemps que possible, jusqu ce quil sache quil peut ou ne peut pas. Le problme de notre Moteur est quil ne sagit pas simplement de faire monter un train en haut dune colline. Il sagit de parcourir un espace (potentiellement) trs compliqu de possibilits, en se souvenant de l o il est pass ou pas. Le Moteur utilise un automate fini non dterministe (NFA, nondeterministic finite-state automaton) pour trouver une correspondance. Cela signifie simplement quil garde une trace de ce quil a et na pas essay, et quand cela ne donne aucun rsultat, il revient en arrire et essaye autre chose. Cest le retour arrire, ou backtracking. Le Moteur Perl est capable dexplorer un million de possibilits pour une partie de la recherche, pour les abandonner et aller la partie de recherche suivante, puis recommencer explorer pour celle-ci le mme million de possibilits. Le Moteur nest pas trs intelligent ; il est juste persvrant et exhaustif. Il est cependant possible dcrire des motifs efficaces qui noccasionnent pas trop de retours arrires inutiles. Quand on vous dit Les regex choisissent la correspondance la plus gauche la plus longue , cela signifie que Perl prfre la plus gauche la plus longue. Mais le Moteur ne sait pas quil privilgie quelque chose ce niveau. Le choix global rsulte de nombreux choix particuliers et indpendants. Voici ces choix :13 Rgle 1 Le Moteur essaye de trouver une correspondance aussi loin que possible gauche de la chane, afin que la totalit de lexpression rgulire corresponde selon la rgle 2. Le Moteur dmarre juste avant le premier caractre et essaye de faire correspondre la totalit de lexpression rgulire depuis ce point. Lexpression rgulire correspond si et seulement si le moteur atteint la fin de lexpression sans stre arrt la fin de la chane. Sil a trouv, il sarrte immdiatement il ne recherche pas sil existe une meilleure solution, mme si le motif peut correspondre la recherche de plusieurs autres manires. Sil narrive pas trouver une correspondance au motif la premire position de la

12. NdT : The little Engine that could est lhistoire dune petite locomotive qui tire un gros chargement de toutes ses forces sans abandonner. Elle est connue de beaucoup denfants amricains, mais na rien de remarquable si ce nest le I think I can. I think I can. I think I can... qui ressemble lgrement au bruit dun moteur vapeur (en anglais). 13. Certains de ces choix peuvent tre ignors si loptimiseur a son mot dire, ce qui revient faire des coupes dans un arbre de dcision. Dans le cadre de cette discussion, nous faisons comme si loptimiseur nexistait pas.

customer_8566

Garder le contrle

179

chane, il reconnat temporairement sa dfaite et va la position suivante de la chane, entre le premier et le deuxime caractres, puis ressaie nouveau toutes les possibilits. En cas de succs, il sarrte. Sinon, il continue plus avant dans la chane. La recherche de correspondance dans son ensemble ne sera considre comme un chec quaprs avoir essay de faire correspondre toute lexpression rgulire toutes les positions de la chane, y compris aprs le dernier caractre. Une chane de n caractres fournit donc en fait n + 1 positions o correspondre. Cest parce que les dbut et fin de correspondance se trouvent entre les caractres de la chane. Cette rgle surprend parfois les gens quand il crivent un motif tel que /x*/ qui recherche zro ou plus x . Si vous essayez ce motif sur une chane comme dix , il ne trouvera pas le x . Il trouvera en fait la chane nulle juste avant le d et nira jamais chercher plus loin. Si vous voulez trouver un ou plusieurs x, vous devriez plutt utiliser le motif /x+/. Voir les quantificateurs la rgle 5. Un corollaire cette rgle est que toute expression rgulire qui peut trouver la chane nulle est assure de correspondre la position la plus gauche de la chane (en labsence de toute assertion de largeur vide qui vrifie le contraire). Rgle 2 Quand le Moteur rencontre une alternative (aux lments spars par des |), que ce soit au niveau global ou au niveau du regroupement courant, il les essaie successivement de gauche droite, en sarrtant la premire correspondance qui assure le succs du motif dans son ensemble. Une alternative correspond une chane si un lment quelconque de lalternative correspond au sens de la rgle 3. Si aucun des lments de lalternative ne correspond, il retourne la rgle qui a invoqu cette rgle, qui est en gnrale la rgle 1, mais pourrait trs bien tre la rgle 4 ou 6 dans un regroupement. Cette rgle cherchera alors une nouvelle position o appliquer la rgle 2. Sil nexiste quun seul terme dalternative, alors celui-ci est vrifi ou non, et la rgle 2 est toujours valable. (Il nexiste pas de zro alternative, car une chane vide correspond toujours quelque chose de longueur nulle.) Rgle 3 Un terme donn dune alternative est vrifi si chacun de ses lments est lui aussi vrifi selon les rgles 4 et 5 (de faon ce que toute lexpression rgulire soit satisfaite). Un lment peut consister en une assertion, qui est rgie par la rgle 4, ou en un atome quantifi, qui est rgi par la rgle 5. Les lments choix multiples sont hirarchiss de la gauche vers la droite. Si les lments ne peuvent tre vrifis, le Moteur rebrousse chemin jusquau choix suivant selon la rgle 2. Les lments qui doivent tre vrifis squentiellement ne sont pas spars dans lexpression rgulire par quoi que ce soit de syntaxique ; ils sont simplement juxtaposs dans lordre dans lequel ils doivent tre vrifis. Lorsque vous cherchez /^toto/, vous demandez en fait la dtection de cinq lments les uns la suite des autres. Le premier est une assertion de longueur nulle et les quatre autres des lettres ordinaires qui se correspondent elles-mmes, lune aprs lautre, selon la rgle 5. Lordre hirarchique de gauche droite implique que dans un motif tel que :
/x*y*/

customer_8566

180

Chapitre 5 Recherche de motif

x* choisit une manire de correspondre, puis y* essaie toutes ses possibilits. Si cela choue, x* choisit alors sa deuxime possibilit, et fait ressayer toutes ses possibilits y*. Et ainsi de suite. Les lments droite varient plus vite , pour emprunter une expression au vocabulaire des tableaux multidimensionnels. Rgle 4 Si une assertion ne correspond pas la position courante, le Moteur revient en arrire la rgle 3 et ressaie les lments plus haut dans la hirarchie avec des choix diffrents. Certaines assertions sont plus fantaisistes que dautres. Perl connat beaucoup dextensions de regex, dont certaines sont des assertions de largeur nulle. Par exemple, lassertion positive de prvision (?=...) et lassertion ngative de prvision (?!...) ne correspondent en ralit aucun caractre, mais sassurent plutt que lexpression rgulire reprsente par ... correspondrait (ou non), si nous lavions essaye.14 Rgle 5 Un atome quantifi nest vrifi que si et seulement si latome lui-mme est vrifi un nombre de fois autoris par le quantificateur. (Latome est vrifi selon la rgle 6). Des quantificateurs diffrents impliquent un nombre diffrent de vrifications, et la plupart dentre eux permettent un nombre variable de vrifications. Les correspondances multiples doivent tre faites la suite, cest--dire quelles sont adjacentes dans la chane. Un atome non quantifi est suppos avoir un quantificateur ne demandant quune seule vrification (cest--dire que /x/ est identique /x{1}/). Si aucune correspondance nest trouve la position courante pour aucune des quantits autorises pour latome en question, le Moteur revient la rgle 3 et ressaye des lments dordre hirarchique plus lv avec des valeurs diffrentes. Les quantificateurs sont *, +, ?, *?, +?, ?? et les diffrentes formes daccolades. Si vous utilisez la forme {COMPTE}, alors il ny a pas le choix et latome doit correspondre le nombre exact de fois prcis, ou pas du tout. Sinon, latome peut tre recherch parmi un ensemble de possibilits de rptition, et le Moteur garde une trace de tous les choix pour revenir en arrire si besoin est. Mais la question est alors de savoir quel choix faire en premier. On pourrait commencer par le nombre maximal et le rduire au fur et mesure, ou dmarrer avec le nombre minimal et laugmenter petit petit. Les quantificateurs traditionnels (sans point dinterrogation la suite) spcifient une recherche gourmande ; cest--dire quils essaient de vrifier autant de caractres que possible. Pour trouver la correspondance maximale, le Moteur doit faire un petit peu attention. Les mauvais choix cotent potentiellement cher, cest pourquoi le Moteur ne compte pas vraiment partir de la valeur maximale, qui pourrait aprs tout tre Trs Grande et provoquer des millions de mauvais choix. Le Moteur fait en ralit quelque chose dun petit peu plus malin : il commence par compter

14. En ralit, elle est teste par le Moteur. Celui-ci retourne la rgle 2 pour tester le sous-motif, puis efface toute trace de ce qui avait t consomm de la chane, pour ne retourner que le succs ou lchec du sous-motif comme valeur de lassertion. (Il se souvient cependant de toute chane capture.)

customer_8566

Garder le contrle

181

de faon croissante combien datomes correspondants ( la suite) sont effectivement prsents dans la chane, puis utilise ce maximum rel comme premier essai. (Il se souvient aussi des choix les plus courts, au cas o le plus long ne marcherait pas.) Il essaie (enfin) de vrifier le reste du motif, en supposant que le choix le plus long est le bon. Si le choix le plus long ne produit de correspondance pour le reste du motif, il revient en arrire et essaie le plus long suivant. Si vous crivez /.*toto/ par exemple, il essayera de trouver le nombre maximum de caractres quelconques (reprsents par le point) jusqu la fin de la ligne avant mme de commencer chercher toto ; puis quand le toto ne correspond pas cet endroit (et il ne peut pas, puisquil ny a pas assez de place en fin de chane pour le trouver), le Moteur va reculer dun caractre la fois jusqu trouver un toto . Sil y a plus dun toto sur la ligne, il sarrtera au dernier, puisque ce sera en fait le premier quil rencontre au cours de sa remonte. Quand le motif complet russit en utilisant une longueur particulire de .*, le Moteur sait quil peut abandonner les autres choix plus courts pour .* (ceux quil aurait utiliss si le toto en cours navait finalement pas fonctionn). En mettant un point dinterrogration aprs nimporte quel quantificateur gourmand, vous le transformez en quantificateur frugal qui choisit la plus petite quantit pour son premier essai. Donc, si vous crivez /.*?toto/, le .*? essayera dabord de correspondre 0 caractres, puis 1, puis 2, et ainsi de suite jusqu trouver le toto . Au lieu de rebrousser chemin en arrire, il rebrousse chemin en avant, pour ainsi dire. Et finit par trouver le premier toto de la ligne au lieu du dernier. Rgle 6 Chaque atome correspond selon son type. Si latome nest pas vrifi (ou lest, mais que sa vrification ne permet pas de correspondance pour le reste du motif), le Moteur revient en arrire la rgle 5 et essaie le choix suivant possible en quantit pour cet atome. Les atomes correspondent selon les types suivants : Une expression rgulire entre parenthses, (...), trouve tout ce que lexpression rgulire reprsente par ... trouve selon la rgle 2. Les parenthses servent donc doprateur de regroupement pour la quantification. Les parenthses simples ont galement pour effet de capturer la sous-chane trouve pour une utilisation ultrieure comme rfrence arrire (ou backreference en anglais). Cet effet de bord peut tre supprim en utilisant plutt (?:...), qui na que les proprits de regroupement ; il ne stocke rien dans $1, $2 et autres. Il existe dautres formes datomes (et dassertions) entre parenthses voir la suite de ce chapitre. Un point correspond tout caractre, sauf ventuellement le saut de ligne. Une liste de caractres entre crochets (une classe de caractres) correspond nimporte lequel des caractres spcifis dans la liste. Une lettre prcde dun antislash correspond soit un caractre particulier, soit un caractre dun ensemble particulier, comme indiqu dans le tableau 5-7. Tout autre caractre prcd dun antislash correspond ce caractre lui-mme. Tout caractre non mentionn ci-dessus se correspond lui-mme.

customer_8566

182

Chapitre 5 Recherche de motif

Tout cela peut sembler plutt compliqu, mais lavantage est que pour chaque liste de choix donne par un quantificateur ou une alternative, le Moteur a un bouton tourner. Il tournera tous ces boutons jusqu ce que tout le motif corresponde. Les rgles ne font quindiquer dans quel ordre le Moteur peut tourner ces boutons. Dire que le Moteur prfre la correspondance la plus longue gauche signifie simplement que le bouton quil tourne le plus lentement est celui correspondant la position de dpart. Revenir en arrire consiste simplement tourner dans lautre sens le bouton tourn linstant de faon essayer un autre bouton plus haut dans lordre hirarchique, cest-dire un qui varie plus lentement. Voici un exemple plus concret sous la forme dun programme qui dtecte quand deux mots conscutif partagent un suffixe et un prfixe communs :
$a = conflit; $b = litige; if ("$a $b" =~ /^(\w+)(\w+) \2(\w+)$/) { print "$2 superpos dans $1-$2-$3\n"; }

Ceci affiche :
lit superpos dans conf-lit-ige

Vous pourriez croire que $1 capture dabord lintgralit de chienlit par gourmandise. Cest exactement ce quil fait dabord. Mais une fois rendu l, il ny a plus de caractres mettre dans $2, qui a besoin de recevoir des caractres cause du quantificateur +. Le Moteur bat donc en retraite et $1 donne contrecur un caractre $2. Cette fois lespace est trouv correctement, mais quand il voit le \2, qui reprsente un simple t . Le caractre suivant dans la chane nest pas un t , mais un l . Ceci fait donc revenir le Moteur en arrire et ressayer plusieurs fois, pour finalement forcer $1 laisser le lit $2. En fait, cela ne marchera pas forcment bien si la superposition elle-mme est un doublon, comme pour les mots rococo et cocon . Lalgorithme ci-dessus aurait simplement dcid que la chane en superposition, $2, devait tre co plutt que coco . Mais nous ne voulons pas de rocococon ; nous voulons plutt un rococon . Nous voici dans un cas o il est possible dtre plus malin que le Moteur. Lajout dun quantificateur minimal la partie correspondant $1 donne le motif bien meilleur /^(\w+?)(\w+) \2(\w+)$/, qui fait exactement ce que nous voulons. Pour une discussion plus dtaille des avantages et inconvnients des diffrentes sortes de moteurs dexpressions rationnelles, reportez-vous au livre de Jeffrey Friedl, Matrise des expressions rgulires (ou en version originale Mastering Regular Expressions). Le Moteur dexpressions rgulires de Perl fonctionne trs bien pour tous les problmes quotidiens que vous voulez rsoudre avec Perl, mais tout aussi correctement pour ce genre de problme pas si quotidien, pourvu que vous soyez un peu comprhensif.

customer_8566

Motifs tendus

183

Motifs tendus
Assertions priphriques
Parfois vous voulez juste jeter un il. Voici quatre extensions de regex qui vous aident justement faire cela. Nous les appelons priphriques (en anglais lookaround) car elles vous permettent de jeter un il alentour de faon hypothtique, sans correspondre effectivement des caractres. Ces assertions testent le fait quun motif correspondrait (ou non) dans le cas o nous lessayerions. Le Moteur fait cela en essayant effectivement de faire correspondre le motif puis en prtendant par la suite quil ny a pas eu de correspondance de faite (mme si cest le cas). Quand le Moteur regarde en avant par rapport sa position actuelle dans la chane, nous parlons dassertion de prvision15 (lookahead). Sil regarde en arrire, nous parlons dassertion de rtrovision. Les motifs de prvision peuvent tre nimporte quelle expression rationnelle, tandis que les motifs de rtrovision ne peuvent qutre de longueur fixe, car ils doivent savoir do partir pour leur correspondance hypothtique. Alors que ces quatre extensions sont toutes de largeur nulle, et ne consomment donc pas de caractres (du moins pas officiellement), vous pouvez en fait capturer des souschanes lintrieur si vous fournissez un niveau supplmentaire de parenthses de capture. (?=MOTIF) (positive de prvision) Quand le Moteur rencontre (?=MOTIF), il regarde en avant dans la chane pour sassurer que MOTIF se produit. Pour mmoire, dans notre prcdent suppresseur de doublons, nous avons d crire une boucle car notre motif consommait trop de texte chaque tour :
$_ = "Paris AU AU AU AU printemps." # supprime les doublons (et les triplons (et les quadruplons...)) 1 while s/\b(\w+) \1\b/$1/gi;

chaque fois que vous entendez consomme trop , vous devriez immdiatement penser assertion de pr-vision . (Enfin, presque toujours.) En regardant lavance au lieu de directement avaler le deuxime mot, vous pouvez crire un suppresseur de doublons qui fonctionne en une passe, comme ceci :
s/ \b(\w+) \s (?= \1\b ) //gxi;

videmment, il y a encore un problme, puisque cela va malmener des phrases parfaitement valides comme Jai une BELLE BELLE-mre . (?!MOTIF) (ngative de prvision) Quand le Moteur rencontre (?!MOTIF), il regarde en avant dans la chane pour sassurer que MOTIF napparat pas. Pour corriger notre exemple prcdent, nous pouvons ajouter une assertion ngative de prvision aprs lassertion positive pour
15. NdT : Ce terme et le suivant ne sont pas forcment trs heureux, cest pourquoi nous vous fournissons le vocabulaire original pour que vous soyez pas tonns en lisant des documentations utilisant ces termes.

customer_8566

184
liminer le cas des mots composs :
s/ \b(\w+) \s (?= \1\b (?! -\w))//xgi;

Chapitre 5 Recherche de motif

Ce \w final est ncessaire pour viter de confondre un mot compos avec mot suivi dun tiret. Nous pouvons mme aller plus loin, puisque plus tt dans ce chapitre nous nous sommes intentionnellement servis de lexpression nous nous sommes , et que nous aimerions que notre programme ne corrige pas cela pour nous. Nous pouvons donc ajouter une alternative lassertion ngative de pr-vision de manire ne pas corriger cela (et montrer ainsi que nimporte quel type de parenthses peut servir regrouper des alternatives) :
s/ \b(\w+) \s (?= \1\b (?! -\w | \s sommes))//gix;

Nous nous sommes maintenant assurs que cette formulation spcifique naura pas de problme. Hlas le pome Mes petites amoureuses de Rimbaud est toujours cass16. Aussi ajoutons-nous une nouvelle exception :
s/ \b(\w+) \s (?= \1\b (?! -\w | \s sommmes | \s aimions))//igx;

Voil qui commence semballer. Faisons plutt une Liste Officielle dExceptions, en utilisant un mignon petit truc dinterpolation avec la variable $" pour sparer les lments de lalternative avec le caractre | :
@nousnous = qw(sommes aimions); local $" = |; s/ \b(\w+) \s (?= \1\b (?! -\w | \s (?: @nousnous )))//xig;

(?<=PATTERN) (positive de rtrovision) When the Engine encounters (?<=PATTERN), it looks backward in the string to ensure that PATTERN already occurred. Notre exemple a toujours un problme. Bien que lon permette Rimbaud de dire Nous nous aimions , cela autorise galement La totalit des des sommes seront converties en Euros . Nous pouvons ajouter une assertion positive de rtrovision en tte de notre liste dexceptions pour nous assurer que nous nappliquons nos exceptions @nousnous qu un vrai nous nous .
s/ \b(\w+) \s (?= \1\b (?! -\w | (?<= nous) \s (?: @nousnous )))//ixg;

Oui, tout cela devient bien compliqu, mais rappelons que cette section sappelle Motifs tendus. Si vous avez besoin de compliquer encore le motif aprs ce que nous lui avons fait subir, lutilisation judicieuse des commentaires et de qr// devrait vous aider ne pas devenir fou. (?<!MOTIF) (ngative de rtrovision) Quand le Moteur rencontre (?<!MOTIF), il regarde en arrire dans la chane pour sassurer que MOTIF na pas t trouv. Essayons avec un exemple simple cette fois-ci. Pourquoi pas une rgle dorthographe facile ? Si vous ne savez plus si un mot se termine en euil ou en ueil , et

16. NdT : Trs exactement la troisime strophe :


Nous nous aimions cette poque, Bleu laideron ! On mangeait des ufs la coque Et du mouron !

customer_8566

Motifs tendus

185

que vous avez plutt la manie dcrire ueil (parce que vous tes n Rueil, par exemple). Lexpression rgulire suivante peut remettre les choses en ordre :
s/(?<!c|g)ueil/euil/g

Ne pas savoir crire fauteuil ou cerfeuil nest pas un cueil et ne doit pas blesser votre orgueil.

Sous-motifs sans retour arrire


Comme nous lavons dcrit dans Le petit Moteur qui /(ne )?pouvait( pas)?/ , le Moteur fait souvent machine arrire alors quil progresse le long dun motif. Vous pouvez empcher le Moteur de faire demi-tour au milieu dune srie de possibilits en crant un sous-motif sans retour arrire. Un sous-motif sans retour arrire se prsente comme (?>MOTIF), et fonctionne exactement comme un simple (?:MOTIF), sauf quune fois que MOTIF a trouv une correspondance, il supprime toute possibilit de retour arrire sur tous les quantificateurs ou alternatives lintrieur du sous-motif. (Cest pourquoi il est inutile dutiliser cela sur un MOTIF qui ne contient pas de quantificateurs ou dalternatives.) La seule manire de le faire changer davis est de rebrousser chemin jusqu quelque chose avant ce sous-motif et de rentrer dans le sous-motif par la gauche. Cest comme rendre visite un concessionaire automobile. Aprs un certain temps de discussion sur le prix, vous finissez par donner un ultimatum : Voici ma meilleure offre : cest prendre ou laisser. . Sils ne la prennent pas, vous ne recommencez pas marchander. Vous oprez un retour arrire vers la porte. Vous pouvez ensuite aller voir un autre concessionaire et recommencer marchander. Vous pouvez recommencer marchander, mais seulement parce que vous tes rentr dans le sous-motif sans retour arrire dans un contexte diffrent. Pour les adorateurs de Prolog ou SNOBOL, vous pouvez voir cela comme un oprateur cut ou fence porte limite. Voyons comment dans "aaab" =~ /(?:a*)ab/, le a* commence par trouver trois a, puis en laisse un car le dernier a est utilis plus loin. Le sous-motif sacrifie une partie de son butin pour permettre toute la correspondance de russir. (Ce qui revient laisser le marchand de voitures obtenir un peu plus de votre argent par peur de ne pas pouvoir conclure laffaire.) En revanche, le sous-motif dans "aaab" = ~ /(?>a*)ab/ nabandonnera rien de ce quil a pu trouver, mme si cette attitude fait chouer la correspondance toute entire. Bien que (?>MOTIF) soit utile pour modifier le comportement dun motif, il est souvent utilis pour acclrer lchec de certaines recherches dont vous savez quelles vont chouer ( moins quelles ne russissent tout fait). Le Moteur peut prendre un temps extraordinairement long pour chouer, en particulier avec des quantificateurs embots. Le motif suivant russira de faon quasi-instantane :
$_ = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab"; /a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*[b]/;

Mais ce nest pas le succs qui est un problme. Cest lchec qui en est un. Si vous retirez ce b final de la chane, le motif va probablement tourner pendant des annes et des annes avant dchouer. Pendant des millnaires et des millnaires. En ralit des mil-

customer_8566

186

Chapitre 5 Recherche de motif

liards et des milliards dannes.17 Vous pouvez constater en examinant le motif quil ne peut russir sil ny a pas de b la fin de la chane ; mais loptimiseur nest pas assez malin (au moment o nous crivons ces lignes) pour se rendre compte que /[b]/ est quivalent /b/. Mais si vous lui donnez un indice, vous pouvez le faire chouer rapidement tout en le laissant russir l o il peut :
/(?>a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*)[b]/;

Voici un exemple plus raliste (esprons). Imaginez un programme qui est suppos lire paragraphe par paragraphe et nafficher que les lignes qui se continuent, les lignes de continuation tant spcifies par un antislash final. Voici un exemple tir du Makefile de Perl qui utilise cette convention :
# Files to be built with variable substitution before miniperl # is available. sh = Makefile.SH cflags.SH config_h.SH makeaperl.SH makedepend.SH \ makedir.SH myconfig.SH writemain.SH

Vous pourriez crire votre programme de cette faon :


#!/usr/bin/perl -00p while ( /( (.+) ( (?<=\\) \n .* )+ ) /gx) { print "Jai $.: $1\n\n"; }

a marche, mais cest vraiment trs lent. Cest parce que le Moteur fait machine arrire un caractre la fois depuis la fin de la ligne, en diminuant ce qui se trouve dans $1. Cest sans intrt. Lcrire sans les captures surnumraires namliore pas sensiblement les choses. Utiliser :
(.+(?:(?<=\\)\n.*)+)

pour un motif est un peu plus rapide, mais pas tellement. Cest dans ce cas quun motif sans retour arrire est trs utile. Le motif :
((?>.+)(?:(?<=\\)\n.*)+)

fait la mme chose, mais est plus rapide dun ordre de grandeur. Cest parce quil ne perd pas son temps chercher quelque chose qui nest pas l. Il nest pas possible dobtenir avec (?>...) un succs que vous nauriez obtenu avec (?:...) ou mme un simple (...). Mais si votre recherche doit chouer, autant chouer rapidement et passer la suite.

Motifs programmatiques
La plupart des programmes Perl sont crits dans un style impratif (aussi appel procdural). Cest un peu comme une suite dordres lists dans un facile suivre : Prchauffer le four, mlanger, glacer, cuire, laisser refroidir, servir aux martiens. . Parfois vous rajoutez ce mlange une bonne cuillere de programmation fonctionnelle ( Utilisez un peu plus de glacage que vous ne pensez en avoir besoin, mme aprs
17. En fait, cest plutt de lordre des septillions dannes. Nous ne savons pas exactement combien de temps cela prendrait. Nous navons pas eu la patience dattendre de le voir chouer. En tous les cas, votre ordinateur risque fort de planter avant que lunivers ne disparaisse, et cette expression rgulire met plus de temps que ces deux vnements se produire.

customer_8566

Motifs tendus

187

avoir tenu compte de ce conseil, rcursivement ) ou vous le saupoudrez de quelques techniques orientes-objet ( Merci de laisser les objets anchois de ct ). Souvent cest un mlange de tout cela la fois. Mais le Moteur dexpressions rgulires a une approche compltement diffrente de la rsolution de problmes, une approche plus dclarative. Vous dcrivez vos objectifs dans le langage des expressions rgulires, et le Moteur implmente la logique ncessaire pour atteindre vos objectifs. Les langages de programmation logique (comme Prolog) ont une moins grande visibilit que les trois autres styles, mais ils sont plus rpandus que vous ne pourriez le croire. Perl ne pourrait mme pas tre construit sans make ou yacc ; tous deux pouvant tre considrs, sinon comme des langages purement dclaratifs, au moins comme des hybrides qui mlangent la programmation imprative et la programmation logique. Vous pouvez aussi faire ce genre de choses en Perl, en mlangeant ensemble des dclarations dobjectifs avec du code impratif, de faon encore plus f luide que nous ne lavons fait jusqu prsent afin de profiter des forces de chacun. Vous pouvez construire programmatiquement la chane que vous allez finir par proposer au Moteur de regex, cest--dire dune certaine manire crer un programme qui crit un nouveau programme la vole. Vous pouvez galement fournir des expressions Perl normales comme remplacement dans s/// laide du modificateur /e. Ceci vous permet de gnrer dynamiquement la chane de remplacement en excutant un morceau de code chaque fois que le motif correspond. Dune manire encore plus labore, vous pouvez inclure des bouts de code partout o vous le voulez au beau milieu dun motif en utilisant lextension (?{CODE}). Celui-ci sera excut chaque fois que le Moteur rencontrera ce code, au fur et mesure de ses prgrinations, dans la danse complique des retours en arrire. Enfin, vous pouvez utiliser s///ee ou (??{CODE}) pour ajouter un nouveau niveau dindirection : le rsultat de lexcution de ces bouts de code sera lui-mme rvalu pour tre rutilis, crant des morceaux de programme et de motif au vol, juste temps.

Motifs gnrs
Il a t dit18 que les programmes qui crivent des programmes sont les programmes les plus heureux au monde. Dans le livre de Jeffrey Friedl, Matrise des expressions rgulires (Mastering Regular Expressions), le tour de force final montre comment crire un programme qui produit une expression rgulire capable de dterminer si une chane est conforme au standard dfini par le RFC 822 ; cest--dire sil contient un en-tte de mail conforme au standard. Le motif produit fait plusieurs milliers de caractres de long, et est aussi facile lire quun dump mmoire binaire aprs un crash. Mais le dtecteur de motif de Perl sen moque ; il compile juste le motif sans difficult et, ce qui est encore plus intressant, lexcute trs rapidement bien plus rapidement, en fait, que beaucoup de motifs beaucoup plus courts qui ont des besoins de retour arrire plus compliqus. Cest un exemple trs compliqu. Nous vous avons prcdemment montr un exemple trs simple de la mme technique quand nous avons fabriqu un motif $nombre partir
18. Par Andrew Hume, le clbre philosophe Unix.

customer_8566

188

Chapitre 5 Recherche de motif

de ses lments constitutifs (voir la section Interpolation de variables). Mais pour vous montrer la puissance de lapproche programmatique pour la production dun motif, nous allons nous pencher sur un problme de complexit moyenne. Supposons que vous vouliez trouver tous les exemples de mots avec une certaine suite de voyelles et de consonnes ; par exemple audio et aeree suivent tous deux un motif VVCVV Mme si dcrire ce qui compte comme voyelle ou consonne est simple19, . vous naurez pas vraiment envie de lcrire plus dune fois. Mme pour un cas simple comme notre VVCVV vous devrez crire un motif comme : ,
^[aeiouy][aeiouy][bcdfghjklmnpqrstvwxzy][aeiouy][aeiouy]$

Un programme plus gnral accepterait une chane comme VVCVV pour gnrer (programmatiquement) le motif pour vous. Pour tre mme encore plus f lexible, il pourrait mme accepter un mot comme audio , lutiliser comme modle pour en dduire VVCVV et de l construire le long motif ci-dessus. Cela a lair compliqu, mais ne lest vraiment pas, car nous allons laisser le programme gnrer le motif pour nous. Voici un simple programme cvmap qui fait tout cela :
#!/usr/bin/perl $voyelles = aeiouy; $consonnes = bcdfghjklmnpqrstvwxzy; %assoc = (C => $consonnes, V => $voyelles); # initialise la liste pour V et C for $classe ($voyelles, $consonnes) { # pour chaque type for (split //, $class) { # rcupre chaque lettre de chaque type $assoc{$_} .= $class; # et rassocie chaque lettre chaque type } } for $char (split //, shift) { $motif .= "[$assoc{$char}]"; approprie } $re = qr/^${motif}$/i; print "REGEX : $re\n"; @ARGV = (/usr/dict/words) if -t && !@ARGV; while (<>) { print if /$re/; } # pour chaque lettre du modle # ajoute la classe de caractres

# compile le motif # affiche une vrification # prend un dictionnaire par dfaut

# et maintenant parcourt lentre # en affichant les lignes qui # correspondent

19. NdT : Plus simple en anglais quen franais, car nos classes de caractres seraient plutot [aeiouy] pour les voyelles et [bcdefghjklmnpqrstvwxyz] pour les consonnes. Et nous ne vous parlons mme pas des ligatures ! Dans les exemples qui suivent, le dictionnaire utilis est une version sans accents. Ladaptation pour traiter les accents est laisse en exercice au lecteur. Notez cependant que use locale; vous facilitera les \w.

customer_8566

Motifs tendus

189

La variable %assoc contient tous les morceaux intressants. Elle utilise chaque lettre de lalphabet comme cl, et la valeur correspondante est lensemble des lettres du mme type. Nous ajoutons galement V et C, pour que vous puissiez utiliser VVCVV ou audio et tout de mme obtenir aeree . Chaque caractre de largument fourni est utilis pour trouver la classe de caractres associe et lajouter au motif. Une fois le motif cr et compil par qr//, la correspondance (mme si le motif est trs long) va tourner rapidement. Voici un extrait de ce que vous pourriez obtenir en faisant tourner ce programme fortuitement :
% cvmap fortuitement /usr/dict/words_fr REGEX : (?i-xsm:^[cbdfghjklmnpqrstvwxzy][aeiouy][cbdfghjklmnpqrstvwxzy][cbd fghjklmnpqrstvwxzy][aeiouy][aeiouy][cbdfghjklmnpqrstvwxzy][aeiouy][cbdfghjk lmnpqrstvwxzy][aeiouy][cbdfghjklmnpqrstvwxzy][cbdfghjklmnpqrstvwxzy]$) banqueterent becqueterent bestialement biscuiterent cabriolerent cabriolerons cabrioleront certainement circuiterent ...

En vous laissant admirer cette REGEX, nous vous persuaderons verbeusement mais certainement de lconomie de frappe ainsi sommairement ralise.

valuations de substitution
Quand le modificateur /e ( e pour valuation dexpression) est utilis sur une expression s/MOTIF/CODE/e, la partie de remplacement est interprte comme une expression, et pas seulement comme une chane entre apostrophes doubles. Cest comme un do {CODE}. Mme si cela a lair dune chane, cest simplement un bloc de code qui sera compil en mme temps que le reste de votre programme, bien avant que la substitution ne soit rellement faite. Vous pouvez utiliser le modificateur /e pour construire des chanes de remplacement avec une logique plus fantaisiste que celle que permet linterpolation entre doubles apostrophes. Voici la diffrence :
s/(\d+)/$1 * 2/; s/(\d+)/$1 * 2/e; # Remplace "42" par "42 * 2" # Remplace "42" par "84"

Et ceci convertit les degrs Celsius en Fahrenheit :


$_ = "Prchauffez le four 233C.\n"; s/\b(\d+\.?\d*)C\b/int($1 * 1.8 + 32) . "F"/e; # convertit en 451F

Les applications sont sans limite. Voici un filtre qui modifie un fichier en place (comme un diteur) en ajoutant 100 tout nombre qui se trouve en dbut de ligne (et qui nest pas suivi par des deux-points, que nous ne faisons que regarder, sans les trouver ni les remplacer) :
% perl -pi -e s/^(\d+)(?=:)/100 + $1/e fichier

customer_8566

190

Chapitre 5 Recherche de motif

De temps autre, vous voudrez faire un peu plus que simplement utiliser dans un autre calcul la chane que vous avez trouve. Vous voulez parfois que cette chane soit un calcul, dont vous utiliserez lvaluation en tant que valeur de remplacement. Chaque modificateur /e supplmentaire rajoute un eval autour du code excuter. Les deux lignes suivantes font la mme chose, mais la premire est plus facile lire :
s/MOTIF/CODE/ee s/MOTIF/eval(CODE)/e

Vous pourriez utiliser cette technique pour remplacer les apparitions de valeurs scalaires simples par leurs valeurs :
s/(\$\w+)/$1/eeg; # Interpole les valeurs de la plupart des scalaires

Comme cest vraiment un eval, le /ee trouve mme les variables lexicales. Un exemple un peu plus labor calcule la valeur de remplacement pour des expressions arithmtiques simples sur des entiers (positifs) :
$_ = "Jai 4 + 19 euros et 8/2 centimes.\n"; s{ ( \d+ \s* # trouve un entier [+*/-] # et un oprateur arithmtique \s* \d+ # et un autre entier ) }{ $1 }eegx; # puis trouve $1 et excute ce code print; # "Jai 23 euros et 4 centimes."

Comme tout autre eval CHAINE, les erreurs de compilation (comme des problmes de syntaxe) et les exceptions lexcution (comme une division par zro) sont captures. Dans ce cas, la variable $@ ($EVAL_ERROR) dit ce qui sest mal pass.

valuation de code lors de la recherche


Dans la plupart des programmes qui utilisent les expressions rgulires, ce sont les structures de contrle du programme tout autour qui dirigent le f lux logique de lexcution. Vous crivez des boucles if ou while, faites des appels de fonctions ou de mthodes, qui se trouvent appeler une opration de recherche de motif de temps autre. Mme avec s///e, cest loprateur de substitution qui a le contrle et nexcute le code de remplacement quaprs une recherche russie. Avec les sous-motifs de code, la relation usuelle entre les expressions rgulires et le code du programme est inverse. Alors que le Moteur applique ses rgles votre motif au moment de la recherche, il peut tomber sur une extension de regex de la forme (?{CODE}). Quand il est dclench, ce sous-motif ne fait aucune reconnaissance ni aucune assertion priphrique. Cest une assertion de largeur nulle qui russit toujours et nest value que pour ses effets de bord. chaque fois que le moteur doit passer sur le sous-motif de code pour progresser dans le motif, il excute ce code.
"glyphe" =~ /.+ (?{ print "yo" }) ./x; # Affiche "yo" deux fois.

Alors que le Moteur essaie dtablir la correspondance entre glyphe et ce motif, il laisse dabord .+ avaler les cinq lettres. Puis il affiche yo . Quand il tombe sur le point final, les cinq lettres ont dj t avales ; il lui faut donc faire machine arrire sur le .+ et lui faire rendre une des lettres. Il avance de nouveau dans le motif, faisant un nouvel affichage de yo au passage, fait correspondre e au point final et termine sa recherche avec succs.

customer_8566

Motifs tendus

191

Les accolades autour du fragment de CODE sont destines vous rappeler quil sagit dun bloc de code Perl, et quil se comporte comme un bloc au sens lexical. Cest--dire que si vous utilisez my pour dclarer une variable porte lexicale, elle sera prive ce bloc. Mais si vous utilisez local pour localiser une variable porte dynamique, il risque de ne pas faire ce quoi vous vous attendez. Un sous-motif (?{CODE}) cre une porte dynamique implicite qui reste valide pour le reste du motif, jusqu ce quil russisse ou quil fasse machine arrire travers ce sous-motif de code. Une manire de voir cela est que le bloc ne retourne pas vraiment quand il arrive la fin. Au lieu de cela, il faut un appel rcursif invisible au Moteur pour essayer de dtecter le reste du motif. Cest seulement quand cet appel rcursif se termine quil revient du bloc, en dlocalisant les variables localises.20 Dans lexemple suivant, nous initialisons $i 0 en incluant un sous-motif de code au dbut du motif. Ensuite nous capturons autant de caractres que possible avec .* mais nous mettons un autre sous-motif de code entre le . et l* comme cela nous pourrons savoir combien de fois le . trouve quelque chose.
$_ = lothlorien; m/ (?{ $i = 0 }) (. (?{ $i++ }) lori /x; # # # # Met $i 0 Met jour $i, mme aprs un retour en arrire Force un retour arrire

)*

Le Moteur se met donc joyeusement en route, mettant $i 0 et laissant .* gober les 10 caractres de la chane. Quand il recontre le lori dans le motif, il revient en arrire et abandonne quatre caractres du .*. la fin de la recherche, $i vaudra toujours 10. Si vous vouliez que $i reprsente le nombre de caractres que le .* a effectivement conservs la fin, vous pouvez utiliser la porte dynamique lintrieur du motif :
$_ = lothlorien; m/ (?{ $i = 0 }) (. (?{ local $i = $i + 1; }) )* # Met jour $i, avec protection contre le retour arrire lori (?{ $resultat = $i }) # Copie dans une variable non localise /x;

Ici nous utilisons local pour nous assurer que $i contient le nombre de caractres trouvs par .*, en tenant compte des retours en arrire. $i sera perdue aprs la fin de lexpression rgulire, aussi le sous-motif de code (?{ $result = $i }) conserve la valeur de $i dans $resultat.
20. Les personnes familires des analyseurs rcursif descendants pourront trouver ce comportement perturbant parce que de tels compilateurs retournent dun appel de fonction rcursif ds quils arrivent trouver quelque chose. Le Moteur ne fait pas cela quand il trouve quelque chose, il descend plus profond en recursion (mme quand il sort dun groupe entre parenthses !). Un analyseur rcursif descendant est un minimum de rcursion quand il russit la fin, mais le Moteur est un maximum de rcursion quand il russit la fin du motif. Vous pourriez trouver utile de faire pendre le motif par son extrmit gauche et de le voir comme une reprsentation de larbre des appels. Si vous arrivez visualiser cette image, la porte dynamique des variables locales vous sera plus comprhensible. (Et si vous ne pouvez pas, ce nest pas pire quavant.)

customer_8566

192

Chapitre 5 Recherche de motif

La variable spciale $^R (dcrite au chapitre 28) contient le rsultat du dernier (?{CODE}) qui a t excut au cours dune recherche russie. Vous pouvez utiliser une extension (?{CODE}) comme la COND dune (?(COND)SIVRAI|SIFAUX). Si vous faites cela, $^R ne sera pas mis jour et vous pouvez omettre les parenthses autour de la condition :
"glyphe" =~ /.+(?(?{ $toto{titi} gt "symbole" }).|signet)./;

Ici, nous testons si $toto{titi} est plus grand que symbole. Si oui, nous incluons . dans le motif, sinon nous incluons signet dans le motif. On peut ltirer pour le rendre un peu plus lisible :
"glyphe" =~ m{ .+ # quelques nimporte quoi (?(?{ # si $toto{titi} gt "symbole" # ceci est vrai }) . # trouve un autre nimporte quoi | # sinon signet # trouve signet ) . # et un nimporte quoi de plus }x;

Quand use re eval est enclench, une regex a le droit de contenir un sous-motif (?{CODE}) mme si lexpression rgulire interpole des variables :
/(.*?) (?{length($1) < 3 && warn}) $suffixe/; # Erreur sans use re eval

Ceci est normalement interdit pour des raisons de scurit. Mme si le motif ci-dessus est sans danger car $suffixe est sans danger, lanalyseur de regex ne peut pas savoir quelles parties de la regex ont t interpoles et lesquelles ne lont pas t. Cest pourquoi il interdit simplement les sous-motifs de code sil y a eu de linterpolation. Si le motif sobtient partir de donnes entaches, mme use re eval nautorisera pas la recherche de motif continuer. Quand use re taint est enclench et quune chane entache est la cible dune regex, les sous-motifs capturs (dans les variables numrotes ou dans la liste de valeurs renvoyes par m// en contexte de liste) sont entachs. Cela est utile quand les oprations de regex sur des donnes entaches sont destines non pas extraire des sous-chanes sres, mais plutt pour faire de nouvelles transformations. Voir le chapitre 23, Scurit, pour en savoir plus sur lentachement. Pour ce pragma, les expressions rgulires prcompiles (obtenues en gnral par qr//) ne sont pas considres comme interpoles :
/toto${motif}titi/

Ceci est autoris si $motif est une expression rgulire prcompile, mme si $motif contient des sous-motifs (?{CODE}). Prcdemment nous vous avons montr un peu de ce que use re debug affiche. Une solution de dboguage un peu plus primitive consiste utiliser des sous-motifs (?{CODE}) pour afficher ce qui a t trouv jusquici dans la recherche :
"abcdef" =~ / .+ (?{print "Trouv jusqu prsent : $&\n"}) bcdef $/x;

Ceci affiche :

customer_8566

Motifs tendus
Trouv Trouv Trouv Trouv Trouv Trouv jusqu jusqu jusqu jusqu jusqu jusqu prsent prsent prsent prsent prsent prsent : : : : : : abcdef abcde abcd abc ab a

193

ce qui montre .+ gobant toutes les lettres et les rendant une par une au fur et mesure que le Moteur rebrousse chemin.

Interpolation de motif lors de la recherche


Vous pouvez construire des morceaux de votre motif depuis lintrieur du motif lui-mme. Lextension (??{CODE}) vous permet dinsrer du code qui svalue en un motif valide. Cest comme crire /$motif/, sauf que vous pouvez gnrer $motif lexcution plus spcifiquement, lors de la recherche. Par exemple :
/\w (??{ if ($seuil > 1) { "rouge" } else { "bleu" } }) \d/x;

Cest quivalent /\wrouge\d/ si $seuil est plus grand que 1 et /\wbleu\d/ sinon. Vous pouvez inclure des rfrences arrires lintrieur du code valu pour dduire de motifs de chanes trouves linstant (mme si elles ne seront plus trouves plus tard pour cause de retour arrire). Par exemple, ceci trouve toutes les chanes qui se lisent de la mme faon lenvers et lendroit (plus connues sous le nom de palindromadaires, ce sont des phrases avec une bosse au milieu) :
/^ (.+) .? (??{quotemeta reverse $1}) $/xi;

Vous pouvez quilibrer des parenthses comme suit :


$texte =~ /( \(+ ) (.*?) (??{ \) x length $1 })/x;

Ceci trouve les chanes de la forme (shazam!) et (((shazam!))), et met shazam! dans $2. Hlas, il est incapable de savoir si les parenthses au milieu sont quilibres. Pour cela nous avons besoin de rcursion. Heureusement, vous pouvez aussi faire des motifs rcursifs. Vous pouvez avoir un motif compil utilisant (??{CODE}) et faisant rfrence lui-mme. La recherche rcursive est plus irrgulire, pour des expressions rgulires. Tous les textes sur les expressions rgulires vous diront quune expression rationnelle standard ne peut pas trouver des parenthses quilibres correctement. Et cest correct. Il est aussi vrai que que les regex de Perl ne sont pas standard. Le motif suivant21 trouve un ensemble de parenthses quilibres, quelle que soit leur profondeur :
$pe = qr{ \( (?: (?> [^()]+ ) | (??{ $pe }) )*
21. Remarquez que vous ne pouvez pas dclarer la variable dans linstruction o vous allez lutiliser. Vous pouvez toujours la dclarer avant, bien sr.

# Non parenthses sans retour arrire # Groupe avec des parenthses quilibres

customer_8566

194
\) }x;

Chapitre 5 Recherche de motif

Vous pourriez lutiliser comme ceci pour trouver un appel de fonction :


$foncmotif = qr/\w+$pe/; mafonc(1,(2*(3+4)),5) =~ /^$foncmotif$/; # Trouv !

Interpolation conditionnelle
Lextension de regex (?(COND)SIVRAI|SIFAUX) ressemble loprateur ?: de Perl. Si COND est vrai, le motif SIVRAI est utilis ; sinon le motif SIFAUX est utilis. COND peut tre une rfrence arrire (exprim comme un entier simple, sans le \ ou le $), une assertion priphrique ou un sous-motif de code (voir Assertions priphriques et valuation de code lors de la recherche plus haut dans ce chapitre). Si COND est un entier, il est trait comme une rfrence arrire. Par exemple :
#!/usr/bin/perl $x = Perl est gratuit.; $y = PatronGiciel cote 99EUR.; foreach ($x, $y) { /^(\w+) (?:est|(cote)) (?(2)(\d+EUR)|\w+)/; # Soit (\d+EUR), soit \w+ if ($3) { print "$1 cote de largent.\n"; # PatronGiciel cote # de largent. } else { print "$1 ne cote rien.\n"; # Perl ne cote rien. } }

Ici, COND est (2), qui est vrai sil existe une deuxime rfrence arrire. Si cest le cas, (\d+EUR) est ajout au motif (et cre la rfrence arrire $3) ; sinon, \w+ est utilis. Si COND est un assertion priphrique ou un sous-motif de code, la vracit de lassertion est utilise pour dterminer sil faut inclure SIVRAI ou SIFAUX :
/[ATGC]+(?(?<=AA)G|C)$/;

Ceci utilise une assertion de rtrovision comme COND pour trouver une squence dADN qui se termine soir par AAG ou une autre combinaison de bases et un C.

Dfinir vos propres assertions


Vous ne pouvez pas modifier le fonctionnement du Moteur de Perl, mais si vous tes suffisament cingl, vous pouvez changer la faon dont il voit votre motif. Comme Perl interprte votre motif de manire analogue une chane entre apostrophes doubles, vous pouvez utiliser les merveilles de la surcharge des constantes chane pour vous arranger pour que les suites de caractres de votre choix soient automatiquement transformes en dautres suites de caractres. Dans lexemple qui suit, nous dfinissons deux transformations qui doivent se produire quand Perl rencontre un motif. Dabord nous dfinissons \tag de faon ce que lorsquil apparat dans un motif, il est automatiquement transform en (?:<.*?>), qui trou-

customer_8566

Motifs tendus

195

ve la plupart des balises HTML et XML. Ensuite, nous redfinissons le mtasymbole \w de faon ce quil naccepte que les lettres anglaises. Nous allons dfinir un paquetage nomm Tagger qui cache la surcharge notre programme principal. Une fois que cela est fait, nous pourrons crire :
use Tagger; $_ = <I>chameau</I>; print "Balise chameau trouve" if /\tag\w+\tag/;

Voici Tagger.pm, soit la forme dun module Perl (voir chapitre 11) :
package Tagger; use overload; sub import { overload::constant qr => \&convert } sub convert { my $re = shift; $re =~ s/ \\tag /<.*?>/xg; $re =~ s/ \\w /[A-Za-z]/xg; return $re; } 1;

Le module Tagger reoit le motif immdiatement avant linterpolation, aussi pouvez vous sauter la surcharge en sautant linterpolation, comme suit :
$re = \tag\w+\tag; print if /$re/; # Cette chane commence avec \t, une tabulation # Trouve une tabulation, suivie dun "a"...

Si vous vouliez personnaliser la variable interpole, appelez la fonction convert directement :


$re = \tag\w+\tag; $re = Tagger::convert $re; print if /$re/; # Cette chane commence avec \t, une tabulation # convertit \tag et \w # $re devient <.*?>[A-Za-z]+<.*?>

Et maintenant, si vous vous demandez toujours ce que sont ces fameuses sub dans le module Tagger, vous allez le dcouvrir bien vite, car cest le sujet du chapitre suivant.

customer_8566

customer_8566

Sous-programmes

Comme beaucoup de langages, Perl fournit des sous-programmes dfinis par lutilisateur.1 Ces sous-programmes peuvent tre dfinis nimporte o dans le programme principal, chargs depuis dautres fichiers grce aux mots-cls do, require ou use ou gnrs lexcution avec eval. Vous pouvez mme les charger lexcution avec le mcanisme dcrit dans la section Autochargement du chapitre 10, Paquetages. Vous pouvez appeler un sous-programme indirectement, en utilisant une variable contenant son nom ou une rfrence la routine ou travers un objet, en laissant lobjet dterminer quel sousprogramme doit vraiment tre appel. Vous pouvez gnrer des sous-programmes anonymes, accessibles seulement travers des rfrences, et si vous voulez, vous en servir pour cloner de nouvelles fonctions quasiment identiques laide de fermetures, qui sont dcrites dans la section du mme nom du chapitre 8, Rfrences.

Syntaxe
Pour dclarer un sous-programme nomm sans le dfinir, utilisez lune de ces formes :
sub sub sub sub sub sub sub sub

NOM NOM PROTO NOM ATTRS NOM PROTO ATTRS NOM BLOC NOM PROTO BLOC NOM ATTRS BLOC NOM PROTO ATTRS BLOC

Pour dclarer et dfinir un sous-programme, ajoutez un BLOC :

1. Nous les appellerons aussi fonctions, mais les fonctions sont identiques aux sous-programmes en Perl. Parfois nous les appellerons mme mthodes, qui sont dfinies de la mme faon, mais appeles diffremment.

customer_8566

198

Chapitre 6 Sous-programmes

Pour crer un sous-programme anonyme ou une fermeture, omettez le NOM :


sub sub sub sub

BLOC BLOC ATTRS BLOC PROTO ATTRS BLOC PROTO

PROTO et ATTRS reprsentent le prototype et les attributs, chacun dentre eux tant prsent dans sa propre section plus loin dans ce chapitre. Ils ne sont pas si importants ; le NOM et le BLOC sont les parties essentielles, y compris quand elles sont absentes. Pour les formes sans NOM, vous devez toujours fournir une manire dappeler le sous-programme. Assurez-vous donc de sauvegarder la valeur de retour, car non seulement cette forme de dclaration de sub est compile comme vous pouviez vous y attendre, mais elle fournit galement une valeur de retour lexcution :
$refsub = sub BLOCK;

Pour importer des sous-programmes dfinis dans un autre module, crivez :


use MODULE qw(NOM1 NOM2 NOM3...);

Pour appeler les sous-programmes directement, crivez : NOM(LISTE) NOM LISTE &NOM
# & est optionel avec des parenthses. # Parenthses facultatives si sub prdclare/importe. # Passe le @_ courant ce sous-programme # (et contourne les prototypes).

Pour appeler des sous-programmes de faon indirecte (par leur nom ou par rfrence), utilisez nimporte laquelle de ces formes :
&$refsub(LISTE) $refsub->(LISTE) &$refsub # Le & nest pas facultatif pour un appel indirect # (sauf en utilisant une notation infixe). # Passe le @_ courant ce sous-programme.

Le nom officiel dun sous-programme comprend le prfixe &. Un sous-programme peut tre appel en utilisant le prfixe, mais le & est en gnral optionnel, ainsi que les parenthses si le sous-programme a t prdclar. Cependant, le & nest pas optionnel quand vous ne faites que nommer le sous-programme, comme quand il est utilis comme argument de defined ou undef ou quand vous voulez gnrer une rfrence un sousprogramme nomm en crivant $refsub = \&nom. Le & nest pas non plus optionnel quand vous voulez faire un appel de sous-programme indirect en utilisant lune des constructions &$refsub() ou &{$refsub}(). Cependant, la notation la plus commode $refsub->() nen a pas besoin. Voir le chapitre 8 pour en savoir plus au sujet des rfrences de sous-programmes. Perl nimpose pas de modle particulier dcriture en majuscules ou minuscules pour vos noms de sous-programme. Cependant une convention vaguement suivie est que les fonctions appeles indirectement par Perl lexcution (BEGIN, CHECK, INIT, END, AUTOLOAD, DESTROY et toutes les fonctions mentionnes au chapitre 14, Variables lies) sont toutes en majuscules, aussi vaut-il probablement mieux viter ce style. (Mais les sousprogrammes utiliss pour des valeurs constantes portent dhabitude un nom tout en capitales. Cest normal. Nous esprons...)

customer_8566

Smantique

199

Smantique
Avant de vous mettre dans tous vos tats cause de toute cette syntaxe, souvenez-vous que la manire normale de dfinir un simple sous-programme finit par ressembler cela :
sub guincher { print "Vous voil guinch.\n"; }

et que la manire normale de lappeler est simplement :


guincher();

Dans ce cas, nous avons ignor lentre (les arguments) et la sortie (les valeurs de retour). Mais les modles Perl pour passer des donnes, et depuis un sous-programme, sont vraiment assez simples : tous les paramtres de la fonction sont passs comme une seule liste plat de scalaires, et sil y a plusieurs valeurs de retour, elles sont de mme retournes lappelant comme une seule liste plat de scalaires. Comme pour toute LISTE, les tableaux et les hachages passs dans cette liste sinterpoleront dans la liste plat, perdant par l mme leur identit. Mais il existe plusieurs manires de contourner cela, et linterpolation automatique de liste est souvent trs utile. Les listes de paramtres, comme les listes de retour, peuvent contenir autant (ou aussi peu) dlments que vous voulez (bien que vous puissiez imposer certaines contraintes aux listes de paramtres en utilisant des prototypes). En effet, Perl est conu autour de cette notion de fonctions variadiques (qui peuvent prendre nimporte quel nombre darguments) ; en C, au contraire, elles sont plus ou moins bidouilles contrecur de faon ce que vous puissiez appeler printf(3). Maintenant, si vous voulez un langage conu pour passer un nombre variable darguments arbitraires, vous devriez vous arranger pour quil soit facile de traiter ces listes arbitraires darguments. Tout argument pass un sous-programme Perl est fourni dans le tableau @_. Si vous appelez une fonction avec deux arguments, ils sont accessibles lintrieur de la fonction comme les deux premiers lments de ce tableau : $_[0] et $_[1]. Comme @_ est un tableau ordinaire avec un nom extraordinaire, vous pouvez lui faire tout ce que vous pouvez normalement faire un tableau.2 Le tableau @_ est un tableau local, mais ses valeurs sont des alias des vritables paramtres scalaires. (Cest connu sous le nom de smantique de passage par rfrence.) Vous pouvez donc modifier les vritables paramtres si vous modifiez llment correspondant de @_ (cest cependant rarement fait, tellement il est facile de renvoyer des valeurs intressantes en Perl). La valeur de retour du sous-programme (ou de nimporte quel bloc, en fait) est la valeur de la dernire expression value. Vous pouvez aussi utiliser une instruction return explicite pour spcifier la valeur de retour et sortir du sous-programme depuis nimporte quel point lintrieur. Dans les deux cas, si la fonction est appele en contexte scalaire ou de liste, lexpression finale de cette fonction est appele dans ce mme contexte.

2. Cest un domaine o Perl est plus orthogonal que la plupart des autres langages de programmation.

customer_8566

200

Chapitre 6 Sous-programmes

Trucs avec la liste de paramtres


Perl na pas encore de paramtres formels nomms, mais en pratique tout ce que vous avez besoin de faire, cest de copier les valeurs de @_ dans une liste my, qui sert parfaitement de liste de paramtres formels. (Ce nest pas une concidence si la copie des valeurs change un passage par rfrence en passage par valeur, ce qui est le fonctionnement que les gens attendent habituellement, mme sils ne connaissent pas le vocabulaire de linformatique thorique.) Voici un exemple typique :
sub setenv_peut_etre { my ($cle, $valeur) = @_; $ENV{$cle} = $valeur unless $ENV{$cle}; }

Mais vous ntes pas oblig de nommer vos paramtres, ce qui est tout lintrt du tableau @_. Par exemple, pour calculer un maximum, vous pouvez juste itrer directement sur @_ :
sub max { my $max = shift(@_); for my $element (@_) { $max = $element if $max < $element; } return $max; } $meilleurjour = max($lun,$mar,$mer,$jeu,$ven);

Ou vous pouvez remplir tout un hachage dun coup :


sub configuration { my %options = @_; print "Verbosit maximale.\n" if $options{VERBOSE} == 9; } configuration(PASSWORD => "xyzzy", VERBOSE => 9, SCORE => 0);

Voici un exemple o vos arguments formels ne sont pas nomms afin de pouvoir modifier les arguments eux-mmes :
majuscules_sur_place($v1, $v2); sub majuscules_sur_place { for (@_) { tr/a-z/A-Z/ } } # ceci change $v1 et $v2

Bien sr, vous navez pas le droit de modifier des constantes de cette faon. Si lun des arguments tait en fait un scalaire comme "hobbit" ou une variable en lecture seule comme $1 et que vous essayiez de le modifier, Perl lverait une exception (vraisemblablement fatale et menaant potentiellement votre carrire). Par exemple, ceci ne marchera pas :
majuscules_sur_place("philippe");

Ce serait beaucoup plus sr si la fonction majuscules_sur_place tait crite de faon renvoyer des copies de ses paramtres, au lieu de les modifier directement :

customer_8566

Smantique
($v3, $v4) = majuscules($v1, $v2); sub majuscules { my @parms = @_; for (@parms) { tr/a-z/A-Z/ } # Vrifie si nous avons t appels en contexte de liste. return wantarray ? @parms : $parms[0]; }

201

Remarquez comme cette fonction (sans prototype) se moque de savoir si on lui a pass de vritables scalaires ou des tableaux. Perl aplatira tout dans une grande liste plat de paramtres dans @_. Cest lun des cas o Perl brille par son style simple de passage de paramtres. La fonction majuscules fonctionnera parfaitement bien sans changer sa dfinition, mme si on lui passe des choses comme a :
@nouvelleliste = majuscules(@liste1, @liste2); @nouvelleliste = majuscules( split /:/, $var );

Ne vous laissez cependant pas tenter par cela :


(@a, @b) = majuscules(@liste1, @liste2); # FAUX

Pourquoi ? Parce que, tout comme la liste des paramtres entrants dans @_ est plate, la liste de retour est aussi plat. Ceci stocke donc tout dans @a, et vide @b en y stockant la liste vide. Voir la section Passage de rfrences pour dautres manires de sy prendre.

Indications derreur
Si vous voulez que votre fonction se termine de faon ce que lappelant ralise quune erreur sest produite, la manire la plus naturelle de faire est dutiliser un return simple sans argument. De cette faon, quand la fonction est appele en contexte scalaire, lappelant reoit undef et quand elle utilise en contexte de liste, lappelant reoit une liste vide. Dans des circonstances extraordinaires, vous pourriez choisir de lever une exception pour indiquer une erreur. Utilisez cependant cette mesure avec parcimonie, sinon votre programme va se retrouver envahi de gestionnaires dexception. Par exemple, ne pas russir ouvrir un fichier dans une fonction gnrique douverture de fichier nest pas vraiment un vnement exceptionnel. En revanche ignorer une telle erreur en serait vraiment un. La fonction intgre wantarray retourne undef si votre fonction a t appele en contexte vide ; vous pouvez donc savoir si la valeur de retour de votre fonction est ignore :
if ($quelquechose_a_plante) { return if defined wantarray; # bon, ce nest pas un contexte vide die "Fais attention mon erreur, espce dinconscient !!!\n"; }

Problmes de porte
Les sous-programmes peuvent tre appels de faon rcursive, car chaque appel reoit son propre tableau darguments, mme quand la routine sappelle elle-mme. Si un sous-programme est appel en utilisant la forme &, la liste darguments est optionnelle. Si la forme en & est utilise, mais que la liste darguments est omise, quelque chose de spcial se produit : le tableau @_ de la routine appelante est fourni implicitement. Il

customer_8566

202

Chapitre 6 Sous-programmes

sagit dun mcanisme defficacit que les nouveaux utilisateurs prfreront viter.
&toto(1,2,3); toto(1,2,3); toto(); &toto(); &toto; toto; # passe trois arguments # pareil # passe une liste vide # pareil # # # # toto() reoit les arguments courants, comme toto(@_), mais plus vite ! comme toto() si sub toto est prdclar, sinon le mot simple "toto"

Non seulement la forme & rend la liste darguments optionnelle, mais elle dsactive galement toute vrification de prototypage sur les arguments fournis. Ceci en partie pour des raisons historiques et en partie pour fournir un moyen efficace de tricher si vous savez ce que vous faites. Voir la section Prototypes plus loin dans ce chapitre. Les variables qui sont utilises dans la fonction, mais qui nont pas t dclares prives cette fonction, ne sont pas ncessairement des variables globales ; elles continuent suivre les rgles normales de porte de Perl. Comme expliqu dans la section Noms du chapitre 2, Composants de Perl, cela signifie quelles cherchent dabord tre rsolues dans la ou les portes lexicales englobantes, puis ensuite dans la porte du paquetage. Du point de vue dun sous-programme, toute variable my dune porte lexicale englobante est donc parfaitement visible. Par exemple, la fonction bumpx, ci-dessous, a accs la variable lexicale $x ( porte sur tout le fichier) car la porte dans laquelle ce my a t dclar le fichier lui-mme na pas t ferme avant la dfinition du sous-programme :
# dbut du fichier my $x = 10; # dclare et initialise la variable sub bumpx { $x++ } # la fonction peut voir la variable lexicale externe

Les programmeurs C et C++ verraient probablement $x comme une variable statique de fichier . Elle est prive en ce qui concerne les fonctions dans les autres fichiers, mais globale du point de vue des fonctions dclares aprs le my. Les programmeurs C qui viennent Perl en cherchant ce quils appeleraient des variables statiques pour des fichiers ou des fonctions ne trouvent pas un tel mot-cl. Les programmeurs Perl vitent en gnral le mot statique , parce que les systmes statiques sont morts et ennuyeux et que le mot est trs charg historiquement. Bien que Perl ne dispose pas du mot static dans son dictionnaire, les programmeurs Perl nont aucun problme pour crer des variables qui restent prives une fonction et persistent dun appel de fonction un autre. Cest juste quil nexiste pas de mot spcial pour dcrire cela. Les primitives de porte de Perl sont plus riches et se combinent avec sa gestion automatique de mmoire de telle manire que quelquun cherchant le mot-cl static pourrait ne jamais penser les utiliser. Les variables lexicales ne passent pas automatiquement au ramasse-miettes simplement parce que lon est sorti de leur porte ; elles attendent de ne plus tre utilises pour tre recycles, ce qui est bien plus important. Pour crer des variables prives qui ne sont pas automatiquement rinitialises entre deux appels de fonction, incluez la fonction tout entire dans un bloc supplmentaire et mettez la fois la dclaration my et la dfinition

customer_8566

Passage de rfrences

203

de la fonction lintrieur de ce bloc. Vous pouvez mme y mettre plus dune fonction pour leur donner un accs partag une variable qui, sinon, est prive.
{ my $compteur = 0; sub next_compteur { return ++$compteur } sub prev_compteur { return --$compteur } }

Comme toujours, laccs la variable lexicale est limit au code se trouvant dans la mme porte lexicale. Les noms des deux fonctions sont cependant globalement accessibles ( lintrieur du paquetage) et, comme les fonctions ont t dfinies dans la porte de $compteur, elles peuvent tout de mme accder cette variable bien que personne dautre ne le puisse. Si cette fonction est charge par require ou use, alors cest probablement parfait. Si tout se passe dans le programme principal, vous devrez vous assurer que toute affectation my lexcution est excute suffisament tt, soit en mettant tout le bloc avant votre programme principal, soit en plaant un bloc BEGIN ou INIT autour pour tre sr quil sera excut avant que votre programme ne dmarre :
BEGIN { my @gamme = qw/ do re mi fa sol la si /; my $note = -1; sub ton_suivant { return $gamme[ ($note += 1) %= @gamme ] }; }

Le BEGIN naffecte ni la dfinition du sous-programme, ni la persistence des lexicales utilises par le sous-programme. Il est juste l pour sassurer que les variables sont initialises avant que la routine soit appele. Pour plus dinformation sur la dclaration de variables prives et globales, voir respectivement my et our au chapitre 29, Fonctions. Les constructions BEGIN et INIT sont expliques au chapitre 18, Compilation.

Passage de rfrences
Si vous voulez passer plus dun tableau ou dun hachage, depuis ou vers une fonction, tout en maintenant leur intgrit, vous aurez alors besoin dun mcanisme explicite de passage de rfrences. Avant cela, vous aurez besoin de comprendre les rfrences ainsi quelles sont expliques au chapitre 8. Faute de quoi, cette section risque de ne pas tre trs comprhensible. Enfin, vous pourrez toujours regarder les images... Voici quelques exemples simples. Dfinissons dabord une fonction qui attend une rfrence un tableau. Quand le tableau est grand, il est beaucoup plus rapide de le passer comme une simple rfrence plutt que comme une longue liste de valeurs :
$total = somme ( \@a ); sub somme { my ($reftab) = @_; my ($total) = 0; foreach (@$reftab) { $total += $_ } return $total; }

customer_8566

204

Chapitre 6 Sous-programmes

Passons plusieurs tableaux une fonction, et faisons-la dpiler (via pop) chacun dentre eux, en renvoyant une nouvelle liste de leurs derniers lments :
@derniers = popplus ( \@a, \@b, \@c, \@d ); sub popplus { my @retliste = (); for my $reftab (@_) { push @retliste, pop @$reftab; } return @retliste; }

Voici comment vous pourriez crire une fonction qui ferait une sorte dintersection, en retournant la liste des cls apparaissant dans tous les hachages qui lui sont passs :
@commun = inter( \%toto, \%titi, \%tutu ); sub inter { my %vus; for my $href (@_) { while (my $k = each %$href ) { $vus{$k}++; } } return grep { $vus{$_} == @_ } keys %vus; }

Jusquici nous navons fait quutiliser le mcanisme normal de retour de liste. Que se passe-t-il si vous voulez passer ou renvoyer un hachage ? Sil ne sagit que dun seul ou que cela ne vous gne pas quils soient concatns, les conventions dappel habituelles conviennent, bien quelles soient un peu coteuses. Comme nous lavons expliqu prcdemment, les gens commencent avoir des problmes avec :
(@a, @b) = func(@c, @d);

ou bien :
(%a, %b) = func(%c, %d);

Cette syntaxe ne fonctionne tout simplement pas. Elle se contente de tout affecter @a ou %a tout en vidant @b ou %b. De plus la fonction ne reoit pas deux tableaux ou deux hachages spars : elle reoit une longue liste dans @_, comme toujours. Vous pouvez vous arranger pour que votre fonction prenne des rfrences en paramtre et en renvoie en rsultat. Voici une fonction qui prend deux rfrences de tableau en argument et renvoie les deux rfrences de tableaux ordonnes selon le nombre dlments quils contiennent.
($aref, $bref) = func(\@c, \@d); print "@$aref en a plus que @$bref\n"; sub func { my ($cref, $dref) = @_; if (@$cref > @$dref) { return ($cref, $dref);

customer_8566

Prototypes
} else { return ($dref, $cref); } }

205

Pour passer des handles de fichier ou de rpertoire des fonctions ou si vous voulez quelles en retournent, voir les sections Rfrences de handles et Rfrences de table de symboles au chapitre 8.

Prototypes
Perl vous permet de dfinir vos propres fonctions de faon ce quelles soient appeles comme les fonctions internes de Perl. Considrez la fonction push(@tableau, $element), qui doit tacitement recevoir une rfrence @tableau, et pas seulement les valeurs de la liste contenues dans @tableau, afin que le tableau soit effectivement modifi. Les prototypes vous permettent de dclarer des sous-programmes qui prennent leurs arguments comme beaucoup de fonctions internes, cest--dire avec certaines contraintes au niveau du nombre et du type des arguments. Nous les appelons prototypes mais ils fonctionnent comme des modles automatiques du contexte dappel plutt que de la faon laquelle penseraient des programmeurs C ou Java quand on leur parle de prototypes. Avec ces modles, Perl ajoutera automatiquement des antislashs implicites ou des appels scalar ou ce quil faut pour que les choses se prsentent de manire respecter le modle fourni. Par exemple, si vous dclarez :
sub monpush (\@@);

alors monpush prendra ses arguments exactement comme push les prend. Pour que cela fonctionne, il faut que la dclaration de la fonction soit visible la compilation. Le prototype naffecte linterprtation des appels de fonction que quand le caractre & est omis. En dautres termes, si vous lappelez comme une fonction intgre, elle se comporte comme un fonction intgre. Si vous lappelez comme une bonne vieille routine, elle se comporte comme une bonne vieille routine. Le & supprime les vrifications de prototype et les effets contextuels associs. Comme les prototypes sont pris en considration seulement la compilation, il en dcoule naturellement quils nont aucune inf luence sur les rfrences de sous-programme comme \&toto ou sur les appels de sous-programme indirects comme &{$refsub} ou $refsub->(). Les appels de mthode ne sont pas non plus inf luencs par les prototypes. Cest parce que la vritable fonction appeler est indtermine au moment de la compilation, puisquelle dpend de lhritage, qui est calcul dynamiquement en Perl. Comme il sagit avant tout de permettre de dfinir des sous-programmes qui fonctionnent comme les commandes internes, voici quelques prototypes de fonctions que vous pourriez utiliser pour muler le fonctionnement des fonctions internes correspondantes :
Dclar comme sub monlink ($$) sub monreverse (@) sub monjoin ($@) sub monpop (\@) Appel par monlink $ancien, $nouveau. monreverse $a,$b,$c. monjoin ":",$a,$b,$c. monpop @array.

customer_8566

206
Dclar comme sub monsplice (\@$$@) sub monkeys (\%) sub monpipe (**) sub monindex ($$;$) sub monsyswrite (*$;$$) sub monopen (*;$@) Appel par

Chapitre 6 Sous-programmes

monsplice @tableau,@tableau,0,@pushmoi . monkeys %{$hashref}. monpipe READHANDLE, WRITEHANDLE. monindex &getstring, "substr". monindex &getstring, "substr", $start. monsyswrite OUTF, $buf. monsyswrite OUTF, $buf, length($buf)-$off, $off. monopen HANDLE. monopen HANDLE, $name. monopen HANDLE, "-|", @cmd.

sub mongrep (&@) sub monrand ($) sub montime ()

mongrep { /toto/ } $a,$b,$c. monrand 42. montime.

Tout caractre de prototype prcd dun antislash (entre parenthses dans la colonne de gauche ci-dessus) reprsente un argument rel (dont la colonne de droite donne un exemple) qui doit imprativement commencer par ce caractre. Le premier argument de monkeys doit donc commencer par un %, tout comme le premier argument de keys. Un point-virgule spare les arguments obligatoires des arguments optionnels. (Il serait redondant devant un @ ou un % puisque les listes peuvent tre vides.) Les caractres de prototype sans antislash ont une signification spciale. Tout caractre @ ou % consomme tout le reste des arguments et force un contexte de liste. (Il est quivalent LISTE dans un diagramme de syntaxe.) Un argument reprsent par $force un contexte scalaire. Un & requiert une rfrence un sous-programme nomm ou anonyme. Une * permet au sous-programme daccepter dans cet emplacement tout ce qui serait accept comme un handle de fichier par une fonction interne : un nom simple, une constante, une expression scalaire, un typeglob ou une rfrence un typeglob. Si vous voulez toujours convertir un tel argument en une rfrence de typeglob, utilisez Symbol::qualify_to_ref comme suit :
use Symbol qualify_to_ref; sub toto (*) { my $fh = qualify_to_ref(shift, caller); ... }

Remarquez que les trois derniers exemples dans le tableau sont traits dune manire spciale par lanalyseur. mongrep est analys comme un vritable oprateur de liste, monrand est analys comme un vritable oprateur unaire avec la mme prcdence unaire que rand et montime ne prend vraiment aucun argument, comme time. Cest--dire que si vous crivez :
montime +2;

customer_8566

Prototypes

207

vous aurez montime() + 2 et non montime(2), qui serait le rsultat dune analyse sans prototype ou avec un prototype unaire. Lexemple mongrep illustre aussi comment & est trait spcialement quand il est le premier argument. Dordinaire, un prototype en & ncessiterait un argument comme \&toto ou sub{}. Cependant, quand il est le premier argument, vous pouvez supprimer le sub de votre sous-programme anonyme et simplement passer le bloc simple lemplacement de l objet indirect (sans virgule aprs). Lun des aspects attrayant du prototype & est quil permet de gnrer une nouvelle syntaxe, tant que le & est en premire position :
sub try (&$) { my ($try, $catch) = @_; eval { &$try }; if ($@) { local $_ = $@; &$catch; } } sub catch (&) { $_[0] } try { die "phooey"; } # ce nest pas la fin de lappel de fonction ! catch { /phooey/ and print "unphooey\n"; };

Ceci affiche unphooey . Ici, try est appel avec deux arguments, la fonction anonyme {die "phooey";} et la valeur de retour de la fonction catch, qui dans ce cas nest rien dautre que son propre argument, tout le bloc dune autre fonction anonyme. Dans le try, la premire fonction en argument est appele sous la protection dun bloc eval pour intercepter tout ce qui pourrait exploser. Si quelque chose explose effectivement, la seconde fonction est appele avec une version locale de la variable globale $_ contenant lexception qui a t leve.3 Si tout cela est du chinois pour vous, vous allez devoir vous reporter die et eval au chapitre 29, puis vous informer au sujet des fonctions anonymes et des fermetures au chapitre 8. Dun autre ct, si tout cela vous intrigue, vous pouvez jeter un il au module Error sur CPAN, qui utilise cette mthode pour implmenter une gestion dexceptions minutieusement structure avec les clauses try, catch, except, otherwise et finally. Voici une rimplmentation de loprateur grep (loprateur interne est plus efficace, bien sr) :
sub mongrep (&@) { my $coderef = shift;

3. Oui, il reste des questions en suspens par rapport la visibilit de @_. Nous les ignorerons pour le moment. Mais si un jour nous rendons @_ porte lexicale, comme cela se fait actuellement dans les versions exprimentales de Perl avec des threads, ces sous-programmes anonymes pourront se comporter comme des fermetures.

customer_8566

208
my @resultat; foreach $_ (@_) { push(@resultat, $_) if &$coderef; } return @resultat; }

Chapitre 6 Sous-programmes

Certains prfreraient des prototypes compltement alphanumriques. Les caractres alphanumriques ont t intentionnellement laisss en dehors des prototypes dans le but avou dajouter un jour des paramtres formels nomms. (Peut-tre.) Lobjectif majeur du mcanisme actuel est de permettre aux auteurs de modules dimposer un certain nombre de vrifications la compilation aux utilisateurs de leurs modules.

Substitution en ligne de fonctions constantes


Les fonctions prototypes avec (), ce qui signifie quelles ne prennent aucun argument, sont analyses comme la fonction interne time. Mieux, le compilateur traite de telles fonctions comme de bonnes candidates pour la mise en ligne. Si le rsultat de cette fonction, aprs la passe doptimisation et de prcalcul des expressions constantes, est soit une constante, soit un scalaire porte lexicale sans autre rfrence, alors cette valeur sera utilise au lieu des appels la fonction. Les appels faits avec &NOM ne sont cependant jamais mis en ligne, tout comme ils ne sont sujets aucun autre effet de prototype. (Pour une mthode simple de dclaration de telles constantes, voir le pragma use constant au chapitre 31, Modules de pragmas.) Les deux versions de ces fonctions calculant ! seront mises en ligne par le compilateur :
sub pi () sub PI () { 3.14159 } { 4 * atan2(1, 1) } # Pas exact, mais proche # Le mieux quon puisse obtenir

En fait, toutes les fonctions suivantes seront mises en ligne, car Perl peut tout dterminer la compilation :
sub FLAG_TOTO () sub FLAG_TITI () sub FLAG_MASK () { 1 << 8 } { 1 << 9 } { FLAG_TOTO | FLAG_TITI }

sub OPT_BLORGH () { (0x1B58 & FLAG_MASK) == 0 } sub BLORGH_VAL () { if (OPT_BLORGH) { return 23 } else { return 42 } } sub N () { int(BLORGH_VAL) / 3 } BEGIN { # le compilateur excute ce bloc la compilation my $prod = 1; # variable prive, persistante for (1 .. N) { $prod *= $_ } sub NFACT () { $prod } }

Dans le dernier exemple, la fonction NFACT est mise en ligne car elle a un prototype vide et que la variable quelle retourne nest pas modifie par la fonction et ne peut plus ensuite tre modifie par personne, puisquelle est dans une porte lexicale. Le compi-

customer_8566

Prototypes

209

lateur remplace donc toutes les utilisations de NFACT par cette valeur, qui a t prcalcule la compilation grce au BEGIN qui lentoure. Si vous redfinissez un sous-programme qui tait susceptible dtre mis en ligne, vous aurez un avertissement obligatoire. (Vous pouvez vous servir de cet avertissement pour savoir si le compilateur a mis en ligne une routine en particulier.) Lavertissement est considr suffisament important pour ne pas tre optionnel, car les invocations prcdemment compiles de la fonction continueront dutiliser lancienne valeur de la fonction. Si vous voulez redfinir la routine, assurez-vous quelle na pas t mise en ligne en retirant le prototype () (qui change la smantique dappel, aussi faites attention) ou en contrecarrant le mcanisme de mise en ligne dune autre manire, comme par exemple :
sub non_enligne () { return 23 if $$; }

Pour en savoir plus sur ce qui se passe durant les phases de compilation et dexcution de votre programme, voyez le chapitre 18.

Prcautions prendre avec les prototypes


Il vaut probablement mieux rserver les prototypes aux nouvelles fonctions et ne pas les appliquer danciennes fonctions. Ce sont des descripteurs de contexte, pas des protypes du C ANSI, il vous faut donc tre extrmement attentif ne pas imposer silencieusement un contexte diffrent. Supposez par exemple que vous dcidiez quune fonction ne doit prendre quun seul paramtre, comme ceci :
sub func ($) { my $n = shift; print "vous mavez donn $n\n"; }

Cela la transforme en oprateur unaire (comme loprateur interne rand) et modifie la faon dont le compilateur dtermine les arguments de la fonction. Avec le nouveau prototype, la fonction consomme un seul argument en contexte scalaire, au lieu de plusieurs arguments en contexte de liste. Si quelquun la appele avec un tableau ou une expression de liste, mme si ce tableau ou cette liste ne contenait quun seul lment, l o cela marchait vous aurez maintenant quelque chose de compltement diffrent :
func @toto; func split /:/; func "a", "b", "c"; func("a", "b", "c"); # # # # # compte les lments de @toto compte le nombre dlments retourns passe "a" seulement, le jette avec "b" et retourne "c" soudain, une erreur du compilateur !

Vous venez juste de fournir un scalar implicite devant la liste darguments, ce qui peut tre trs surprenant. Ce nest pas le vieux @toto qui contenait une seule valeur qui est pass. la place, cest 1 (le nombre dlments de @toto) qui est maintenant pass func. Le split, tant appel en contexte scalaire, scribouille partout dans votre liste de paramtres @_. Dans le troisime exemple, comme func a t prototype comme un oprateur unaire, seul a lui est pass ; puis la valeur de retour de func est jete tandis que loprateur virgule value les deux lments suivants et retourne c . Dans le dernier exemple, lutilisateur obtient maintenant une erreur de syntaxe la compilation,

customer_8566

210

Chapitre 6 Sous-programmes

sur du code qui compilait et fonctionnait parfaitement. Si vous crivez du nouveau code et que vous voudriez un oprateur unaire qui ne prend quune variable scalaire, et pas une expression scalaire, vous pouvez toujours le prototyper pour quil prenne une rfrence un scalaire :
sub func (\$) { my $nref = shift; print "vous mavez donn $$nref\n"; }

Maintenant le compilateur ne laissera rien passer qui ne commence pas par un dollar :
func func func func func func @toto; split/:/; $s; $a[3]; $h{bazar}[-1]; 2+5; # # # # # # # # # erreur de compilation, voit @, veut $ erreur de compilation, voit une fonction, veut $ celui-ci va bien ; on a eu un vrai $ celui-ci aussi et mme a expression scalaire, toujours une erreur de compilation a marche, mais le remde nest-il pas pire que le mal ?

func ${ \(2+5) };

Si vous ne faites pas attention, vous pouvez vous attirer des ennuis avec les prototypes. Mais si vous faites attention, vous pouvez faire tout un tas de trucs classe avec. Tout cela est bien sr trs puissant, et ne devrait tre utilis quavec modration pour rendre le monde meilleur.

Attributs de sous-programmes
Une dclaration ou une dfinition de sous-programme peut se voir associer une liste dattributs. Si une telle liste dattributs est prsente, elle sera dcoupe en fonction des blancs ou des deux-points et traite comme si un use attributes avait t vu. Voir le pragma use attributes au chapitre 31 pour des dtails internes. Il existe trois attributs standards pour les sous-programmes : locked, method et lvalue.

Les attibuts locked et method


# Un seul thread est autoris dans cette fonction. sub afunc : locked { ... } # Un seul thread est autoris dans cette fonction pour un objet donn. sub afunc : locked method { ... }

Mettre lattribut locked na de sens que lorsque la fonction ou la mthode est suppose tre appele par plusieurs threads simultanment. Quand il est appliqu une fonction qui nest pas une mthode, Perl sassure quun verrou est mis sur la routine elle-mme avant que lon ny entre. Quand il est appliqu une fonction qui est une mthode (cest--dire une fonction galement marque avec lattribut method), Perl sassure que toute invocation de cette mthode verrouille implicitement son premier argument (lobjet) avant lexcution.

customer_8566

Attributs de sous-programmes

211

La smantique de ce verrou est la mme quen utilisant loprateur lock dans un sousprogramme en premire instruction de ce sous-programme. Pour en savoir plus sur les verrous, voir le chapitre 17, Threads. Lattribut method peut tre utilis tout seul :
sub afunc : method { ... }

lheure actuelle, cela na pour seul effet que de marquer la routine de faon ne pas dclencher lavertissement Ambiguous call resolved as CORE::%s . (Nous pourrons lui donner une signification plus importante un de ces jours.) Le systme dattributs est extensible par lutilisateur, ce qui vous permet de crer vos propres noms dattribut. Ces nouveaux attributs doivent porter des noms didentificateur valides (sans autre caractre de ponctuation que _ ). Une liste de paramtres peut y tre ajoute, pour laquelle nest vrifie pour le moment que le bon quilibrage des parenthses. Voici des exemples de syntaxe valide (bien que les attributs soient inconnus) :
sub fnord (&\%) : switch(10,foo(7,3)) : expensive; sub plugh () : Ugly(\(") :Bad; sub xyzzy : _5x5 { ... }

Voici des exemples de syntaxe incorrecte :


sub sub sub sub fnord snoid xyzzy plugh : : : : switch(10,toto(); Laid((); 5x5; Y2::nord; # # # # # # chane () dsquilibre chane () dsquilibre "5x5" nest pas un identificateur valide "Y2::nord" nest pas un identificateur simple "+" nest ni un espace ni un deux-points

sub snurt : toto + titi;

La liste dattributs est passe comme une liste de chanes constantes au code qui les associe avec le sous-programme. La faon exacte dont cela fonctionne (ou ne fonctionne pas) est hautement exprimentale. Pour des dtails actuels sur les listes dattributs et leur manipulation, voir attributes(3).

Lattribut lvalue
Il est possible de renvoyer un scalaire modifiable depuis un sous-programme, mais seulement si vous dclarez que le sous-programme retourne une lvalue :
my $val; sub modifiable : lvalue { $val; } sub nonmodifiable { $val; } modifiable() = 5; nonmodifiable() = 5; # Affecte $valeur. # ERREUR

Si vous passez des paramtres un sous-programme lvalu, vous aurez besoin de parenthses pour lever lambigut sur ce qui est affect :

customer_8566

212
modifiable $x modifiable 42 modifiable($x) modifiable(42) = 5; = 5; = 5; = 5; # # # # #

Chapitre 6 Sous-programmes
affecte 5 $x avant ! impossible de modifier une constante : erreur de compilation ceci fonctionne et cela aussi

Si vous voulez finasser, vous pouvez contourner cela dans le cas particulier dune fonction ne prenant quun seul argument. Dclarer la fonction avec le prototype ($) la fait analyser avec la prcdence dun oprateur unaire nomm. Comme les oprateurs unaires nomms ont une prcdence suprieure celle de laffectation, vous navez plus besoin de parenthses. (La question de savoir si cela est souhaitable ou pas est laisse lapprciation de la milice du style.) En revanche, vous navez pas besoin de finasser dans le cas dun sous-programme qui ne prend aucun argument (cest--dire avec un prototype ()). Vous pouvez sans ambigut crire :
modifiable = 5;

Cela fonctionne car aucun terme valide ne commence par =. De mme, vous pouvez omettre les parenthses dans les appels de mthodes lvalues quand vous ne passez aucun argument :
$obj->modifiable = 5;

Nous promettons de ne pas casser ces deux constructions dans les prochaines versions de Perl. Elles sont pratiques quand vous voulez encapsuler des attributs dobjet dans des appels de mthodes (de faon ce quils soient hrits comme des appels de mthodes, mais accessibles comme des variables). Le contexte scalaire ou de liste du sous-programme avec lattribut lvalue et de la partie droite dune affectation ce sous-programme est dans les deux cas dtermin en remplaant lappel de fonction par un scalaire. Considrez par exemple :
data(2,3) = get_data(3,4);

Les deux sous-programmes ont t appels en contexte scalaire, tandis que dans :
(data(2,3)) = get_data(3,4);

et dans :
(data(2),data(3)) = get_data(3,4);

tous les sous-programmes sont appels en contexte de liste. Limplmentation actuelle ne permet pas des tableaux ou des hachages dtre retourns directement par des sous-programme lvalus. Vous pouvez toujours renvoyer une rfrence la place.

customer_8566

Formats

Perl dispose dun mcanisme pour vous aider gnrer des rapports et des tableaux simples. Ainsi, Perl vous aide coder votre page de sortie dune faon proche de ce quoi elle ressemblera quand elle saffichera. Il garde trace du nombre de lignes sur la page, du numro de page courant, de quand imprimer les en-ttes de page et ainsi de suite. Les mots-cls sont emprunts FORTRAN : format pour les dclarer et write pour les excuter. Voir les sections correspondantes au chapitre 29, Fonctions. Heureusement la disposition est beaucoup plus lisible, plus proche du PRINT USING de BASIC. Vous pouvez le voir comme le nroff(1) du pauvre. (Si vous connaissez nroff, a ne ressemble peuttre pas un encouragement.) Les formats, comme les paquetages et les sous-programmes, sont dclars plutt quexcuts, et peuvent donc apparatre nimporte o dans votre programme. (Bien quen gnral il vaille mieux les regrouper tous ensemble.) Ils ont leur propre espace de nommage diffrent de ceux de tous les autres types de Perl. Cela signifie que si vous avez une fonction nomme toto , elle na rien voir avec le format nomm toto . Cependant le nom par dfaut du format associ un handle de fichier donn est le mme que le nom de ce handle. Le format par dfaut de STDOUT est donc nomm STDOUT , et le format par dfaut du handle de fichier TEMP est galement appel TEMP . Ils ont lair identiques. Mais ils ne le sont pas. Les formats denregistrement de sortie sont dclars de la manire suivante :
format NOM = FORMLISTE .

If NOM est omis, cest le format STDOUT qui est dfini. FORMLISTE est compose dune srie de lignes, chacun pouvant tre de trois types : un commentaire, indiqu par une # en premire colonne ; une ligne image , donnant le format pour une ligne de sortie ; une ligne darguments fournissant les valeurs insrer dans la ligne dimage prcdente.

customer_8566

214

Chapitre 7 Formats

Les lignes images sont imprimes exactement comme elles apparaissent hormis certains champs auxquels sont substitues des valeurs.1 Chaque champ de substitution dans une ligne image commence, soit par un signe @, soit par un ^. Ces lignes ne subissent aucune forme dinterpolation de variable. Le champ @ ( ne pas confondre avec le marqueur de tableau @) reprsente le type normal de champ ; lautre type, ^, est utilis pour un remplissage rudimentaire de blocs de texte multilignes. La longueur du champ est indique en remplissant le champ avec plusieurs caractres <, > ou | pour indiquer respectivement la justification gauche, droite ou au centre. Si la variable excde la longueur spcifie, elle est tronque. Vous pouvez galement utiliser, comme autre forme de justification droite, des caractres # (aprs un caractre @ ou ^ initial) pour spcifier un champ numrique. Vous pouvez insrer un . la place de lun des caractres # pour aligner les points dcimaux. Si lune des valeurs fournies pour ces champs contient un saut de ligne, seul le texte avant ce saut de ligne est imprim. Enfin, le champ spcial @* peut tre utilis pour imprimer des valeurs multilignes de manire non tronque ; il devrait gnralement apparatre seul sur une ligne image. Les valeurs sont spcifies sur la ligne suivante dans le mme ordre que les champs images. Les expressions fournissant les valeurs doivent tre spares par des virgules. Les expressions sont toutes values en contexte de liste avant que la ligne ne soit traite, et une seule expression peut donc produire plusieurs lments de liste. Les expressions peuvent stendre sur plusieurs lignes, si elles sont mises entre accolades. (Dans ce cas, laccolade ouvrante doit tre le premier token sur la premire ligne.) Cela vous permet daligner les valeurs sous leurs champs de format respectifs pour faciliter la lecture. Si lvaluation dune expression donne un nombre avec une partie dcimale, et si limage correspondante spcifie que la partie dcimale doit apparatre dans la sortie (cest-dire nimporte quelle image sauf une srie de # sans . inclus), le caractre pour le point dcimal est toujours dtermin par la valeur de la locale LC_NUMERIC. Cela signifie que si lenvironnement dexcution spcifie par exemple une locale franaise, une virgule sera utilise plutt quun point. Pour plus dinformation, voir la page de manuel perllocale. lintrieur dune expression, les caractres blancs \n, \t et \f sont tous considrs comme quivalents un espace seul. Vous pourriez voir cela comme si le filtre suivant tait appliqu chaque valeur dans le format :
$valeur =~ tr/\n\t\f/ /;

Le caractre blanc restant, \r, force laffichage dune nouvelle ligne si la ligne image le permet. Les champs images qui commencent par ^ plutt que @ sont traits de manire spciale. Avec un champ #, celui-ci est vide si la valeur est indfinie. Pour les autres types de champ, le chapeau permet un genre de mode de remplissage. Au lieu dune expression arbitraire, la valeur fournie doit tre un nom de variable scalaire contenant une chane
1. Mme ces champs conservent lintgrit des colonnes o vous les mettez. Il ny a rien dans une ligne image qui peut faire crotre ou rtrcir ou se dcaler un champ. Les colonnes que vous voyez sont sacres au sens WYSIWYG (si vous utilisez une fonte chasse fixe). Mme les caractres de contrle sont supposs avoir une largeur de un.

customer_8566

Formats

215

de caractres. Perl met tout le texte quil peut dans le champ, puis coupe le dbut de la chane de faon ce que la fois suivante o la variable est rfrence le reste du texte puisse tre imprim. (Oui, cela signifie que le contenu de la variable est altr pendant lexcution de lappel write et nest pas prserv. Utilisez une variable temporaire si vous voulez prserver la valeur originale.) Normalement, vous devrez utiliser une squence de champs aligns verticalement pour afficher un bloc de texte. Vous pouvez terminer le champ final par le texte ... , qui apparatra dans la sortie seulement si le texte tait trop long pour tre affich entirement. Vous pouvez modifier les caractres de rupture en modifiant la valeur de la variable $: ($FORMAT_LINE_BREAK_CHARACTERS si vous utilisez le module English) en une liste des caractres dsirs. Les champs ^ peuvent produire des enregistrements de longueur variable. Si le texte formater est court, rptez quelques fois la ligne de format avec le champ ^. Si vous faites cela pour de courtes donnes, vous obtiendrez quelques lignes blanches. Pour supprimer les lignes qui finiraient blanches, mettez un caractre ~ (tilde) nimporte o sur la ligne. (Le tilde lui-mme est transform en espace la sortie.) Si vous mettez un second tilde la suite du premier, la ligne sera rpte jusqu ce que tout le texte des champs de cette ligne ait t affich. (Cela fonctionne car tous les champs ^ avalent les chanes quils impriment. Mais si vous utilisez un champ de type @ en conjonction avec deux tildes, vous avez intrt ce que lexpression fournie ne renvoie pas perptuellement la mme valeur ! Utilisez un shift ou un autre oprateur dont lun des effets secondaires puise toutes les valeurs.) Le traitement des en-ttes de format est gr par dfaut par un format de mme nom que le handle de fichier courant, auquel _TOP a t concatn. Il est dclench au dbut de chaque page. Voir write au chapitre 29. Voici quelques exemples :
# un rapport sur le fichier /etc/passwd format STDOUT_TOP = Fichier Passwd Nom Login Bureau Uid Gid Home -----------------------------------------------------------------. format STDOUT = @<<<<<<<<<<<<<<<<<< @||||||| @<<<<<<@>>>> @>>>> @<<<<<<<<<<<<<<<<< $nom, $login, $bureau,$uid,$gid, $home . # un rapport partir dun formulaire de rapport de bogues format STDOUT_TOP = Rapport de bogues @<<<<<<<<<<<<<<<<<<<<<<< @||| @>>>>>>>>>>>>>>>>>>>>>>> $systeme, $%, $date -----------------------------------------------------------------. format STDOUT = Sujet: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $suject

customer_8566

216

Chapitre 7 Formats

Index: @<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< $index, $description Priorit: @<<<<<<<<<< Date: @<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< $priorite, $date, $description De: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< $de, $description Assign : @<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< $programmeur, $description ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< $description ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< $description ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< $description ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< $description ~ ^<<<<<<<<<<<<<<<<<<<<<<<... $description .

Les variables lexicales ne sont pas visibles dans un format sauf si le format est dclar dans la porte de la variable lexicale. Il est possible de mlanger des appels print et write sur le mme canal de sortie, mais il vous faudra grer la variable spciale $- ($FORMAT_LINES_LEFT si vous utilisez le module English) vous-mme.

Variables de format
Le nom de format en cours est stock dans la variable $~ ($FORMAT_NAME), et le nom de len-tte de format en cours dans $^ ($FORMAT_TOP_NAME). Le numro de page de sortie courant est stock dans $% ($FORMAT_PAGE_NUMBER), et le nombre de lignes dans la page se trouve dans $= ($FORMAT_LINES_PER_PAGE). Le vidage automatique du tampon de sortie de ce handle est positionn dans $| ($OUTPUT_AUTOFLUSH). La chane sortie avant chaque en-tte de page est stocke dans $^L ($FORMAT_FORMFEED). Ces variables sont positionnes pour chaque handle de fichier, aussi devrez-vous faire un select sur le handle de fichier associ un format pour modifier ses variables de format :
select((select(OUTF), $~ = "Mon_Autre_Format", $^ = "Mon_Entete_de_Format" )[0]);

Cest bien moche, hein ? Cest cependant un idiome commun, aussi ne soyez pas trop surpris en le voyant. Vous pouvez au moins utiliser une variable temporaire pour conserver le handle de fichier prcdent :
$ofh = select(OUTF); $~ = "Mon_Autre_Format"; $^ = "Mon_Entete_de_Format"; select($ofh);

customer_8566

Variables de format

217

Non seulement cest une meilleure approche en gnral, car cela amliore la lisibilit du code, mais vous avez maintenant en plus une instruction intermdiaire o sarrter dans le code avec un debogueur en pas pas. Si vous utilisez le module English, vous pouvez mme lire le nom des variables :
use English; $ofh = select(OUTF); $FORMAT_NAME = "Mon_Autre_Format"; $FORMAT_TOP_NAME = "Mon_Entete_de_Format"; select($ofh);

Mais il vous reste quand mme ces appels bizarres select. Si vous voulez les viter, utilisez le module FileHandle fourni avec Perl. Maintenant vous pouvez accder ces variables spciales en utilisant des noms de mthodes en minuscules la place :
use FileHandle; OUTF->format_name("Mon_Autre_Format"); OUTF->format_top_name("Mon_Entete_de_Format");

Cest quand mme mieux ! Comme la ligne de valeurs qui suit votre ligne image peut contenir des expressions arbitraires (pour les champs @, pas pour les champs ^), vous pouvez passer les traitements plus compliqus dautres fonctions, comme printf ou une de vos propres fonctions. Par exemple pour insrer des virgules dans un nombre :
format Ident = @<<<<<<<<<<<<<<< commify($n) .

Pour afficher un vrai @, ~ ou ^ dans un champ, faites comme ceci :


format Ident = Jai un @ ici. "@" .

Pour centrer tout une ligne de texte, faites quelque chose comme cela :
format Ident = @|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| "Une ligne de texte" .

Lindicateur de longueur de champ > garantit que le texte sera justifi droite dans le champ, mais le champ lui-mme se place exactement o vous lavez plac. Il nexiste pas de manire intgre de dire mets ce champ droite de la page, quelle que soit sa largeur . Vous devez spcifier o il se trouve relativement la marge de gauche. Ceux qui sont vraiment dsesprs peuvent gnrer leur propre format au vol, en sappuyant sur le nombre courant de colonnes (non fourni) et puis faire un eval :
$format = . . . . "format STDOUT = \n" ^ . < x $cols . "\n" $entry . "\n" "\t^" . "<" x ($cols-8) . "~~\n" $entry . "\n"

customer_8566

218
. ".\n"; print $format if $Debug; eval $format; die $@ if $@;

Chapitre 7 Formats

La ligne la plus importante est probablement celle du print. Ce quil imprime ressemble ceci :
format STDOUT = ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $entry ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<~~ $entry .

Voici un petit programme qui se comporte comme lutilitaire Unix fmt(1) :


format = ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~~ $_ . $/ = ""; while (<>) { s/\s*\n\s*/ /g; write; }

Pieds de page
Alors que $^ ($FORMAT_TOP_NAME) contient le nom du format den-tte courant, il nexiste pas de mcanisme correspondant pour les pieds de page. Lun des problmes majeurs est de ne pas savoir quelle sera la taille dun format avant de lavoir valu. Cest dans la liste des choses faire.2 Voici une stratgie : si vous avez un pied de page de taille fixe, vous pouvez lafficher en vrifiant $- ($FORMAT_LINES_LEFT) avant chaque write puis afficher le pied de page si ncessaire. Voici une autre stratgie : ouvrez un tube sur vous-mme, en utilisant open(MOIMEME, "|-") (voir lentre open au chapitre 29) et faites toujours des write sur MOIMEME au lieu de STDOUT. Le processus fils devra traiter son STDIN aprs coup pour rarranger ses enttes et pieds de page votre guise. Pas trs pratique, mais faisable.

2. Bien sr, cela ne garantit en rien que ce sera fait un jour. Les formats sont quelque chose dun peu dpass en cet ge du WWW, de lUnicode, du XML, du XSLT et toutes les autres choses quon inventera aprs tout a.

customer_8566

Pieds de page

219

Accs au mcanisme interne de formatage


Pour accder au mcanisme interne de formatage, vous pouvez utiliser loprateur intgr formline et accder $^A (la variable $ACCUMULATOR) directement. Par exemple :
$str = formline <<END, 1,2,3; @<<< @||| @>>> END print "Wouah, je viens juste de mettre `$^A dans laccumulateur !\n";

Ou pour crer un sous-programme swrite qui serait write ce que sprintf est printf :
use Carp; sub swrite { croak "usage: swrite IMAGE ARGS" unless @_; my $format = shift; $^A = ""; formline($format, @_); return $^A; } $chaine = swrite(<<END, 1, 2, 3); Vrifiez-moi @<<< @||| @>>> END print $chaine;

Si vous utilisiez le module FileHandle, vous pourriez utiliser formline comme suit pour passer la ligne la colonne 72 :
use FileHandle; STDOUT->formline("^" . ("<" x 72) . "~~\n", $long_texte);

customer_8566

customer_8566

Rfrences

Pour des raisons tant philosophiques que pratiques, Perl a toujours favoris les structures de donnes plates et linaires. Et pour beaucoup de problmes, cest exactement ce dont vous avez besoin. Imaginez que vous vouliez construire une table simple (un tableau deux dimensions) listant certaines informations anthropomtriques ge, couleur des yeux, poids concernant un groupe de personnes. Vous pourriez faire cela en crant un tableau pour chaque individu :
@john = (47, "marron", 84); @mary = (23, "noisette", 58); @bill = (35, "bleu", 71);

Vous pourriez ensuite construire un simple tableau supplmentaire contenant les noms des autres tableaux :
@infos = (john, mary, bill);

Pour changer la couleur des yeux de John en rouge aprs une vire en ville, il nous faut un moyen de changer le contenu de @john partir de la simple chane john . Cest le problme classique des indirections, que diffrents langages rsolvent de diffrentes manires. En C, la forme la plus courante dindirection est le pointeur, qui permet une variable de contenir ladresse en mmoire dune autre variable. En Perl, la forme la plus courante dindirection est la rfrence.

Quest-ce quune rfrence ?


Dans notre exemple, $infos[0] contient la valeur john . Cest--dire quil contient une chane qui se trouve tre le nom dune autre variable (globale). On dit que la premire variable se rfre la seconde ; cette sorte de rfrence est appele symbolique, puisque Perl doit rechercher @john dans une table de symboles pour le retrouver. (Vous pouvez voir les rfrences symboliques comme analogues aux liens symboliques dun systme de fichiers.) Nous parlerons des rfrences symboliques un peu plus loin dans ce chapitre.

customer_8566

222

Chapitre 8 Rfrences

Lautre type de rfrences sont les rfrences en dur (hard references), qui constituent ce que les programmeurs Perl utilisent le plus souvent pour accomplir leurs indirections (quand ce ne sont pas leurs indiscrtions). Nous les appelons rfrences en dur non pas parce quelles sont compliques, mais parce quelles sont relles et solides. Si vous prfrez, vous pouvez voir les rfrences en dur comme de vraies rfrences et les rfrences symboliques comme de fausses rfrences. Cest un peu comme la diffrence entre avoir des amis et avoir des relations. Quand nous ne prcisons pas de quel type de rfrence nous parlons, il sagit de rfrences en dur. La figure 8-1 prsente une variable nomme $titi faisant rfrence au contenu dune variable nomme $toto qui a la valeur robot .

Figure 8-1. Une rfrence en dur et une rfrence symbolique Contrairement aux rfrences symboliques, une vraie rfrence ne se rfre non pas au nom dune autre variable (qui nest que le conteneur dune valeur), mais la valeur ellemme, un bout de donne interne. Il ny a pas de mot pour dcrire cela, mais quand il le faut nous lappellerons le rfrent. Supposez par exemple que vous crez une rfrence en dur vers le tableau porte lexicale @tableau. Cette rfrence en dur, et le rfrent auquel elle se rfre, continueront dexister mme quand @tableau sera hors de porte. Un rfrent nest dtruit que quand toutes les rfrences qui pointent sur lui ont t limines. Un rfrent na pas vraiment de nom propre, en dehors des rfrences qui sy rfrent. Pour le dire dune autre faon, chaque variable Perl vit dans une sorte de table de symboles, qui contient une rfrence vers le rfrent sous-jacent (qui lui na pas de nom). Le rfrent peut tre simple, comme un nombre ou une chane, ou complexe, comme un tableau ou un hachage. Dans tous les cas, il y a toujours exactement une rfrence de la variable sa valeur. Vous pouvez ventuellement crer de nouvelles rfrences en dur vers le mme rfrent, mais si vous le faites, la variable elle-mme nen sait rien (et sen moque).1 Une rfrence symbolique est juste une chane qui se trouve tre le nom de quelque chose dans la table des symboles. Ce nest pas tellement un type distinct, mais plutt quelque chose que vous faites avec une chane. Alors quune rfrence en dur est une crature compltement diffrente. Cest le troisime des trois types scalaires fondamentaux, les deux autres tant les chanes et les nombres. Une rfrence en dur na pas be-

1. Si vous tes curieux, vous pouvez vous servir du module Devel::Peek, fourni avec Perl, pour dterminer la valeur du compteur de rfrences sous-jacent.

customer_8566

Cration de rfrences

223

soin de connatre le nom de quelque chose pour pointer dessus, et en fait il est compltement normal quil ny ait pas de nom utiliser du tout. De tels rfrents sans nom du tout sont anonymes ; nous en parlons dans la partie Donnes anonymes ci-dessous. Rfrencer une valeur, dans la terminologie de ce chapitre, consiste crer une rfrence en dur vers elle. (Il existe un oprateur spcial pour cette action cratrice.) La rfrence ainsi cre est un simple scalaire, qui se comporte dans les situations usuelles comme nimporte quel autre scalaire. Drfrencer ce scalaire signifie utiliser la rfrence pour obtenir le rfrent. Le rfrencement et le drfrencement se produisent quand vous invoquez des mcanismes explicites ; il ne se produit jamais de rfrencement ou de drfrencement implicites en Perl. Enfin, presque jamais. Un appel de fonction peut passer implicitement des rfrences si elle a un prototype qui la dclare ainsi. Dans ce cas, lappelant de la fonction ne passe pas explicitement une rfrence, bien quil vous faille toujours drfrencer explicitement celle-ci lintrieur de la fonction. Voir la section Prototypes au chapitre 6, Sous-programmes. Et pour tre totalement honnte, il se produit aussi des drfrencements en coulisses quand vous utilisez certains types de handles de fichiers. Mais cela relve de la compatibilit antrieure et reste transparent pour lutilisateur lambda. Finalement, deux fonctions internes, bless et lock, prennent toutes deux une rfrence en argument mais la drfrencent implicitement pour faire leurs manipulations sur ce qui se cache derrire. Ces indiscrtions admises, le principe selon lequel Perl na pas envie de toucher vos niveaux dindirections tient toujours. Une rfrence peut pointer sur nimporte quelle structure de donnes. Comme les rfrences sont des scalaires, vous pouvez les stocker dans des tableaux et des hachages, et ainsi construire des tableaux de tableaux, des tableaux de hachages, des hachages de tableaux, des tableaux de hachages de fonctions, et ainsi de suite. Vous trouverez des exemples de cela dans le chapitre 9, Structures de donnes. Gardez cependant lesprit que les tableaux et les hachages de Perl sont une dimension en interne. Cest--dire que leurs lments ne peuvent contenir que des valeurs scalaires (chanes, nombres et rfrences). Quand nous disons quelque chose comme tableau de tableaux , nous pensons en fait tableau de rfrences des tableaux , tout comme nous pensons hachage de rfrences des fonctions quand nous disons hachage de fonctions . Mais comme les rfrences sont la seule faon dimplmenter de telles structures en Perl, il sensuit que lexpression plus courte et moins prcise nest tout de mme pas fausse, et ne devrait donc pas tre totalement dnigre, moins que vous ne soyez maniaque.

Cration de rfrences
Il existe plusieurs faons de crer des rfrences, dont nous dcrirons la plupart avant dexpliquer comment utiliser (drfrencer) les rfrences rsultantes.

Loprateur antislash
Vous pouvez crer une rfrence une variable nomme ou un sous-programme grce un antislash. (Vous pouvez aussi vous en servir sur une valeur scalaire anonymes

customer_8566

224

Chapitre 8 Rfrences

comme 7 ou "chameau", bien que cela soit rarement ncessaire.) Cet oprateur fonctionne comme loprateur & (adresse de) en C du moins premire vue. Voici quelques exemples :
$refscalaire $refconst $reftableau $refhash $refcode $refglob = = = = = = \$toto; \186_282.42; \@ARGV; \%ENV; \&handler; \*STDOUT;

Loprateur antislash peut faire bien plus que de crer de simples rfrences. Il crera toute une liste de rfrences sil est appliqu une liste. Pour plus de dtails, voir la section Dautres tours avec les rfrences en dur.

Donnes anonymes
Dans les exemples que nous venons de vous montrer, loprateur antislash se contente de dupliquer une rfrence qui est dj contenue dans un nom de variable avec une exception. Le 186_282.42 nest rfrenc par aucune variable cest juste une valeur. Cest lun de ces rfrents anonymes que nous avons mentionns prcdemment. On ne peut accder aux rfrents anonymes qu travers des rfrences. Celui-ci est un nombre, mais vous pouvez aussi bien crer des tableaux anonymes, des hachages anonymes et des sous-programmes anonymes.

Le composeur de tableaux anonymes


Vous pouvez crer une rfrence un tableau anonyme en employant des crochets :
$reftableau = [1, 2, [a, b, c, d]];

Ici nous avons construit un tableau anonyme de trois lments, dont le dernier lment est une rfrence un tableau anonyme quatre lments (dcrit la figure 8-2). (La syntaxe multidimensionnelle dcrite plus loin peut tre utilise pour y accder. Par exemple, $reftableau->[2][1] aurait la valeur b .)

Figure 8-2. Une rfrence un tableau, dont le troisime lment est lui-mme une rfrence de tableau Nous avons maintenant une mthode pour reprsenter la table du dbut de ce chapitre :

customer_8566

Cration de rfrences
$table = [ [ "john", 47, "marron", 84], [ "mary", 23, "noisette", 58], [ "bill", 35, "bleu", 71] ];

225

Les crochets fonctionnent de cette faon seulement quand lanalyseur de Perl attend un terme dans une expression. Ils ne doivent pas tre confondus avec les crochets dans une expression comme $tableau[6] bien que lassociation mnmotechnique avec les tableaux soit volontaire. lintrieur dune chane entre guillemets, les crochets ne provoquent pas la cration de tableaux anonymes ; ils deviennent simplement des caractres littraux dans la chane. (Les crochets fonctionnent toujours pour lindexation lintrieur de chanes, sinon vous ne pourriez pas afficher des valeurs comme "VAL=$tableau[6]\n". Et pour tre tout fait honnte, vous pouvez en fait glisser des composeurs de tableaux anonymes dans une chane, mais seulement sils sont inclus dans une expression plus grande qui est interpole. Nous parlerons de cette fonctionnalit sympathique un peu plus loin dans ce chapitre, car elle implique du drfrencement aussi bien que du rfrencement.)

Le composeur de hachages anonymes


Vous pouvez crer une rfrence un hachage anonyme avec des accolades :
$hashref = { Adam => Eve, Clyde => $bonnie, Antoine => Clo . patre, };

Vous pouvez librement mlanger les composeurs dautres tableaux, hachages ou sousprogrammes anonymes pour les valeurs (mais pas pour les cls) afin de construire une structure aussi complique que vous le souhaitez. Nous avons maintenant une nouvelle manire de reprsenter la table du dbut de ce chapitre :
$table = { "john" => [ 47, "marron", 84 ], "mary" => [ 23, "noisette", 58 ], "bill" => [ 35, "bleu", 71 ], };

Cest un hachage de tableaux. Le choix de la meilleure structure est une affaire dlicate, et le prochain chapitre y est entirement ddi. Mais pour vous faire saliver, nous pouvons mme utiliser un hachage de hachages pour notre table :
$table = { "john" => { age => 47, yeux => "marron", poids => 84, }, "mary" => { age => 23, yeux => "noisette", poids => 58, },

customer_8566

226
"bill" => { age => 35, yeux => "bleu", poids => 71, }, };

Chapitre 8 Rfrences

Comme avec les crochets, les accolades fonctionnent de cette faon uniquement quand Perl attend un terme dans une expression. Il ne faut pas les confondre avec les accolades dans une expression comme $hash{cle} bien que lassociation mnmotechnique soit (encore) volontaire. Les mmes avertissements sappliquent quant lutilisation des accolades lintrieur dune chane. Voici un avertissement supplmentaire qui ne sappliquait pas aux crochets. Comme les accolades sont aussi utilises pour plusieurs autres choses (y compris les blocs), vous pourrez occasionnellement avoir besoin de distinguer les accolades au dbut dune instruction en mettant un + ou un return devant, afin que Perl ralise que ce nest pas un bloc qui commence. Par exemple, si vous voulez une fonction qui cre un nouveau hachage et renvoie une rfrence sur lui, vous avez les possibilits suivantes :
sub hacheles { { @_ } } sub hacheles { +{ @_ } } sub hacheles { return { @_ } } # Silencieusement FAUX -- renvoie @_. # Ok. # Ok.

Le composeur de sous-programmes anonymes


Vous pouvez crer une rfrence un sous-programme anonyme en utilisant sub sans nom de sous-programme :
$refcode = sub { print "Boink!\n" }; "Boink!" # Maintenant &$refcode affiche

Remarquez la prsence du point-virgule, qui est obligatoire pour terminer lexpression. (Il ne le serait pas aprs la dclaration usuelle subNOM{} qui dclare et dfinit un sousprogramme nomm.) Hormis le fait que le code lintrieur nest pas excut immdiatement, un sub {} sans nom est plus un oprateur quune dclaration comme do {} ou eval {}. Il se contente de gnrer une rfrence au code, qui dans notre exemple est stocke dans $refcode. Cependant, quel que soit le nombre de fois que vous excutez la ligne ci-dessus, $refcode se rfrera toujours au mme sous-programme anonyme.2

Constructeurs dobjets
Les sous-programmes peuvent aussi renvoyer des rfrences. Cela peut sembler banal, mais vous tes parfois cens vous servir dun sous-programme pour renvoyer une rfrence, plutt que de crer la rfrence vous-mme. En particulier, des sous-programmes spciaux appels constructeurs crent et renvoient des rfrences sur des objets. Un objet est juste un type spcial de rfrence qui sait quelle classe il est associ ; les constructeurs savent crer ce genre dassociation. Ils les crent en prenant un rfrent ordinaire

2. Mais bien quil ny ait quun seul sous-programme anonyme, il peut y avoir plusieurs copies des variables lexicales utilises par le sous-programme, selon le moment o la rfrence a t gnre. Cela sera abord plus loin dans la section Fermetures.

customer_8566

Cration de rfrences

227

et en le transformant en objet grce loprateur bless (qui signifie bnir en anglais), cest pourquoi nous pouvons parler dobjets comme de rfrences consacres. Il ny a rien de religieux dans tout cela ; tant donn quune classe fonctionne comme un type dfini par lutilisateur, consacrer un rfrent en fait un type utilisateur en plus dun type prdfini. Les constructeurs sont souvent nomms new en particulier par les programmeurs C++ mais en Perl on peut les appeler comme on veut. Les constructeurs peuvent tre appels de nimporte laquelle de ces manires :
$refobj $refobj $refobj $refobj = = = = Chien::->new(Queue => courte, Oreilles => longues); #1 new Chien:: Queue => courte, Oreilles => longues; #2 Chien->new(Queue => courte, Oreilles => longues); #3 new Chien Queue => courte, Oreilles => longues; #4

La premire et la deuxime invocations sont identiques. Toutes deux appelent une fonction nomme new qui est fournie par le module Chien. Les troisime et quatrime invocations sont identiques aux deux premires mais sont lgrement plus ambigus : lanalyseur va se tromper si vous avez dfini votre propre fonction new et que vous navez fait ni de require, ni de use, sur le module Chien, chacun des deux ayant pour effet de dclarer le module. Dclarez toujours vos modules si vous voulez utiliser la mthode numro 4. (Et faites attention aux sous-programmes Chien errants.) Voir le chapitre 12, Objets, pour une discussion sur les objets Perl.

Rfrences de handles
Les rfrences un handle de fichier ou de rpertoire peuvent tre cres en prenant une rfrence un typeglob de mme nom :
bafouille(\*STDOUT); sub bafouille { my $fh = shift; print $fh "heu hum h bien a hmmm\n"; } $rec = get_rec(\*STDIN); sub get_rec { my $fh = shift; return scalar <$fh>; }

Si vous faites circuler des handles de fichier, vous pouvez aussi utiliser le typeglob seul pour le faire : dans lexemple ci-dessus, vous auriez pu utiliser *STDOUT ou *STDIN au lieu de \*STDOUT et \*STDIN. Bien que vous puissiez en gnral indiffrement utiliser les typeglobs et les rfrences de typeglob, il y a quelques cas o vous ne pouvez pas. Les typeglobs simples ne peuvent pas tre consacrs (avec bless) en objets et les rfrences de typeglobs ne peuvent tre passes en dehors de la porte dun typeglob localis. Pour gnrer de nouveaux handles de fichiers, du code ancien ferait plutt des choses comme ceci pour ouvrir une liste de fichiers :

customer_8566

228
for $fichier (@noms) { local *FH; open(*FH, $fichier) || next; $handle{$fichier} = *FH; }

Chapitre 8 Rfrences

a marche encore, mais de nos jours il est aussi facile de laisser une variable non dfinie sautovivifier en typeglob anonyme :
for $fichier (@names) { my $fh; open($fh, $fichier) || next; $handle{$fichier} = $fh; }

Avec les handles de fichiers indirects, que vous utilisiez des typeglobs, des rfrences de typeglob ou lun des objets dE/S plus exotiques na aucune importance. Vous utilisez simplement un scalaire qui dune manire ou dune autre sera interprt comme un handle de fichier. Dans la plupart des cas, vous pouvez utiliser un typeglob ou une rfrence un typeglob presque alatoirement. Comme nous lavons reconnu plus tt, ce qui se passe ici, cest la magie du drfrencement implicite.

Rfrences de table de symboles


Dans des circonstances inhabituelles, vous pourriez ne pas savoir de quel type de rfrence vous aurez besoin au moment o vous crivez votre programme. Une rfrence peut tre cre en utilisant une syntaxe spciale connue affectueusement sous le nom de syntaxe *foo{THING} (en anglais dans le texte). *toto{CHOSE} (en franais dans le texte) retourne une rfrence la case CHOSE de *toto, qui est lentre de la table de symbole contenant les valeurs de $toto, @toto, %toto et tous leurs amis.
$refscalaire $reftableau $refhash $refcode $refglob $refio = = = = = = *toto{SCALAR}; *ARGV{ARRAY}; *ENV{HASH}; *handler{CODE}; *toto{GLOB}; *STDIN{IO}; # # # # # # Mme chose Mme chose Mme chose Mme chose Mme chose Euh... que que que que que \$toto \@ARGV \%ENV \&handler \*toto

Les noms parlent deux-mmes, sauf dans le cas de *STDIN{IO}. Il contient lobjet interne IO::Handle que le typeglob contient, cest--dire la partie du typeglob qui intresse vritablement les diffrentes fonctions dentre/sortie. Pour assurer la compatibilit avec les anciennes versions de Perl, *toto{FILEHANDLE} est un synonyme de la notation *toto{IO} la mode. En thorie, vous pouvez utiliser un *HANDLE{IO} partout o vous auriez utilis un *HANDLE ou un \*HANDLE, comme par exemple pour passer des handles des fonctions ou pour en retourner, ou pour les stocker dans des structures plus grandes. (En pratique il reste encore quelques obstacles aplanir.) Leur avantage est quils accdent uniquement au vritable objet dE/S qui vous intresse et pas tout le typeglob, donc vous ne courez pas le risque de dfaire plus de choses que vous ne voulez par une affectation de typeglob (mais si vous voulez assigner une variable scalaire au lieu dun typeglob, cela ne posera pas de problme). Un des inconvnients est quil nest pas possible den autovivi-

customer_8566

Utilisation des rfrences en dur


fier lheure actuelle.3
bafouille(*STDOUT); bafouille(*STDOUT{IO}); sub bafouille { my $fh = shift; print $fh "heu hum h bien a hmmm\n"; }

229

Les deux invocations de bafouille() affichent heu hum h bien a hmmm . *toto{CHOSE} renvoie undef si cette CHOSE en particulier na pas encore t vue par le compilateur, sauf si CHOSE vaut SCALAR. Il se trouve que *toto{SCALAR} renvoie une rfrence un scalaire anonyme mme si $toto na pas encore t vu. (Perl ajoute toujours le scalaire au typeglob pour optimiser un bout de code ailleurs. Mais ne supposez pas que cela restera ainsi dans les prochaines versions.)

Cration implicite de rfrences


Une dernire mthode de cration de rfrences nen est pas vraiment une. Les rfrences dun certain type se mettent simplement exister quand vous les drfrencez dans un contexte de lvalue qui suppose quelle existent. Cela est extrmement utile, et cest aussi Ce Quoi On sAttend. Ce sujet est trait plus loin dans ce chapitre, quand nous verrons comment drfrencer toutes les rfrences que nous avons cres jusquici.

Utilisation des rfrences en dur


Tout comme il existe de nombreuses manires de crer des rfrences, il existe galement plusieurs manires dutiliser, ou de drfrencer une rfrence. Il existe un seul principe suprieur : Perl ne fait pas de rfrencement ou de drfrencement implicite.4 Quand un scalaire contient une rfrence, il se comporte comme un simple scalaire. Il ne devient pas magiquement un tableau ou un hachage ou un sous-programme ; vous devez lui signifier explicitement de le faire, en le drfrenant.

Emploi dune variable comme nom de variable


Quand vous rencontrez un scalaire comme $toto, vous devriez penser la valeur scalaire associe toto . Cest--dire quil y a une entre toto dans la table des symboles et que le drle de caractre $ est une manire de regarder quelle valeur scalaire se trouve lintrieur. Si ce qui se trouve lintrieur est une rfrence, vous pouvez regarder lintrieur de cette rfrence (drfrencer $toto en le faisant prcder dun autre drle de caractre. Ou en le regardant du point de vue oppos, vous pouvez remplacer le toto littral dans $toto par une variable scalaire qui pointe sur le vritable rfrent. Cela est
3. Aujourdhui, open my $fh autovivifie un typeglob au lieu dun objet IO::Handle ; mais un des ces jours nous corrigerons cela, aussi ne devriez vous pas vous fier au fait quopen autovivifie actuellement un typeglob. 4. Nous avons dj reconnu que ctait un petit mensonge. Nous nallons pas recommencer.

customer_8566

230

Chapitre 8 Rfrences

vrai pour tout type de variable, donc non seulement $$toto est la valeur scalaire de ce quoi $toto se rfre, mais @$titi est la valeur tableau de ce quoi $titi se rfre, %$tutu est la valeur hachage de ce quoi $tutu se rfre, et ainsi de suite. Le rsultat est que vous pouvez rajouter un drle de caractre devant nimporte quelle valeur scalaire pour la drfrencer :
$toto $refscalaire = "trois bosses"; = \$toto; # # $type_chameau = $$refscalaire; # # $refscalaire est maintenant une rfrence $toto $type_chameau vaut maintenant "trois bosses"

Voici dautres drfrences :


$titi = $$refscalaire; push(@$reftableau, $fichier); $$reftableau[0] = "Janvier";

# # @$reftableau[4..6] = qw/Mai Juin Juillet/; # #

Affecte le premier lment de @$reftableau Affecte plusieurs lments de @$reftableau

%$refhash = (CLE => "TROUSSEAU", OISEAU => "SIFFLER");

# Initialise tout # le hash $$refhash{CLE} = "VALEUR"; # Change un couple cl/valeur @$refhash{"CLE1","CLE2"} = ("VAL1","VAL2"); # Ajoute deux nouveaux couples &$refcode(1,2,3); print $refhandle "sortie\n";

Cette forme de drfrencement ne peut utiliser quune variable simple (sans indice). Cest--dire que le drfrencement se produit avant (ou lie plus fort que) toute recherche dans un tableau ou un hachage. Utilisons des accolades pour clarifier notre pense : une expression comme $$reftableau[0] est quivalente ${$reftableau}[0] et signifie le premier lment du tableau rfrenc par $reftableau. Ce nest pas du tout la mme chose que ${$reftableau[0]} qui drfrence le premier lment du tableau nomm @reftableau (et qui nexiste probablement pas). De mme, $$refhash{CLE} est quivalent ${$refhash}{CLE} et na rien voir avec ${$refhash{CLE}} qui drfrencerait une entre du hachage nomm %refhash (qui nexiste probalement pas). Vous serez malheureux tant que vous naurez pas compris cela. Vous pouvez raliser plusieurs niveaux de rfrencement et de drfrencement en concatnant les drles de caractres de faon approprie. Ce qui suit affiche salut :
$refrefref = \\\"salut"; print $$$$refrefref;

Vous pouvez voir les dollars comme oprant de droite gauche. Mais le dbut de la chane doit toujours tre un simple scalaire sans indice. Il existe cependant une technique qui met un peu plus de fantaisie, que nous avons dj subrepticement utilise un peu plus tt, et que nous allons expliquer dans la section suivante.

customer_8566

Utilisation des rfrences en dur

231

Emploi dun BLOC comme nom de variable


Non seulement vous pouvez drfrencer un simple nom de variable, mais vous pouvez aussi drfrencer le contenu dun BLOC. Partout o vous mettriez un identificateur comme partie dune variable ou dun nom de sous-programme, vous pouvez remplacer lidentificateur par un BLOC qui renvoie une rfrence du bon type. En dautres termes, tous les exemple prcdents peuvent tre clarifis comme suit :
$titi = ${$refscalaire}; push(@{$reftableau}, $fichier); ${$reftableau}[0] = "Janvier"; @{$reftableau}[4..6] = qw/Mai Juin Juillet/; ${$refhash}{"CLE"} = "VALEUR"; @{$refhash}{"CLE1","CLE2"} = ("VAL1","VAL2"); &{$refcode}(1,2,3);

sans oublier :
$refrefref = \\\"salut"; print ${${${$refrefref}}};

Nous sommes daccord quil est idiot de mettre des accolades dans des cas aussi simples, mais le BLOC peut contenir nimporte quelle expression. En particulier, il peut contenir une expression avec des indices. Dans lexemple suivant, on suppose que $dispatch{$index}} contient une rfrence un sous-programme (parfois appel coderef ). Lexemple appelle le sous-programme avec trois arguments.
&{ $dispatch{$index} }(1, 2, 3);

Ici le BLOC est indispensable. Sans le couple daccolades extrieures, Perl aurait trait $dispatch comme le coderef la place de $dispatch{$index}.

Emploi de loprateur flche


Dans le cas de hachages, de tableaux ou de sous-programmes, une troisime mthode de drfrencement implique lutilisation de loprateur infixe ->. Cette forme de sucre syntaxique facilite laccs un lment individuel dun tableau ou dun hachage, ainsi que lappel indirect un sous-programme. Le type de drfrencement est dtermin par loprande de droite, cest--dire par ce qui suit directement la f lche. Si ce qui suit la f lche est un crochet ou une accolade, loprande de gauche est trait respectivement comme une rfrence un tableau ou un hachage, index par lexpression droite. Si ce qui suit est une parenthse ouvrante, loprande de gauche est trait comme un sous-programme appeler avec les paramtres fournis entre les parenthses droite. Chacun des trios qui suivent sont quivalents et correspondent aux trois notations que nous avons prsentes. (Nous avons rajout des espaces pour que les lments qui se correspondent soient aligns.)
$ $reftableau [2] = "Dorian"; ${ $reftableau }[2] = "Dorian"; $reftableau->[2] = "Dorian"; #1 #2 #3

customer_8566

232
$ $refhash {TON} = "Fa#majeur"; ${ $refhash }{TON} = "Fa#majeur"; $refhash->{TON} = "Fa#majeur"; & $refcode (Presto => 192); &{ $refcode }(Presto => 192); $refcode->(Presto => 192); #1 #2 #3 #1 #2 #3

Chapitre 8 Rfrences

Vous pouvez voir que le premier drle de caractre manque dans la troisime notation de chaque srie. Le drle de caractre est devin par Perl, ce qui fait que cette notation ne peut servir pour drfrencer des tableaux ou des hachages entiers, ni mme des tranches de ceux-ci. Cependant, tant que vous vous en tenez des valeurs scalaires, vous pouvez utiliser nimporte quelle expression gauche de ->, y compris un autre drfrencement, car plusieurs oprateurs f lches sassocient de gauche droite :
print $tableau[3]->{"Anglais"}->[0];

Vous pouvez dduire de cette expression que le quatrime lment de @tableau est suppos tre une rfrence un hachage, et que la valeur associe lentre Anglais de ce hachage est suppose tre une rfrence un tableau. Remarquez que $tableau[3] et $tableau->[3] ne sont pas les mmes. Le premier donne le quatrime lment de @tableau, tandis que le second donne le quatrime lment du tableau (peut-tre anonyme) dont la rfrence se trouve dans $tableau. Supposez maintenant que $tableau[3] soit indfini. Linstruction suivante est toujours lgale :
$tableau[3]->{"Anglais"}->[0] = "January";

Cest lun des cas que nous avons mentionn prcdemment o les rfrences se mettent exister (ou sont autovivifies ) quand on les utilise comme des lvalues (cest--dire quand une valeur leur est affecte). Si $tableau[3] tait indfini, il est automatiquement dfini comme une rfrence un hachage afin que nous puissions affecter une valeur $tableau[3]->{"Anglais"} lintrieur. Une fois que cest fait, $tableau[3]>{"Anglais"} est automatiquement dfini comme une rfrence un tableau, afin que nous puissions affecter une valeur au premier lment de ce tableau. Remarquez que les rvalues (les valeurs droite dune affectation) sont lgrement diffrentes : print $tableau[3]->{"Anglais"}->[0] ne cre que $tableau[3] et $tableau[3]->{"Anglais"}, et pas $tableau[3]->{"Anglais"}->[0], puisque le dernier lment nest pas une lvalue. (Le fait que cela dfinisse les deux premiers dans un contexte de rvalue devrait tre considr comme une bogue. Nous corrigerons peut-tre cela un jour.) La f lche est optionnelle entre les indices dlimits par des accolades ou des crochets, et entre une accolade ou un crochet fermant et une parenthse destine un appel de fonction indirect. Vous pouvez donc rduire le code prcdent :
$dispatch{$index}(1, 2, 3); $tableau[3]{"Anglais"}[0] = "January";

Dans le cas des tableaux ordinaires, cela vous permet davoir des tableaux multidimensionnels exactement comme ceux de C :
$reponse[$x][$y][$z] += 42;

Bon daccord, pas exactement comme ceux de C. Dabord C ne sait pas comment faire grossir ses tableaux la demande, comme Perl. Ensuite certaines constructions similai-

customer_8566

Utilisation des rfrences en dur

233

res dans les deux langages sont analyses diffremment. En Perl, les deux instructions suivantes font la mme chose :
$refliste->[2][2] = "coucou"; $$refliste[2][2] = "coucou"; # Assez clair # Prte confusion

La seconde instruction peut choquer le programmeur C, qui est habitu utiliser *a[i] pour signifier ce qui est point par le ie lment de a . Mais en Perl, les cinq caractres ($ @ * % &) lient plus troitement que les accolades ou les crochets.5 Cest donc $$refliste et non $refliste[2] qui est pris comme rfrence un tableau. Si vous voulez le comportement de C, soit vous devez crire ${$refliste[2]} pour forcer lvaluation de $refliste[2] avant le premier $drfrenceur, ou bien utiliser la notation -> :
$refliste[2]->[$salutation] = "coucou";

Emploi des mthodes dobjets


Si une rfrence se trouve tre une rfrence un objet, alors la classe qui dfinit cet objet fournit probablement des mthodes pour accder ce quil contient, et vous devriez gnralement vous en tenir ces mthodes si vous ne faites quutiliser la classe (par opposition ceux qui limplmentent). En dautres termes, soyez correct et ne traitez pas un objet comme une simple rfrence, bien que Perl vous laisse faire si vous le devez vraiment. Perl nimpose pas lencapsulation. Nous ne sommes pas des dictateurs. Mais nous esprons cependant un peu de civilit de votre part. En retour de cette civilit, vous gagnez un complte orthogonalit entre les objets et les structures de donnes. Toute structure de donnes peut se comporter comme un objet, si vous le voulez. Et ne pas le faire, si vous ne voulez pas.

Pseudo-hachages
Un pseudo-hachage est une rfrence un tableau dont le premier lment est une rfrence un hachage. Vous pouvez traiter le pseudo-hachage soit comme une rfrence de tableau (comme vous pouviez vous y attendre) ou comme une rfrence de hachage (ce quoi vous ne vous attendiez peut-tre pas). Voici un exemple de pseudo-hachage :
$john = [ {age => 1, yeux => 2, poids => 3}, 47, "marron", 84 ];

Le hachage sous-jacent dans $john->[0] dfinit les noms "age", "yeux" et "poids" des lments de tableau qui suivent (47, "marron" et 84). Maintenant vous pouvez accder un lment la fois par la notation de hachage et par celle de tableau :
$john->{poids} $john->[3] # Traite $john comme une rfrence de hachage # Traite $john comme une rfrence de tableau

La magie des pseudo-hachages nest pas trs puissante ; ils ne connaissent quun seul tour : comment transformer un drfrencement de hachage en drfrencement de tableau. Quand vous ajoutez un nouvel lment au pseudo-hachage, vous devez ex5. Mais pas cause de la prcdence des oprateurs. Les drles de caractres de Perl ne sont pas des oprateurs dans ce sens-l. La grammaire de Perl interdit simplement tout ce qui est plus compliqu quune simple variable ou un bloc de suivre le drle de caractre initial, pour plein de drles de raisons.

customer_8566

234

Chapitre 8 Rfrences

plicitement prciser au hachage de correspondance sous-jacent o llment va rsider avant dutiliser la notation de hachage :
$john->[0]{hauteur} = 4; $john->{hauteur} = "grand"; # hauteur sera llment 4 # Ou $john->[4] = "grand"

Perl lve une exception si vous essayez deffacer une cl de pseudo-hachage, bien que vous puissiez toujours effacer une cl du hachage de correspondance. Perl lve galement une exception si vous essayez daccder une cl qui nexiste pas ( existence signifiant ici prsence dans le hachage de correspondance ).
delete $john->[0]{hauteur}; $john->{hauteur}; $john->[4]; # # # # Supprime seulement dans le hachage sous-jacent Ceci lve dsormais une exception Affiche toujours "grand"

Ne tentez pas de splice du tableau sans savoir ce que vous faites. Si les lments du tableau se dplacent, les valeurs de correspondance du hachage feront toujours rfrence aux anciennes positions des lments, moins que vous ne les changiez elles aussi explicitement. La magie des pseudo-hachages nest pas trs puissante. Pour viter les incohrences, vous pouvez utiliser la fonction fields::phash fournie par le pragma use fields pour crer un pseudo-hachage :
use fields; $ph = fields::phash(age => 47, yeux => "marron", poids => 84); print $ph->{age};

Il existe deux manires de vrifier lexistence dune cl dans un pseudo-hachage. La premire est dutiliser exists, qui vrifie si le champ fourni a jamais t affect. Il fonctionne de cette faon pour reproduire le comportement dun vritable hachage. Par exemple :
use fields; $ph= fields::phash([qw(age yeux poids)], [47]); $ph->{yeux} = undef; print exists $ph->{age}; # Vrai, age a t modifi dans la dclaration. print exists $ph->{poids}; # Faux, poids na pas t utilis. print exists $ph->{yeux}; # Vrai, les yeux ont t modifis.

La seconde manire est dutiliser exists sur le hachage de correspondance install dans le premier lment. Ceci vrifie que la cl donne est un champ valide pour ce pseudohachage :
print exists $ph->[0]{age}; # Vrai, age est un champ valide print exists $ph->[0]{nom}; # Faux, nom ne peut pas tre utilis

Contrairement ce qui se produit pour un vritable hachage, appeler delete sur un lment de pseudo-hachage nefface que la valeur dans le tableau, et pas la cl dans le hachage de correspondance. Pour effacer la cl, vous devrez leffacer explicitement du hachage de correspondance. Une fois que cela est fait, vous ne pouvez plus utiliser ce nom de cl comme indice du pseudo-hachage :
print delete $ph->{age}; print exists $ph->{age}; # Dtruit $ph->[1], 47 et le renvoie # Maintenant cest faux.

customer_8566

Utilisation des rfrences en dur


print exists $ph->[0]{age}; # Vrai, age est encore utilisable print delete $ph->[0]{age}; # Maintenant age nexiste plus print $ph->{age}; # Exception lexcution

235

Vous commencez srement vous demander ce qui a pu motiver ce carnaval de tableaux se promenant dans un habit de hachage. Les tableaux fournissent un accs plus rapide et un stockage plus efficace, tandis que les hachages offrent la possibilit de nommer (au lieu de numroter) vos donnes ; les pseudo-hachages offrent le meilleur des deux mondes. Mais cest en considrant la phase de compilation de Perl que vous verrez apparatre le meilleur bnfice de lopration. Avec laide dun pragma ou deux, le compilateur peut vrifier laccs correct aux champs valides, aussi pouvez-vous vrifier linexistence dun champ (ou les fautes dorthographe) avant le dbut de votre programme. Les proprits de vitesse, defficacit, de vrification daccs la compilation (vous pouvez mme le voir comme de la validation de type) sont particulirement pratiques pour crer des modules de classes robustes et efficaces. Voir la discussion du pragma use fields au chapitre 12 et au chapitre 31, Modules de pragmas. Les pseudo-hachages sont une fonctionnalit nouvelle et relativement exprimentale ; en tant que telle, limplmentation en interne est susceptible de changer lavenir. Afin de vous protger de tels changements, utilisez toujours linterface documente du module fields, en utilisant ses fonctions phash et new.

Dautres tours avec les rfrences en dur


Comme mentionn prcdemment, loprateur antislash est en gnral utilis sur un seul rfrent pour gnrer une rfrence unique, mais ce nest pas obligatoire. Quand il est utilis sur une liste de rfrents, il produit une liste de rfrences correspondantes. La seconde ligne de lexemple suivant produit exactement le mme resultat que la premire, car lantislash est automatiquement distribu sur toute la liste.
@listeref = (\$s, \@a, \%h, \&f); @listeref = \($s, @a %h, &f); # Liste de quatre rfrences # Mme chose

Si une expression entre parenthses contient exactement un tableau ou un hachage, toutes ses valeurs sont interpoles et des rfrences sont renvoyes pour chacune :
@listeref = \(@x); @listeref = map { \$_ } @x; @listeref = \(@x, (@y)); @listeref = (\@x, map { \$_ } @y); # Interpole le tableau puis prend # les rfrences # Mme chose # Seuls les aggrgats simples sont # interpols # Mme chose

Cela se produit galement quand il y a des parenthses lintrieur :

Si vous essayez cela avec un hachage, le rsultat contiendra des rfrences aux valeurs (comme vous vous y attendez), mais aussi des rfrences des copies des cls (comme vous en vous y attendez peut-tre pas). Comme les tranches de tableaux et de hachages sont seulement des listes, vous pouvez antislasher des tranches de lun ou lautre type pour obtenir une liste de rfrences. Chacune des trois listes suivantes fait exactement la mme chose :

customer_8566

236

Chapitre 8 Rfrences

@envrefs = \@ENV{HOME, TERM}; # Antislashe une tranche @envrefs = \( $ENV{HOME}, $ENV{TERM} ); # Antislashe une liste @envrefs = ( \$ENV{HOME}, \$ENV{TERM} ); # Une liste de deux rfrences

Comme les fonctions peuvent retourner des listes, vous pouvez leur appliquer loprateur antislash. Si vous avez plusieurs appels de fonction, interpolez dabord la valeur de retour de chaque fonction dans une liste plus grande avant dantislasher lensemble :
@listeref = \fx(); @listeref = map { \$_ } fx(); @listeref = \( fx(), fy(), fz() ); @listeref = ( \fx(), \fy(), \fz() ); @listeref = map { \$_ } fx(), fy(), fz(); # Mme chose

# Mme chose # Mme chose

Comme loprateur antislash fourni un contexte de liste ses oprandes, ces fonctions sont toutes appeles en contexte de liste. Si lantislash est lui-mme en contexte scalaire, vous finirez avec une rfrence la dernire valeur de la liste renvoye par la fonction :
@listeref = \localtime(); $reffinale = \localtime(); # Ref chacun des neuf lments de la date # Ref lindicateur de lheure dt

cet gard, loprateur antislash se comporte comme les oprateurs de liste nomms, comme print, reverse et sort, qui fournissent toujours un contexte de liste leur droite, quoiquil se passe leur gauche. Comme avec les oprateurs de liste nomms, utilisez un scalar explicite pour forcer ce qui suit tre en contexte de liste :
$refdate = \scalar localtime(); # \"Thu Jul 26 11:37:38 2001"

Vous pouvez vous servir de loprateur ref pour dterminer vers quoi une rfrence pointe. Vous pouvez voir loprateur ref comme un oprateur typeof qui renvoie vrai si son argument est une rfrence et faux dans le cas contraire. La valeur renvoye dpend du type de chose rfrence. Les types prdfinis comprennent SCALAR, ARRAY, HASH, CODE, GLOB, REF, LVALUE, IO, IO::Handle et Regexp. Ici, nous nous en servons pour valider les arguments dun sous-programme :
sub somme { my $reftableau = shift; warn "Ce nest pas une rfrence de tableau" if ref($reftableau) ne "ARRAY"; return eval join("+", @$reftableau); }

Si vous utilisez une rfrence en dur dans un contexte de chane, elle sera convertie en une chane contenant le type et ladresse : SCALAR(0x1fc0e). (La conversion inverse ne peut pas tre faite, puisque linformation de dcompte de rfrences est perdue pendant lopration de conversion en chane et aussi car il serait dangereux de laisser des programmes accder une adresse mmoire donne par une chane arbitraire.) Vous pouvez utiliser loprateur bless pour associer un rfrent un paquetage fonctionnant comme une classe dobjet. Quand vous faites cela, ref renvoie le nom de la classe au lieu du type interne. Une rfrence dobjet utilise en contexte de chane renvoie une chane avec les types interne et externe, ainsi que ladresse en mmoire : MonType=HASH(0x20d10) ou IO::Handle=IO(0x186904). Pour plus de dtails sur les objets, voir le chapitre 12.

customer_8566

Utilisation des rfrences en dur

237

Puisque le type de rfrent que vous dsirez est indiqu par la faon dont vous le drfrencez, un typeglob peut tre utilis de la mme faon quune rfrence, malgr le fait quun rfrent contienne plusieurs rfrents de types divers. ${*main::toto} et ${\$main::toto} accdent donc tous deux la mme variable scalaire, mme si le second est plus efficace. Voici une astuce pour interpoler la valeur de retour dun appel de fonction dans une chane :
print "Ma fonction a renvoy @{[ mafonction(1,2,3) ]} cette fois.\n";

Voici comment cela fonctionne. la compilation, quand le @{...} est vu lintrieur de la chane entre guillemets doubles, il est analys comme un bloc qui renvoie une rfrence. lintrieur du bloc, les crochets crent une rfrence un tableau anonyme partir de ce qui se trouve entre eux. lexcution, mafonction(1,2,3) est donc appele en contexte de liste, et les rsultats sont chargs dans un tableau anonyme dont une rfrence est renvoye lintrieur du bloc. Cette rfrence de tableau est immdiatement drfrence par le @{...} qui lentoure, et la valeur de tableau est interpole dans la chane doubles guillemets tout comme un tableau ordinaire le serait. Ce stratagme savre galement utile pour des expressions quelconques, comme :
print "Il nous faut @{ [$n + 5] } machins !\n";

Cependant faites attention : les crochets fournissent un contexte de liste leur expression. Dans ce cas, cela na aucune importance, mais lappel prcdent mafonction aurait pu y tre sensible. Quand il le faut, utilisez un scalar explicite pour forcer le contexte :
print "mafonction renvoie @{ [scalar mafonction(1,2,3)] } maintenant.\n";

Fermetures
Nous avons parl plus haut de la cration de sous-programmes anonymes avec un sub {} sans nom. Vous pouvez voir ces sous-programmes comme sils taient dfinis lexcution, ce qui signifie quils ont un instant de gnration en plus dune position de dfinition. Certaines variables pourraient tre porte quand le sous-programme est cr, et dautres variables pourraient tre porte quand le sous-programme est appel. Oubliez les sous-programmes pour le moment et considrez une rfrence qui se rfre une variable lexicale :
{ my $bestiau = "chameau"; $refbestiau = \$creature; }

La valeur de $$refbestiau restera chameau bien que $bestiau disparaisse aprs laccolade fermante. Mais $refbestiau aurait trs bien pu faire rfrence un sous-programme qui se rfre $bestiau :
{ my $bestiau = "chameau"; $refbestiau = sub { return $bestiau }; }

customer_8566

238

Chapitre 8 Rfrences

Cest une fermeture, qui est une notion sortie du monde de la programmation fonctionnelle de LISP et Scheme.6 Cela signifie que quand vous dfinissez un sous-programme anonyme dans une porte lexicale particulire un moment donn, il prtend continuer fonctionner dans cette porte particulire, mme si vous lappelez plus tard depuis lextrieur de cette porte. (Un puriste dirait quil na pas besoin de prtendre il fonctionne rellement dans cette porte.) En dautres termes, vous tes assur de garder la mme copie dune variable lexicale chaque fois, mme si dautres instances de cette variable lexicale ont t cres avant ou aprs pour dautres instances de cette fermeture. Cela vous permet de dajuster les valeurs utilises par un sous-programme quand vous le dfinissez, et pas seulement quand vous lappelez. Vous pouvez aussi voir les fermetures comme une manire dcrire un patron de sousprogramme sans utiliser eval. Les variables lexicales servent de paramtres pour remplir le modle, ce qui est utile pour configurer des petits bouts de code excuter plus tard. On les appelle communment des fonctions de rappel en programmation vnementielle, quand vous associez un bout de code la pression dune touche, un clic de souris, lexposition dune fentre et ainsi de suite. Quand on les utilise comme des fonctions de rappel, les fermetures font exactement ce quoi vous vous attendez, mme si vous ne connaissez rien la programmation fonctionnelle. (Remarquez que cette histoire de fermeture ne sapplique quaux variables my. Les variables globales fonctionnent comme elles ont toujours fonctionn, tant cres et dtruites de faon compltement diffrente des variables lexicales. Une autre utilisation des fermetures se fait lintrieur de gnrateurs de fonctions ; cest-dire de fonctions qui crent et retournent de nouvelles fonctions. Voici un exemple de gnrateur de fonction implment avec des fermetures :
sub faitbonjour { my $salut = shift; my $newfunc = sub { my $cible = shift; print "$salut, $cible !\n"; }; return $newfunc; # Renvoie une fermeture } $f = faitbonjour("Bonjour"); # Cre une fermeture $g = faitbonjour("Salutations"); # Cre une autre fermeture # Le temps passe... $f->("monde"); $g->("Terriens");

Cela affiche :
Bonjour, monde ! Salutations, Terriens !
6. Dans ce contexte, fonctionnel ne doit pas tre interprt comme le contraire de dysfonctionnel .

customer_8566

Utilisation des rfrences en dur

239

Remarquez en particulier comme $salut continue de faire rfrence la valeur effectivement passe faitbonjour, malgr le fait que le my $salut soit hors de porte quand le sous-programme anonyme tourne. Cest tout lintrt des fermetures. Comme $f et $g contiennent des rfrences des fonctions qui, quand on les appelle, ont toujours besoin daccder des versions distinctes de $salut, ces versions restent automatiquement dans les environs. Si maintenant vous effacez $f, sa version de $salut disparaitra automatiquement. (Perl nettoie quand vous avez le dos tourn.) Perl ne fournit pas de rfrences aux mthodes dobjets (dcrites au chapitre 12) mais vous pouvez obtenir un effet similaire en utilisant une fermeture. Supposons que vous voulez une rfrence, pas seulement la fonction que la mthode reprsente, mais aussi une rfrence qui, quand vous linvoquez, appelle cette mthode sur un objet particulier. Vous pouvez commodment vous souvenir la fois de lobjet et de la mthode en en faisant des variables lexicales lies une fermeture :
sub get_ref_methode { my ($self, $nommethode) = @_; my $refmeth = sub { # le @_ ci-dessous est diffrent de celui au-dessus ! return $self->$nommethode(@_); }; return $refmeth; } my $toutou = new Chien:: Nom => "Lucky", Pattes => 3, Queue => "coupe"; our $remueur = get_ref_methode($toutou, remuer); $remueur->("queue"); # Appelle $dog->remuer(queue).

Vous pouvez donc demander Lucky de remuer ce qui lui reste de queue mme quand la variable lexicale $toutou est hors de porte et que Lucky nest plus visible. La variable globale $remueur peut toujours lui faire remuer la queue, o quil se trouve.

Fermetures comme modles de fonctions


Utiliser une fermeture comme modle de fonctions vous permet de gnrer plusieurs fonctions qui agissent de faon similaire. Supposons que vous voulez une suite de fonctions qui gnrent des changements de fonte HTML pour diverses couleurs :
print "Soyez ", rouge("prudent"), "avec cette ", vert("lumire"), " !!!";

Les fonctions rouge et vert seraient trs similaires. Nous aimerions bien nommer nos fonctions, mais les fermetures nont pas de nom puisquil sagit juste de routines qui sy croient. Pour contourner cela, nous allons utiliser une jolie astuce pour nommer nos sous-programmes anonymes. Vous pouvez lier une rfrence de code un nom existant en laffectant au typeglob du nom de la fonction que vous voulez. (Voir la section Tables de symboles au chapitre 10, Paquetages). Dans ce cas, nous allons la lier deux noms diffrents, lun en majuscules et lautres en minuscules :
@couleurs = qw(red blue green yellow orange purple violet);

customer_8566

240

Chapitre 8 Rfrences

for my $nom (@couleurs) { no strict refs; # Autorise les rfrences symboliques *$nom = *{uc $nom} = sub { "<FONT COLOR=$nom>;@_</FONT>" }; }

Vous pouvez maintenant appeler les fonctions nommes red, RED, blue, BLUE et ainsi de suite, et la fermeture approprie sera invoque. Cette technique rduit la dure de compilation et conserve la mmoire ; elle est aussi moins susceptible derreur, puisque la vrification de syntaxe se fait la compilation. Il est impratif que les variables dans le sous-programme anonyme soient lexicales afin de crer une fermeture. Cest la raison du my dans lexemple ci-dessus. Voici lun des rares cas o donner un prototype une fermeture sert quelque chose. Si vous aviez voulu imposer un contexte scalaire aux arguments de ces fonctions (ce nest probablement pas une bonne ide pour cet exemple), vous auriez plutt crit ceci :
*$nom = sub ($) { "<FONT COLOR=$nom>$_[0]</FONT>" };

Cest presque suffisant. Cependant comme la vrification de prototypes se produit la compilation, laffectation lexcution se produit trop tard pour servir quelque chose. Vous pouvez corriger cela en mettant toute la boucle daffectations dans un bloc BEGIN qui la forcera se produire la compilation. (Plus probalement, vous la mettriez dans un module sur lequel vous ferez un use la compilation.) Les prototypes seront alors visibles pour le reste de la compilation.

Sous-programmes embots
Si vous avez lhabitude (prise dans dautres langages de programmation) dutiliser des procdures embotes dans dautres procdures, chacune avec ses propres variables prives, il va vous falloir travailler un peu en Perl. Les sous-programmes nomms ne sembotent pas bien, alors que les sous-programmes anonymes le peuvent.7 De toute faon, nous pouvons muler des sous-programmes embots porte lexicale laide de fermetures. En voici un exemple :
sub exterieur { my $x = $_[0] + 35; local *interieur = sub { return $x * 19 }; return $x + interieur(); }

Maintenant interieur ne peut tre appel que depuis exterieur cause de laffectation temporaire de la fermeture. Mais quand il lest, il a accs normalement la variable lexicale $x depuis la porte de exterieur. Ceci a lintressant effet de crer une fonction locale une autre, ce qui est quelque chose qui nest normalement pas support en Perl. Comme local est porte dynamique, et parce que les noms de fonctions sont globaux leur paquetage, toute autre fonction qui serait appele par exterieur pourrait aussi appeler la version temporaire
7. Pour tre plus prcis, les sous-programmes ayant un nom global ne sembotent pas. Malheureusement cest le seul type de dclaration de sous-programmes nomms que nous ayons. Nous navons pas encore implment les sous-programmes nomms porte lexicale (connus sous le nom de my sub), mais quand nous le ferons, ils semboteront correctement.

customer_8566

Rfrences symboliques

241

dinterieur. Pour empcher cela, il vous faudra un niveau supplmentaire dindirection :


sub exterieur { my $x = $_[0] + 35; my $interieur = sub { return $x * 19 }; return $x + $interieur->(); }

Rfrences symboliques
Que se passe-t-il si vous essayez de drfrencer une valeur qui nest pas une rfrence en dur ? La valeur est alors traite comme une rfrence symbolique. Cest--dire que la rfrence est interprte comme une chane reprsentant le nom dune variable globale. Voici comment cela fonctionne :
$nom = "bam"; $$nom = 1; $nom->[0] = 4; $nom->{X} = "Y"; @$nom = (); keys %$nom; &$nom; # # # # # # Dfinit $bam Dfinit le premier lment de @bam Dfinit llment X de %bam Y Vide @bam Renvoie les cls de %bam Appelle &bam

Cest trs puissant et lgrement dangereux, en ce quil est possible de vouloir (avec la plus grande sincrit) utiliser une rfrence en dur, mais daccidentellement utiliser une rfrence symbolique la place. Pour vous protger contre cela, vous pouvez crire :
use strict refs;

et seules les rfrences en dur seront autorises dans le reste du bloc englobant. Un bloc intrieur peut suspendre cette restriction par :
no strict refs;

Il est aussi important de comprendre la diffrence entre les deux lignes de code suivantes :
${identificateur}; # Comme $identificateur. ${"identificateur"}; # $identificateur aussi, mais une rfrence symbolique.

Parce que la seconde forme est entre guillemets, elle est traite comme une rfrence symbolique, et gnrera une erreur avec use strict refs. Mme si use strict refs nest pas activ, elle peut seulement faire rfrence une variable de paquetage. Mais la premire forme est identique la forme sans accolades, et fera mme rfrence une variable porte lexicale sil y en a de dclare. Lexemple suivant le montre (et la section suivante en parle). Seules les variables de paquetage sont accessibles par des rfrences symboliques, car les rfrences symboliques passent toujours par la table de symboles du paquetage. Comme les variables lexicales ne se trouvent pas la table de symboles, elles sont invisibles pour ce mcanisme. Par exemple :
our $valeur = "globale";

customer_8566

242
{ my $valeur = "prive"; print " lintrieur, my est ${valeur}, "; print "mais our est ${valeur}.\n";

Chapitre 8 Rfrences

} print " lextrieur, ${valeur} est de nouveau ${valeur}.\n";

ce qui affiche :
lintrieur, my est prive, mais our est globale. lextrieur, globale est de nouveau globale.

Accolades, crochets et guillemets


Dans la section prcdente nous avons vu que ${identificateur} nest pas trait comme une rfrence symbolique. Vous vous demandez srement comment cela peut interagir avec les mots rservs. La rponse est que cela ninteragit pas. Bien que push soit un mot rserv, ces deux instructions affichent pop par dessus :
$push = "pop par "; print "${push}dessus";

La raison en est quhistoriquement, cette utilisation des accolades est celle des shells Unix pour isoler un nom de variable du texte alphanumrique qui le suit, et qui aurait sinon t interprt comme faisant partie du nom. Cest la faon dont beaucoup de gens sattendent voir fonctionner linterpolation, aussi lavons nous fait fonctionner de la mme faon en Perl. Mais en Perl cette notion stend plus loin, et sapplique galement aux accolades utilises pour gnrer les rfrences, quelles soient ou non entre guillemets. Cela signifie que :
print ${push} . dessus;

ou mme (puisque les blancs ne changent rien) :


print ${ push } . dessus;

affichent tous deux pop par dessus , mme si les accolades sont en dehors des guillemets doubles. La mme rgle sapplique tout identificateur utilis pour indexer un hachage. Ainsi, au lieu dcrire :
$hash{ "aaa" }{ "bbb" }{ "ccc" }

vous pouvez simplement crire :


$hash{ aaa }{ bbb }{ ccc }

ou :
$hash{aaa}{bbb}{ccc}

sans vous soucier de savoir si les indices sont des mots rservs. Donc ceci :
$hash{ shift }

est interprt comme $hash{"shift"}. Vous pouvez forcer linterprtation comme un mot rserv en ajoutant quelque chose qui le diffrencie dun identificateur :
$hash{ shift() } $hash{ +shift } $hash{ shift @_ }

customer_8566

Accolades, crochets et guillemets

243

Les rfrences ne fonctionnent pas comme cls de hachages


Les cls de hachage sont stockes en interne comme des chanes.8 Si vous essayez de stocker une rfrence dans un hachage, la valeur de la cl sera convertie en chane :
$x{ \$a } = $a; ($cle, $valeur) = each %x; print $$cle;

# FAUX

Nous avons mentionn plus tt que vous ne pouvez pas reconvertir une chane en rfrence en dur. Si vous essayez de drfrencer $cle qui contient une simple chane, vous ne rcuprerez pas une rfrence en dur, mais simplement un drfrencement symbolique. Et comme vous navez pas de variable nomme SCALAR(0x1fc0e), vous nobtiendrez pas ce que vous voulez. Vous devriez plutt essayer quelque chose comme ceci :
$r = \@a; $x{ $r } = $r;

Comme cela vous pourrez au moins utiliser la valeur du hachage, qui sera une rfrence en dur, au lieu de la cl qui nen est pas une. Bien que vous ne puissiez pas stocker une rfrence en tant que cl, si vous utilisez une rfrence en dur dans un contexte de chane (comme dans lexemple prcdent), vous tes certain que cela produira une chane unique, puisque ladresse de la rfrence fait partie de la chane retourne. Vous pouvez donc utiliser une rfrence comme cl dun hachage. Seulement vous ne pourrez pas la drfrencer par la suite. Il existe un cas particulier de hachage dans lequel vous pouvez utiliser des rfrences comme cls. Par la magie9 du module Tie::RefHash fourni avec Perl, vous pouvez faire ce que nous venons juste de dire que vous ne pouviez pas faire :
use Tie::RefHash; tie my %h, Tie::RefHash; %h = ( ["ceci", "ici"] => " la maison", ["cela", "l-bas"] => "ailleurs", ); while ( my($refcle, $valeur) = each %h ) { print "@$refcle is $valeur\n"; }

En fait, en liant des implmentations diffrentes aux types prdfinis, vous pouvez faire se comporter des scalaires, des hachages et des tableaux de beaucoup de manires dont nous vous avions dit que ctait impossible. a nous apprendra, imbciles dauteurs... Pour en savoir plus sur les liens avec tie, voir le chapitre 14, Variables lies.

8. Elles sont galement stockes en externe comme des chanes, par exemple quand vous les stockez dans des fichiers DBM. En fait, les fichiers DBM imposent que leurs cls (et valeurs) soient des chanes. 9. Oui, cest un terme technique, comme vous vous en rendrez compte si vous fouillez un peu dans le fichier mg.c dans les sources de Perl.

customer_8566

244

Chapitre 8 Rfrences

Ramasse-miettes, rfrences circulaires et rfrences faibles


Les langages de haut niveau permettent aux programmeurs de ne pas sinquiter de la libration de la mmoire quand ils ont fini de lutiliser. Ce procd de rcupration automatique de la mmoire sappelle en franais le ramassage des miettes (en anglais garbage collecting ou collecte des ordures). Dans la plupart des cas, Perl se sert dun mcanisme simple et rapide de ramasse miettes fond sur le comptage de rfrences. Quand on sort dun bloc, ses variables porte locale sont normalement libres, mais il est possible de cacher vos miettes de faon ce que le ramasse miettes de Perl ne puisse les trouver. Un problme srieux est que de la mmoire inatteignable avec un dcompte de rfrences non nul ne sera normalement pas libre. Cest pourquoi les rfrences circulaires sont une mauvaise ide :
{ my ($a, $b); $a = \$b; $b = \$a; } # fait pointer $a et $b lun sur lautre

ou plus simplement :
{ my $a; $a = \$a; } # fait pointer $a sur lui-mme

Bien que $a doive tre dsallou la fin du bloc, en fait il ne lest pas. Quand vous construisez des structures de donnes rcursives, il vous faudra casser (ou affaiblir, voir plus loin) lautorfrence vous-mme si vous voulez que la mmoire soit rcupre avant la fin de votre programme (ou de votre thread). ( la sortie, la mmoire sera automatiquement rcupre pour vous par un mcanisme coteux mais complet de ramasse-miettes par marquage et balayage.) Si la structure de donnes est un objet, vous pouvez utiliser la mthode DESTROY pour casser automatiquement la rfrence ; voir Ramasse-miettes avec les mthodes DESTROY au chapitre 12. Une situation similaire peut se produire avec les caches des entrepts de donnes conus pour une rcupration plus rapide que la normale. Hors du cache on trouve des rfrences donnes lintrieur du cache. Le problme se produit quand toutes ces rfrences sont effaces, mais que les donnes du cache et les rfrences internes restent. Lexistence dune rfrence empche Perl de rcuprer le rfrent, mme si nous voulons que les donnes du cache disparaissent ds quelles ne sont plus utiles. Comme pour les rfrences circulaires, nous vous une rfrence qui naffecte pas le compte de rfrences, et donc ne retarde pas le ramasse-miettes. Les rfrences faibles rsolvent les problmes causs par les rfrences circulaires en vous permettant d affaiblir nimporte quelle rfrence ; cest--dire lui permettre de ne pas modifier le compte des rfrences. Quand la dernire rfrence non faible un objet est dtruite, lobjet est dtruit et toutes les rfrences faibles sont automatiquement libres. Pour utiliser cette fonctionnalit, vous aurez besoin du module WeakRef disponible sur CPAN qui contient une documentation complmentaire. Les rfrences faibles sont une fonctionnalit exprimentale. Mais il faut bien que quelquun serve de cobaye.

customer_8566

Structures de donnes

Perl fournit gratuitement beaucoup des structures de donnes que vous devez construire vous-mme dans dautres langages de programmation. Les piles et et les files que les informaticiens en herbe apprennent en cours ne sont que des tableaux en Perl. Quand vous faites push et pop (ou shift et unshift) sur un tableau, cest une pile ; quand vous faites push et shift (ou unshift et pop) sur un tableau, cest une file. Beaucoup de structures arborescentes dans le monde sont construites pour fournir un accs rapide et dynamique une table de consultation conceptuellement plate. Bien sr, les hachages font partie de Perl et ils fournissent un accs rapide et dynamique une table de consultation conceptuellement plate. Tout cela sans les abrutissantes structures de donnes que trouvent magnifiques ceux dont les esprits ont dj t convenablement abrutis. Mais parfois vous avez besoin de structures de donnes imbriques parce quelle modlisent naturellement le problme que vous essayez de rsoudre. Perl vous permet alors de combiner et demboter des tableaux et des hachages de manire crer des structures de donnes aussi complexes que vous voulez. Quand ils sont utiliss correctement, ils peuvent servir crer des listes chanes, des arbres binaires, des tas, des arbres-B, des ensembles, des graphes et tout ce que vous pouvez imaginer dautre. Voir Mastering Algorithms with Perl (OReilly, 1999), Perl en action (OReilly, France, 1999)1, ou CPAN qui sert de dpt central pour tout ce genre de modules. Mais vous naurez peut-tre jamais besoin que de simples combinaisons de tableaux et de hachages, aussi est-ce ce dont nous allons parler dans ce chapitre.

Tableaux de tableaux
Il existe de nombreuses sortes de structures de donnes. La plus simple construire est le tableau de tableaux, aussi appel matrice deux dimensions. (Ceci se gnralise de manire vidente : un tableau de tableaux de tableaux est une matrice trois dimensions, et ainsi de suite pour les dimensions suprieures.) Cest relativement simple
1. Perl Cookbook (OReilly, 1998) pour la version originale.

customer_8566

246

Chapitre 9 Structures de donnes

comprendre, et presque tout ce qui sapplique dans ce cas sappliquera aussi aux structures plus compliques que nous explorerons dans les sections suivantes.

Cration et accs un tableau deux dimensions


Voici comment construire un tableau deux dimensions :
# Affecte une liste de rfrences de tableaux un tableau @TdT = ( [ "fred", "barney" ], [ "george", "jane", "elroy" ], [ "homer", "marge", "bart" ], ); print $TdT[2][1]; # affiche "marge"

La liste complte est entoure par des parenthses et non par des crochets car vous faites une affectation une liste et non une rfrence. Si vous prfriez une rfrence, vous utiliseriez des crochets :
# Cre une rfrence un tableau de rfrences. $ref_a_TdT = [ [ "fred", "barney", "pebbles", "bamm bamm", "dino", ], [ "homer", "bart", "marge", "maggie", ], [ "george", "jane", "elroy", "judy", ], ]; print $ref_a_TdT->[2][3]; # affiche "judy"

Rappelez-vous quil y a un -> implicite entre deux accolades ou crochets adjacents. Ces deux lignes :
$TdT[2][3] $ref_a_TdT->[2][3]

sont donc quivalentes aux deux lignes suivantes :


$TdT[2]->[3] $ref_a_TdT->[2]->[3]

Il ny a cependant aucun -> implicite avant la premire paire de crochets, cest pourquoi le drfrencement de $ref_a_TdT ncessite le -> initial. Noubliez pas que vous pouvez aussi compter partir de la fin dun tableau avec un indice ngatif, donc :
$TdT[0][-2]

est lavant-dernier lment de la premire ligne.

Volez de vos propres ailes


Ces grosses affectations de listes sont belles et bonnes pour crer une structure de donnes fixe, mais comment faire si vous voulez construire chaque lment au vol ou construire la structure au coup par coup ? Lisons une structure de donnes partir dun fichier. Nous supposerons quil sagit dun fichier texte, o chaque ligne est une range de la structure et est compose dlments

customer_8566

Tableaux de tableaux
spars par des blancs. Voici comment procder :2

247

while (<>) { @tmp = split; # Splite les lments dans un tableau push @TdT, [ @tmp ]; # Ajoute une rfrence de tableau anonyme @TdT }

Bien sr, vous navez pas besoin de donner un nom au tableau temporaire et vous pourriez donc aussi crire :
while (<>) { push @TdT, [ split ]; }

Si vous voulez une rfrence un tableau de tableaux, vous pouvez procder ainsi :
while (<>) { push @$ref_a_TdT, [ split ]; }

Ces deux exemples ajoutent de nouvelles lignes au tableau de tableaux. Comment faire pour ajouter de nouvelles colonnes ? Si vous ne travaillez quavec des tableaux deux dimensions, il est souvent plus facile dutiliser une affectation simple :3
for $x (0 .. 9) { for $y (0 .. 9) { $TdT[$x][$y] = func($x, $y); } } for $x ( 0..9 ) { $ref_a_TdT->[$x][3] = func2($x); } # Pour chaque ligne... # Pour chaque colonne... # ...affecte cette valeur

# Pour chaque ligne... # ...affecte la quatrime colonne

Lordre dans lequel vous affectez les lments na pas dimportance, pas plus que le fait que les lments indics de @TdT existent dj ou non ; Perl les crera pour vous si besoin est en mettant les lments intermdiaires la valeur indfinie. (Perl crera mme la rfrence initiale dans $ref_a_TdT pour vous sil le faut.) Si vous voulez juste ajouter des lments au bout dune ligne, vous devrez faire quelque chose dun peu plus trange :
# Ajoute de nouvelles colonnes une ligne existante. push @{ $TdT[0] }, "wilma", "betty";

Remarquez que ceci ne marcherait pas :


push $TdT[0], "wilma", "betty"; # FAUX !

Cela ne compilerait mme pas, car largument de push doit tre un vritable tableau, et pas seulement une rfrence un tableau. Cest pourquoi le premier argument doit absolument commencer par un caractre @. Ce qui suit le @ est assez ngociable.
2. Ici comme dans dautres chapitres, nous omettons (pour la clart des exemples) les dclarations my que vous devriez normalement mettre. Dans cet exemple, vous devriez crire my @tmp = split. 3. Comme avec laffectation temporaire prcdente, nous avons simplifi ; les boucles de ce chapitre seraient trs probablement crites for my $x dans du code rel.

customer_8566

248

Chapitre 9 Structures de donnes

Utilisation et affichage
Affichons maintenant la structure de donnes. Si vous ne voulez quun seul lment, ceci suffit :
print $TdT[3][2];

Mais si vous voulez tout imprimer, vous ne pouvez pas vous contenter dcrire :
print @TdT; # FAUX

Cest incorrect car vous aurez des rfrences sous forme de chanes de caractres au lieu de vos donnes. Perl ne drfrence jamais automatiquement votre place. Il vous faut donc construire une boucle ou deux. Le code qui suit affiche la structure complte, en bouclant sur les lments de @TdT et en les drfrenant chacun lintrieur de linstruction print :
for $ligne ( @TdT ) { print "@$ligne\n"; }

Pour garder la trace des indices, vous pouvez faire comme ceci :
for $i ( 0 .. $#TdT ) { print "La ligne $i est : @{$TdT[$i]}\n"; }

ou mme cela (remarquez la boucle intrieure) :


for $i ( 0 .. $#TdT ) { for $j ( 0 .. $#{$TdT[$i]} ) { print "Llment $i $j est $AoA[$i][$j]\n"; } }

Comme vous pouvez le voir, les choses se compliquent. Cest pourquoi il est parfois plus simple dutiliser une variable temporaire en cours de route :
for $i ( 0 .. $#TdT ) { $ligne = $TdT[$i]; for $j ( 0 .. $#{$ligne} ) { print "Llment $i $j est $ligne->[$j]\n"; } }

Tranches
Si vous voulez accder une tranche (une partie de ligne) dun tableau multidimensionnel, vous allez devoir faire des indexations subtiles. Loprateur f lche nous donne une faon simple daccder un lment unique, mais rien de tel nexiste pour les tranches. Vous pouvez toujours extraire les lments de votre tranche un par un avec une boucle :
@partie = (); for ($y = 7; $y < 13; $y++) { push @partie, $TdT[4][$y]; }

customer_8566

Tableaux de tableaux
Cette boucle particulire pourrait tre remplace par une tranche de tableau :
@partie = @{ $TdT[4] } [ 7..12 ];

249

Si vous voulez une tranche deux dimensions, par exemple, avec $x dans lintervalle 4..8 et $y dans 7..12, voici une manire de procder :
@nouveauTdT = (); for ($startx = $x = 4; $x <= 8; $x++) { for ($starty = $y = 7; $y <= 12; $y++) { $nouveauTdT[$x - $startx][$y - $starty] = $TdT[$x][$y]; } }

Dans cet exemple, les valeurs individuelles dans notre tableau darrive deux dimensions, @nouveauTdT, sont affectes une par une partir dun sous-tableau deux dimensions de @TdT. Une autre possibilit consiste crer des tableaux anonymes, chacun dentre eux tant constitu de la tranche dsire dun sous-tableau de @TdT, puis mettre des rfrences ces tableaux anonymes dans @nouveauTdT. Nous pourrions alors stocker les rfrences dans @nouveauTdT (index une seule fois, pour ainsi dire) au lieu de stocker des valeurs de sous-tableau dans un @nouveauTdT index deux fois. Cette mthode limine la boucle intrieure :
for ($x = 4; $x <= 8; $x++) { push @nouveauTdT, [ @{ $TdT[$x] } [ 7..12 ] ]; }

Bien sr, si vous faites cela souvent, vous devriez probablement crire un sous-programme appel par exemple extraire_rectangle. Et si vous faites cela trs souvent avec de grandes sries de donnes multidimensionnelles, vous devriez probablement utiliser le module PDL (Perl Data Language), disponible sur CPAN.

Erreurs frquentes
Comme nous lavons dj mentionn, les tableaux et les hachages de Perl sont une dimension. En Perl, mme les tableaux multidimensionnels sont en fait une dimension, mais les valeurs le long de cette dimension sont des rfrences dautres tableaux, qui agrgent plusieurs lments en un seul. Si vous affichez ces valeurs sans les drfrencer, vous obtiendrez les rfrences converties en chanes en lieu et place des donnes dsires. Par exemple ces deux lignes :
@TdT = ( [2, 3], [4, 5, 7], [0] ); print "@TdT";

donneront quelque chose comme :


ARRAY(0x83c38) ARRAY(0x8b194) ARRAY(0x8b1d0)

Dun autre ct, cette ligne affiche 7 :


print $TdT[1][2];

Quand vous construisez un tableau de tableaux, noubliez pas de crer de nouvelles rfrences pour les sous-tableaux. Sinon, vous vous contenterez de crer un tableau contenant le nombre dlments des sous-tableaux, comme ceci :

customer_8566

250
for $i (1..10) { @tableau = fonction($i); $TdT[$i] = @tableau; }

Chapitre 9 Structures de donnes

# FAUX !

Ici on accde @tableau en contexte scalaire, ce qui renvoie donc le nombre de ses lments, lequel est affect comme il se doit $TdT[$i]. La manire correcte daffecter la rfrence vous sera montre dans un moment. Aprs avoir fait lerreur prcdente, les gens ralisent quils doivent affecter une rfrence. Lerreur quils font naturellement ensuite implique de prendre et reprendre une rfrence vers toujours le mme emplacement mmoire :
for $i (1..10) { @tableau = fonction($i); $TdT[$i] = \@tableau; }

# ENCORE FAUX !

Chaque rfrence gnre par la seconde ligne de la boucle for est la mme, cest--dire une rfrence au seul tableau @tableau. Certes, ce tableau change effectivement chaque passage dans la boucle, mais quand tout est fini, $TdT contient 10 rfrences au mme tableau, qui contient maintenant la dernire srie de valeurs qui lui ont t affectes. print @{$TdT[1]} prsentera les mmes valeurs que print @{$TdT[2]}. Voici une approche qui aura plus de succs :
for $i (1..10) { @tableau = fonction($i); $TdT[$i] = [ @tableau ]; }

# CORRECT !

Les crochets autour de @tableau crent un nouveau tableau anonyme, dans lequel les lments de @tableau sont copis. Nous stockons ensuite une rfrence ce nouveau tableau. Un rsultat similaire, bien que beaucoup plus difficile lire, pourra tre obtenu par :
for $i (1..10) { @tableau = fonction($i); @{$TdT[$i]} = @tableau; }

Comme $TdT[$i] doit tre une nouvelle rfrence, la rfrence se met exister. Le @ qui prcde drfrence alors cette nouvelle rfrence, avec pour rsultat daffecter (en contexte de liste) les valeurs de @tableau au tableau rfrenc par $TdT[$i]. Pour des raisons de clart, vous pouvez prfrer viter cette construction. Mais il existe une situation dans laquelle vous voudrez lutiliser. Supposons que @TdT est dj un tableau de rfrences des tableaux. Cest--dire que vous avez fait des affectations comme :
$TdT[3] = \@tableau_original;

Et supposons maintenant que vous vouliez modifier @tableau_original (cest--dire que vous voulez modifier la quatrime ligne de $TdT) de faon ce quil rfre aux lments de @tableau. Ce code fonctionnera :
@{$TdT[3]} = @tableau;

customer_8566

Tableaux de tableaux

251

Dans ce cas, la rfrence ne change pas, mais les lments du tableau rfrenc changent. Cela crase les valeurs de @tableau_original. Finalement, ce code dangereux en apparence fonctionne parfaitement :
for $i (1..10) { my @tableau = fonction($i); $TdT[$i] = \@tableau; }

Cest parce que la variable porte lexicale my @tableau est recre compltement chaque passage dans la boucle. Bien que vous ayez limpression davoir stock une rfrence la mme variable chaque fois, ce nest en fait pas le cas. Cest une subtile distinction, mais cette technique peut produire du code plus efficace, au risque de tromper les programmeurs moins clairs. (Cest plus efficace car il ny a pas de copie dans la dernire affectation.) Dun autre ct, sil vous faut de toute faon copier les valeurs (ce que fait la premire affectation de la boucle), vous pouvez aussi bien utiliser la copie implique par les crochets et viter la variable temporaire :
for $i (1..10) { $TdT[$i] = [ fonction($i) ]; }

En rsum :
$TdT[$i] = [ @tableau ]; $TdT[$i] = \@tableau; @{ $TdT[$i] } = @tableau; # # # # Plus sr, parfois plus rapide Rapide mais risqu, dpend du ct "my" de @tableau Un peu rus

Une fois que vous matrisez les tableaux de tableaux, vous voudrez vous mesurer des structures de donnes plus complexes. Si vous cherchez les structures (struct) de C ou les enregistrements (record) de Pascal, vous ne trouverez aucun mot rserv en Perl qui en crera pour vous. Ce que vous avez en revanche est un systme plus f lexible. Si votre ide dune structure est moins f lexible que cela, ou si vous voulez fournir vos utilisateurs quelque chose de plus rigide et de plus opaque, alors vous pouvez utiliser les fonctionnalits orientes objet dtailles au chapitre 12, Objets. Perl dispose de deux manires dorganiser les donnes : comme des listes ordonnes dans des tableaux, dont laccs aux lments se fait par leur position, ou comme des listes non ordonnes de couples cl/valeur stocks dans des hachages et auxquels on accde par leur nom. La meilleure faon de reprsenter un enregistrement en Perl consiste utiliser une rfrence de hachage, mais la manire dorganiser de tels enregistrements peut varier. Si vous dsirez conserver une liste ordonne de ces enregistrements et y accder par leur numro, vous utiliserez un tableau de rfrences de hachages pour stocker les enregistrements. Ou bien, si vous prfrez accder ces enregistrements par leurs noms, vous maintiendrez un hachage de rfrences des hachages. Vous pourriez mme faire les deux la fois avec un pseudo-hachage. Dans les sections suivantes, vous trouverez des exemples de code dcrivant comment composer ( partir de rien), gnrer (depuis dautres sources), accder et afficher plusieurs structures de donnes diffrentes. Nous montrerons dabord trois combinaisons videntes de hachages et de tableaux, suivies par un hachage de fonctions puis des structures de donnes plus irrgulires. Nous terminerons par la prsentation dune manire

customer_8566

252

Chapitre 9 Structures de donnes

de sauver ces structures de donnes. Ces exemples supposent que vous vous tes dj familiaris avec les explications qui prcdent dans ce chapitre.

Hachages de tableaux
Utilisez un hachage de tableaux quand vous voulez accder chaque tableau par une chane particulire plutt que par un numro dindice. Dans notre exemple de personnages dmissions de tlvision, au lieu de parcourir la liste de noms partir de la zroime mission, la premire et ainsi de suite, nous allons mettre en place notre structure de faon pouvoir obtenir la liste des personnages partir du nom du dessin anim. Comme notre structure de donnes est un hachage, nous ne pouvons pas en ordonner le contenu, mais nous pouvons utiliser la fonction sort pour spcifier un ordre de sortie particulier.

Composition dun hachage de tableaux


Vous pouvez crer un hachage de tableaux anonymes comme suit :
# Nous omettons habituellement les guillemets quand les cls sont # des identificateurs. %HdT = ( flintstones => [ "fred", "barney" ], jetsons => [ "george", "jane", "elroy" ], simpsons => [ "homer", "marge", "bart" ], );

Pour ajouter un nouveau tableau au hachage, vous pouvez simplement crire :


$HdT{teletubbies} = [ "tinky winky", "dipsy", "laa-laa", "po" ];

Gnration dun hachage de tableaux


Voici quelques techniques pour remplir un hachage de tableaux. Pour le lire partir dun fichier avec le format suivant :
flintstones: fred barney wilma dino jetsons: george jane elroy simpsons: homer marge bart

vous pourriez utiliser lune des deux boucles suivantes :


while ( <> ) { next unless s/^(.*?):\s*//; $HdT{$1} = [ split ]; } while ( $ligne = <> ) { ($qui, $reste) = split /:\s*/, $ligne, 2; @champs = split , $reste; $HdT{$qui} = [ @champs ]; }

customer_8566

Hachages de tableaux

253

Si vous avez un sous-programme get_famille qui renvoie un tableau, vous pouvez vous en servir pour remplir %HdT avec lune de ces deux boucles :
for $groupe ( "simpsons", "jetsons", "flintstones" ) { $HdT{$groupe} = [ get_famille($groupe) ]; } for $groupe ( "simpsons", "jetsons", "flintstones" ) { @membres = get_famille($groupe); $HdT{$groupe} = [ @membres ]; }

Vous pouvez ajouter de nouveaux membres un tableau existant comme ceci :


push @{ $HdT{flintstones} }, "wilma", "pebbles";

Utilisation et affichage dun hachage de tableaux


Vous pouvez fixer le premier lment dun tableau en particulier comme suit :
$HdT{flintstones}[0] = "Fred";

Pour mettre en majuscule linitiale du deuxime Simpson, appliquez une substitution llment de tableau appropri :
$HdT{simpsons}[1] =~ s/(\w)/\u$1/;

Vous pouvez afficher toutes les familles en bouclant sur toutes les cls du hachage :
for $famille ( keys %HdT ) { print "$famille : @{ $HdT{$famille} }\n"; }

Avec un petit effort supplmentaire, vous pouvez galement ajouter les indices de tableau :
for $famille ( keys %HoA ) { print "$famille : "; for $i ( 0 .. $#{ $HdT{$famille} } ) { print " $i = $HdT{$famille}[$i]"; } print "\n"; }

Ou trier les tableaux par leur nombre dlments :


for $famille ( sort { @{$HdT{$b}} <=> @{$HdT{$a}} } keys %HdT ) { print "$famille : @{ $HdT{$famille} }\n" }

Ou mme trier les tableaux par leur nombre dlments puis trier les lments ASCIIbtiquement (ou pour tre prcis, utf8-tiquement ) :
# Affiche lensemble tri par le nombre de personnes et leurs noms. for $famille ( sort { @{$HdT{$b}} <=> @{$HdT{$a}} } keys %HdT ) { print "$famille : ", join(", ", sort @{ $HdT{$famille} }), "\n"; }

customer_8566

254

Chapitre 9 Structures de donnes

Tableaux de hachages
Un tableau de hachages est utile quand vous avez un tas denregistrements auxquels vous aimeriez accder squentiellement et que chaque enregistrement comporte des couples cl/valeur. Les tableaux de hachages sont moins frquemment utiliss que les autres structures de ce chapitre.

Composition dun tableau de hachages


Vous pouvez crer un tableau de hachages anonymes comme suit :
@TdH = ( { mari femme fils }, { mari femme fils }, { mari femme fils }, );

=> "barney", => "betty", => "bamm bamm",

=> "george", => "jane", => "elroy",

=> "homer", => "marge", => "bart",

Pour ajouter un nouveau hachage au tableau, vous pouvez simplement crire :


push @TdH, { mari => "fred", femme => "wilma", fille => "pebbles" };

Gnration dun tableau de hachages


Voici quelques techniques pour remplir un tableau de hachages. Pour lire depuis un fichier crit selon le format suivant :
mari=fred ami=barney

vous pourriez utiliser lune des deux boucles suivantes :


while ( <> ) { $enrt = {}; for $champ ( split ) { ($cle, $valeur) = split /=/, $champ; $enrt->{$cle} = $valeur; } push @TdH, $enrt; }

customer_8566

Hachages de hachages
while ( <> ) { push @TdH, { split /[\s=]+/ }; }

255

Si vous avez un sous-programme get_paire_suivante qui renvoie des couples cl/valeur, vous pouvez lutiliser pour remplir @TdH avec lun de ces deux boucles :
while ( @champs = get_paire_suivante() ) { push @TdH, { @champs }; } while (<>) { push @TdH, { get_paire_suivante($_) }; }

Vous pouvez ajouter de nouveaux lments un hachage existant comme ceci :


$TdH[0]{animal} = "dino"; $TdH[2]{animal} = "petit papa Nol";

Utilisation et affichage dun tableau de hachages


Vous pouvez modifier un couple cl/valeur dun hachage particulier comme suit :
$TdH[0]{mari} = "fred";

Pour mettre en majuscule le mari du deuxime hachage appliquez une substitution :


$TdH[1]{mari} =~ s/(\w)/\u$1/;

Vous pouvez afficher toutes les donnes comme suit :


for $href ( @TdH ) { print "{ "; for $role ( keys %$href ) { print "$role=$href->{$role} "; } print "}\n"; }

et avec les indices :


for $i ( 0 .. $#TdH ) { print "$i est { "; for $role ( keys %{ $TdH[$i] } ) { print "$role=$TdH[$i]{$role} "; } print "}\n"; }

Hachages de hachages
Le hachage multidimensionnel est la plus souple des structures embotes de Perl. Cela revient construire un enregistrement qui contient dautres enregistrement Vous indexez chaque niveau avec des chanes (entre guillemets si besoin est). Souvenez vous cependant que les couples cl/valeur du hachage ne sortiront dans aucun ordre particu-

customer_8566

256

Chapitre 9 Structures de donnes

lier ; vous pouvez utiliser la fonction sort pour rcuprer les couples dans lordre qui vous intresse.

Composition dun hachage de hachage


Vous pouvez crer un hachage de hachages anonymes comme suit :
%HdH = ( flintstones => { mari => pote => }, jetsons => { mari => femme => "son fils"=> }, simpsons => { mari => femme => fiston => }, );

"fred", "barney",

"george", "jane", "elroy", # Guillemets ncessaires sur la cl

"homer", "marge", "bart",

Pour ajouter un autre hachage anonyme %HdH, vous pouvez simplement crire :
$HdH{ mash } = { capitaine => "pierce", major => "burns", caporal => "radar", };

Gnration dun hachage de hachages


Voici quelques techniques pour remplir un hachage de hachages. Pour lire des donnes partir dun fichier dans le format suivant :
flintstones: mari=fred pote=barney femme=wilma animal=dino

vous pourriez utiliser lune des deux boucles suivantes :


while ( <> ) { next unless s/^(.*?):\s*//; $qui = $1; for $champ ( split ) { ($cle, $valeur) = split /=/, $champ; $HdH{$qui}{$cle} = $valeur; } } while ( <> ) { next unless s/^(.*?):\s*//; $qui = $1;

customer_8566

Hachages de hachages
$enrt = {}; $HdH{$qui} = $enrt; for $champ ( split ) { ($cle, $valeur) = split /=/, $champ; $enrt->{$cle} = $valeur; } }

257

Si vous avez un sous-programme get_famille qui renvoie une liste de couples cl/valeur, vous pouvez vous en servir pour remplir %HdH avec lun de ces trois bouts de code :
for $groupe ( "simpsons", "jetsons", "flintstones" ) { $HdH{$groupe} = { get_famille($groupe) }; } for $groupe ( "simpsons", "jetsons", "flintstones" ) { @membres = get_famille($groupe); $HdH{$groupe} = { @membres }; } sub hash_familles { my @ret; for $groupe ( @_ ) { push @ret, $groupe, { get_famille($groupe) }; } return @ret; } %HdH = hash_familles( "simpsons", "jetsons", "flintstones" );

Vous pouvez ajouter de nouveaux membres un hachage comme suit :


%nouveaux = ( femme => "wilma", animal => "dino"; ); for $quoi (keys %nouveaux) { $HdH{flintstones}{$quoi} = $nouveaux{$quoi}; }

Utilisation et affichage dun hachage de hachages


Vous pouvez modifier un couple cl/valeur dun hachage particulier comme suit :
$HdH{flintstones}{femme} = "wilma";

Pour mettre en majuscule la valeur associe une cl particulire, appliquez une substitution un lment :
$HdH{jetsons}{son fils} =~ s/(\w)/\u$1/;

Vous pouvez afficher toutes les familles en bouclant sur les cls du hachage externe, puis en bouclant sur les cls du hachage interne :
for $famille ( keys %HdH ) { print "$famille : ";

customer_8566

258

Chapitre 9 Structures de donnes


for $role ( keys %{ $HdH{$famille} } ) { print "$role=$HdH{$famille}{$role} "; } print "\n";

Dans les hachages trs grands, il peut tre un peu plus rapide de rcuprer la fois les cls et les valeurs en utilisant each (ce qui exclut le tri) :
while ( ($famille, $roles) = each %HdH ) { print "$famille : "; while ( ($role, $personne) = each %$roles ) { print "$role=$personne "; } print "\n"; }

(Hlas, ce sont les grands hachages qui ont vraiment besoin dtre tris, sinon vous ne trouverez jamais ce que vous cherchez dans ce qui est affich.) Vous pouvez trier les familles, puis les rles, comme suit :
for $famille ( sort keys %HdH ) { print "$famille : "; for $role ( sort keys %{ $HdH{$famille} } ) { print "$role=$HdH{$famille}{$role} "; } print "\n"; }

Pour trier les familles par leur nombre de membres (plutt quASCII-btiquement (ou utf8-tiquement)), vous pouvez utiliser keys en contexte scalaire :
for $famille ( sort { keys %{$HdH{$a}} <=> keys %{$HdH{$b}} } keys %HdH ) { print "$famille : "; for $role ( sort keys %{ $HdH{$famille} } ) { print "$role=$HdH{$family}{$role} "; } print "\n"; }

Pour trier les membres dune famille dans un certain ordre, vous pouvez leur donner chacun un rang :
$i = 0; for ( qw(mari femme fils fille pote animal) ) { $rang{$_} = ++$i } for $famille ( sort { keys %{$HdH{$a}} <=> keys %{$HdH{$b}} } keys %HdH ) { print "$famille : "; for $role ( sort { $rang{$a} <=> $rang{$b} } keys %{ $HdH{$famille} } ) { print "$role=$HdH{$famille}{$role} "; } print "\n"; }

customer_8566

Hachages de fonctions

259

Hachages de fonctions
Quand vous crivez une application complexe ou un service rseau en Perl, vous voulez probablement mettre un grand nombre de commandes la disposition de vos utilisateurs. Un tel programme pourrait avoir du code comme celui-ci pour examiner le choix de lutilisateur et agir en consquence :
if ($cmd =~ /^exit$/i) elsif ($cmd =~ /^help$/i) elsif ($cmd =~ /^watch$/i) elsif ($cmd =~ /^mail$/i) elsif ($cmd =~ /^edit$/i) elsif ($cmd =~ /^delete$/i) else { warn "Commande inconnue : } { { { { { { exit } show_help() } $watch = 1 } mail_msg($msg) } $edited++; editmsg($msg); } confirm_kill() }

$cmd; Essayez help la prochaine fois\n";

Vous pouvez galement stocker des rfrences des fonctions dans vos structures de donnes, tout comme vous pouvez y stocker des tableaux ou des hachages :
%HdF = ( exit help watch mail edit delete ); # Compose un hachage de fonctions => sub { exit }, => \&show_help, => sub { $watch = 1 }, => sub { mail_msg($msg) }, => sub { $edited++; editmsg($msg); }, => \&confirm_kill,

if ($HdF{lc $cmd}) { $HdF{lc $cmd}->() } # Appelle la fonction else { warn "Commande inconnue : $cmd; Essayez help la prochaine fois\n" }

Dans lavant-dernire ligne, nous vrifions si le nom de commande spcifi (en minuscules) existe dans notre table de distribution %HdF. Si cest le cas, nous appelons la commande approprie en drfrenant la valeur du hachage comme une fonction et passons cette fonction une liste darguments vide. Nous pourrions aussi lavoir drfrence comme &{ $HoF{lc $cmd} }(), ou partir de la version 5.6 de Perl, simplement par $HoF{lc $cmd}().

Enregistrements plus labors


Jusquici nous avons vu dans ce chapitre des structures de donnes simples, homognes et deux niveaux : chaque lment contient le mme genre de rfrent que tous les autres lments de ce niveau. Ce nest pas indispensable. Tout lment peut contenir nimporte quel type de scalaire, ce qui signifie quil peut sagir dun chane, dun nombre ou dune rfrence nimporte quoi dautre. La rfrence peut tre une rfrence un tableau ou un hachage, ou un pseudo-hachage, ou une rfrence une fonction nomme ou anonyme, ou un objet. La seule chose que vous ne pouvez pas faire est de mettre plusieurs rfrents dans un seul scalaire. Si vous vous retrouvez essayer de faire ce genre de chose, cest le signe que vous avez besoin dune rfrence un tableau ou un hachage pour superposer plusieurs valeurs en une seule.

customer_8566

260

Chapitre 9 Structures de donnes

Dans les sections qui suivent, vous trouverez des exemples de code destins montrer ce quil est possible de stocker dans un enregistrement, que nous implmenterons comme une rfrence un hachage. Les cls sont en majuscules, une convention parfois employe quand le hachage est utilis comme un type denregistrement spcifique.

Composition, utilisation et affichage denregistrements plus labors


Voici un enregistrement avec six champs de types diffrents :
$enrt = { TEXTE SEQUENCE RECHERCHE CODE1 CODE2 HANDLE }; => => => => => => $chaine, [ @anc_valeurs ], { %une_table }, \&une_fonction, sub { $_[0] ** $_[1] }, \*STDOUT,

Le champ TEXTE est une simple chane, que vous pouvez donc afficher :
print $enrt->{TEXT};

SEQUENCE et RECHERCHE sont des rfrences normales un tableau et un hachage :


print $enrt->{SEQUENCE}[0]; $dernier = pop @{ $enrt->{SEQUENCE} }; print $enrt->{RECHERCHE}{"cle"}; ($premier_c, $premier_v) = each %{ $enrt->{RECHERCHE} };

CODE1 est un sous-programme nomm et CODE2 un sous-programme anonyme, mais sont appels de la mme faon :
$reponse1 = $enrt->{CODE1}->($arg1, $arg2); $reponse2 = $enrt->{CODE2}->($arg1, $arg2);

Avec une paire daccolades supplmentaires, pour pouvez traiter $rec->{HANDLE} comme un objet indirect :
print { $enrt->{HANDLE} } "une chane\n";

Si vous utilisez le module FileHandle, vous pouvez mme traiter le handle comme un objet normal :
use FileHandle; $enrt->{HANDLE}->autoflush(1); $enrt->{HANDLE}->print("une chane\n");

Composition, utilisation et affichage denregistrements encore plus labors


Naturellement, les champs de vos structures de donnes peuvent eux-mmes tre des structures de donnes arbitrairement complexes :

customer_8566

Enregistrements plus labors


%TV = ( flintstones => { serie => "flintstones", soirs => [ "lundi", "jeudi", membres => [ { nom => "fred", role => { nom => "wilma", role => { nom => "pebbles", role => ], },

261

"vendredi" ], "mari", age => 36, }, "femme", age => 31, }, "enfant", age => 4, },

jetsons => { serie => "jetsons", soirs => [ "mercredi", "samedi" ], membres => [ { nom => "george", role => "mari", age => 41, }, { nom => "jane", role => "femme", age => 39, }, { nom => "elroy", role => "enfant", age => 9, }, ], }, simpsons => { serie => "simpsons", soirs => [ "lundi" ], membres => [ { nom => "homer", role => "mari", { nom => "marge", role => "femme", { nom => "bart", role => "enfant", ], }, );

age => 34, }, age => 37, }, age => 11, },

Gnration dun hachage denregistrements complexes


Comme Perl est assez bon pour analyser des structures de donnes complexes, pour pouvez aussi bien mettre vos dclarations de donnes dans un fichier spar comme du code Perl normal, puis le charger avec les fonctions intgres do ou require. Une autre approche courante est dutiliser un module de CPAN (comme XML::Parser) pour charger des structures de donnes quelconques crites dans un autre langage (comme XML). Vous pouvez construire vos structures de donnes petit petit :
$enrt = {}; $enrt->{serie} = "flintstones"; $enrt->{soirs} = [ quels_jours() ];

Ou les lire partir dun fichier (quon suppose ici crit sous la forme champ=valeur) :
@membres = (); while (<>) { %champs = split /[\s=]+/; push @membres, { %champs }; }

customer_8566

262
$enrt->{membres} = [ @membres ];

Chapitre 9 Structures de donnes

Puis les inclure dans des structures de donnes plus grandes, indexes par lun des souschamps :
$TV{ $enrt->{serie} } = $enrt;

Vous pouvez utiliser des champs supplmentaires pour viter de dupliquer les donnes. Par exemple, vous pourriez vouloir inclure un champ "enfants" dans lenregistrement dune personne, lequel pourrait tre une rfrence un tableau contenant des rfrences aux propres enregistrements des enfants. En ayant des parties de votre structure de donnes qui pointent sur dautres, vous viter les drives rsultant de la mise jour des donnes un endroit mais pas un autre :
for $famille (keys %TV) { my $enrt = $TV{$famille}; # pointeur temporaire my @enfants = (); for $personne ( @{$enrt->{membres}} ) { if ($personne->{role} =~ /enfant|fils|fille/) { push @enfants, $personne; } } # $enrt et $TV{$famille} pointent sur les mmes donnes ! $enrt->{enfants} = [ @enfants ]; }

Laffectation $enrt->{enfants} = [ @enfants ] copie le contenu du tableau mais ce sont simplement des rfrences des donnes non copies. Cela signifie que si vous modifiez lge de Bart comme suit :
$TV{simpsons}{enfants}[0]{age}++; # incrmente 12

alors vous verrez le rsultat suivant, car $TV{simpsons}{enfants}[0] et $TV{simpsons}{membres}[2] pointent tous deux vers le mme hachage anonyme :
print $TV{simpsons}{membres}[2]{age}; # affiche 12 galement

Et maintenant pour imprimer toute la structure de donnes %TV :


for $famille ( keys %TV ) { print "la famille $famille"; print " passe ", join (" et ", @{ $TV{$famille}{nights} }), "\n"; print "ses membres sont :\n"; for $qui ( @{ $TV{$famille}{membres} } ) { print " $qui->{name} ($qui->{role}), age $qui->{age}\n"; } print "enfants: "; print join (", ", map { $_->{nom} } @{ $TV{$famille}{enfants} } ); print "\n\n"; }

Sauvegarde de structures de donnes


Il existe plusieurs manires de sauver vos structures de donnes pour les utiliser avec un autre programme par la suite. La manire la plus simple consiste utiliser le module

customer_8566

Sauvegarde de structures de donnes

263

Data::Dumper de Perl, qui convertit une structure de donnes (potientiellement autorfrente) en une chane qui peut tre sauve pour tre reconstitue par la suite avec eval ou do.
use Data::Dumper; $Data::Dumper::Purity = 1; # car %TV est autorfrent open (FILE, "> tvinfo.perldata") or die "impossible douvrir tvinfo: $!"; print FILE Data::Dumper->Dump([\%TV], [*TV]); close FILE or die "impossible de fermer tvinfo: $!";

Un autre programme (ou le mme programme) pourra lire le fichier plus tard :
open (FILE, "< tvinfo.perldata") or die "impossible douvrir tvinfo: $!"; undef $/; # lit tout le fichier dun coup eval <FILE>; # recre %TV die "impossible de recrer les donnes depuis tvinfo.perldata: $@" if $@; close FILE or die "impossible de fermer tvinfo: $!"; print $TV{simpsons}{membres}[2]{age};

ou simplement :
do "tvinfo.perldata" or die "impossible de recrer tvinfo: $! $@"; print $TV{simpsons}{membres}[2]{age};

Beaucoup dautres solutions sont disponibles, avec des formats de stockage qui vont des donnes binaires (trs rapide) au XML (trs interoprable). Visitez vite un miroir du CPAN prs de chez vous !

customer_8566

customer_8566

Paquetages

10

Dans ce chapitre, nous allons pouvoir commencer nous amuser, car nous allons aborder la bonne conception des logiciels. Pour ce faire, parlons de Paresse, dImpatience et dOrgueil, les bases de la bonne conception des logiciels. Nous sommes tous tombs dans le pige du copier/coller alors quil fallait dfinir une abstraction de haut niveau, ne serait-ce quune boucle ou une routine simple.1 Il est vrai que certains partent lautre extrme en dfinissant des tas croissants dabstractions de plus haut niveau alors quil aurait suffi dun copier/coller.2 Mais en g7nral, la plupart dentre nous devraient penser employer plus dabstraction plutt que moins. Entre les deux se trouvent ceux qui ont une vision quilibre du degr dabstraction ncessaire, mais qui se lancent dans la conception de leurs propres abstractions alors quils devraient utiliser un code existant.3 Chaque fois que vous tes tent dadopter lune ou lautre de ces attitudes, il vous faut dabord vous asseoir et penser ce qui sera le mieux pour vous et votre prochain long terme. Si vous allez dverser vos nergies cratives dans une masse de code, pourquoi ne pas rendre le monde meilleur pendant que vous y tes ? (Mme si vous ne visez qu russir le programme, vous devez vous assurer quil convient la bonne niche cologique.) La premire tape vers une programmation cologiquement soutenable est simple : pas de dtritus dans le parc. Lorsque vous crivez un bout de code, pensez lui donner son propre espace de noms, de sorte que vos variables et vos fonctions ncrasent pas celles de quelquun dautre, ou vice-versa. Un espace de noms est un peu comme votre maison, dans laquelle il vous est permis dtre aussi dsordonn que vous le voulez, tant que votre interface externe avec les autres citoyens reste un tant soit peu correcte. En Perl, un espace de noms sappelle un paquetage (package). Les paquetages fournissent la bri-

1. Ce qui est une mauvaise forme de Paresse. 2. Ce qui est une forme dOrgueil mal plac. 3. Ce qui, vous lavez devin, est une mauvaise forme dImpatience. Mais si vous voulez vraiment rinventer la roue, essayez au moins den inventer une meilleure.

customer_8566

266

Chapitre 10 Paquetages

que de base sur laquelle les concepts de plus haut niveau de module et de classe sont labors. Tout comme la notion de maison , la notion de paquetage est un peu nbuleuse. Les paquetages sont indpendants des fichiers. On peut aussi bien avoir plusieurs paquetages dans un seul fichier, ou un unique paquetage rparti sur plusieurs fichiers, tout comme votre maison peut tre soit une petite mansarde dans un grand btiment (si vous tes un artiste sans le sou), soit un ensemble de btiments (si votre nom se trouve tre Reine Elizabeth). Mais une maison est habituellement compose dun seul btiment, comme un paquetage est habituellement compos dun seul fichier. Avec Perl, vous pouvez mettre un paquetage dans un seul fichier, tant que vous acceptez de donner au fichier le mme nom que le paquetage et dutiliser lextension .pm, qui est labrviation de perl module . Le module est lunit fondamentale de rutilisation de Perl. En effet, pour utiliser un module, vous vous servez de la commande use, qui est une directive de compilation qui contrle limportation des fonctions et des variables dun module. Chaque exemple de use que vous avez vu jusqu maintenant est un exemple de rutilisation de module. Le Comprehensive Perl Archive Network, ou CPAN, est lendroit o mettre vos modules si dautres personnes pouvaient les trouver utiles. Perl a prospr grce la volont des programmeurs partager les fruits de leur travail avec la communaut. videmment, CPAN est galement lendroit o vous pouvez trouver des modules que dautres ont gentiment tlcharg pour lusage de tous. Voir le chapitre 22, CPAN, et www.cpan.org plus de dtails. Depuis 25 ans environ, il est la mode de concevoir des langages informatiques qui imposent un tat de paranoa. On attend de vous de programmer chaque module comme sil tait en tat de sige. Il existe sans doute certaines cultures fodales au sein desquelles ceci est justifiable, mais toutes les cultures ne sont pas ainsi faites. Dans la culture Perl, par exemple, on attend de vous que vous restiez en dehors de la maison de quelquun parce que vous ny avez pas t invit, et non parce quil y a des barreaux aux fentres.4 Ceci nest pas un livre sur la programmation oriente objet, et nous ne sommes pas l pour vous convertir en fanatique dlirant de lorient objet, mme si justement vous souhaitez tre converti. Il existe dj de nombreux livres disponibles sur ce sujet. La philosophie Perl de la conception oriente objet correspond parfaitement la philosophie Perl de tout le reste ; utilisez la conception oriente objet (OO) l o elle a un sens, et vitez-la l o elle nen a pas. vous de voir. En parler OO, chaque objet appartient un groupement appel classe. En Perl, les classes, les paquetages et les modules sont tellement lis que les dbutants peuvent souvent les considrer interchangeables. Typiquement, une classe est implmente par un module qui dfinit un paquetage ayant le mme nom que la classe. Nous expliquerons cela dans les quelques chapitres qui suivent. Lorsque vous utilisez un module avec use, vous bnficiez de la rutilisation directe de logiciel. Avec les classes, vous bnficiez de la rutilisation indirecte de logiciel lorsquune classe en utilise une autre par hritage. Avec les classes, vous gagnez quelque chose de plus : une interface propre avec un autre espace de noms. On naccde quelque
4. Mais Perl fournit aussi des barreaux si vous le voulez. Voir Gestion des donnes non sres au chapitre 23, Scurit.

customer_8566

Paquetages
chose dans une classe quindirectement, isolant ainsi la classe du monde extrieur.

267

Comme nous lavons indiqu dans le chapitre 8, Rfrences, la programmation oriente objet est ralise par des rfrences dont les rfrents savent quelle classe ils appartiennent. En fait, maintenant que vous connaissez les rfrences, vous connaissez presque tout ce que les objets ont de difficile. Le reste se trouve sous les doigts , comme dirait un pianiste. Mais cependant il va falloir pratiquer un peu. Un de vos exercices de gammes de base consiste apprendre comment protger diffrents bouts de code pour quune partie naltre pas par inadvertance les variables des autres parties. Chaque bout de code appartient un paquetage bien dfini, ce qui dtermine quelles variables et quelles fonctions sont sa disposition. Lorsque Perl rencontre un bout de code, il le compile dans le paquetage courant. Le paquetage courant initial est appel main , mais vous pouvez passer du paquetage courant un autre tout moment avec la dclaration package. Le paquetage courant dtermine quelle table de symboles est utilise pour trouver vos variables, fonctions, handles dentre/sortie, et formats. Toute variable qui nest pas dclare avec my est associe un paquetage mme des variables apparemment omniprsentes comme $_ et %SIG. En fait, les variables globales nexistent pas vraiment en Perl, ce sont simplement des variables de paquetage. (Les identificateurs spciaux comme _ et SIG ne sont quapparemment globaux, car ils sont par dfaut dans le paquetage main plutt que dans le paquetage courant.) La porte dune dclaration package commence la dclaration elle-mme et se termine la fin de la porte qui la contient (bloc, fichier ou eval celle qui arrive en premier) ou jusqu une autre dclaration package au mme niveau, qui remplace la prcdente. (Ceci est une pratique courante.) Tous les identificateurs ultrieurs (dont ceux qui sont dclars avec our, mais non ceux qui sont dclars avec my ou qualifis avec le nom dun autre paquetage) seront placs dans la table de symboles appartenant au paquetage courant. (Les variables dclares avec my sont indpendantes des paquetages. Elles sont toujours visibles lintrieur, et uniquement lintrieur, de la porte les contenant, quelles que soient les dclarations de paquetage.) Une dclaration de paquetage sera habituellement la premire instruction dun fichier destin tre inclus par require ou use. Mais ce nest quune convention. Vous pouvez mettre une dclaration package partout o vous pouvez mettre une instruction. Vous pouvez mme la mettre la fin dun bloc, auquel cas elle naura pas le moindre effet. Vous pouvez passer dun paquetage un autre plus dun endroit, car une dclaration de paquetage ne fait que slectionner la table de symboles utiliser par le compilateur pour le reste de ce bloc. (Cest ainsi quun paquetage donn peut se rpartir sur plusieurs fichiers.) Vous pouvez faire rfrence aux identificateurs5 appartenant dautres paquetages en
5. Par identificateurs, nous dsignons les noms utiliss comme clefs de table de symboles pour accder aux variables scalaires, variables de tableau, variables de hachage, fonctions, handles de fichier ou de rpertoire et formats. Syntaxiquement parlant, les tiquettes sont aussi des identificateurs, mais elles ne sont pas places dans une table de symboles prcise ; elles sont plutt rattaches directement aux instructions de votre programme. Les tiquettes ne peuvent tre qualifies par un paquetage.

customer_8566

268

Chapitre 10 Paquetages

les prfixant ( qualifiant ) avec leur nom de paquetage et un double deux-points : $Paquetage::Variable. Si le nom du paquetage est nul, cest le paquetage principal (main) qui est pris par dfaut. Cest--dire que $::chaude est quivalent $main::chaude. 6 Lancien dlimiteur de paquetage tait lapostrophe, ainsi dans danciens programmes Perl vous verrez des variables comme $mainchaude et $unpackdebiere. Mais le double deux-points est conseill parce quil est plus lisible, dune part pour les humains, et dautre part pour les macros emacs. Il donne aussi aux programmeurs C++ le sentiment quils savent ce qui se passe alors que lapostrophe tait l pour donner aux programmeurs Ada le sentiment de savoir ce qui se passe. Comme la syntaxe dmode est encore supporte pour la compatibilit arrire, si vous essayez dutiliser une chane comme "This is $owners house", vous accderez $owner::s, cest dire la variable $s dans le paquetage owner, ce qui nest probablement pas ce que vous vouliez dire. Utilisez des accolades pour liminer lambigut, par exemple "This is ${owner}s house". Le double deux-points peut tre utilis pour mettre bout bout des identificateurs dans un nom de paquetage : $Rouge::Bleu::var. Ce qui veut dire : le $var appartenant au paquetage Rouge::Bleu. Le paquetage Rouge::Bleu na rien voir avec un quelconque paquetage Rouge ou Bleu existant ventuellement. Une relation entre Rouge::Bleu et Rouge ou Bleu peut avoir un sens pour la personne qui crit ou utilise le programme, mais nen a aucun pour Perl. (Enfin, part le fait que, dans limplmentation actuelle, la table de symboles Rouge::Bleu se trouve tre range dans la table de symboles Rouge. Mais le langage Perl nen fait aucun usage direct.) Pour cette raison, chaque dclaration package doit dclarer un nom de paquetage complet. Aucun nom de paquetage ne sous-entend un quelconque prfixe , mme sil est (apparemment) dclar lintrieur de la porte dune autre dclaration de paquetage. Seuls les identificateurs (les noms commenant par une lettre ou un soulign) sont rangs dans la table de symboles dun paquetage. Tous les autres symboles sont gards dans le paquetage main, notamment toutes les variables non-alphabtiques comme $!, $?, et $_. De plus, lorquils ne sont pas qualifis, les identificateurs STDIN, STDOUT, STDERR, ARGV , ARGVOUT, ENV INC et SIG se trouvent obligatoirement dans le paquetage main, mme lors, quils sont utiliss dautres fins que celles auxquelles ils sont destins par construction. Ne nommez pas votre paquetage m, s, y, tr, q, qq, qr, qw, ou qx sauf si vous cherchez beaucoup dennuis. Par exemple, vous ne pourrez pas utiliser la forme qualifie dun identificateur comme handle de fichier, car il sera interprt au contraire comme une recherche de motif, une substitution ou une translittration. Il y a longtemps, les variables commenant avec un soulign appartenaient obligatoirement au paquetage main, mais nous avons dcid quil tait plus utile pour les crateurs dun paquetage de pouvoir utiliser un soulign en dbut de nom pour indiquer des identificateurs semi-privs destins uniquement lusage interne de ce paquetage. (Des variables rellement prives peuvent tre dclares comme variables lexicales dans la porte dun fichier, mais cela marche le mieux quand un paquetage et un module ont
6. Pour viter un autre sujet de confusion ventuelle, dans le cas dun nom de variable comme $main::chaude, nous utilisons le terme identificateur pour parler de main et de chaude, mais pas de main::chaude, que nous nommons plutt nom de variable, car les identificateurs ne peuvent pas contenir de deux-points.

customer_8566

Tables de symboles
une relation bijective, ce qui est courant mais pas obligatoire.)

269

Le hachage %SIG (qui sert intercepter les signaux, voir le chapitre 16, Communication interprocessus) est galement spcial. Si vous dfinissez un gestionnaire de signal en tant que chane, il est sous-entendu quil fait rfrence une fonction du paquetage main, sauf si le nom dun autre paquetage est explicitement utilis. Qualifiez compltement le nom dun gestionnaire de signal si vous voulez utiliser un paquetage spcifique, ou vitez entirement les chanes en affectant plutt un typeglob ou une rfrence une fonction :
$SIG{QUIT} $SIG{QUIT} $SIG{QUIT} $SIG{QUIT} $SIG{QUIT} = = = = = "Pack::attrape_quit"; # nom de gestionnaire qualifi "attrape_quit"; # sous-entend "main::attrape_quit" *attrape_quit; # impose la fonction du paquetage courant \&attrape_quit; # impose la fonction du paquetage courant sub { print "Attrap SIGQUIT\n" }; # fonction anonyme

La notion de paquetage courant est un concept concernant la fois la compilation et lexcution. La plupart des vrifications de nom de variable se font la compilation, mais les vrifications lexcution se font lorsque des rfrences symboliques sont drfrences et quand de nouveaux bouts de code sont analyss avec eval. En particulier, quand vous appliquez eval une chane, Perl sait dans quel paquetage eval a t invoqu et propage ce paquetage vers lintrieur en valuant la chane. (Bien sr, vous pouvez toujours passer un autre paquetage lintrieur de la chane eval, puisquune chane eval compte pour un bloc, tout comme un fichier charg avec un do, un require, ou un use.) Dun autre ct, si eval veut dterminer dans quel paquetage il se trouve, le symbole spcial __PACKAGE__ contient le nom du paquetage courant. Puisque vous pouvez le traiter comme une chane, vous pourriez lutiliser dans une rfrence symbolique pour accder une variable de paquetage. Mais si vous faites cela, il y a des chances que vous ayez plutt intrt dclarer la variable avec our, de sorte quon puisse y accder comme si ctait une variable lexicale.

Tables de symboles
Les lments contenus dans un paquetage sont dans leur ensemble appels table de symboles. Les tables de symboles sont ranges dans un hachage dont le nom est le mme que celui du paquetage, avec un double deux-points ajout la fin. Ainsi le nom de la table de symboles principale, main, est %main::. Puisque main se trouve aussi tre le paquetage par dfaut, Perl fournit %::comme abbrviation pour %main::. De mme, la table de symboles du paquetage Rouge::Bleu est appel %Rouge::Bleu::. Il se trouve que la table de symboles main contient toutes les autres tables de symboles de haut niveau, elle-mme incluse, donc %Rouge::Bleu:: est aussi %main::Rouge::Bleu::. Quand nous disons que la table de symboles contient une autre table de symboles, nous voulons dire quelle contient une rfrence une autre table de symboles. Puisque main est le paquetage de plus haut niveau, il contient une rfrence lui-mme, ainsi %main:: est pareil que %main::main::, et %main::main::main::, et ainsi de suite, ad infinitum. Il est important de prvoir ce cas spcial si vous crivez du code qui parcourt toutes les tables de symboles.

customer_8566

270

Chapitre 10 Paquetages

lintrieur du hachage dune table de symboles, chaque couple clef/valeur fait correspondre un nom de variable sa valeur. Les clefs sont les identificateurs de symbole et les valeurs les typeglobs correspondants. Donc quand vous utilisez la notation typeglob *NOM, vous accdez en ralit une valeur dans le hachage qui contient la table de symboles du paquetage courant. En fait, les instructions suivantes ont (quasiment) le mme effet :
*sym = *main::variable; *sym = $main::{"variable"};

La premire est plus efficace car on accde la table de symboles main au moment de la compilation. Elle crera aussi un nouveau typeglob de ce nom sil nen existait pas prcdemment, alors que la deuxime version ne le fera pas. Puisquun paquetage est un hachage, vous pouvez rechercher les clefs du paquetage et rcuprer toutes les variables du paquetage. Puisque les valeurs du hachage sont des typeglobs, vous pouvez les drfrencer de diverses faons. Essayez ceci :
foreach $nomsym (sort keys %main::) { local *sym = $main::{$nomsym}; print "\$$nomsym est dfini\n" if defined $sym; print "\@$nomsym is non nul\n" if @sym; print "\%$nomsym is non nul\n" if %sym; }

Puisque tous les paquetages sont accessibles (directement ou indirectement) par le paquetage main, vous pouvez crire du code Perl pour visiter chaque variable de paquetage de votre programme. Cest prcisment ce que fait le dbogueur Perl lorsque vous lui demandez dafficher toutes vos variables avec la commande V Notez que si vous faites . cela, vous ne verrez pas les variables dclares avec my, puisquelles sont indpendantes des paquetages, bien que vous verrez les variables dclares avec our. Voir le chapitre 20, Le dbogueur Perl. Prcdemment nous avons dit que seuls les identificateurs taient rangs dans des paquetages autres que main. Ctait un tout petit mensonge : vous pouvez utiliser la chane que vous voulez comme clef dans le hachage de la table de symboles mais a ne serait pas du Perl valide si vous essayiez dutiliser un non-identificateur directement :
$!@#$% ${!@#$%} = 0; = 1; # FAUX, erreur de syntaxe. # Ok, mais non qualifi. # On peut qualifier dans la chane # Ok, imprime 2!

${main::!@#$%} = 2; print ${ $main::{!@#$%} } *dick = *richard;

Les typeglobs servent essentiellement dalias : rend les variables, fonctions, formats, et handles de fichiers et rpertoires accessibles par lidentificateur richard galement accessibles par lidentificateur dick. Si vous ne souhaitez affecter un alias qu une seule variable ou fonction, affectez plutt la rfrence :
*dick = \$richard;

Ce qui fait que $richard et $dick sont littralement la mme variable, mais que @richard et @dick restent des tableaux diffrents. Rus, non ?

customer_8566

Tables de symboles

271

Cest ainsi que fonctionne le paquetage Exporter lorsque lon importe des variables dun paquetage vers un autre. Par exemple :
*UnPack::dick = \&AutrePack::richard;

importe la fonction &richard du paquetage AutrePack dans le paquetage UnPack, le rendant disponible comme fonction &dick. (Le module Exporter sera dcrit dans le prochain chapitre.) Si vous prcdez laffectation avec un local, lalias ne durera que le temps de la porte dynamique courante. Ce mcanisme peut tre utilis pour rcuprer une rfrence partir dune fonction, rendant le rfrent disponible avec le type de donnes appropri :
*unites = renseigner() ; print $unites{kg}; # Affecter \%nouveau_hachage au typeglob # Affiche 70; pas ncessaire de drfrencer!

sub renseigner { my %nouveau_hachage = (km => 10, kg => 70); return \%nouveau_hachage; }

De mme, vous pouvez passer une rfrence une fonction et lutiliser sans la drfrencer :
%unites = (kilometres => 6, kilos => 11); faireleplein( \%unites ); # Passer une rfrence print $unites{litres}; # Affiche 4 sub faireleplein { local *hashsym = shift; $hashsym{litres} = 4; }

# Affecter \%unites au typeglob # Modifie %unites; pas ncessaire # de drfrencer !

Ce sont des moyens astucieux de manipuler des rfrences quand vous ne voulez pas devoir les drfrencer explicitement. Notez que les deux techniques ne fonctionnent quavec des variables de paquetage. Elles ne marcheraient pas si on avait dclar %unites avec my. Les tables de symboles sutilisent aussi pour crer des scalaires constants :
*PI = \3.14159265358979;

Il vous est maintenant impossible daltrer $PI, ce qui probablement une bonne chose, somme toute. Ceci nest pas pareil quune fonction constante, qui est optimise la compilation. Une fonction constante est une fonction dont le prototype indique quelle ne prend pas de paramtres et quelle retourne une expression constante ; voir pour plus de dtails la section Substitution en ligne de fonctions constantes, chapitre 6, Sous-programmes. Le pragma use constant est un raccourci commode :
use constant PI => 3.14159;

Sous le capot, ceci utilise la case fonction de *PI, plutt que la case scalaire utilise ci-dessus. Lexpression suivante, plus compacte (mais moins lisible), est quivalente :
*PI = sub () { 3.14159 };

customer_8566

272

Chapitre 10 Paquetages

En tout cas cest un idiome pratique connatre. Affecter un sub {} un typeglob permet de donner un nom une fonction anonyme lors de lexcution. Affecter une rfrence un typeglob un autre typeglob (*sym = \*oldvar) revient affecter the typeglob en entier, car Perl drfrence automatiquement la rfrence au typeglob votre place. Lorsque vous affectez simplement une chane une typeglob, vous obtenez le typeglob entier nomm par cette chane, car Perl va chercher la chane dans la table de symboles courante. Les instructions suivantes sont toutes quivalentes entre elles, bien que les deux premires sont calcules la compilation, alors que les deux dernires le sont lexcution :
*sym *sym *sym *sym = *anciennevar; = \*anciennevar; # drfrence auto = \*{"anciennevar"}; # recherche explicite dans la table de symboles = "anciennevar"; # recherche implicite dans la table de symboles

Lorsque vous faites lune des affectations suivantes, vous ne faites que remplacer lune des rfrences lintrieur du typeglob :
*sym *sym *sym *sym = = = = \$frodon; \@sam; \%merry; \&pippin;

Dun autre point de vue, le typeglob lui-mme peut tre considr comme une espce de hachage, incluant des entres pour les diffrents types de variables. Dans ce cas, les clefs sont fixes, puisquun typeglob contient exactement un scalaire, un tableau, un hachage, et ainsi de suite. Mais vous pouvez extraire les rfrences individuelles, comme ceci :
*pkg::sym{SCALAR} *pkg::sym{ARRAY} *pkg::sym{HASH} *pkg::sym{CODE} *pkg::sym{GLOB} *pkg::sym{IO} *pkg::sym{NAME} *pkg::sym{PACKAGE} # # # # # # # # pareil que \$pkg::sym pareil que \@pkg::sym pareil que \%pkg::sym pareil que \&pkg::sym pareil que \*pkg::sym handle de fichier/rp interne, pas dquivalent direct "sym" (pas une rfrence) "pkg" (pas une rfrence)

Vous pouvez dire *foo{PACKAGE} et *foo{NAME} pour dterminer de quel nom et et de quel paquetage provient lentre *foo dune table de symboles. Ceci peut tre utile dans une fonction laquelle des typeglobs sont passs en paramtres :
sub identifier_typeglob { my $glob = shift; print Vous mavez donn , *{$glob}{PACKAGE}, ::, *{$glob}{NAME}, "\n" } identifier_typeglob(*foo); identifier_typeglob(*bar::glarch);

Ceci affiche :
Vous mavez donn main::foo Vous mavez donn bar::glarch

customer_8566

Autochargement

273

La notation *foo{TRUC} peut tre utilise pour obtenir des rfrences aux lments individuels de *foo. Voir pour plus de dtails la section Rfrences de table de symboles, chapitre 8. Cette syntaxe est principalement utilise pour accder au handle de fichier ou de rpertoire interne, car les autres rfrences internes sont dj accessibles dautres faons. (Lancien *foo{FILEHANDLE} reste support et signifie *foo{IO}, mais ne laissez pas son nom vous faire croire quil peut distinguer entre des handles de fichier et de rpertoire.) Nous avons pens gnraliser cela parce que quelque part, cest joli. Quelque part. Vous navez probablement pas vous souvenir de tout cela sauf si vous avez lintention dcrire un autre dbogueur de Perl.

Autochargement
Normalement, vous ne pouvez pas appeler une fonction non dfinie. Cependant, sil y a une fonction nomme AUTOLOAD dans le paquetage de la fonction non dfinie (ou dans le cas dune mthode dobjet, dans le paquetage de lune quelconque des classes de base de lobjet), alors la fonction AUTOLOAD est appele avec les mmes paramtres qui seraient passs la fonction dorigine. Vous pouvez dfinir la fonction AUTOLOAD pour quelle retourne des valeurs exactement comme une fonction normale, ou vous pouvez dfinir la fonction qui nexistait pas et ensuite lappeler comme si elle avait exist tout du long. Le nom pleinement qualifi de la fonction dorigine apparat magiquement dans la variable globale au paquetage $AUTOLOAD, dans le mme paquetage que la fonction AUTOLOAD. Voici un exemple simple qui vous avertit gentiment lors des appels de fonctions non dfinies, au lieu darrter le programme.
sub AUTOLOAD { our $AUTOLOAD; warn "la tentative dappeler $AUTOLOAD a chou.\n"; } blarg(10); # notre $AUTOLOAD aura la valeur to main::blarg print "Encore vivant!\n"

Ou vous pouvez retourner une valeur pour le compte de la fonction non dfinie :
sub AUTOLOAD { our $AUTOLOAD; return "Je vois $AUTOLOAD(@_)\n"; } print blarg(20); # affiche: Je vois main::blarg(20)

Votre fonction AUTOLOAD pourrait charger une dfinition de la fonction non dfinie en utilisant eval ou require, ou utiliser lastuce daffectation au glob discute prcdemment, puis excuter cette fonction en utilisant une forme spciale du goto qui peut effacer le stack frame de la fonction sans laisser de trace. Ici nous dfinissons la fonction en affectant une fermeture au glob :
sub AUTOLOAD { my $nom = our $AUTOLOAD;

customer_8566

274

Chapitre 10 Paquetages
*$AUTOLOAD = sub { print "Je vois $nom(@_)\n" }; goto &$AUTOLOAD; # Redmarrer la nouvelle fonction

} blarg(30); glarb(40); blarg(50);

# affiche : je vois main::blarg(30) # affiche : je vois main::glarb(40) # affiche : je vois main::blarg(50)

Le module standard AutoSplit est utilis par les crateurs de modules pour les aider diviser leurs modules en plusieurs fichiers (avec des noms de fichier se terminant avec .al), chacun contenant une fonction. Les fichiers sont placs dans le rpertoire auto/ de la bibliothque Perl de votre systme, aprs quoi les fichiers peuvent tre autochargs par le module standard AutoLoader. Une approche similaire est utilise par le module SelfLoader, mis part quil autocharge des fonctions partir de la zone DATA du fichier lui-mme, ce qui est moins efficace certains gards, et plus efficace dautres. Lautochargement de fonctions Perl par AutoLoader et SelfLoader est analoque au chargement dynamique de fonctions C compiles par DynaLoader, mais lautochargement est fait avec la granularit dun appel de fonction, alors que le chargement dynamique est fait avec la granularit dun module entier, et liera en gnral un grand nombre de fonction C ou C++ la fois. (Notez que beaucoup de programmeurs Perl se dbrouillent trs bien sans les modules AutoSplit, AutoLoader, SelfLoader, or DynaLoader. Il faut juste que vous sachiez quils sont l, au cas o vous ne pourriez pas vous dbrouiller sans eux.) On peut samuser avec des fonctions AUTOLOAD qui servent demballage pour dautres interfaces. Par exemple, faisons semblant quune fonction qui nest pas dfinie doive juste appeler system avec ses paramtres. Tout ce que vous auriez faire est ceci :
sub AUTOLOAD { my $programme = our $AUTOLOAD; $programme =~ s/.*:://; # enlever le nom du paquetage system($programme, @_); }

(Flicitations, vous venez dimplmenter une forme rudimentaire du module Shell qui vient en standard avec Perl.) Vous pouvez appeler votre autochargeur (sur Unix) ainsi :
date(); who(am, i); ls(-l); echo("Ga bu zo meu...");

En fait, si vous prdclarez les fonctions que vous voulez appeler de cette faon, vous pouvez procder comme si elles taient pr-construites dans le langage et omettre les parenthses lors de lappel :
sub sub sub sub date (;$$); who (;$$$$); ls; echo ($@); # # # # Permettre Permettre Permettre Permettre de de un au zro deux paramtres. zro quatre paramtres. nombre quelconque de paramtres. moins un paramtre.

date; who "am", "i"; ls "-l"; echo "Cest tout pour aujourdhui !";

customer_8566

11

Modules

Le module est lunit fondamentale de rutilisation de Perl. bien le regarder, un module nest quun paquetage dfini dans un fichier de mme nom (avec .pm la fin). Dans ce chapitre, nous allons explorer comment utiliser les modules des autres et crer les siens. Perl inclut en standard un grand nombre de modules, que vous pouvez trouver dans le rpertoire lib de votre distribution Perl. Beaucoup de ces modules sont dcrits au chapitre 32, Modules standards, et au chapitre 31, Modules de pragmas. Tous les modules standard ont aussi une documentation dtaille en ligne, qui peut (scandale !) tre plus jour que ce livre. Essayez la commande perldoc si votre commande man ne fonctionne pas. Le Comprehensive Perl Archive Network (CPAN) contient un dpt de modules aliment par la communaut Perl mondiale, et est prsent au chapitre 22, CPAN. Voir aussi http://www.cpan.org.

Utilisation des modules


Il y a deux sortes de modules : traditionnel et orient objet. Les modules traditionnels dfinissent des fonctions et des variables destines tre importes et utilises par un programme qui y fait appel. Les modules orients objet fonctionnent comme des dfinitions de classe auxquelles on accde par des appels de mthodes, dcrites au chapitre 12, Objets. Certains modules font les deux. Les modules Perl sont habituellement inclus dans votre programme en crivant :
use MODULE LISTE;

ou simplement :
use MODULE;

MODULE doit tre un identificateur qui nomme le paquetage et le fichier du module. (Les descriptions de syntaxe ne sont donnes ici qu titre indicatif, car la syntaxe complte de linstruction use est dtaille au chapitre 29, Fonctions.)

customer_8566

276

Chapitre 11 Modules

Linstruction use prcharge MODULE au moment de la compilation, puis importe les symboles que vous avez demands pour quils soient disponibles pour le reste de la compilation. Si vous ne fournissez pas une LISTE des symboles que vous voulez, les symboles nomms dans le tableau @EXPORT interne au module sont utiliss en supposant que vous utilisez le module Exporter, dcrit plus loin dans ce chapitre sous Espace priv de module et Exporter . (Si vous fournissez une LISTE, tous vos symboles doivent tre mentionns, soit dans le tableau @EXPORT, soit dans le tableau @EXPORT_OK, faute de quoi une erreur en rsultera.) Puisque les modules utilisent Exporter pour importer des symboles dans le paquetage courant, vous pouvez utiliser les symboles dun module sans les qualifier avec le nom du paquetage :
use Fred; pierrafeu(); # Si Fred.pm contient @EXPORT = qw(pierrafeu) # ...ceci appelle Fred::pierrafeu().

Tous les fichiers de module Perl ont lextension .pm. Ceci (ainsi que les doubles apostrophes) est pris en compte par use ainsi que par require afin que vous nayez pas crire "MODULE.pm". Cette convention permet de diffrencier les nouveaux modules des bibliothques .pl et .ph utilises dans danciennes versions de Perl. Elle dfinit aussi MODULE comme nom officiel de module, ce qui aide lanalyseur dans certaines situations ambigus. Tout double deux-points dans le nom de module est traduit comme le sparateur de rpertoires de votre systme, de sorte que si votre module a pour nom Rouge::Bleu::Vert, Perl pourrait le chercher sous Rouge/Bleu/Vert.pm. Perl ira chercher vos modules dans tous les rpertoires lists dans le tableau @INC. Comme use charge les modules au moment de la compilation, toutes modifications au tableau @INC doivent aussi survenir au moment de la compilation. Vous pouvez faire cela avec le pragma lib, dcrit au chapitre 31 ou avec un bloc BEGIN. Une fois quun module est inclus, un couple clef/valeur sera ajout au hachage %INC. La clef sera le nom de fichier du module (Rouge/Bleu/Vert.pm dans notre exemple) et la valeur sera le chemin complet, qui pourrait tre quelque chose comme C:/perl/site/lib/Rouge/Bleu/Vert.pm pour un fichier convenablement install sur un systme Windows. Les noms de module doivent commencer avec une lettre majuscule, sauf sils fonctionnent comme pragmas. Les pragmas sont essentiellement des directives de compilation (des conseils pour le compilateur), donc nous rservons les noms de pragma en minuscules pour un usage ultrieur. Lorsque vous utilisez un module avec use, tout le code du module est excut, tout comme il le serait avec un require ordinaire. Sil vous est gal que le module soit pris en compte la compilation ou lexcution, vous pouvez juste dire :
require MODULE;

Cependant, en gnral on prfre use plutt que require, car il recherche les modules la compilation, donc vous dcouvrez les erreurs ventuelles plus tt. Ces deux instructions font presque la mme chose :
require MODULE; require "MODULE.pm";

Elles diffrent nanmoins de deux faons. Dans la premire instruction, require traduit

customer_8566

Cration de modules

277

tout double deux-points en sparateur de rpertoire de votre systme, tout comme le fait use. La deuxime instruction ne fait pas de traduction, vous obligeant spcifier explicitement le chemin de votre module, ce qui est moins portable. Lautre diffrence est que le premier require indique au compilateur que les expressions utilisant la notation objet indirecte avec MODULE (comme $ob = purgeMODULE) sont des appels de mthode, pas des appels de fonction. (Si, a peut rellement faire une diffrence, sil y a une dfinition purge dans votre module qui entre en conf lit avec une autre.) Comme la dclaration use et la dclaration apparente no impliquent un bloc BEGIN, le compilateur charge le module (et excute son ventuel code dinitialisation) ds quil rencontre cette dclaration, avant de compiler le reste du fichier. Cest ainsi que les pragmas peuvent modifier le comportement du compilateur, et que les modules peuvent dclarer des fonctions qui sont par la suite visibles comme oprateurs de liste pour le reste de la compilation. Ceci ne marchera pas si vous utilisez un require la place dun use. La seule raison dutiliser un require est davoir deux modules dont chacun ncessite une fonction de lautre. (Et nous ne sommes pas srs que ce soit une bonne raison.) Les modules Perl chargent toujours un fichier .pm, mais ce fichier peut son tour charger des fichiers associs, comme des bibliothques C ou C++ lies dynamiquement, ou des dfinitions de fonction Perl autocharges. Dans ce cas, les complications supplmentaires seront entirement invisibles pour lutilisateur du module. Cest la responsabilit du fichier .pm de charger (ou de sarranger pour autocharger) toute fonctionnalit supplmentaire. Il se trouve que le module POSIX fait du chargement dynamique et de lautochargement, mais lutilisateur peut simplement dire :
use POSIX;

pour avoir accs toutes les fonctions et variables exportes.

Cration de modules
Prcdemment, nous avons dit quun module a deux faons de mettre son interface la disposition de votre programme : en exportant des symboles ou en permettant des appels de fonction. Nous vous montrerons un exemple de la premire technique ici ; la deuxime technique est utilise pour les modules orients objet, et est dcrite dans le prochain chapitre. (Les modules orients objet ne devraient rien exporter, car les mthodes objet ont pour principe que Perl les trouve automatiquement votre place en se basant sur le type de lobjet.) Pour construire un module appel Bestiaire, crez un fichier appel Bestiaire.pm qui ressemble ceci :
package require our our our our Bestiaire; Exporter; = = = = qw(Exporter); qw(dromadaire); qw($poids); 1.00;

@ISA @EXPORT @EXPORT_OK $VERSION

# Symboles exporter par dfaut # Symboles exporter la demande # Numro de version

### Mettez vos variables et vos fonctions ici

customer_8566

278
sub dromadaire { print "Chameau une seule bosse" } $poids = 1024; 1;

Chapitre 11 Modules

Maintenant un programme peut dire use Bestiaire pour pouvoir accder la fonction dromadaire (mais pas la variable $poids), et use Bestiaire qw(dromadaire $poids) pour accder la fois la fonction et la variable. Vous pouvez galement crer des modules qui chargent dynamiquement du code crit en C. Voir le chapitre 21, Mcanismes internes et accs externes, pour plus de dtails.

Espace priv de module et Exporter


Perl ne patrouille pas automatiquement le long de frontires entre le priv et le public dans ses modules ontrairement des langages comme C++, Java et Ada, Perl nest pas obsd par le droit la vie prive. Un module Perl prfrerait que vous restiez hors de son salon parce que vous ny avez pas t invit, pas parce quil a un fusil. Le module et son utilisateur ont un contrat, dont une partie se base sur la loi coutumire, et dont lautre est crite. Une partie du contrat de loi coutumire est quun module doit sabstenir de modifier tout espace de noms quon ne lui a pas demand de modifier. Le contrat crit du module (cest--dire la documentation) peut prendre dautres dispositions. Mais vous savez sans doute, aprs avoir lu le contrat, que quand vous dites use RedefinirLeMonde vous redfinissez le monde, et vous tes prt en risquer les consquences. La faon la plus commune de redfinir des mondes est dutiliser le module Exporter. Comme nous le verrons plus loin dans ce chapitre, vous pouvez mme redfinir des fonctions Perl de base avec ce module. Lorsque vous faites appel un module avec use, le module met habituellement certaines fonctions et variables la disposition de votre programme, ou plus prcisment du paquetage courant de votre programme. Cet acte dexportation de symboles du module (et donc dimportation dans votre programme) est parfois appel pollution de votre espace de noms. La plupart des modules utilisent Exporter pour faire cela. Cest pourquoi la plupart des modules disent quelque chose comme ceci vers le dbut :
require Exporter; our @ISA = ("Exporter");

Ces deux lignes font hriter au module de la classe Exporter. Lhritage est dcrit au prochain chapitre, mais tout ce que vous avez besoin de savoir cest que notre module Bestiaire peut maintenant exporter des symboles dans dautres paquetages avec des lignes comme celle-ci :
our @EXPORT = qw($chameau %loup belier); # Exporter par dfaut our @EXPORT_OK = qw(leopard @lama $emeu); # Exporter la demande our %EXPORT_TAGS = ( # Exporter en groupe camelides => [qw($chameau @lama)], bestiaux => [qw(belier $chameau %loup)], );

Du point de vue du module qui exporte, le tableau @EXPORT contient les noms de varia-

customer_8566

Cration de modules

279

bles et de fonctions exporter par dfaut : ce quobtient votre programme lorsquil dit use Bestiaire. Les variables et les fonctions dans @EXPORT_OK ne sont exportes que lorsque le programme en fait explicitement la demande dans linstruction use. Enfin, les couples clef/valeur dans %EXPORT_TAGS permettent au programme dinclure des groupes de symboles spcifiques, lists dans @EXPORT et @EXPORT_OK. Du point de vue du module qui importe, linstruction use spcifie la liste des symboles importer, un groupe nomm %EXPORT_TAGS, un motif de symboles, ou rien du tout, auquel cas les symboles dans @EXPORT seront imports du module dans votre programme. Vous pouvez inclure lune quelconque de ces instructions pour importer des symboles du module Bestiaire :
use Bestiaire; # Importer les symboles de @EXPORT use Bestiaire (); # Ne rien importer use Bestiaire qw(belier @lama); # Importer la fonction belier et le # tableau @lama use Bestiaire qw(:camelides); # Importer $chameau et @lama use Bestiaire qw(:DEFAULT); # Importer les symboles de @EXPORT use Bestiaire qw(/am/); # Importer $chameau et @lama use Bestiaire qw(/^\$/); # Importer tous les scalaires use Bestiaire qw(:bestiaux !belier); # Importer bestiaux, mais exclure belier use Bestiaire qw(:bestiaux !:camelides); # Importer bestiaux, mais pas camelides

Omettre un symbole des listes dexportation (ou le supprimer explicitement de la liste dimport avec le point dexclamation) ne le rend pas inaccessible pour le programme qui utilise le module. Le programme pourra toujours accder au contenu du paquetage du module en le qualifiant avec le nom du paquetage, comme par exemple %Bestiaire::gecko. (Comme les variables lexicales nappartiennent pas au paquetage, lespace priv est possible : voir Mthodes prives au chapitre suivant.) Vous pouvez dire BEGIN { $Exporter::Verbose=1 } pour voir comment sont gres les spcifications et pour voir ce qui est rellement import dans votre paquetage. Exporter est lui-mme un module Perl, et si cela vous intresse vous pouvez voir les astuces typeglob qui sont utilises pour exporter des symboles dun paquetage un autre. lintrieur du module Exporter, la fonction essentielle, appele import, cre les alias ncessaires pour quun symbole dun paquetage soit visible dans un autre paquetage. En fait, linstruction use BestiaireLISTE est prcisment quivalente :
BEGIN { require Bestiaire; import Bestiaire LISTE; }

Cela veut dire que vos modules ne sont pas obligs dutiliser Exporter. Un module peut faire ce qui lui plat, puisque use ne fait quappeler la mthode import du module, et vous pouvez dfinir cette mthode pour quelle fasse ce que vous voulez.

customer_8566

280

Chapitre 11 Modules

Exporter sans utiliser la mthode import de Exporter


Le module Exporter dfinit une mthode appele export_to_level pour les situations o vous ne pouvez pas directement appeler la mthode import de Exporter. La mthode export_to_level est invoque comme ceci : MODULE->export_to_level($ou_exporter, @quoi_exporter); Lentier $ou_exporter indique quelle hauteur dans la pile dappel exporter vos symboles, et le tableau $quoi_exporter liste les symboles exporter (habituellement @_). Par exemple, supposons que notre Bestiaire contienne sa propre fonction import :
package Bestiaire; @ISA = qw(Exporter); @EXPORT_OK = qw ($zoo); sub import { $Bestiaire::zoo = "mnagerie"; }

La prsence de cette fonction import empche dhriter de la fonction import de Exporter. Si vous vouliez quaprs avoir affect $Bestiaire::zoo, la fonction import de Bestiaire se comporte exactement comme la fonction import de Exporter, vous la dfiniriez de la faon suivante :
sub import { $Bestiaire::zoo = "mnagerie"; Bestiaire->export_to_level(1, @_); }

Ceci exporte des symboles vers le paquetage situ un niveau au-dessus du paquetage courant, cest--dire vers tout programme ou module qui utilise Bestiaire.

Vrification de version
Si votre module dfinit une variable $VERSION, un programme qui utilise votre module peut sassurer que le module est suffisamment rcent. Par exemple :
use Bestiaire 3.14; # Le Bestiaire doit tre de version 3.14 ou plus use Bestiaire v1.0.4; # Le Bestiaire doit tre de version 1.0.4 ou plus

Ces instructions sont converties en appels Bestiaire->require_version, dont hrite ensuite votre module.

Gestion de symboles inconnus


Dans certaines situations, vous voudrez peut-tre empcher lexportation de certains symboles. Typiquement, cest le cas de certains modules qui ont des fonctions ou des constantes qui nont pas de sens sur certains systmes. Vous pouvez empcher Exporter dexporter ces symboles en les plaant dans le tableau @EXPORT_FAIL. Si un programme tente dimporter lun de ces symboles, Exporter permet au module de grer la situation avant de produire une erreur. Il le fait en appelant une mthode export_fail avec une liste des symboles qui ont chou, que vous pouvez dfinir ainsi (en supposant que votre module utilise le module Carp) :

customer_8566

Supplanter des fonctions internes


sub export_fail { my $class = shift; carp "Dsol, ces symboles ne sont pas disponibles : @_"; return @_; }

281

Exporter fournit une mthode export_fail par dfaut, qui retourne simplement la liste inchange et fait chouer le use en levant une exception pour chaque symbole. Si export_fail retourne une liste vide, aucune erreur nest enregistre et tous les symboles demands sont exports.

Fonctions de gestion des tiquettes


Comme les symboles lists dans %EXPORT_TAGS doivent galement apparatre, soit dans @EXPORT, soit dans @EXPORT_OK, Exporter fournit deux fonctions qui vous permettent dajouter ces ensembles de symboles tiquets.
%EXPORT_TAGS = (foo => [qw(aa bb cc)], bar => [qw(aa cc dd)]); Exporter::export_tags(foo); Exporter::export_ok_tags(bar); # ajouter aa, bb et cc @EXPORT # ajouter aa, cc et dd @EXPORT_OK

Cest une erreur de spcifier des noms qui ne sont pas des tiquettes.

Supplanter des fonctions internes


De nombreuses fonctions internes peuvent tre supplantes, bien que (comme pour faire des trous dans vos murs) vous ne devriez faire cela que rarement et pour de bonnes raisons. Typiquement, ce serait fait par un paquetage qui tente dmuler des fonctions internes manquantes sur un systme autre quUnix. (Ne confondez pas supplanter avec surcharger, qui ajoute des significations orientes objet supplmentaires aux oprateurs internes, mais ne supplante pas grand chose. Le module overload dans le chapitre 13, Surcharge, donne plus de dtails sur ce sujet.) On ne peut supplanter quen important le nom dun module ; la prdclaration ordinaire ne suffit pas. Pour tre parfaitement francs, cest laffectation dune rfrence de code un typeglob qui permet Perl de supplanter, comme dans *open = \&myopen. De plus, laffectation doit survenir dans un autre paquetage ; ceci rend intentionnellement difficile de supplanter accidentellement par alias de typeglob. Malgr tout, si vous voulez vraiment supplanter vous-mme, ne dsesprez pas, car le pragma subs vout permet de prdclarer des fonctions avec la syntaxe dimportation, et ces noms supplantent alors ceux qui existent en interne :
use subs qw(chdir chroot chmod chown); chdir $quelque_part sub chdir { ... }

En gnral, les modules ne doivent pas exporter des noms internes comme open ou chdir comme partie de leur liste @EXPORT par dfaut, puisque ces noms pourraient se glisser dans lespace de noms de quelquun dautre et en changer le contenu de faon inattendue. Si au lieu de cela le module inclut le nom dans la liste @EXPORT_OK, les importateurs seront obligs de demander explicitement que le nom interne soit supplant, vitant ainsi les surprises.

customer_8566

282

Chapitre 11 Modules

La version dorigine des fonctions internes est toujours accessible via le pseudo-paquetage CORE. En consquence, CORE::chdir sera toujours la version compile dorigine dans Perl, mme si le mot-clef chdir a t supplant. Enfin, presque toujours. Le mcanisme dcrit ci-dessus pour supplanter les fonctions internes est restreint, trs dlibrment, au paquetage qui fait la demande dimportation. Mais il existe un mcanisme plus radical que vous pouvez utiliser lorsque vous souhaitez supplanter une fonction interne partout, sans prendre en compte les frontires despaces de noms. Ceci est accompli en dfinissant la fonction dans le pseudo-paquetage CORE::GLOBAL. Voyez ci-dessous un exemple qui supplante loprateur glob avec quelque chose qui comprend les expressions rationnelles. (Notez que cet exemple nimplmente pas tout ce qui est ncessaire pour supplanter proprement le glob interne de Perl, qui se comporte diffremment selon quil apparat dans un contexte scalaire ou un contexte de liste. En vrit, de nombreuses fonctions internes de Perl ont de tels comportements sensibles au contexte, et tout fonction visant les correctement supplanter une fonction interne doit grer adquatement ces comportements. Pour voir un exemple compltement fonctionnel o glob est supplant, tudiez le module File::Glob inclus avec Perl.) En tout cas, voici la version anti-sociale :
*CORE::GLOBAL::glob = sub { my $motif = shift; my @trouve; local *D; if (opendir D, .) { @trouve = grep /$motif/, readdir D; closedir D; } return @trouve; } package Quelconque; print <^[a-z_]+\.pm\$>; # montrer tous les pragmas dans le rpertoire courant

En supplantant glob globalement, ceci impose un nouveau (et subversif) comportement pour loprateur glob dans tous les espaces de noms, sans la connaissance ou la coopration des modules popritaires de ces espaces de noms. Bien sr, sil faut faire cela, il faut le faire avec la plus extrme prudence. Et probablement il ne faut pas le faire. Nous supplantons avec le principe suivant : cest sympa dtre important, mais cest plus important dtre sympa.

customer_8566

12
Bref rappel de vocabulaire orient objet

Objets

Pour commencer, vous devez comprendre les paquetages et les modules ; voir le chapitre 10, Paquetages, et le chapitre 11, Modules. Vous devez aussi connatre les rfrences et les structures de donnes ; voir le chapitre 8, Rfrences, et le chapitre 9, Structures de donnes. Comme il est utile de sy connatre un peu en programmation oriente objet, nous vous donnerons un petit cours de vocabulaire orient objet dans la section suivante.

Un objet est une structure de donnes munie dune collection de comportements. Nous dirons parfois quun objet agit directement sur la base de comportements, allant parfois jusqu lanthropomorphisme. Par exemple, nous dirons quun rectangle sait comment safficher lcran ou quil sait comment calculer sa propre surface. Un objet exhibe des comportements en tant une instance dune classe. La classe dfinit des mthodes : des comportements qui sappliquent la classe et ses instances. Lorsquil faut faire la distinction, nous appelons mthode dinstance une mthode qui ne sapplique qu un objet donn et mthode de classe une mthode qui sapplique la classe dans son entier. Mais ce nest quune convention : pour Perl, une mthode nest quune mthode qui ne se distingue que par le type de son premier argument. Vous pouvez considrer quune mthode dinstance est une action excute par un objet donn, comme laction de safficher, de se copier ou de modifier une ou plusieurs de ses proprits ( affecter Anduril au nom de cette pe ). Les mthodes de classe peuvent excuter des oprations sur un ensemble dobjets ( afficher toutes les pes ) ou fournir dautres oprations qui ne dpendent pas dun objet particulier ( partir de maintenant, chaque fois quune nouvelle pe est forge, enregistrer dans cette base de donnes le nom de son propritaire ). Les mthodes qui produisent des instances (ou objets) dune classe sont appeles constructeurs ( crer une pe incruste de pierres prcieuses et avec une inscription secrte ). Celles-ci sont en gnral des mthodes de classe ( fais-moi une nouvelle pe ), mais elles peuvent aussi tre des mthodes dinstance ( fais-moi une copie exacte de cette pe-ci ).

customer_8566

284

Chapitre 12 Objets

Une classe peut hriter des mthodes de classes parentes, appeles aussi classes de base ou surclasses. Dans ce cas, on lappelle classe drive ou sous-classe. (Brouillant un peu les cartes, certains livres entendent par classe de base la surclasse racine , mais ce nest pas ce que nous voulons dire.) Lorsque vous invoquez une mthode dont la dfinition ne se trouve pas dans la classe, Perl consulte automatiquement les classes parentes pour chercher une dfinition. Par exemple, une classe pe pourrait hriter sa mthode attaquer dune classe gnrique arme destoc et de taille . Les classes parentes peuvent elles-mmes avoir des classes parentes, et Perl examinera galement ces classes si besoin est. La classe arme destoc et de taille peut son tour hriter la mthode attaquer dune classe encore plus gnrique arme . Lorsque la mthode attaquer est invoque sur un objet, le comportement rsultant peut varier, selon que lobjet est une pe ou une f lche. Il se peut quil ny ait aucune diffrence, ce qui serait le cas si les pes et les f lches hritaient leur comportement dattaque de la classe arme gnrique. Mais sil y avait une diffrence de comportement, le mcanisme dacheminement de mthode slectionnerait toujours la mthode attaquer la plus approprie pour le type dobjet donn. Cette proprit fort utile de slection du comportement le plus appropri pour un type donn dobjet sappelle le polymorphisme. Cest une faon importante de ne se soucier de rien. Vous devez vous soucier des entrailles de vos objets lorsque vous implmentez une classe, mais lorsque vous utilisez une classe (avec use), vous devriez traiter vos objets comme des botes noires . Vous ne voyez pas ce quil y a lintrieur, vous navez pas besoin de savoir comment a marche, et vous interagissez avec la bote sur ses termes : par les mthodes fournies par la classe. Cest comme la tlcommande de votre tlviseur : mme si vous savez ce qui se passe dedans, vous ne devriez pas sans bonne raison trifouiller dans ses entrailles. Perl vous permet de scruter lintrieur dun objet de lextrieur de la classe lorsque vous en avez besoin. Mais de faire ainsi enfreint lencapsulation, le principe qui spare linterface publique (comment un objet doit tre utilis) de limplmentation (comment lobjet fonctionne en ralit). Perl ne fournit pas un dispositif dinterface explicite, mis part le contrat implicite entre le concepteur et lutilisateur. Lun et lautre sont censs tre raisonnables et respectueux : lutilisateur en ne dpendant que de linterface documente, le concepteur en prservant cette interface. Perl ne vous impose pas un style de programmation particulier, et ne partage pas lobsession avec la vie prive dautres langages de programmation oriente objet. Nanmoins Perl a lobsession de la libert, et lune de vos liberts en tant que programmeur Perl est le droit de choisir si vous voulez beaucoup ou peu de vie prive. En fait, Perl permet un espace priv plus restrictif encore que C++. Cest--dire quil ny a rien que Perl vous empche de faire, et en particulier il ne vous empche pas de vous empcher vous-mme, si ce genre de choses vous intresse. Les sections Mthodes prives et Utilisation de fermetures pour objets privs de ce chapitre vous montrent comment vous pouvez augmenter votre dose de discipline. Reconnaissons quil y a beaucoup plus dire sur les objets, et beaucoup de faons den apprendre plus sur la conception oriente objet. Mais ce nest pas notre propos. Continuons donc.

customer_8566

Le systme objet de Perl

285

Le systme objet de Perl


Perl ne fournit pas de syntaxe objet particulire pour dfinir les objets, les classes ou les mthodes. Au lieu de cela, il rutilise des constructions existantes pour implmenter ces trois notions.1 Voici quelques dfinitions simples que vous trouverez peut-tre rassurantes : Un objet nest quune rfrence... enfin, un rfrent. Comme une rfrence permet de reprsenter une collection de donnes avec un seul scalaire, il ne devrait pas tre surprenant quon utilise les rfrences pour tous les objets. Pour tre prcis, un objet nest pas la rfrence elle-mme, mais plutt le rfrent sur lequel pointe la rfrence. Toutefois cette distinction est souvent brouille par les programmeurs Perl, et comme nous trouvons que cest une jolie mtonymie, nous la perptuons ici lorsque cela nous arrange.2 Une classe nest quun paquetage. Un paquetage agit comme une classe en utilisant les fonctions du paquetage pour excuter les mthodes de la classe et en utilisant les variables du paquetage pour contenir les donnes globales de la classe. Souvent, on utilise un module pour contenir une ou plusieurs classes. Une mthode nest quune fonction. Vous dclarez simplement des fonctions dans le paquetage que vous utilisez comme classe ; celles-ci seront ensuite utilises comme mthodes de la classe. Linvocation de mthode, une nouvelle faon dappeler une fonction, ajoute un paramtre supplmentaire : lobjet ou le paquetage utilis pour invoquer la mthode.

Invocation de mthode
Si vous aviez rduire toute la programmation oriente objet une notion essentielle, ce serait labstraction. Cest le fil conducteur de tous ces mots ronf lants quaiment employer les enthousiastes OO, comme le polymorphisme, lhritage et lencapsulation. Nous croyons en ces mots savants, mais nous les traiterons du point de vue pratique de ce que signifie invoquer des mthodes. Les mthodes sont au cur des systmes objet parce quelles fournissent la couche dabstraction ncessaire limplmentation de ces termes savants. Au lieu daccder directement une donne rsidant dans un objet, vous invoquez une mthode dinstance. Au lieu dappeler directement une fonction dans un paquetage, vous invoquez une mthode de classe. En interposant un niveau dindirection entre lutilisation dune classe et son implmentation, le concepteur de programme reste libre de bricoler le fonctionnement interne de la classe, sans grand risque dinvalider des programmes qui lutilisent. Perl permet deux formes syntaxiques diffrentes pour invoquer les mthodes. Lune utilise le style familier que vous avez dj vu ailleurs en Perl, et la seconde est une forme

1. En voil un exemple de rutilisation de logiciel ! 2. Nous prfrons vigueur linguistique rigueur mathmatique. Vous serez daccord ou non.

customer_8566

286

Chapitre 12 Objets

que vous aurez peut-tre dj rencontre dans dautres langages de programmation. Quelle que soit la forme dinvocation de mthode utilise, un paramtre initial supplmentaire est pass la fonction servant de mthode. Si une classe est utilise pour invoquer la mthode, ce paramtre sera le nom de la classe. Si un objet est utilis pour invoquer la mthode, ce paramtre sera la rfrence lobjet. Quel que soit ce paramtre, nous lappellerons invoquant de la mthode. Pour une mthode de classe, linvoquant est le nom dun paquetage. Pour une mthode dinstance, linvoquant est la rfrence qui spcifie un objet. En dautres termes, linvoquant est ce avec quoi la mthode a t invoque. Certains livres OO lappellent lagent ou lacteur de la mthode. Dun point de vue grammatical, linvoquant nest ni le sujet de laction, ni son destinataire. Il est plutt comme un objet indirect, le bnficiaire au nom duquel laction est excute tout comme le mot moi dans la commande Forge-moi une pe ! . Smantiquement vous pouvez voir linvoquant comme ce qui invoque ou ce qui est invoqu, selon ce qui correspond mieux votre appareil mental. Nous nallons pas vous dire comment penser. (Pas sur ce sujet-l, en tout cas.) La plupart des mthodes sont invoques explicitement, mais des mthodes peuvent aussi tre invoques implicitement lorsquelles sont dclenches par un destructeur dobjet, un oprateur surcharg ou une variable lie. Ce ne sont pas proprement parler des appels de fonction ordinaires, mais plutt des invocations de mthode dclenches automatiquement par Perl au nom de lobjet. Les destructeurs sont dcrits plus loin dans ce chapitre, la surcharge est dcrite dans le chapitre 13, Surcharge, et les variables lies sont dcrites dans le chapitre 14, Variables lies. Les mthodes et les fonctions normales diffrent par le moment auquel leur paquetage est rsolu cest--dire, le moment o Perl dcide quel code doit tre excut pour la mthode ou la fonction. Le paquetage dune fonction est rsolu la compilation, avant que le programme ne commence sexcuter.3 Au contraire, le paquetage dune mthode nest rsolu que lorsquelle est effectivement invoque. (Les prototypes sont vrifis la compilation, cest pourquoi les fonctions normales peuvent les utiliser, mais les mthodes ne le peuvent pas.) La raison pour laquelle le paquetage dune mthode ne peut pas tre rsolu plus tt est relativement vidente : le paquetage est dtermin par la classe de linvoquant, et linvoquant nest pas connu tant que la mthode na rellement t invoque. Au cur de lOO est cette simple chane logique : si on connat linvoquant, on connat la classe de linvoquant ; si on connat la classe, on connat lhritage de la classe ; si on connat lhritage de la classe, on connat la fonction appeler. La logique de labstraction a un cot. cause de la rsolution tardive des mthodes, une solution oriente objet en Perl risque de sexcuter plus lentement que la solution nonOO correspondante. Pour certaines des techniques sophistiques dcrites plus loin, elle pourrait tre beaucoup plus lente. Toutefois, la solution de beaucoup de problmes nest
3. Plus prcisment, lappel de fonction est rsolu jusqu un typeglob spcifique, et une rfrence ce typeglob est rentre dans larbre dopcodes compils. Le sens de ce typeglob est ngociable mme au moment de lexcution cest ainsi que AUTOLOAD peut vous autocharger une fonction. Normalement, cependant, le sens du typeglob est aussi rsolu la compilation par la dfinition dune fonction nomme de faon correspondante.

customer_8566

Invocation de mthode

287

pas de travailler plus vite, mais de travailler plus intelligemment. Cest l que brille lOO.

Invocation de mthode avec loprateur f lche


Nous avons indiqu quil existe deux styles dinvocation de mthode. Le premier style se prsente comme ceci : INVOQUANT->METHODE(LISTE) INVOQUANT->METHODE Pour des raisons videntes, ce style est habituellement appel la forme f lche dinvocation. (Ne confondez pas -> avec =>, la f lche deux coups utilise comme virgule de luxe.) Les parenthses sont exiges sil y a des paramtres. Lorsquelle est excute, linvocation commence par trouver la fonction dtermine conjointement par la classe de lINVOQUANT et par le nom de la METHODE, lui passant INVOQUANT comme premier paramtre. Lorsque INVOQUANT est une rfrence, nous disons que METHODE est invoque comme mthode dinstance, et lorsque INVOQUANT est un nom de paquetage, nous disons que METHODE est invoque comme mthode de classe. Il ny a en ralit aucune diffrence entre les deux, mis part que le nom de paquetage est plus clairement associ la classe ellemme quavec les objets de la classe. Vous allez devoir nous faire confiance lorsque nous disons que les objets connaissent leur classe. Nous vous dirons bientt comment associer un objet un nom de classe, mais vous pouvez utiliser les objets sans savoir cela. Par exemple, pour construire un objet avec la mthode de classe invoquer puis invoquer la mthode dinstance dire sur lobjet rsultant, vous pourriez dire ceci :
$mage = Magicien->invoquer("Gandalf"); # mthode de classe $mage->dire("ami"); # mthode dinstance

Les mthodes invoquer et dire sont dfinies par la classe Magicien --- ou par une des classes dont elle hrite. Mais ne vous inquitez pas de cela. Ne vous mlez pas des affaires de Magiciens. Comme loprateur f lche est associatif vers la gauche (voir le chapitre 3, Oprateurs unaires et binaires), vous pouvez mme combiner les deux instructions :
Magicien->invoquer("Gandalf")->dire("ami");

Parfois vous souhaiterez invoquer une mthode sans connatre son nom par avance. Vous pouvez utiliser la forme f lche dinvocation et remplacer le nom de mthode avec une simple variable scalaire :
$methode = "invoquer"; $mage = Magicien->$methode("Gandalf"); # Invoquer Magicien->invoquer $voyager = $compagnon eq "Grispoil" ? "monter" : "marcher"; $mage->$voyager("sept lieues"); # Invoquer $mage->monter ou # $mage->marcher

Bien que vous utilisiez le nom dune mthode pour linvoquer indirectement, cet usage nest pas interdit par use strict refs, car tous les appels de mthode sont en fait recherchs par symbole au moment o ils sont rsolus.

customer_8566

288

Chapitre 12 Objets

Dans notre exemple, nous stockons le nom dune fonction dans $voyager, mais vous pourriez aussi stocker une rfrence de fonction. Ceci contourne lalgorithme de recherche de mthode, mais parfois cest exactement ce que vous voulez faire. Voir la section Mthodes prives et la discussion de la mthode can dans la section UNIVERSAL : la classe anctre ultime. Pour crer une rfrence la mthode spcifique dappel pour une instance spcifique, voir la section Fermetures dans le chapitre 8.

Invocation de mthode avec des objets indirects


Le second style dinvocation de mthode se prsente comme ceci : METHODE INVOQUANT (LISTE) METHODE INVOQUANT LISTE METHODE INVOQUANT Les parenthses autour de LISTE sont optionnelles ; si elles sont omises, la mthode se comporte comme un oprateur de liste. Vous pouvez donc avoir des instructions comme les suivantes, toutes utilisant ce style dappel de mthode :
$mage = invoquer Magicien "Gandalf"; $nemesis = invoquer Balrog demeure => "Moria", arme => "fouet"; deplacer $nemesis "pont"; dire $mage "Tu ne peux pas passer"; briser $baton; # il est plus sr dutiliser : briser $baton ();

La syntaxe doprateur de liste devrait vous tre familire, car cest le mme style quon utilise pour passer des handles de fichiers print ou printf :
print STDERR "au secours !!!\n";

Elle est galement similaire des phrases en franais comme Donner () Gollum le trsor , donc nous lappelons la forme avec objet indirect. Linvoquant est attendu dans la case dobjet indirect. Lorsquil est fait mention de passer quelque chose une fonction interne comme system ou exec dans sa case dobjet indirect , cela veut dire que vous fournissez ce paramtre supplmentaire et dpourvu de virgule au mme endroit que vous le feriez si vous invoquiez une mthode avec la syntaxe dobjet indirect. La forme avec objet indirect vous permet mme de spcifier que lINVOQUANT soit un BLOC valuable comme objet (rfrence) ou comme classe (paquetage). Ce qui vous permet de combiner deux invocations en une instruction ainsi :
dire { invoquer Magicien "Gandalf" } "ami";

Piges syntaxiques avec les objets indirects


Une syntaxe sera souvent plus lisible que lautre. La syntaxe dobjet indirect est moins lourde, mais souffre de plusieurs sortes dambigut syntaxique. La premire est que la partie LISTE dune invocation avec objet indirect est analyse de la mme faon que tout autre oprateur de liste. Ainsi, les parenthses de :
enchanter $epee ($points + 2) * $cout;

sont censes entourer tous les paramtres, quel que soit ce qui suit. Cela quivaut :
($epee->enchanter($points + 2)) * $cout;

customer_8566

Invocation de mthode

289

Cela ne fait probablement pas ce que vous pensez : enchanter nest appele quavec $points + 2, et la valeur de retour de la mthode est ensuite multiplie par $cout. Comme avec dautres oprateurs de liste, vous devez faire attention la prcdence de && et de || par rapport and et or. Par exemple ceci :
appeler $epee $ancien_nom || "Glamdring"; # ne pas utiliser "or" ici !

devient comme prvu :


$epee->appeler($ancien_nom || "Glamdring");

mais ceci :
dire $mage "ami" && entrer(); # il aurait fallu "and" ici !

devient le douteux :
$mage->dire("ami" && entrer());

qui pourrait tre corrig en rcrivant avec une des formes quivalentes :
entrer() if $mage->dire("ami"); $mage->dire("ami") && entrer(); dire $mage "ami" and entrer();

Le deuxime ennui syntaxique de la forme avec objet indirect est que lINVOQUANT ne peut tre quun nom, une variable scalaire non-indice ou un bloc.4 Ds que lanalyseur voit une de ces choses, il a son INVOQUANT, donc il commence chercher sa LISTE. Ainsi ces invocations :
deplacer $groupe->{CHEF}; deplacer $cavaliers[$i]; # probablement faux ! # probablement faux !

sont en fait analyses comme celles-ci :


$groupe->deplacer->{CHEF}; $cavaliers->deplacer([$i]);

au lieu de ce que vous vouliez sans doute :


$groupe->{CHEF}->deplacer; $cavaliers[$i]->deplacer;

Lanalyseur ne regarde quun petit peu vers lavant pour trouver linvoquant dun objet indirect, pas mme aussi loin quil ne regarderait dans le cas dun oprateur unaire. Cette bizarrerie na pas lieu avec la premire forme syntaxique, donc vous souhaiterez peuttre faire de la f lche votre arme de choix. Mme en franais il peut se poser un problme similaire. Pensez linstruction : Envoyez-moi par la poste la lettre pour que je la lise . Si vous analysez cette phrase trop vite, vous finirez par envoyer quelquun, et non pas une lettre, par la poste. Comme Perl, le franais a parfois deux syntaxes diffrentes pour dcrire un agent : Envoyezmoi la lettre et Envoyez la lettre moi . Parfois la forme plus longue est plus claire et plus naturelle, et parfois cest le contraire. Au moins en Perl, vous tes oblig dutiliser des accolades autour dun objet indirect complexe.
4. Les lecteurs attentifs se souviendront que cest prcisment la mme liste ditems syntaxiques qui sont permis aprs les drles de caractres ($, @, % ou *) pour indiquer un drfrencement de variable par exemple, @tableau, @$ref_tableau ou @{$ref_tableau}.

customer_8566

290

Chapitre 12 Objets

Classes paquetage explicite


La dernire ambigut syntaxique du style dinvocation de mthode avec objet indirect est quelle peut ne pas du tout tre analyse comme appel de mthode, parce que le paquetage courant peut contenir une fonction ayant le mme nom que la mthode. Lorsque vous utilisez une mthode de classe avec un nom de paquetage littral comme invoquant, il y a moyen de rsoudre cette ambigut tout en gardant la syntaxe dobjet indirect : explicitez le nom de paquetage en y ajoutant un double deux-points.
$obj = methode CLASSE::; $obj = new CLASSE; # imposer "CLASSE"->methode # pourrait ne pas tre analys comme mthode

Ceci est important car la notation courante : ne se comportera pas toujours correctement si le paquetage courant comporte une fonction nomme new ou CLASSE. Mme si prudemment vous utilisez la forme avec f lche au lieu de la forme avec objet indirect pour invoquer des mthodes, ceci peut, rarement, rester un problme. Au prix dun peu plus de ponctuation, la notation CLASSE:: garantit comment Perl analysera votre invocation de mthode. Dans les exemples suivants, les deux premiers ne sont pas toujours analyss de la mme faon, mais les deux derniers le sont :
$obj = new AnneauElfique; $obj = AnneauElfique->new; $obj = new AnneauElfique::; $obj = AnneauElfique::->new; $obj = new AnneauElfique:: nom => proprietaire => domaine => pierre => # pourrait tre new("AnneauElfique") # ou mme new(AnneauElfique()) # pourrait tre AnneauElfique()->new() # toujours "AnneauElfique"->new() # toujours "AnneauElfique"->new()

Cette notation de paquetage explicite peut tre enjolive avec un peu dalignement :
"Narya", "Gandalf", "feu", "rubis";

Nanmoins, vous vous exclamerez peut-tre Quil est laid ! en voyant ce double deux-points, donc nous vous dirons que vous pouvez presque toujours vous en sortir avec un simple nom de classe, deux conditions. Premirement, quil ny ait pas de fonction avec le mme nom que la classe. (Si vous observez la convention que les noms de fonction comme new commencent avec une lettre minuscule, et que les noms de classe comme AnneauElfique commencent avec une majuscule, ceci ne posera jamais de problme.) Deuximement, que la classe soit charge avec lune des instructions suivantes :
use AnneauElfique; require AnneauElfique;

Chacune de ces dclarations assure que Perl sait que AnneauElfique est un nom de module, ce qui oblige tout nom simple comme new avant le nom de classe AnneauElfique tre interprt comme un appel de mthode, mme sil se trouve que vous avez vousmme dclar une fonction new dans le paquetage courant. On ne rencontre habituellement de problme avec les objets indirects que si lon entasse plusieurs classes dans un mme fichier, auquel cas Perl ne sait pas forcment quun paquetage spcifique tait

customer_8566

Construction dobjet

291

cens tre un nom de classe. Ceux qui nomment des fonctions avec des noms qui ressemblent NomsDeModule finissent galement par le regretter un jour ou lautre.

Construction dobjet
Tout objet est une rfrence, mais toute rfrence nest pas un objet. Une rfrence ne fonctionnera comme objet que si son rfrent est marqu spcialement pour dire Perl quel paquetage il appartient. On appelle consacrer (du sens anglais de la fonction bless) lacte de marquer un rfrent avec le nom dun paquetage et donc de sa classe, puisquune classe nest quun paquetage. Vous pouvez considrer que consacrer une rfrence la transforme en objet, bien quil soit plus prcis de dire que cela transforme la rfrence en rfrence un objet. La fonction bless prend un ou deux paramtres. Le premier paramtre est une rfrence et le deuxime est le paquetage avec lequel est consacr le rfrent. Si le deuxime paramtre est omis, cest le paquetage courant qui est utilis.
$obj = { }; # Obtenir une rfrence un hachage anonyme. bless($obj); # Consacrer le hachage avec le paquetage courant. bless($obj, "Bestiau"); # Consacrer le hachage avec la classe Bestiau.

Ici nous avons utilis une rfrence un hachage anonyme, ce que les gens utilisent habituellement comme structure de donnes pour leurs objets. Les hachages sont aprs tout extrmement f lexibles. Mais permettez-nous de souligner que vous pouvez consacrer une rfrence toute chose laquelle vous pouvez faire une rfrence en Perl, comme les scalaires, les tableaux, les fonctions et les typeglobs. Vous pouvez mme consacrer une rfrence au hachage de la table de symboles dun paquetage si vous trouvez une bonne raison de le faire. (Ou mme si vous nen trouvez pas.) Lorientation objet de Perl est entirement distincte de la structure des donnes. Une fois que le rfrent est consacr, lappel de la fonction interne ref sur sa rfrence retourne le nom de la classe consacre au lieu du type de base, comme HASH. Si vous voulez le type de base, utilisez la fonction reftype du module attributes. Voir use attributes dans le chapitre 31, Modules de pragmas. Voil comment crer un objet. Prenez simplement une rfrence quelque chose, donnez-lui une classe en la consacrant avec un paquetage, et vous avez termin. Cest tout ce que vous avez faire si vous crez une classe minimale. Si vous utilisez une classe, vous avez encore moins faire, car lauteur de la classe aura cach le bless lintrieur dune fonction nomme constructeur, qui cre et retourne des instances de la classe. Comme bless retourne son premier paramtre, un constructeur typique peut tre aussi simple que ceci :
package Bestiau; sub engendrer { bless {}; }

Ou, pour tre un peu plus explicite :


package Bestiau; sub engendrer { my $self = {}; # Rfrence un hachage anonyme vide bless $self, "Bestiau"; # Faire de ce hachage un objet Bestiau return $self; # Retourner le Bestiau nouvellement cre }

customer_8566

292

Chapitre 12 Objets

Muni de cette dfinition, voici comment on pourrait crer un objet Bestiau :


$animal = Bestiau->engendrer;

Constructeurs hritables
Comme toutes les mthodes, un constructeur nest quune fonction, mais nous ne lappelons pas fonction. Nous linvoquons toujours comme mthode ici une mthode de classe, car linvoquant est un nom de paquetage. Les invocations de mthode diffrent des appels de fonctions normales de deux faons. Premirement, elles reoivent un paramtre supplmentaire, comme indiqu prcdemment. Deuximement, elles obissent lhritage, permettant ainsi une classe dutiliser les mthodes dune autre. Nous dcrirons plus rigoureusement la mcanique sous-jacente de lhritage dans la section suivante, mais pour linstant, quelques exemples simples de ses effets devraient vous permettre de crer vos constructeurs. Par exemple, supposons que nous avons une classe Araignee qui hrite des mthodes de la classe Bestiau. En particulier, supposons que la classe Araignee ne possde pas sa propre mthode engendrer. On obtient les correspondances suivantes :
Appel de mthode Bestiau->engendrer() Araignee->engendrer() Appel de fonction rsultant Bestiau::engendrer("Bestiau"). Bestiau::engendrer("Araignee").

La fonction appele est la mme dans les deux cas, mais le paramtre est diffrent. Notez que notre constructeur engendrer ne prtait aucune attention son paramtre, ce qui signifie que notre objet Araignee tait incorrectement consacr avec la classe Bestiau. Un meilleur constructeur fournirait le nom du paquetage (pass comme premier paramtre) bless :
sub engendrer { my $classe = shift; my $self = { }; bless($self, $classe); return $self; } # Enregistrer le nom de paquetage # Consacrer la rfrence avec ce paquetage

Maintenant vous pourriez utiliser la mme fonction pour les deux cas :
$vermine = Bestiau->engendrer; $shelob = Araignee->engendrer;

Et chaque objet serait de la classe approprie. Ceci fonctionne mme indirectement, comme par exemple :
$type = "Araignee"; $shelob = $type->engendrer; # pareil que "Araignee"->engendrer

Cela reste une mthode de classe, pas une mthode dinstance, parce que son invoquant contient une chane et non une rfrence. Si $type tait un objet au lieu dun nom de classe, la dfinition de constructeur ci-dessus ne fonctionnerait pas, car bless ncessite un nom de classe. Mais pour beaucoup de clas-

customer_8566

Construction dobjet

293

ses, il est intressant dutiliser un objet existant comme modle pour la cration dun nouvel objet. Dans ces cas, vous pouvez dfinir vos constructeurs de faon ce quils fonctionnent la fois avec des objets ou avec des noms de classe :
sub engendrer { my $invoquant = shift; my $classe = ref($invoquant) || $invoquant; # Objet ou nom de classe my $self = { }; bless($self, $classe); return $self; }

Initialiseurs
La majorit des objets grent des informations internes qui sont indirectement manipules par les mthodes de lobjet. Tous nos constructeurs jusqu maintenant ont cr des hachages vides, mais il ny a pas de raison de les laisser vides. Par exemple, un constructeur pourrait accepter des paramtres supplmentaires ranger dans le hachage comme couples clef/valeur. Les livres OO appellent souvent de telles donnes proprits, attributs, accesseurs, donnes membres, donnes dinstance ou variables dinstance. La section Gestion des donnes dinstance plus loin dans ce chapitre donne plus de dtails sur les attributs. Imaginez une classe Cheval avec des attributs dinstance comme nom et couleur :
$monture = Cheval->new(nom => "Grispoil", couleur => "blanc");

Si lobjet est implment comme rfrence un hachage, les couples clef/valeur peuvent tre interpols directement dans le hachage une fois que linvoquant est supprim de la liste des paramtres :
sub new { my $invoquant = shift; my $classe = ref($invoquant) || $invoquant; my $self = { @_ }; # Les paramtres restants deviennent des attributs bless($self, $classe);# Transformer en objet return $self; }

Cette fois-ci nous avons utilis une mthode appele new comme constructeur de la classe, ce qui pourrait bien donner aux programmeurs C++ limpression de savoir ce qui se passe. Mais Perl ne considre pas new comme tant quelque chose de spcial ; vous pouvez nommer vos constructeurs comme vous voulez. Toute mthode qui cre et retourne un objet est de fait un constructeur. En gnral, nous vous recommandons de donner vos constructeurs des noms qui correspondent au contexte du problme que vous rsolvez. Par exemple, les constructeurs du module Tk ont le mme nom que le widget quils crent. Dans le module DBI, un constructeur nomm connect retourne un objet handle de base de donnes, et un autre constructeur nomm prepare est invoqu comme mthode dinstance et retourne un objet handle de statement. Mais sil ny a pas de nom de constructeur qui convienne au contexte, new nest peut-tre pas un mauvais choix. Cela dit, ce nest peut-tre pas une si mauvaise chose de choisir au hasard un nom

customer_8566

294

Chapitre 12 Objets

pour obliger les gens lire le contrat dinterface (cest--dire la documentation de la classe) avant dutiliser ses constructeurs. Vous pouvez aussi configurer votre constructeur avec des couples clef/valeur par dfaut, que lutilisateur peut supplanter en les passant comme paramtres :
sub new { my $invoquant = shift; my $classe = ref($invoquant) || $invoquant; my $self = { couleur => "bai", pattes => 4, proprietaire => undef, @_, # Supplanter les attributs prcdents }; return bless $self, $classe; } $ed = Cheval->new; $etalon = Cheval->new(couleur => "noir"); # Un cheval bai 4 pattes # Un cheval noir 4 pattes

Ce constructeur de Cheval ne prte pas attention aux attributs existants de son invoquant lorsquil est utilis comme mthode dinstance. Vous pourriez crer un deuxime constructeur conu pour tre appel comme mthode dinstance, et sil tait conu correctement, vous pourriez utiliser les valeurs de lobjet invoquant comme valeurs par dfaut du nouvel objet :
$monture = Cheval->new(couleur => "gris"); $poulain = $monture->clone(proprietaire => "EquuGen Guild, Ltd."); sub clone { my $modele = shift; my $self = $modele->new(%$modele, @_); return $self; # Dj consacr par ->new }

(Vous auriez galement pu intgrer cette fonction directement dans new, mais alors le nom ne correspondrait plus tout fait son rle.) Remarquez comment, mme dans le constructeur clone, nous ne codons pas en dur le nom de la classe Cheval. Ainsi lobjet dorigine invoque sa mthode new, quelle quelle soit. Si nous avions crit cela Cheval->new au lieu de $modele->new, la classe naurait pas facilit lhritage par une classe Zebre ou une classe Licorne. Il serait dommage de cloner Pgase et de se retrouver avec un vulgaire bidet. Cependant, parfois vous avez le problme contraire : au lieu de partager un mme constructeur entre plusieurs classes, vous essayez de faire partager lobjet dune mme classe entre plusieurs constructeurs. Cela se passe chaque fois quun constructeur veut appeler le constructeur dune classe de base pour faire une partie du travail de construction. Perl ne fait pas de construction hirarchique votre place. Cest--dire que Perl nappelle pas automatiquement les constructeurs (ou les destructeurs) des classes de base de la classe en question, donc votre constructeur devra faire cela lui-mme et ensuite rajouter tout autre attribut dont a besoin la classe drive. Donc la situation est similaire la m-

customer_8566

Hritage de classe

295

thode clone, sauf quau lieu de copier un objet existant vers un nouvel objet, vous voulez appeler le constructeur de votre classe de base et ensuite transformer le nouvel objet de base en votre nouvel objet driv.

Hritage de classe
Comme pour le reste du systme objet de Perl, lhritage dune classe par une autre ne ncessite lajout au langage daucune syntaxe particulire. Lorsque vous invoquez une mthode pour laquelle Perl ne trouve pas de fonction dans le paquetage de linvoquant, le tableau @ISA5 de ce paquetage est examin. Cest ainsi que Perl implmente lhritage : chaque lment du tableau @ISA dun paquetage donn contient le nom dun autre paquetage, dans lequel est faite une recherche lorsque manquent des mthodes. Par exemple, ce qui suit fait de la classe Cheval une sous-classe de la classe Bestiau. (Nous dclarons @ISA avec our parce quil doit tre une variable de paquetage, pas une variable lexicale dclare avec my.)
package Cheval; our @ISA = "Bestiau";

Vous devriez maintenant pouvoir utiliser un objet ou une classe Cheval partout o Bestiau tait utilis. Si votre classe russit ce test de sous-classe vide, vous savez que Bestiau est une classe de base correcte, apte lhritage. Supposons que vous avez un objet Cheval dans $monture et que vous invoquez une mthode deplacer dessus :
$monture->deplacer(10);

Comme $monture est un Cheval, le premier choix de Perl pour cette mthode est la fonction Cheval::deplacer. Sil ny en a pas, au lieu de lever une exception lexcution, Perl consulte dabord le premier lment du tableau @Cheval::ISA, qui lui indique de chercher Bestiau::deplacer dans le paquetage Bestiau. Si cette fonction nest pas trouve non plus, et que Bestiau a son propre tableau @Bestiau::ISA, alors lui aussi sera consult pour trouver le nom dun paquetage ancestral qui puisse fournir une mthode deplacer, et ainsi de suite en remontant la hirarchie dhritage jusqu ce que lon tombe sur un paquetage sans un @ISA. La situation que nous venons de dcrire est lhritage simple, dans lequel chaque classe na quun seul parent. Perl permet aussi lhritage multiple : il suffit dajouter dautres paquetages l@ISA de la classe. Ce type dhritage fonctionne davantage comme une structure de donnes en arbre, car chaque paquetage peut avoir plus dun parent immdiat. Certaines personnes trouvent cela plus sexy. Lorsque vous invoquez une mthode nom_meth sur un invoquant de type nom_classe, Perl essaie six faons diffrentes de trouver une fonction utiliser : 1. Dabord, Perl cherche une fonction nomme nom_classe::nom_meth dans le paquetage de linvoquant. Si cela choue, lhritage entre en jeu, et nous passons la deuxime tape.
5. Se prononce is a ( est un ) en anglais, comme A horse is a critter. ( Un cheval est un bestiau. )

customer_8566

296

Chapitre 12 Objets

2. Ensuite, Perl cherche une mthode hrite de classes de base en cherchant dans tous les paquetages parent lists dans @nom_classe::ISA une fonction parent::nom_meth. La recherche se fait de gauche droite, rcursivement, et en cherchant en profondeur dabord (depth-first). La rcursivit garantit que lon recherche dans les classes grand-parent, arrire-grand-parent, arrire-arrire-grandparent et ainsi de suite. 3. Si cela choue, Perl cherche une fonction nomme UNIVERSAL::nom_meth. 4. ce stade, Perl abandonne nom_meth et commence chercher un AUTOLOAD. Dabord, il cherche une fonction nomme nom_classe::AUTOLOAD. 5. Sil nen trouve pas, Perl cherche dans toutes les classes parent listes dans @nom_classe::ISA une fonction parent::AUTOLOAD . La recherche est nouveau de gauche droite, rcursive, et en profondeur dabord. 6. Pour finir, Perl cherche une fonction nomme UNIVERSAL::AUTOLOAD. Perl sarrte la premire tentative russie et invoque cette fonction. Si aucune fonction nest trouve, une exception est leve, que vous verrez frquemment :
Cant locate object method "nom_meth" via package "nom_classe"

Si vous avez compil une version Perl de dbogage avec loption -DDEBUGGING de votre compilateur C, en utilisant loption -Do de Perl, vous pouvez le regarder passer par chacune de ces tapes lorsquil rsout une invocation de mthode. Nous dtaillerons le mcanisme dhritage au fur et mesure dans ce qui suit.

Hritage avec @ISA


Si @ISA contient plusieurs noms de paquetage, les paquetages sont tous parcourus de gauche droite. La recherche se fait en profondeur dabord, donc si vous avez une classe Mule configure pour lhritage de la faon suivante :
package Mule; our @ISA = ("Cheval", "Ane");

Perl cherche les mthodes manquantes de Mule dabord dans Cheval (et dans tous ses anctres, comme Bestiau) avant de continuer chercher dans Ane et ses anctres. Si une mthode manquante est trouve dans la classe de base, pour plus defficacit, Perl place cet emplacement en interne dans un cache dans la classe courante, pour quil nait pas chercher aussi loin la prochaine fois quil doit trouver cette mthode. Modifier @ISA ou dfinir de nouvelles mthodes invalide le cache et oblige Perl faire la recherche de nouveau. Lorsque Perl cherche une mthode, il sassure que vous navez pas cr de hirarchie dhritage circulaire. Ceci pourrait se produire si deux classes hritaient lune de lautre, mme indirectement par dautres classes. Essayer dtre votre propre grand-pre est trop paradoxal, mme pour Perl, donc la tentative lve une exception. Toutefois, Perl ne considre pas comme une erreur dhriter de plusieurs classes partageant de mmes anctres, ce qui fait penser un mariage entre cousins. Simplement, votre hirarchie dhritage ne ressemble plus un arbre et commence ressembler un graphe acyclique orient. Ceci ne drange pas Perl tant que le graphe est rellement acyclique.

customer_8566

Hritage de classe

297

Lorsque vous initialisez @ISA, laffectation se produit normalement lexcution, donc sauf si vous prenez des prcautions, le code dans un bloc BEGIN, CHECK ou INIT ne pourra pas utiliser la hirarchie dhritage. Le pragma use base est une prcaution (ou commodit) qui vous permet dutiliser des classes avec require et les ajoute @ISA la compilation. Voici comment vous pourriez lutiliser :
package Mule; use base ("Cheval", "Ane"); # dclarer les surclasses

Ceci est un raccourci de :


package Mule; BEGIN { our @ISA = ("Cheval", "Ane"); require Cheval; require Ane; }

sauf que use base prend aussi en compte toute dclaration use fields. Il arrive que les gens stonnent que linclusion dune classe dans @ISA neffectue pas le require correspondant votre place. Cest parce que le systme de classes de Perl est largement spar du systme de modules. Un fichier peut contenir plusieurs classes (puisquelles ne sont que des paquetages), et un paquetage peut tre mentionn dans plusieurs fichiers. Mais dans la situation la plus courante, dans laquelle un paquetage et une classe et un module et un fichier deviennent assez interchangeables si vous plissez suffisamment les yeux, le pragma use base fournit une syntaxe dclarative qui tablit lhritage, charge les fichiers de module, et gre les dclarations de champs de classe de base. Cest une de ces diagonales commodes que nous mentionnons souvent. Voir pour plus de dtails les descriptions de use base et de use fields au chapitre 31.

Accs aux mthodes supplantes


Lorsquune classe dfinit une mthode, cette fonction supplante les mthodes de mme nom dans toutes les classes de base. Imaginons que vous avez un objet Mule (driv de la classe Cheval et de la classe Ane), et que vous dcidez dinvoquer la mthode procreer de votre objet. Bien que les classes parentes aient leur propres mthodes procreer, le concepteur de la classe Mule les a supplantes en fournissant la classe Mule sa propre mthode procreer. Cela veut dire que le croisement suivant risque de ne pas tre productif :
$etalon = Cheval->new(sexe => "male"); $molly = Mule->new(sexe => "femelle"); $poulain = $molly->procreer($etalon);

Supposons maintenant que par le miracle de lingnierie gntique, vous trouvez un moyen de contourner le problme bien connu de strilit de la mule, donc vous souhaitez passer outre la mthode Mule::procreer non viable. Vous pourriez appeler votre mthode comme une fonction ordinaire, en sassurant de passer explicitement linvoquant :
$poulain = Cheval::procreer($molly, $etalon);

Toutefois ceci contourne lhritage, ce qui est presque toujours la mauvaise chose faire.

customer_8566

298

Chapitre 12 Objets

Il est parfaitement imaginable que la fonction Cheval::procreer nexiste pas, car Cheval et Ane drivent ce comportement dun parent commun nomm Equide. Si, dun autre ct, vous voulez que Perl commence chercher une mthode dans une classe donne, utilisez simplement linvocation de mthode ordinaire, mais qualifiez le nom de mthode avec la classe :
$poulain = $molly->Cheval::procreer($etalon);

Parfois vous voudrez quune mthode dans une classe drive serve demballage pour une mthode dans une classe de base. La mthode de la classe drive peut elle-mme appeler la mthode dans la classe de base, ajoutant ses propres actions avant ou aprs cette invocation. Vous pourriez utiliser la notation ci-dessus pour spcifier dans quelle classe commencer la recherche. Mais dans la plupart des cas de mthodes supplantes, vous voudrez probablement viter de savoir ou de spcifier quelle classe parente appartient la mthode supplante que vous voulez excuter. Cest l que la pseudo-classe SUPER est trs utile. Elle vous permet dinvoquer une mthode supplante de classe de base sans avoir spcifier quelle classe a dfini cette mthode.6 La fonction suivante consulte le tableau @ISA du paquetage courant sans vous faire spcifier de nom de classe :
package Mule; our @ISA = qw(Cheval Ane); sub coup_de_pied { my $self = shift; print "La mule donne un coup de pied !\n"; $self->SUPER::coup_de_pied(@_); }

Le pseudo-paquetage na un sens que lorsquil est utilis lintrieur dune mthode. Bien que celui qui implmente une classe peut faire usage de SUPER dans son propre code, quelquun qui ne fait quutiliser les objets de la classe ne le peut pas. SUPER ne fonctionne pas toujours comme vous le voudriez dans le cas dun hritage multiple. Comme vous pourriez vous y attendre, il parcourt @ISA exactement comme le fait le mcanisme dhritage normal : de gauche droite, rcursivement, et en profondeur dabord. Si Cheval et Ane avaient chacun une mthode dire, et que vous prfriez la mthode dAne, vous auriez nommer explicitement la classe parente :
sub dire { my $self = shift; print "La mule parle !\n"; $self->Ane::dire(@_); }

Des manires plus labores de traiter les situations avec hritage multiple peuvent tre cres avec la mthode UNIVERSAL::can dcrite dans la section suivante. Vous pouvez aussi rcuprer le module Class::Multimethods de CPAN, qui fournit de nombreuses

6. Ceci nest pas confondre avec le mcanisme mentionn au chapitre 11 pour supplanter les fonctions internes de Perl, qui ne sont pas des mthodes dobjet et ne sont donc pas supplantes par hritage. Vous appelez les fonctions internes supplantes avec le pseudo-paquetage CORE, pas le pseudo-paquetage SUPER.

customer_8566

Hritage de classe

299

solutions sophistiques, dont une qui trouve la mthode la plus proche au lieu de celle situe le plus gauche. Chaque bout de code Perl sait dans quel paquetage il se trouve, daprs la dernire instruction package. Une mthode SUPER ne consulte le @ISA que du paquetage dans lequel lappel SUPER a t compil. Il ne se soucie pas de la classe de linvoquant, ni du paquetage de la fonction appele. Ceci peut causer des problmes si vous tentez de dfinir des mthodes dans une autre classe simplement en jouant sur le nom de mthode :
package Oiseau; use Libellule; sub Libellule::bombarder { shift->SUPER::bombarder(@_) }

Malheureusement, ceci invoque la surclasse dOiseau, pas celle de Libellule. Pour faire ce que vous essayez de faire, vous devez aussi explicitement passer dans le paquetage appropri pour la compilation de SUPER :
package Oiseau; use Libellule; { package Libellule; sub bombarder { shift->SUPER::bombarder(@_) } }

Comme lindique cet exemple, il nest jamais ncessaire de modifier un fichier de module pour simplement ajouter des mthodes une classe existante. Puisquune classe nest quun paquetage, et quune mthode nest quune fonction, tout ce que vous devez faire cest dfinir une fonction dans ce paquetage comme nous lavons fait ici, et la classe possde soudainement une nouvelle mthode. Lhritage nest pas ncessaire. Seul compte le paquetage, et comme les paquetages sont globaux, on peut accder tout paquetage de nimporte o dans le programme. (Vous a-t-on inform que nous allions installer une baignoire dans votre salon la semaine prochaine ?)

UNIVERSAL : la classe anctre ultime


Si aucune dfinition de mthode de nom correspondant nest trouve aprs avoir recherch dans la classe de linvoquant et rcursivement dans toutes ses classes anctres, une dernire recherche de mthode de ce nom est faite dans la classe spciale prdfinie nomme UNIVERSAL. Ce paquetage napparat jamais dans un @ISA, mais il est toujours consult lorsque la recherche dans @ISA choue. Vous pouvez voir UNIVERSAL comme lanctre ultime dont drivent implicitement toutes les classes. Les mthodes prdfinies suivantes sont disponibles dans la classe UNIVERSAL, et donc dans toutes les classes. Elles fonctionnent toutes quelles soient invoques comme mthodes de classe ou comme mthodes dobjet. INVOQUANT->isa(CLASSE) La mthode isa retourne vrai si la classe dINVOQUANT est CLASSE ou une classe hritant de CLASSE. la place dun nom de paquetage, CLASSE peut aussi tre un des types internes, comme HASH ou ARRAY . (Mais la dtermination du type exact nest pas bon signe pour lencapsulation et le polymorphisme. Vous devriez dpendre de lacheminement de mthode pour vous donner la bonne mthode.)

customer_8566

300
use FileHandle; if (FileHandle->isa("Exporter")) { print "FileHandle est un Exporter.\n"; }

Chapitre 12 Objets

$fh = FileHandle->new(); if ($fh->isa("IO::Handle")) { print "\$fh est un objet en rapport avec IO.\n"; } if ($fh->isa("GLOB")) { print "\$fh est en fait une rfrence un GLOB.\n"; }

INVOQUANT->can(METHODE) La mthode can retourne une rfrence la fonction qui serait appele si METHODE tait applique INVOQUANT. Si une telle fonction nest pas trouve, can retourne undef.
if ($invoquant->can("copier")) { print "Notre invoquant peut copier.\n"; }

Ceci pourrait tre utilis pour ninvoquer une mthode que si elle existe :
$obj->grogner if $obj->can("grogner");

Avec lhritage multiple, ceci permet une mthode dinvoquer toutes les mthodes de classe de base supplantes, et non pas seulement celle la plus gauche :
sub grogner { my $self = shift; print "Grognement: @_\n"; my %vues; for my $parent (@ISA) { if (my $code = $parent->can("grogner")) { $self->$code(@_) unless $vues{$code}++; } } }

Nous utilisons le hachage %vues pour nous souvenir des fonctions dj appeles. Ceci pourrait se produire si plusieurs classes parentes avaient un anctre commun. Les mthodes qui dclencheraient un AUTOLOAD (dcrit dans la section suivante) ne seront pas correctement signales sauf si le paquetage a dclar (mais pas dfini) les fonctions quil souhaite voir autocharger. INVOQUANT->VERSION(REQUIS) La mthode VERSION retourne le numro de version de la classe dINVOQUANT, tel quil a t enregistr dans la variable $VERSION du paquetage. Si le paramtre REQUIS est fourni, elle vrifie que la version courante nest pas plus petite que REQUIS, et lve une exception si elle lest. Cest la mthode quinvoque use pour dterminer si un module est suffisamment rcent.
use Thread 1.0; # appelle Thread->VERSION(1.0) print "Excute la version ", Thread->VERSION, " de Thread.\n";

customer_8566

Hritage de classe

301

Vous pouvez fournir votre propre mthode VERSION pour supplanter la mthode dans UNIVERSAL. Nanmoins, ceci obligera aussi toute classe drive de votre classe utiliser la mthode supplante. Si vous ne souhaitez pas que cela se produise, vous devriez concevoir votre mthode de telle sorte quelle dlgue UNIVERSAL les requtes de version des autres classes. Les mthodes dans UNIVERSAL sont des fonctions internes de Perl, que vous pouvez appeler si vous les qualifiez et leur passez deux paramtres, comme dans UNIVERSAL::isa($obj_form, "HASH"). (Mais ceci nest pas vraiment conseill puisque can a normalement la rponse que vous cherchez vraiment.) Vous tes libre dajouter vos propres mthodes la classe UNIVERSAL. (Vous devez tre trs prudent, videmment ; vous pourriez vraiment gcher les choses pour quelquun qui sattend ne pas trouver le nom de mthode que vous dfinissez, peut-tre pour quil puisse lautocharger dun autre endroit.) Ici nous crons une mthode copier que les objets dune classe quelconque peuvent utiliser sils ne lont pas dfinie eux-mmes. (Elle choue de faon spectaculaire si elle est invoque pour une classe au lieu dun objet.)
use Data::Dumper; use Carp; sub UNIVERSAL::copier { my $self = shift; if (ref $self) { return eval Dumper($self); # pas de ref de CODE } else { confess "UNIVERSAL::copier ne peut pas copier la classe $self"; } }

Cette utilisation de Data::Dumper ne fonctionne pas si lobjet contient des rfrences aux fonctions, car elle ne peuvent pas tre reproduites correctement. Mme si le source tait disponible, les liens lexicaux seraient perdus.

Autochargement de mthode
Normalement, lorsque vous appelez une fonction non dfinie dans un paquetage qui dfinit une fonction AUTOLOAD, la fonction AUTOLOAD est appele au lieu de lever une exception (voir la section Autochargement au chapitre 10). Avec les mthodes, ceci fonctionne un peu diffremment. Si la recherche de mthode normale (dans la classe, dans ses anctres, et finalement dans UNIVERSAL) choue, la mme squence est de nouveau excute, en cherchant cette fois une fonction AUTOLOAD. Si elle est trouve, cette fonction est appele comme mthode, en affectant la variable $AUTOLOAD du paquetage le nom complet de la fonction au nom de laquelle a t appel AUTOLOAD. Vous devez tre un peu prudent lorsque vous autochargez des mthodes. Premirement, la fonction AUTOLOAD doit retourner immdiatement si elle est appele au nom dune mthode nomme DESTROY, sauf si votre but tait de simuler DESTROY, qui en Perl a une signification spciale dcrite dans la section Destructeurs dinstance plus loin dans ce chapitre.

customer_8566

302
sub AUTOLOAD { return if our $AUTOLOAD =~ /::DESTROY$/; ... }

Chapitre 12 Objets

Deuximement, si une classe fournit un filet de sret AUTOLOAD, vous ne pourrez pas utiliser UNIVERSAL::can sur un nom de mthode pour vrifier si lon peut linvoquer. Vous devez vrifier AUTOLOAD sparment :
if ($obj->can("nom_meth") || $obj->can("AUTOLOAD")) { $obj->nom_meth(); }

Finalement, avec lhritage multiple, si une classe hrite de deux classes ou plus, chacune ayant un AUTOLOAD, seul celui le plus gauche sera jamais dclench, puisque Perl sarrte ds quil trouve le premier AUTOLOAD. Ces deux dernires tracasseries sont facilement contournes en dclarant les fonctions dans le paquetage dont le AUTOLOAD est cens grer ces mthodes. Vous pouvez faire ceci, soit avec des dclarations individuelles :
package Goblin; sub taper; sub mordre; sub griffer;

soit avec le pragma use subs, qui est plus commode si vous avez de nombreuses mthodes dclarer :
package Goblin; use subs qw(taper mordre griffer);

Mme si vous navez que dclar ces fonctions sans les dfinir, cest assez pour que le systme pense quelles sont relles. Elles apparaissent dans la vrification avec UNIVERSAL::can, et plus important encore, elles apparaissent dans ltape 2 de recherche de mthode, qui nira jamais jusqu ltape 3 et encore moins la 4. Mais, mais, vous vous exclamez, elles invoquent AUTOLOAD, non ? Eh bien oui, elles finissent par le faire, mais le mcanisme est diffrent. Ayant trouv le bout de mthode grce ltape 2, Perl essaie de lappeler. Lorsquil dcouvre que la mthode nest pas tout ce quelle aurait pu tre, la recherche de mthode AUTOLOAD dmarre de nouveau, mais cette fois-ci, elle dmarre dans la classe contenant le bout de mthode, ce qui restreint la recherche de mthode la classe et ses anctres (et UNIVERSAL). Voil comment Perl trouve le bon AUTOLOAD excuter et ignore les AUTOLOAD de la mauvaise partie de larbre gnalogique.

Mthodes prives
Il existe un moyen dinvoquer une mthode de telle faon que Perl ignore compltement lhritage. Si au lieu dutiliser un nom de mthode littral, vous spcifiez une simple variable scalaire contenant une rfrence la fonction, alors la fonction est appele immdiatement. Dans la prcdente description de UNIVERSAL->can, le dernier exemple invoque toutes les mthodes supplantes en utilisant la rfrence la fonction, pas son nom.

customer_8566

Destructeurs dinstance

303

Un aspect intrigant de ce comportement est quil peut tre utilis pour implmenter des appels de mthode prive. Si vous mettez la classe dans un module, vous pouvez utiliser la porte lexicale du fichier pour faire un espace priv. Premirement, stockez une fonction anonyme dans une variable lexicale dont la porte est le fichier :
# dclarer une mthode prive my $porte_secrete = sub { my $self = shift; ... };

Plus loin dans ce fichier, vous pouvez utiliser la variable comme si elle contenait un nom de variable. La fermeture sera appele directement, sans prendre lhritage en considration. Comme pour toute autre mthode, linvoquant est pass en paramtre supplmentaire.
sub frapper { my $self = shift; if ($self->{frappe}++ > 5) { $self->$porte_secrete(); } }

Ceci permet aux fonctions appartenant un fichier (les mthodes de classe) dinvoquer une mthode laquelle tout code hors de leur porte lexicale ne peut accder.

Destructeurs dinstance
Comme pour tout autre rfrent en Perl, lorsque la dernire rfrence un objet disparat, sa mmoire est implicitement recycle. Avec un objet, vous avez la possibilit de prendre la main juste au moment o ceci est prs de se passer en dfinissant une fonction DESTROY dans le paquetage de la classe. Cette mthode est dclenche automatiquement au moment appropri, avec lobjet prt tre recycl comme unique paramtre. Les destructeurs sont rarement ncessaires en Perl, parce que la mmoire est gre automatiquement pour vous. Cependant, la mmoire mise part, certains objets peuvent avoir des informations dtat dont vous pouvez souhaiter vous occuper, comme des handles de fichier ou des connexions une base de donnes.
package NotifierCourrier; sub DESTROY { my $self = shift; my $fh = $self->{handle_courrier}; my $id = $self->{nom}; print $fh "\n$id s'en va " . localtime() . "\n"; close $fh; # fermer la connexion au systme de courrier }

De mme que Perl nutilise quune unique mthode pour construire un objet mme lorsque la classe du constructeur hrite dune ou plusieurs autres classes, Perl nutilise aussi quune unique mthode DESTROY par objet dtruit quel que soit lhritage. En dautres termes, Perl ne fait pas de la destruction hirarchique votre place. Si votre classe supplante le destructeur dune surclasse, alors votre mthode DESTROY devra peut-tre

customer_8566

304
invoquer la mthode DESTROY dune classe de base :

Chapitre 12 Objets

sub DESTROY { my $self = shift; # voir sil y a un destructeur supplant... $self->SUPER::DESTROY if $self->can("SUPER::DESTROY"); # faites vos choses maintenant, avant ou aprs }

Ceci ne sapplique quaux classes hrites ; un objet qui est simplement contenu dans lobjet courant comme, par exemple, une valeur dans un hachage sera libr et dtruit automatiquement. Cest une raison pour laquelle lappartenance par simple agrgation (parfois appele relation has-a ou possde-un ) est souvent plus propre et plus claire que lhritage (une relation est-un ). En dautres termes, il suffit parfois de stocker un objet directement lintrieur dun autre au lieu demployer lhritage, qui peut inutilement ajouter de la complexit. Parfois lorsque des utilisateurs se tournent vers lhritage multiple, lhritage simple peut suffire. Il est possible, mais rarement ncessaire, dappeler DESTROY explicitement. Cela peut mme tre dangereux car lexcution du destructeur plus dune fois sur un mme objet pourrait savrer dsagrable.

Ramasse-miettes avec les mthodes DESTROY


Comme nous lavons dcrit dans la section Ramasse-miettes, rfrences circulaires et rfrences faibles du chapitre 8, une variable qui fait rfrence elle-mme nest libre que quand le programme (ou linterprteur intgr) est sur le point de se terminer (il en est de mme pour plusieurs variables qui se font rfrence indirectement entre elles). Si vous voulez rcuprer la mmoire plus tt, vous devez normalement annuler explicitement la rfrence ou laffaiblir avec le module WeakRef de CPAN. Avec les objets, une autre solution est de crer une classe conteneur qui contient un pointeur la structure de donnes autorfrentielle. Dfinissez une mthode DESTROY pour la classe de lobjet conteneur qui annule manuellement les boucles dans la structure autorfrentielle. Vous trouverez un exemple de ceci dans le chapitre 13 du Perl en action dans la recette 13.13, Grer les structures de donnes circulaires. Lorsquun interprteur se termine, tous ses objets sont dtruits, ce qui est important pour les applications Perl multi-threades ou intgrs dans un autre logiciel. Les objets sont presque toujours dtruits lors dune tape distincte, avant les rfrences ordinaires. Ceci afin dempcher les mthodes DESTROY dutiliser des rfrences qui ont elles-mmes t dtruites. (Et aussi parce que les rfrences ordinaires ne sont soumises au ramassemiettes que dans les interprteurs intgrs, puisque terminer un processus est une faon trs rapide de rcuprer les rfrences. Mais terminer nexcutera pas les destructeurs dobjet, donc Perl le fait dabord.)

Gestion des donnes dinstance


La plupart des classes crent des objets qui ne sont essentiellement que des structures de donnes avec plusieurs champs de donnes internes (ou variables dinstance) avec des mthodes pour les manipuler.

customer_8566

Gestion des donnes dinstance

305

Les classes Perl hritent de mthodes, pas de donnes, mais tant que tout accs lobjet se fait par des appels de mthode, tout se passe trs bien. Si vous voulez lhritage de donnes, vous devez le raliser par lhritage de mthodes. Gnralement, ceci nest pas ncessaire en Perl, car la plupart des classes stockent les attributs de leur objet dans un hachage anonyme. Les donnes dinstance de lobjet sont contenues dans ce hachage, qui constitue son propre petit espace de noms dans lequel peut tailler toute classe faisant quelque chose avec lobjet. Par exemple, si vous voulez quun objet appel $ville possde un champ nomm altitude, vous pouvez y accder simplement avec $ville>{altitude}. Aucune dclaration nest ncessaire. Mais les mthodes demballage ont leur utilit. Supposons que vous voulez implmenter un objet Personne. Vous dcidez davoir un champ appel nom , que par curieuse concidence vous stockez sous la clef nom dans le hachage anonyme qui servira dobjet. Pour profiter de lencapsulation, les utilisateurs ncessitent des mthodes qui permettent daccder cette variable dinstance sans lever le voile de labstraction. Par exemple, vous pourriez crer une paire daccesseurs :
sub recuperer_nom { my $self = shift; return $self->{nom}; } sub affecter_nom { my $self = shift; $self->{nom} = shift; }

ce qui permet le code suivant :


$lui = Person->new(); $lui->affecter_nom("Frodon"); $lui->affecter_nom( ucfirst($lui->recuperer_nom) );

Vous pourriez mme combiner les deux mthodes :


sub nom { my $self = shift; if (@_) { $self->{nom} = shift } return $self->{nom}; }

Ce qui permettrait le code suivant :


$lui = Person->new(); $lui->nom("Frodon"); $lui->nom( ucfirst($lui->nom) );

Lavantage dcrire une fonction diffrente pour chaque variable dinstance (qui pour notre classe Personne pourrait tre nom, ge, taille et ainsi de suite) est dtre direct, vident et f lexible. Le dsavantage est que chaque fois que vous voulez une nouvelle classe, vous finissez par dfinir une ou deux mthodes identiques par variable dinstance. Au dbut, ceci nest pas gnant, et vous tes libre de le faire si vous le souhaitez. Mais si vous prfrez la commodit la f lexibilit, vous prfrerez peut-tre une des techniques dcrites dans les sections suivantes.

customer_8566

306

Chapitre 12 Objets

Notez que nous ferons varier limplmentation et non linterface. Si les utilisateurs de votre classe respectent lencapsulation, vous pourrez passer de manire transparente dune implmentation lautre sans que les utilisateurs le remarquent. (Les membres de la famille de votre arbre dhritage ne seront peut-tre pas aussi tolrants, puisquils vous connaissent beaucoup mieux que ne vous connaissent des trangers.) Si vos utilisateurs ont pris lhabitude de mettre leur nez ou leurs mains dans les affaires prives de votre classe, le dsastre invitable est de leur faute et ne vous concerne pas. Tout ce que vous pouvez faire cest respecter votre partie du contrat en gardant la mme interface. Essayer dobliger tout le monde ne jamais rien faire de mal prendra tout votre temps et toute votre nergie et en fin de compte chouera de toute faon. Il est plus difficile de soccuper des membres de la famille. Si une sous-classe supplante laccesseur dattribut dune surclasse, doit-elle ou non accder au mme champ dans le hachage ? Les deux approches sont dfendables, selon la nature de lattribut. Pour tre plus sr dans le cas gnral, chaque accesseur peut prfixer le nom de champ de hachage avec son propre nom de classe, de telle faon que la sous-classe et la surclasse puissent chacune avoir leur propre version. Plusieurs des exemples ci-dessous, dont le module Class::Struct, utilisent cette stratgie rsistante aux sous-classes . Vous verrez des accesseurs qui ressemblent ceci :
sub nom { my $self = shift; my $champ = __PACKAGE__ . "::nom"; if (@_) { $self->{$champ} = shift } return $self->{$champ}; }

Dans chacun des exemples suivants, nous crons une classe Personne simple avec les champs nom, race, et surnoms, chacun avec une interface identique mais une implmentation compltement diffrente. Nous nallons pas vous dire laquelle nous prfrons, car nous les prfrons toutes, selon loccasion. Et tous les gots sont dans la nature. Certains prfrent le ragot de lapin, dautres le poisson.

Dclarations de champ avec use fields


Un objet nest pas obligatoirement implment avec un hachage anonyme. Nimporte quelle rfrence suffira. Par exemple, si vous utilisiez un tableau anonyme, vous pourriez dfinir un constructeur comme ceci :
sub new { my $invoquant = shift; my $classe = ref($invoquant) || $invoquant; return bless [], $classe; }

et des accesseurs comme ceci :


sub nom { my $self = shift; if (@_) { $self->[0] = shift } return $self->[0]; }

customer_8566

Gestion des donnes dinstance


sub race { my $self = shift; if (@_) { $self->[1] = shift } return $self->[1]; } sub surnoms { my $self = shift; if (@_) { $self->[2] = shift } return $self->[2]; }

307

Les tableaux sont un peu plus rapides daccs que les hachages et occupent un peu moins de mmoire, mais ils ne sont pas terriblement commodes utiliser. Vous devez tenir compte des numros dindex (pas juste dans votre classe, mais aussi dans votre surclasse), qui doivent dune faon ou dun autre indiquer quelles parties du tableau utilise votre classe. Sinon, vous pourriez rutiliser une case. Le pragma use fields traite tous ces points :
package Personne; use fields qw(nom race surnoms);

Ce pragma ne vous cre pas les mthodes accesseurs, mais il dpend de magie interne (appele pseudo-hachages) pour faire quelque chose de similaire. (Vous souhaiterez peuttre tout de mme emballer les champs dans des accesseurs, comme nous le faisons dans lexemple suivant.) Les pseudo-hachages sont des rfrences de tableau que vous pouvez utiliser comme des hachages parce quils sont associs avec un tableau qui met les clefs en correspondance avec les index. Le pragma use fields vous met en place cette table de correspondance, dclarant effectivement quels champs sont valides pour lobjet Personne ; ceci les fait prendre en compte par le compilateur Perl. Si vous dclarez le type de votre variable objet (comme avec my Personne $self dans lexemple suivant), le compilateur est suffisamment intelligent pour optimiser laccs aux champs avec des simples accs par tableau. De faon peut-tre plus importante, il fait la compilation de la validation de type pour les noms de champ (cest en quelque sorte une validation de typographie contre les fautes de frappe). (Voir la section Pseudo-hachages au chapitre 8.) Un constructeur et des exemples daccesseurs ressembleraient ceci :
package Personne; use fields qw(nom race surnoms); sub new { my $type = shift; my Personne $self = fields::new(ref $type || $type); $self->{nom} = "pas de nom"; $self->{race} = "inconnue"; $self->{surnoms} = []; return $self; } sub nom { my Personne $self = shift; $self->{nom} = shift if @_; return $self->{nom}; }

customer_8566

308
sub race { my Personne $self = shift; $self->{race} = shift if @_; return $self->{race}; } sub surnoms { my Personne $self = shift; $self->{surnoms} = shift if @_; return $self->{surnoms}; } 1;

Chapitre 12 Objets

Si vous crivez incorrectement lune des clefs littrales utilises pour accder au pseudohachage, vous naurez pas attendre lexcution pour vous en rendre compte. Le compilateur sait quel type $self est cens faire rfrence (parce que vous le lui avez dit), donc il peut vrifier que le code naccde qu des champs rellement existants dans les objets Personne. Sil arrive que vos doigts semballent et que vous tentez daccder un champ inexistant (comme $self->{mon}), le compilateur peut tout de suite signaler cette erreur et ne laissera jamais excuter par linterprteur le programme erron. Il reste un peu de redite dans la dclaration de mthodes pour accder aux variables dinstance, donc vous souhaiterez peut-tre encore automatiser la cration de mthodes accesseur simples avec lune des techniques ci-dessous. Toutefois, comme ces techniques utilisent toutes une forme dindirection ou une autre, vous perdrez lavantage de la vrification la compilation de fautes de frappe pour les accs typs lexicalement aux hachages. Il vous restera nanmoins les (lgres) conomies de temps et despace. Si vous dcidez dutiliser un pseudo-hachage pour implmenter votre classe, toute classe qui en hrite doit prendre en compte cette implmentation sous-jacente. Si un objet est implment avec un pseudo-hachage, tous les membres de la hirarchie dhritage doivent utiliser les dclarations use base et use fields. Par exemple :
package Magicien; use base "Personne"; use fields qw(baton couleur sphere);

Ceci fait du module Magicien une sous-classe de la classe Personne, et charge le fichier Personne.pm. Ceci dclare galement trois nouveaux champs dans cette classe, qui sajoutent ceux de Personne. Ainsi lorsque vous crirez :
my Magicien $mage = fields::new("Magicien");

vous aurez un objet pseudo-hachage avec accs aux champs des deux classes :
$mage->nom("Gandalf"); $mage->couleur("Gris");

Puisque toutes les sous-classes doivent savoir quelles utilisent une implmentation de pseudo-hachage, elles doivent utiliser la notation directe de pseudo-hachage pour des raisons defficacit et de validation des types :
$mage->{nom} = "Gandalf"; $mage->{couleur} = "Gris";

Toutefois, si vous voulez garder des implmentations interchangeables, les utilisateurs extrieurs de votre classe doivent utiliser les mthodes accesseurs.

customer_8566

Gestion des donnes dinstance

309

Bien que use base ne permette que lhritage simple, ceci est rarement une contrainte svre. Voir les descriptions de use base et de use fields au chapitre 31.

Gnration de classes avec Class::Struct


Le module standard Class::Struct exporte une fonction appele struct. Celle-ci cre tout ce quil vous faut pour commencer lcriture dune classe entire. Elle gnre un constructeur appel new, ainsi que des mthodes accesseurs pour chacun des champs (variables dinstance) nomms dans cette structure. Par exemple, si vous mettez la classe dans un fichier Personne.pm :
package Personne; use Class::Struct; struct Personne => { # crer la dfinition dune "Personne" nom => $, # le champ nom est un scalaire race => $, # le champ race est aussi un scalaire surnoms => @, # mais le champ surnoms est une rf de tableau }; 1;

Alors vous pourriez utiliser le module de cette faon :


use Personne; my $mage = Personne->new(); $mage->nom("Gandalf"); $mage->race("Istar"); $mage->surnoms( ["Mithrandir", "Olorin", "Incanus"] );

Le module Class::Struct a cr ces quatre mthodes. Comme il respecte le principe rsistant aux sous-classes de toujours prfixer le nom du champ avec le nom de la classe, il permet aussi sans conf lit une sous-classe davoir son propre champ spar de mme nom quun champ de la classe de base. Cela veut dire quil utilise ici Personne::nom au lieu du simple nom comme clef de hachage pour cette variable dinstance. Les champs dune dclaration struct ne sont pas obligatoirement des types Perl de base. Ils peuvent aussi spcifier dautres classes, mais les classes cres avec struct fonctionnent le mieux car la fonction fait des prsuppositions sur le comportement des classes qui ne sont pas gnralement vraies de toutes les classes. Par exemple, la mthode new de la classe approprie est invoque pour initialiser le champ, mais beaucoup de classes ont des constructeurs nomms diffremment. Voir la description de Class::Struct au chapitre 32, Modules standards, et sa documentation en ligne pour plus dinformation. Beaucoup de modules standard utilisent Class::Struct pour implmenter leurs classes, dont notamment User::pwent et Net::hostent. La lecture de leur code peut savrer instructive.

Gnration daccesseurs par autochargement


Comme nous lavons mentionn prcdemment, lorsque vous invoquez une mthode inexistante, Perl cherche une mthode AUTOLOAD de deux faons diffrentes, selon que vous ayez dclar la mthode ou non. Vous pouvez utiliser cette proprit pour donner

customer_8566

310

Chapitre 12 Objets

accs aux donnes dinstance de lobjet sans dfinir une fonction diffrente pour chaque variable dinstance. Dans la fonction AUTOLOAD, le nom de la mthode rellement invoque peut tre dtermin partir de la variable $AUTOLOAD. Examinons le code suivant :
use Personne; $lui = Personne->new; $lui->nom("Aragorn"); $lui->race("Homme"); $lui->surnoms( ["Grands-Pas", "Estel", "Elessar"] ); printf "La race de %s est : %s.\n", $lui->nom, $lui->race; print "Ses surnoms sont : ", join(", ", @{$lui->surnoms}), ".\n";

Comme prcdemment, cette classe Personne implmente une structure de donnes avec trois champs : nom, race, et surnoms :
package Personne; use Carp; my %Fields = ( "Personne::nom" => "pas de nom", "Personne::race" => "inconnue", "Personne::surnoms" => [], ); # Cette dclaration nous assure dobtenir notre propre autochargeur use subs qw(nom race surnoms); sub new { my $invoquant = shift; my $classe = ref($invoquant) || $invoquant; my $self = { %Fields, @_ }; # cloner comme Class::Struct bless $self, $classe; return $self; } sub AUTOLOAD { my $self = shift; # ne grer que les mthode dinstance, pas les mthodes de classe croak "$self nest pas un objet" unless ref($self); my $nom = our $AUTOLOAD; return if $nom =~ /::DESTROY$/; unless (exists $self->{$nom}) { croak "impossible daccder au champ $nom dans $self"; } if (@_) { return $self->{$nom} = shift } else { return $self->{$nom} } }

Comme vous le voyez, il ny a aucune mention de mthodes nommes nom, race ou surnoms. La fonction AUTOLOAD prend tout cela en charge. Lorsque quelquun utilise $lui->nom("Aragorn"), la fonction AUTOLOAD est appele avec la valeur Personne::nom affecte $AUTOLOAD. Commodment, le nom qualifi est exacte-

customer_8566

Gestion des donnes dinstance

311

ment sous la forme ncessaire pour accder au champ du hachage de lobjet. Ainsi si vous utilisez cette classe lintrieur dune hirarchie de classes, vous nentrerez pas en conf lit avec lutilisation du mme nom dans dautres classes.

Gnration daccesseurs par fermetures


La plupart des mthodes accesseurs font essentiellement la mme chose : elles ne font que rcuprer ou stocker une valeur dans une variable dinstance. En Perl, la faon la plus naturelle de crer une famille de fonctions quasiment identiques est de boucler autour dune fermeture. Mais une fermeture est une fonction anonyme, et une mthode, pour quelle puisse tre appele par nom, doit tre une fonction nomme dans la table de symboles du paquetage de la classe. Ceci nest pas un problme il suffit daffecter la rfrence la fermeture un typeglob de nom appropri.
package Personne; sub new { my $invoquant = shift; my $self = bless({}, ref $invoquant || $invoquant); $self->init(); return $self; } sub init { my $self = shift; $self->nom("pas de nom"); $self->race("inconnue"); $self->surnoms([]); } for my $champ (qw(nom race surnoms)) { my $slot = __PACKAGE__ . "::$champ"; no strict "refs"; # Pour que fonctionne la rf symbolique au typeglob *$slot = sub { my $self = shift; $self->{$champ} = shift if @_; return $self->{$champ}; }; }

Les fermetures sont la faon fait main la plus propre de crer une multitude de mthodes accesseurs pour vos donnes dinstance. Cest une mthode efficace la fois pour lordinateur et pour vous. Non seulement tous les accesseurs partagent le mme bout de code (ils ne ncessitent que leur propre emplacement lexical), mais plus tard si vous dcidez dajouter un autre attribut, les changements requis sont minimaux : il suffit dajouter un mot de plus la liste de la boucle for, et peut-tre quelque chose la mthode init.

customer_8566

312

Chapitre 12 Objets

Utilisation de fermetures pour objets privs


Jusquici, ces techniques de gestion de donnes dinstance nont propos aucun mcanisme pour les protger daccs externes. Toute personne en dehors de la classe peut ouvrir la bote noire de lobjet et fouiner dedans si elle na pas peur dannuler la garantie. Imposer un espace priv obligatoire tend mettre des btons dans les roues de personnes qui essaient simplement de faire leur travail. Perl part du principe quil est mieux dencapsuler ses donnes avec un criteau sur lequel il est crit :
EN CAS DINCENDIE BRISER LA GLACE

Vous devez si possible respecter lencapsulation, tout en gardant un accs ais au contenu en cas durgence, comme pour le dbogage. Mais si vous souhaitez imposer un espace priv, Perl ne va pas vous en empcher. Perl fournit des briques de base de bas niveau dont vous pouvez faire usage pour entourer votre classe et ses objets dun bouclier impntrable despace priv un bouclier en fait plus fort que celui dont on dispose dans de nombreux langages orients objet. Les portes lexicales et les variables lexicales quils contiennent en sont les lments principaux, et les fermetures y jouent un rle essentiel. Dans la section Mthodes prives, nous avons vu comment une classe peut utiliser les fermetures pour implmenter des mthodes qui sont invisibles lextrieur du fichier de module. Plus loin nous verrons des mthodes accesseurs qui rgulent des donnes de classe si prives que mme le reste de la classe ny a pas un accs illimit. Ces techniques restent des utilisations assez traditionnelles des fermetures. Lapproche vritablement intressante est dutiliser une fermeture pour lobjet lui-mme. Les variables dinstance de lobjet sont verrouilles lintrieur dune porte laquelle seul lobjet cest--dire, la fermeture a librement accs. Ceci est une forme trs forte dencapsulation ; elle empche non seulement toute altration de lextrieur, mais aussi dautres mthodes de la mme classe doivent utiliser les mthodes daccs appropries pour accder aux donnes dinstance de lobjet. Voici un exemple de comment cela pourrait fonctionner. Nous utiliserons des fermetures la fois pour les objets eux-mmes et pour les accesseurs gnrs :
package Personne; sub new { my $invoquant = shift; my $classe = ref($invoquant) || $invoquant; my $donnees = { NOM => "pas de nom", RACE => "inconnue", SURNOMS => [], }; my $self = sub { my $champ = shift; ############################################ ### METTRE LES VERIFICATIONS DACCES ICI ### ############################################ if (@_) { $donnees->{$champ} = shift } return $donnees->{$champ};

customer_8566

Gestion des donnes dinstance


}; bless($self, $classe); return $self; } # gnrer les noms de mthodes for my $champ (qw(nom race surnoms)) { no strict "refs"; # pour laccs la table de symboles *$champ = sub { my $self = shift; return $self->(uc $champ, @_); }; }

313

Lobjet cr et retourn par la mthode new nest plus un hachage, comme ctait le cas des autres constructeurs que nous avons vus. Cest une fermeture avec accs unique aux donnes des attributs stocks dans le hachage rfrenc par $donnees. Une fois lappel au constructeur termin, laccs $donnees (et donc aux attributs) ne se fait plus que par la fermeture. Dans un appel comme $lui->nom("Bombadil"), lobjet invoquant stock dans $self est la fermeture consacre et retourne par le constructeur. On ne peut pas faire grand-chose avec une fermeture sinon lappeler, donc cest ce que nous faisons avec $self->(uc $champ, @_). Ne vous laissez pas tromper par la f lche : ceci nest quun appel de fonction indirect, pas une invocation de mthode. Le paramtre initial est la chane nom , et dautres paramtres peuvent tre passs sa suite.7 Une fois quon sexcute lintrieur de la fermeture, la rfrence de hachage dans $donnees est nouveau accessible. La fermeture est alors libre de permettre ou dinterdire laccs ce qui lui plat. Personne en dehors de lobjet fermeture na daccs direct ces donnes dinstance extrmement prives, pas mme les autres mthodes de la classe. Elles pourraient essayer dappeler la fermeture de la mme faon que le font les mthodes gnres par la boucle for, dfinissant ventuellement une variable dinstance dont la classe naurait jamais entendu parler. Mais cette approche est aisment bloque en insrant divers bouts de code dans le constructeur lendroit du commentaire sur les vrifications daccs. Dabord, nous avons besoin dun prambule commun :
use Carp; local $Carp::CarpLevel = 1; # Afficher des messages croak courts my ($pack_appelant, $fichier_appelant) = caller();

Ensuite nous faisons chacune des vrifications. La premire sassure que le nom dattribut existe :
croak "Pas de champ valide $champ dans lobject" unless exists $donnees->{$champ};

Celle-ci ne permet laccs quaux appelants du mme fichier :


carp "Accs direct interdit aux fichiers trangers" unless $fichier_appelant eq __FILE__;

7. Bien sr, le double appel de fonction est lent, mais si vous vouliez que ce soit rapide, auriez vous vraiment choisi dutiliser des objets ?

customer_8566

314
Celle-ci ne permet laccs quaux appelants du mme paquetage :

Chapitre 12 Objets

carp "Accs direct interdit au paquetage tranger ${pack_appelant}::" unless $pack_appelant eq __PACKAGE__;

Et celle-ci ne permet laccs quaux appelants dont la classe hrite de la ntre :


carp "Accs direct interdit la classe inconnue ${pack_appelant}::" unless $pack_appelant->isa(__PACKAGE__);

Toutes ces vrifications ne font quempcher laccs direct. Les utilisateurs dune classe qui, poliment, nemploient que les mthodes de classes prvues ne souffrent pas dune telle restriction. Perl vous donne les outils pour tre aussi maniaque que vous le souhaitez. Heureusement, peu de gens souhaitent tre vraiment maniaques. Mais certaines personnes devraient ltre. Cest bien dtre maniaque lorsquon crit un logiciel de calculateur de vol. Si vous voulez tre ou devriez tre une telle personne, et que vous prfrez utiliser du code fonctionnel au lieu de tout rinventer vous-mme, jetez un coup dil sur CPAN au module Tie::SecureHash de Damian Conway. Il implmente des hachages restreints qui permettent des maniaqueries publiques, protges ou prives. Damian a aussi crit un module encore plus ambitieux, Class::Contract, qui impose un rgime dingnierie logicielle formelle au systme objet f lexible de Perl. La liste des fonctionnalits de ce module ressemble la liste de contrle dun livre crit par un professeur dingnierie logicielle8, avec notamment lencapsulation obligatoire, lhritage statique, et la vrification de conditions de conception par contrat pour le Perl orient objet, avec une syntaxe dclarative pour les dfinitions dattribut, de mthode, de constructeur, et de destructeur, la fois au niveau de lobjet et de la classe, et des prconditions, des post-conditions, et des invariants de classe. Ouf !

Nouvelles astuces
Depuis la version 5.6 de Perl, vous pouvez aussi dclarer une mthode pour indiquer quelle retourne une lvalue. Ceci se fait avec lattribut de fonction lvalue ( ne pas confondre avec les attributs dobjet). Cette fonctionnalit exprimentale vous permet de traiter une mthode comme quelque chose qui apparatrait du ct gauche dun signe gal :
package Bestiau; sub new { my $classe = shift; my $self = { petits => 0, @_ }; # Supplanter la valeur par dfaut. bless $self, $classe; } sub petits : lvalue { my $self = shift; $self->{petits}; } # Nous affecterons petits() plus loin.

8. Pouvez-vous deviner la profession de Damian ? propos, nous vous recommandons fortement son livre, Object Oriented Perl (Manning Publications, 1999).

customer_8566

Gestion des donnes de classe

315

package main; $vermine = Bestiau->new(petits => 4); $vermine->petits *= 2; # Affecter $vermine->petits ! $vermine->petits =~ s/(.)/$1$1/; # Modifier $vermine->petits sur place ! print $vermine->petits; # Nous avons maintenant 88 petits.

Ceci vous laisse faire semblant que $vermine->petits est une variable tout en respectant lencapsulation. Voir la section Lattribut lvalue du chapitre 6, Sous-programmes. Si vous excutez une version de Perl avec threads et que vous voulez vous assurer quun seul thread nappelle une mthode donne pour un objet, vous pouvez faire cela avec les attributs locked et method :
sub petits : locked method { ... }

Lorsquun thread invoque la mthode petits pour un objet, Perl verrouille lobjet avant excution, empchant dautres threads de faire la mme chose. Voir la section Les attibuts locked et method du chapitre 6.

Gestion des donnes de classe


Nous avons examin plusieurs approches pour accder aux donnes associes un objet. Mais parfois vous voulez un tat commun partag par tous les objets dune classe. Au lieu dtre seulement un attribut dune instance de la classe, ces variables sont globales pour la classe entire, quelle que soit linstance de classe (lobjet) que vous utilisez pour y accder. (Les programmeurs C++ les appelleraient des membres statiques de la classe.) Voici des situations o ces variables de classe seraient commodes : Pour compter au fur et mesure tous les objets crs, ou tous les objets en cours dutilisation. Pour garder la liste de tous les objets, liste que vous pouvez parcourir. Pour stocker le nom ou le descripteur dun fichier log utilis par une mthode de dbogage de toute la classe. Pour recenser des donnes accumules, comme la somme totale de liquide distribue en une journe par tous les distributeurs de billets dun rseau. Pour suivre le dernier objet cr par une classe ou lobjet le plus utilis. Pour grer un cache des objets en mmoire qui ont dj t reconstitus partir dune mmoire persistante. Pour fournir une table associative inverse permettant de trouver un objet partir de la valeur de lun de ses attributs.

Il reste dcider o stocker ltat de ces attributs partags. Perl na pas de mcanisme syntaxique particulier pour dclarer les attributs de classe, pas plus quil nen a pour les attributs dinstance. Perl fournit au dveloppeur un large ensemble de fonctionnalits puissantes mais f lexibles qui peuvent tre adaptes habilement aux exigences particulires dune situation. Vous pouvez donc slectionner le mcanisme qui correspond le mieux la situation donne au lieu de devoir vivre avec les choix de conception de quel-

customer_8566

316

Chapitre 12 Objets

quun dautre. Ou alors, vous pouvez vivre avec les choix de conception que quelquun dautre a empaquet et mis sur CPAN. Comme toujours, il y a plus dune faon de le faire, TMTOWTDI. Comme pour tout ce qui a trait une classe, on ne doit pas accder directement aux donnes de classe, particulirement de lextrieur de limplmentation de la classe ellemme. Ce nest gure respecter lencapsulation que de soigneusement crer des mthodes accesseurs pour les variables dinstance mais ensuite dinviter le public tripoter directement vos variables de classe, en affectant par exemple $UneClasse::Debug = 1. Pour tablir une barrire bien claire entre interface et implmentation, vous pouvez, pour manipuler les donnes de classe, crer des mthodes accesseurs similaires celles que vous employez pour les donnes dinstance. Imaginons que nous voulions connatre tout moment le compte de la population mondiale des objets Bestiau. Nous rangeons ce nombre dans une variable de paquetage, mais nous fournissons une mthode appele population pour que les utilisateurs de la classe naient pas connatre son implmentation.
Bestiau->population() $gollum->population() # Accs par le nom de classe # Accs par linstance

Comme en Perl une classe nest quun paquetage, une variable de paquetage est lendroit le plus naturel pour ranger une donne de classe. Voici une implmentation simple dune telle classe. La mthode population ne tient pas compte de son invoquant et ne fait que retourner la valeur courante de la variable de paquetage $Population. (Certains programmeurs aiment commencer leurs variables globales par une majuscule.)
package Bestiau; our $Population = 0; sub population { return $Population; } sub DESTROY { $Population-- } sub engendrer { my $invoquant = shift; my $classe = ref($invoquant) || $invoquant; $Population++; return bless { nom => shift || "anon" }, $classe; } sub nom { my $self = shift; $self->{nom} = shift if @_; return $self->{nom}; }

Si vous voulez crer des mthodes de donnes de classe qui fonctionnent comme les accesseurs de donnes dinstance, faites ceci :
our $Deboguage = 0; # donne de classe sub debug { shift; # on ignore intentionnellement linvoquant $Deboguage = shift if @_; return $Deboguage; }

Maintenant vous pouvez spcifier le niveau de dbogage global avec la classe ou avec lune quelconque de ses instances.

customer_8566

Gestion des donnes de classe

317

Comme $Deboguage est une variable de paquetage, elle est globalement accessible. Mais si vous changez la variable our en variable my, seul peut la voir le code situ sa suite dans le fichier. Vous pouvez en faire encore plus vous pouvez mme restreindre laccs aux attributs de classe au reste de la classe elle-mme. Emballez la dclaration de variable dans une porte de bloc :
{ my $Deboguage = 0; # donne de classe porte lexicale sub debug { shift; # on ignore intentionnellement linvoquant $Deboguage = shift if @_; return $Deboguage; } }

Maintenant personne na le droit de lire ou dcrire les attributs de classe sans utiliser la mthode accesseur, puisque seule cette fonction est dans la mme porte que la variable et y a accs. Si une classe drive hrite de ces accesseurs de classe, ils accdent tout de mme aux donnes dorigine, que ces variables soient dclares avec our ou avec my. Les donnes ne sont pas relatives au paquetage. Vous pouvez considrer que les accesseurs sexcutent dans la classe o ils ont t dfinis lorigine, pas dans la classe qui les invoque. Pour certaines donnes de classe, cette approche fonctionne correctement, mais pour dautres non. Supposons que nous crions une sous-classe Ouargue de Bestiau. Si nous voulons garder spares nos populations, Ouargue ne peut hriter de la mthode population de Bestiau, car cette mthode telle quelle est crite retourne la valeur de $Bestiau::Population. Il vous faudra dcider selon le cas de lutilit de rendre les attributs de classe relatifs au paquetage. Si vous voulez des attributs relatifs au paquetage, utilisez la classe de linvoquant pour situer le paquetage contenant les donnes de classe :
sub debug { my $invoquant = shift; my $classe = ref($invoquant) || $invoquant; my $nom_var = $classe . "::Deboguage"; no strict "refs"; # pour accder symboliquement #aux donnes de p aquetage $$nom_var = shift if @_; return $$nom_var; }

Nous annulons temporairement le pragma strict references car sans cela nous ne pourrions pas utiliser le nom symbolique qualifi de la variable globale de paquetage. Ceci est parfaitement raisonnable : puisque toutes les variables de paquetage se trouvent par dfinition dans la table de symboles du paquetage, il ny a pas de mal y accder par la table de symboles de ce paquetage. Une autre approche consiste rendre disponible tout ce dont a besoin un objet y compris ses donnes globales de classe par lobjet (ou pass en tant que paramtre). Pour ce faire, vous aurez souvent crer un constructeur spcifique pour chaque classe ou au moins une fonction dinitialisation spcifique appeler par le constructeur. Dans

customer_8566

318

Chapitre 12 Objets

le constructeur ou linitialiseur, vous stockez des rfrences aux donnes de classe directement dans lobjet lui-mme, pour ne pas devoir les chercher plus tard. Les mthodes accesseurs utilisent lobjet pour trouver une rfrence aux donnes. Au lieu de mettre la complexit de la recherche des donnes de classe dans chaque mthode, laissez simplement dire par lobjet la mthode o se situent les donnes. Cette approche ne fonctionne bien que lorsque les mthodes daccs aux donnes de classe sont invoques comme mthodes dinstance, car les donnes de classe pourraient tre dans des variables lexicales inaccessibles partir du nom dun paquetage. De quelque faon que lon sy prenne, les donnes de classes relatives un paquetage sont toujours un peu incommodes. Cest vraiment plus propre si, lorsque vous hritez dune mthode daccs une donne de classe, vous hritez aussi de la donne dtat laquelle elle accde. Voir la page man perltootc pour de nombreuses approches plus labores de la gestion des donnes de classe.

Rsum
Cest peu prs tout ce quil y a savoir, sauf tout le reste. Maintenant vous navez plus qu aller acheter un livre sur la mthodologie de la conception oriente objet et vous cogner le front avec durant six mois environ.

customer_8566

13
print $objet->comme_chaine; $nouvel_objet = $sujet->ajouter($objet);

Surcharge

Les objets sont chics, mais parfois ils sont juste un peu trop chics. Parfois lon prfrerait quils se comportent un peu moins comme des objets et un peu plus comme des types de donnes ordinaires. Mais voil le hic : les objets sont des rfrents reprsents par des rfrences, et celles-ci ne sont gure utiles sauf comme rfrences. Vous ne pouvez pas ajouter des rfrences, ou les afficher, ou leur appliquer (utilement) la plupart des oprateurs prdfinis de Perl. La seule chose que vous puissiez faire cest les drfrencer. Donc vous finissez par crire beaucoup dinvocations de mthode explicites, comme ceci :

De telles rfrences explicites sont en gnral une bonne chose ; vous ne devez jamais confondre vos rfrences avec vos rfrents, sauf quand vous voulez les confondre. Cest le cas qui se prsente ici. Si vous concevez votre classe avec la surcharge, vous pouvez faire comme si les rfrences ntaient pas l et dire simplement :
print $objet; $nouvel_objet = $sujet + $objet;

Lorsque vous surchargez lun des oprateurs prdfinis de Perl, vous dfinissez comment il se comporte lorsquil est appliqu aux objets dune classe donne. Un certain nombre de modules Perl standard utilisent la surcharge, comme Math::BigInt, qui vous permet de crer des objets Math::BigInt se comportant comme des entiers ordinaires mais sans limite de taille. Vous pouvez les ajouter avec +, les diviser avec /, les comparer avec <=>, et les afficher avec print. Notez que la surcharge diffre de lautochargement, qui charge la demande une fonction manquante. Il faut galement distinguer entre surcharger et supplanter, qui masque une fonction avec une autre. La surcharge ne cache rien ; elle ajoute un sens une opration qui naurait pas de sens sur une simple rfrence.

customer_8566

320

Chapitre 13 Surcharge

Le pragma overload
Le pragma use overload implmente la surcharge doprateur. Vous lui fournissez une liste de couples clef/valeur doprateurs et de leur comportement associ :
package MaClasse; use overload + => \&mon_addition, # rf de code < => "inferieur_a", # mthode nomme abs => sub { return @_ }; # fonction anonyme

Maintenant lorsque vous ajoutez deux objets MaClasse, la fonction mon_addition est appele pour crer le rsultat. Lorsque vous comparez deux objets MaClasse avec loprateur <, Perl remarque que le comportement est spcifi par une chane et interprte la chane comme le nom dune mthode et non comme un simple nom de fonction. Dans lexemple ci-dessus, la mthode inferieur_a pourrait tre fournie par le paquetage MaClasse lui-mme ou hrite dune classe de base de MaClasse, mais la fonction mon_addition doit tre fournie dans le paquetage courant. La fonction anonyme pour abs est fournie encore plus directement. De quelque manire que ces fonctions soient fournies, nous les appellerons des handlers. Dans le cas des oprateurs unaires (ceux qui ne prennent quun seul oprande, comme abs), le handler spcifi pour une classe est invoqu chaque fois que loprateur est appliqu un objet de cette classe. Dans le cas des oprateurs binaires comme + ou <, le handler est invoqu lorsque le premier oprande est un objet de la classe ou lorsque le deuxime oprande est un objet de la classe et le premier oprande na pas de comportement de surcharge. Cest pour que vous puissiez dire soit :
$objet + 6

soit :
6 + $objet

sans avoir vous soucier de lordre des oprandes. (Dans le deuxime cas, les oprandes seront permuts lorsquils seront passs au handler.) Si notre expression tait :
$animal + $legume

et $animal et $legume taient des objets de classes diffrentes, chacune utilisant la surcharge, cest le comportement de surcharge de $animal qui serait dclench. (Nous esprons que lanimal aime les lgumes.) Il ny a quun seul oprateur trinaire (ternaire) en Perl, ?:, et vous ne pouvez pas le surcharger. Heureusement.

Handlers de surcharge
Lorsquun oprateur surcharg sexcute, le handler correspondant est invoqu avec trois paramtres. Les deux premiers paramtres sont les deux oprandes. Si loprateur nutilise quun oprande, le deuxime paramtre est undef.

customer_8566

Handlers de surcharge

321

Le troisime paramtre indique si les deux premiers paramtres sont permuts. Mme selon les rgles de larithmtique ordinaire, certaines oprations ne se soucient pas de lordre de leurs paramtres, comme laddition et la multiplication, alors que dautres si, comme la soustraction ou la division.1 Considrez la diffrence entre :
$objet - 6

et :
6 - $objet

Si les deux premiers paramtres dun handler ont t permuts, le troisime paramtre sera vrai. Sinon, le troisime paramtre sera faux, auquel cas on fera aussi une distinction plus fine : si le handler a t dclench par un autre handler en rapport avec laffectation (si par exemple += appelle + pour dterminer comment faire une addition), alors le troisime paramtre nest pas simplement faux, mais undef. Cette distinction permet certaines optimisations. Par exemple, voici une classe qui vous permet de manipuler un intervalle born dentiers. Elle surcharge la fois + et - de manire contraindre le rsultat de laddition ou de la soustraction dobjets tre une valeur dans lintervalle de 0 255 :
package OctetBorne; use overload + => \&ajouter_borne, - => \&soustraire_borne; sub new { my $classe = shift; my $valeur = shift; return bless \$valeur => $classe; } sub ajouter_borne { my ($x, $y) = @_; my ($valeur) = ref($x) ? $valeur += ref($y) ? $valeur = 255 if $valeur $valeur = 0 if $valeur return bless \$valeur => }

$$x : $x; $$y : $y; > 255; < 0; ref($x);

sub soustraire_borne { my ($x, $y, $swap) = @_; my ($valeur) = (ref $x) ? $$x : $x; $valeur -= (ref $y) ? $$y : $y;

1. Vos objets surchargs nont pas lobligation de respecter les rgles de larithmtique ordinaire, bien entendu, mais il est habituellement conseill de ne pas surprendre son monde. Curieusement, de nombreux langages font lerreur de surcharger + avec la concatnation de chanes, qui nest pas commutative et qui nest que vaguement additive. Pour une approche diffrente, voir Perl.

customer_8566

322
if ($swap) { $valeur = -$valeur } $valeur = 255 if $valeur > 255; $valeur = 0 if $valeur < 0; return bless \$valeur => ref($x); } package main; $octet1 = OctetBorne->new(200); $octet2 = OctetBorne->new(100); $octet3 = $octet1 + $octet2; $octet4 = $octet1 - $octet2; $octet5 = 150 - $octet2; # 255 # 100 # 50

Chapitre 13 Surcharge

Vous noterez que chacune des fonctions est ici par ncessit un constructeur, donc chacune sassure de consacrer (avec bless) son nouvel objet dans la classe courante, quelle quelle soit ; nous supposons que la classe peut tre hrite. Nous supposons aussi que si $y est une rfrence, cest une rfrence un objet de notre propre type. Au lieu de tester ref($y), nous pourrions appeler $y->isa("OctetBorne"), si nous voulions tre plus complet (et excuter plus lentement).

Oprateurs surchargeables
Vous ne pouvez surcharger que certains oprateurs, qui sont lists dans le tableau 13-1. Les oprateurs sont galement lists dans le hachage %overload::ops mis disposition lorsque vous employez use overload, bien que la catgorisation y soit lgrement diffrente. Tableau 13-1. Oprateurs surchargeables
Catgorie Conversion Arithmtique Logique Sur les bits Affectation Comparaison Mathmatique Itratif Drfrence Pseudo Oprateurs "" 0+ bool + - * / % ** x . neg ! & | ~ ^ ! << >> += -= *= /= %= **= x= .= <<= >>= ++ -== < <= > >= != <=> lt le gt ge eq ne cmp atan2 cos sin exp abs log sqrt <> ${} @{} %{} &{} *{} nomethod fallback =>

Notez que neg, bool, nomethod et fallback ne sont pas rellement des oprateurs Perl. Les cinq oprateurs de drfrence, "" et 0+ ne ressemblent sans doute pas non plus des oprateurs. Nanmoins tous sont des clefs valides de la liste de paramtres que vous

customer_8566

Oprateurs surchargeables

323

fournissez use overload. Ceci nest pas vraiment un problme. Nous allons vous rvler un petit secret : cest un petit mensonge de dire que le pragma overload surcharge les oprateurs. Il surcharge les oprations sous-jacentes, quelles soient invoques explicitement par leurs oprateurs officiels ou implicitement par un oprateur apparent. (Les pseudo-oprateurs mentionns ci-dessus ne peuvent tre invoqus quimplicitement.) En dautres termes, la surcharge ne se produit pas au niveau syntaxique, mais au niveau smantique. Le but nest pas davoir lair bien, mais de faire ce qui est bien. Vous pouvez gnraliser. Notez aussi que = ne surcharge pas loprateur daffectation de Perl, comme vous pourriez le croire. Cela ne serait pas la bonne chose faire. Nous verrons cela plus tard. Commenons par traiter les oprateurs de conversion, non parce quils sont les plus vidents (ils ne le sont pas), mais parce quils sont les plus utiles. De nombreuses classes ne surchargent que la conversion en chane, spcifie par la clef "". (Oui, ce sont vraiment deux doubles apostrophes la suite.) Oprateurs de conversion : "", 0+, bool Ces trois clefs vous permettent de fournir Perl des comportements pour les conversions automatiques en chane, en nombre et en valeur boolenne, respectivement. La conversion en chane ou stringification a lieu lorsquune variable non-chane est utilise en tant que chane. Cest ce qui se passe lorsque vous convertissez une variable en chane par affichage, par interpolation, par concatnation ou mme en lutilisant comme clef de hachage. Cest la conversion en chane qui fait que vous voyez quelque chose comme SCALAR(0xba5fe0) lorsque vous essayez dafficher un objet avec print. La conversion en nombre ou numification a lieu lorsquune variable non-numrique est convertie en nombre dans un contexte numrique comme une expression mathmatique, un indice de tableau, ou mme un oprande de .., loprateur dintervalle. Enfin, bien que personne ici nose tout fait appeler cela boolification, vous pouvez dfinir comment un objet doit tre interprt en contexte boolen (comme if, unless, while, for, and, or, &&, ||, ?:, ou dans le bloc dune expression grep) en crant un handler de bool. Si vous avez dfini lun des trois oprateurs de conversion, les deux autres peuvent tre autognrs (nous expliquerons lautognration plus loin). Vos handlers peuvent retourner la valeur quils veulent. Notez que si lopration qui a dclench la conversion est galement surcharge, cette dernire surcharge aura lieu immdiatement aprs. Voici une dmonstration de "" qui invoque le handler comme_chaine dun objet au moment de la conversion en chane. Noubliez pas de dlimiter les doubles apostrophes :
package Personne; use overload q("") => \&comme_chaine; sub new { my $classe = shift;

customer_8566

324
return bless { @_ } => $classe; } sub comme_chaine { my $self = shift; my ($clef, $valeur, $resultat); while (($clef, $valeur) = each %$self) { $resultat .= "$clef => $valeur\n"; } return $resultat; }

Chapitre 13 Surcharge

$obj = Personne->new(taille => 72, poids => 165, yeux => "marron"); print $obj;

Au lieu de quelque chose comme Personne=HASH(0xba1350), ceci affiche (dans lordre du hachage) :
poids => 165 taille => 72 yeux => marron

(Nous esprons sincrement que cette personne na pas t mesure en kilos et en centimtres.) Oprateurs arithmtiques : +, -, *, /, %, **, x, ., neg Ceux-ci devraient tous vous tres familiers, sauf neg, qui est une clef spciale de surcharge du moins unaire : le - de -123. La distinction entre les clefs neg et - vous permet de spcifier des comportements diffrents pour le moins unaire et pour le moins binaire, plus connu sous le nom de soustraction. Si vous surchargez - mais pas neg, et quensuite vous utilisez le moins unaire, Perl vous mulera un handler de neg. Ceci est appel autognration, et se produit lorsque certains oprateurs peuvent raisonnablement tre dduits dautres oprateurs (en supposant que les oprateurs surchargs auront le mme rapport que les oprateurs ordinaires). Comme le moins unaire peut tre exprim en fonction du moins binaire (ainsi -123 quivaut 0 - 123), Perl ne vous oblige pas surcharger neg lorsque - suffit. (Bien sr, si vous avez arbitrairement spcifi que le moins binaire divise le second paramtre par le premier, le moins unaire sera une excellente manire de lever une exception de division par zro.) La concatnation avec loprateur . peut tre autognre partir du handler de conversion de chane (voir "" ci-dessus). Oprateur logique : ! Si un handler pour ! nest pas spcifi, il peut tre autognr partir du handler de bool, "", ou 0+. Si vous surchargez loprateur !, loprateur not dclenchera aussi le comportement que vous avez spcifi. (Vous souvenez-vous de notre petit secret ?) Vous serez peut-tre surpris par labsence des autres oprateurs logiques, mais ils ne peuvent pas pour la plupart tre surchargs car ils font un court-circuit. Ce sont en ralit des oprateurs de f lot de contrle qui doivent tre capables de retarder lva-

customer_8566

Oprateurs surchargeables

325

luation de certains de leurs paramtres. Cest aussi la raison pour laquelle loprateur ?: nest pas surchargeable. Oprateurs sur les bits : &, |, ~, ^, <<, >> Loprateur ~ est un oprateur unaire ; tous les autres sont binaires. Voici comment nous pourrions surcharger >> pour faire quelque chose comme chop :
package DecaleChaine; use overload >> => \&decale_droite, "" => sub { ${ $_[0] } }; sub new { my $classe = shift; my $valeur = shift; return bless \$valeur => $classe; } sub decale_droite { my ($x, $y) = @_; my $valeur = $$x; substr($valeur, -$y) = ""; return bless \$valeur => ref($x); } $chameau = DecaleChaine->new("Chameau"); $belier = $chameau >> 2; print $belier; # Chame

Oprateurs daffectation : +=, -=, *=, /=, %=, **=, x=, .=, <<=, >>=, ++, -Ces oprateurs daffectation peuvent changer la valeur de leurs paramtres ou les laisser inchangs. Le rsultat nest affect loprateur de gauche que si la nouvelle valeur diffre de lancienne. Ceci permet dutiliser le mme handler la fois pour += et pour +. Bien que ce soit permis, ceci est rarement recommand, puisque daprs la smantique dcrite plus loin dans la section Lorsquun handler de surcharge fait dfaut (nomethod et fallback), Perl invoquera de toute faon le handler de +, en supposant que += nait pas t surcharg directement. La concatnation (.=) peut tre autognre avec la conversion de chane, suivie de la concatnation de chanes ordinaire. Les oprateurs ++ et -- peuvent tre autognrs partir de + et de - (ou de += et de -=). Il est attendu des handlers implmentant ++ et -- quils mutent (altrent) leur paramtre. Si vous vouliez que lautodcrmentation fonctionne pour les lettres comme pour les nombres, vous pourriez le faire avec un handler comme ceci :
package DecMagique; use overload q(--) => \&decrementer, q("") => sub { ${ $_[0] } };

customer_8566

326
sub new { my $classe = shift; my $valeur = shift; bless \$valeur => $classe; }

Chapitre 13 Surcharge

sub decrementer { my @chaine = reverse split(//, ${ $_[0] } ); my $i; for ($i = 0; $i < @chaine; $i++ ) { last unless $chaine[$i] =~ /a/i; $chaine[$i] = chr( ord($chaine[$i]) + 25 ); } $chaine[$i] = chr( ord($chaine[$i]) - 1 ); my $resultat = join(, reverse @chaine); $_[0] = bless \$resultat => ref($_[0]); } package main; for $normal (qw/perl NZ Pa/) { $magique = DecMagique->new($normal); $magique--; print "$normal devient $magique\n"; }

Ce qui affiche :
perl devient perk NZ devient NY Pa devient Oz

inversant prcisment loprateur magique dauto-incrmentation de Perl. Lopration ++$a peut tre autognre avec $a += 1 ou avec $a = $a + 1 , et $a-avec $a -= 1 ou $a = $a - 1. Cependant, cela ne dclenche pas le comportement de copie dun vrai oprateur ++. Voir Le constructeur de copie (=) plus loin dans ce chapitre. Oprateurs de comparaison : ==, <, <=, >, >=, !=, <=>, lt, le, gt, ge, eq, ne, cmp Si <=> est surcharg, il peut servir pour autognrer les comportements des oprateurs suivants : <, <=, >, >=, ==, et !=. De manire similaire, si cmp est surcharg, il peut servir pour autognrer les comportements des oprateurs suivants : lt, le, gt, ge, eq, and ne. Notez que la surcharge de cmp ne vous permettra pas de trier les objets aussi facilement que vous le souhaiteriez, car ce sont les versions converties en chanes des objets qui seront compares, et non les objets eux-mmes. Si votre but tait de comparer les objets eux-mmes, vous auriez aussi surcharger "". Fonctions mathmatiques : atan2, cos, sin, exp, abs, log, sqrt Si abs nest pas disponible, il peut tre autognr partir de < ou de <=> en combinaison avec le moins unaire ou avec la soustraction. Un oprateur - surcharg peut servir autognrer les handlers manquants du

customer_8566

Oprateurs surchargeables

327

moins unaire ou de la fonction abs, qui peuvent aussi tre surchargs sparment. (Oui, nous savons que abs ressemble une fonction, alors que le moins unaire ressemble un oprateur, mais ils ne sont pas si diffrents que cela en ce qui concerne Perl.) Oprateur itratif : <> Le handler de <> peut tre dclench en utilisant la fonction readline (lorsquelle lit dans un fichier, comme dans while (<FH>)) ou la fonction glob (lorsquelle sert faire un glob de fichiers, comme dans @files = <*.*>).
package TirageHeureux; use overload <> => sub { my $self = shift; return splice @$self, rand @$self, 1; };

sub new { my $classe = shift; return bless [@_] => $classe; } package main; $loto = new TirageHeureux 1 .. 49; for (qw(1er 2eme 3eme 4eme 5eme 6eme)) { $numero_chanceux = <$loto>; print "Le $_ numro chanceux est : $numero_chanceux\n"; } $numero_chanceux = <$loto>; print "\nEt le numro complmentaire est : $numero_chanceux\n";

En France, ceci affiche :


The The The The The The 1er numro chanceux est : 14 2eme numro chanceux est : 29 3eme numro chanceux est : 45 4eme numro chanceux est : 23 5eme numro chanceux est : 9 6eme numro chanceux est : 25

Et le numro complmentaire est : 8

et vous rapporte 98 450 870 F. Oprateurs de drfrencement : ${}, @{}, %{}, &{}, *{} Les tentatives de drfrencement dune rfrence de scalaire, de tableau, de hachage, de fonction, ou de glob peuvent tre interceptes en surchargeant ces cinq symboles.

customer_8566

328

Chapitre 13 Surcharge

La documentation Perl en ligne de overload montre comment vous pouvez utiliser ces oprateurs pour simuler vos propres pseudo-hachages. Voici un exemple plus simple qui implmente un objet avec un tableau anonyme mais permet de le rfrencer comme un hachage. Nessayez pas de le traiter comme un vrai hachage ; vous ne pourrez pas utiliser delete pour supprimer des couples clef/valeur de lobjet. Si vous voulez combiner les notations de tableau et de hachage, utilisez un vrai pseudo-hachage (si lon peut dire).
package PsychoHachage; use overload %{} => \&comme_hachage; sub comme_hachage { my ($x) = shift; return { @$x }; } sub new { my $classe = shift; return bless [ @_ ] => $classe; } $bestiau = new PsychoHachage( taille => 72, poids => 365, type => "chameau" ); print $bestiau->{poids}; # affiche 365

Voyez aussi le chapitre 14, Variables lies, pour un mcanisme qui vous permet de redfinir les oprations de base sur les hachages, les tableaux, et les scalaires. Lorsque vous surchargez un oprateur, essayez de ne pas crer des objets avec des rfrences sur eux-mmes. Par exemple,
use overload + => sub { bless [ \$_[0], \$_[1] ] };

Ceci revient chercher des ennuis, car si vous dites $animal += $legume, le rsultat fera de $animal une rfrence un tableau consacr dont le premier lment est $animal. Ceci est une rfrence circulaire, ce qui veut dire que si vous dtruisez $animal, sa mmoire ne sera libre que lorsque se termine votre processus (ou votre interprteur). Voir Ramasse-miettes, rfrences circulaires et rfrences faibles au chapitre 8, Rfrences.

Le constructeur de copie (=)


Bien quil ressemble un oprateur ordinaire, = a une signification spciale et lgrement non-intuitive en tant que clef de surcharge. Il ne surcharge pas loprateur daffectation de Perl. Il ne le peut pas, car cet oprateur doit tre rserv pour laffectation des rfrences, sinon plus rien ne fonctionne. Le handler de = est utilis dans des situations o un oprateur de mutation (comme ++, -- ou lun des oprateurs daffectation) est appliqu une rfrence qui partage son objet avec une autre rfrence. Le handler de = vous permet dintercepter loprateur de mutation et de copier lobjet vous-mme de telle faon que la copie seule soit mute (al-

customer_8566

Lorsquun handler de surcharge fait dfaut (nomethod et fallback)


tre). Sans cela, vous craseriez lobjet dorigine.
$copie = $origine; ++$copie; # ne copie que la rfrence # modifie lobjet partag sous-jacent

329

Cest ici quil faut faire bien attention. Supposons que $origine soit une rfrence un objet. Pour faire en sorte que ++$copie ne modifie que $copie et non $origine, on commence par faire une copie de $copie et lon affecte $copie une rfrence ce nouvel objet. Cette opration na lieu que lorsque ++$copie est excut, donc $copie est identique $origine avant lincrmentation mais pas aprs. En dautres termes, cest le ++ qui reconnat la ncessit de faire une copie et qui appelle votre constructeur de copie. La ncessit de faire une copie nest reconnue que par les oprateurs de mutations comme ++ ou +=, ou par nomethod, dcrit plus loin. Si lopration est autognre avec +, comme dans :
$copie = $origine; $copie = $copie + 1;

alors il ny a pas de copie, car + ne sait pas quil est utilis comme oprateur de mutation. Si lexcution dun oprateur de mutation ncessite le constructeur de copie, mais quun handler pour = nest pas spcifi, il peut tre autognr comme copie de chane tant que lobjet reste un simple scalaire et non quelque chose de plus compliqu. Par exemple, le code rellement excut lors de la squence :
$copie = $origine; ... ++$copie;

pourrait ressembler quelque chose comme ceci :


$copie = $origine; ... $copie = $copie->clone(undef, ""); $copie->incr(undef, "");

Dans cet exemple $origine fait rfrence un objet surcharg, ++ est surcharg avec \&incr, et = est surcharg avec \&clone. Un comportement similaire est dclench par $copie = $origine++, ce qui est interprt comme $copie = $origine; ++$origine .

Lorsquun handler de surcharge fait dfaut (nomethod et fallback)


Si vous appliquez un oprateur non surcharg un objet, Perl tente dabord dautognrer un comportement partir dautres oprateurs surchargs en utilisant les rgles dcrites ci-dessus. Si cela choue, Perl cherche un comportement de surcharge de nomethod et lutilise sil est disponible. Ce handler joue le mme rle pour les oprateurs que joue la fonction AUTOLOAD pour les fonctions : cest ce que vous faites lorsque vous ne savez pas quoi faire dautre.

customer_8566

330

Chapitre 13 Surcharge

Si elle est employe, la clef nomethod doit tre suivie dune rfrence un handler prenant quatre paramtres (et non trois comme pour tous les autres handlers). Les trois premiers paramtres ne diffrent pas de ceux des autres handlers ; le quatrime est une chane correspondante loprateur dont le handler fait dfaut. Ceci joue le mme rle que la variable $AUTOLOAD pour les fonctions AUTOLOAD. Si Perl doit chercher un handler de nomethod mais nen trouve pas, une exception est leve. Si vous voulez empcher lautognration, ou si vous voulez quune tentative dautognration infructueuse ne produise aucune surcharge, vous pouvez dfinir la clef spciale de surcharge fallback. Celle-ci comporte trois tats : undef Si fallback nest pas dfinie, ou si undef lui est explicitement affect, la squence dvnements de surcharge nest pas modifie : Perl cherche les handlers, tente lautognration, et finit par invoquer le handler de nomethod. Si cela choue une exception est leve. faux Si lon affecte fallback une valeur dfinie mais fausse (comme 0), Perl ne tente jamais dautognration. Il appellera le handler de nomethod sil existe, mais lvera une exception dans le cas contraire. vrai Ceci est presque le mme comportement que pour undef, mais aucune exception nest leve si un handler appropri ne peut tre synthtis par autognration. Au lieu de cela, Perl retourne au comportement non surcharg de cet oprateur, comme si la classe ne contenait aucun pragma use overload.

Surcharge de constantes
Vous pouvez modifier la faon dont Perl interprte les constantes avec overload::constant, qui est le plus utilement plac dans la mthode import dun paquetage. (Si vous faites cela, vous devriez normalement invoquer overload::remove_constant dans la mthode unimport du paquetage pour que le paquetage puisse tout nettoyer lui-mme lorsque vous le lui demandez.) Les fonctions overload::constant et overload::remove_constant prennent chacune comme paramtre une liste de couples clef/valeur. Les clefs doivent tre parmi les suivantes : integer, float, binary, q, et qr. Chaque valeur doit tre le nom dune fonction, une fonction anonyme ou une rfrence de code qui traitera les constantes.
sub import { overload::constant ( integer float binary q qr => => => => => \&entier_handler, \&decimal_handler, \&base_handler, \&chaine_handler, \&regex_handler ) }

Les handlers que vous spcifiez pour integer et float sont invoqus chaque fois que lanalyseur lexical de Perl traite un nombre constant. Ceci est indpendant du pragma use constant ; de simples instructions comme :

customer_8566

Surcharge de constantes
$annee = cube(12) + 1; $pi = 3.14159265358979; # entier # nombre dcimal

331

dclencheront le handler spcifi. La clef binary vous permet dintercepter des constantes binaires, octales et hexadcimales. q traite les chanes entre apostrophes (dont les chanes introduites avec q) et les souschanes constantes contenues dans les chanes cites avec qq et qx et les documents icimme. Pour finir, qr traite les parties constantes contenues dans les expressions rgulires, comme il est mentionn la fin du chapitre 5, Recherche de motif. Le handler prend trois paramtres. Le premier paramtre est la constante dorigine, sous la forme fournie Perl. Le deuxime paramtre contient la constante une fois quelle est interprte par Perl ; par exemple, 123_456 apparatra comme 123456. Le troisime paramtre nest dfini que pour les chanes traites par les handlers de q et de qr et aura pour valeur qq, q, s ou tr selon lutilisation de la chane. qq signifie que la chane provient dun contexte interpol, comme les doubles apostrophes, les apostrophes inverses, une correspondance m// ou le motif dune substitution s///. q signifie que la chane provient dun contexte non interpol, s signifie que la constante est la chane de remplacement dune substitution s///, et tr signifie quelle est un composant dune expression tr/// ou y///. Le handler doit retourner un scalaire, qui sera utilis la place de la constante. Souvent, ce scalaire sera une rfrence un objet surcharg, mais rien ne vous empche de faire quelque chose de plus pervers :
package Doubleur; use overload; # Un module placer dans Doubleur.pm

sub import { overload::constant ( integer => \&handler, float => \&handler ) } sub handler { my ($orig, $interp, $contexte) = @_; return $interp * 2; # doubler toutes les constantes } 1;

Notez que handler est partag par les deux clefs, ce qui fonctionne correctement dans ce cas. Maintenant quand vous dites :
use Doubleur; $ennuis = 123; $danger = 3.21; # ennuis est maintenant 246 # danger est maintenant 6.42

vous redfinissez le monde. Si vous interceptez les chanes constantes, il est conseill de fournir galement un oprateur de concatnation ( . ), puisquune expression interpole comme "ab$cd!!" nest quun raccourci pour lexpression plus longue ab . $cd . !!. De faon similaire, on considre les nombres ngatifs comme les ngations de constantes positives, donc vous devez fournir un handler pour neg lorsque vous interceptez des entiers ou

customer_8566

332

Chapitre 13 Surcharge

des nombres dcimaux. (Il ny avait pas besoin de faire cela ci-dessus car nous retournons des nombres, et non des rfrences dobjets surchargs.) Notez que overload::constant ne se propage pas lintrieur dun eval compil au moment de lexcution, ce qui est soit un bogue soit une fonctionnalit selon votre point de vue.

Fonctions publiques de surcharge


Depuis la version 5.6 de Perl, le pragma use overload fournit les fonctions suivantes usage public : overload::StrVal(OBJ) Cette fonction retourne la valeur de chane que retournerait OBJ en labsence de la surcharge de la conversion en chane (""). overload::Overloaded(OBJ) Cette fonction retourne vrai si OBJ est sujet la surcharge dun oprateur quel quil soit, et faux sil ne lest pas. overload::Method(OBJ, OPERATEUR) Cette fonction retourne une rfrence au code qui implmente la surcharge de OPERATEUR lorsquil opre sur OBJ, ou undef si une telle surcharge nexiste pas.

Hritage et surcharge
Lhritage interagit avec la surcharge de deux faons. La premire a lieu lorsquun handler est nomm en tant que chane au lieu dtre spcifi comme rfrence de code ou comme fonction anonyme. Lorsquil est nomm en tant que chane le handler est interprt comme une mthode, et peut donc tre hrit de surclasse. La deuxime interaction entre lhritage et la surcharge provient du fait que toute classe drive dune classe surcharge est elle-mme sujette cette surcharge. En dautres termes, la surcharge est elle-mme hrite. Lensemble des handlers dune classe est lunion des handlers de tous les anctres de cette classe, rcursivement. Si un handler peut tre trouv dans plusieurs anctres diffrents, le choix du handler utiliser est rgi par les rgles habituelles dhritage de mthode. Par exemple, si la classe Alpha hrite des classes Betaet Gamma dans cet ordre, et que la classe Beta surcharge + avec \&Beta::fonction_plus, mais que la classe Gamma surcharge + avec la chane "methode_plus", alors cest Beta::fonction_plus qui sera appele lorsque vous appliquez + un objet Alpha. Comme la valeur de la clef fallback nest pas un handler, son hritage nest pas rgi par les rgles ci-dessus. Dans limplmentation actuelle, on utilise la valeur de fallback du premier anctre surcharg, mais ceci est accidentel et sujet modification sans pravis (enfin, sans trop de pravis).

customer_8566

Surcharge lexcution

333

Surcharge lexcution
Comme les instructions use sont excutes la compilation, la seule faon de modifier la surcharge lexcution est :
eval " use overload + => \&mon_addition ";

Vous pouvez aussi dire :


eval " no overload +, --, <= ";

bien que lemploi de ces formules lexcution soit douteux.

Surcharge de diagnostics
Si votre Perl est compil avec -DDEBUGGING, vous pouvez voir les messages de diagnostics de surcharge lorsque vous excutez un programme avec loption -Do ou son quivalent. Vous pouvez aussi dduire quelles oprations sont surcharges en utilisant la commande m du dbogueur interne de Perl. Si maintenant vous vous sentez un peu surcharg, le chapitre suivant vous permettra peut-tre de lier un peu la sauce.

customer_8566

customer_8566

Variables lies

14

Certaines activits humaines ncessitent un dguisement. Parfois lintention est de tromper, mais le plus souvent il sagit de communiquer quelque chose de vrai un niveau plus profond. Souvent, par exemple, quelquun qui vous fait passer un entretien dembauche sattend ce que vous portiez une cravate pour signifier que vous souhaitez srieusement vous intgrer, mme si vous savez tous les deux que vous ne porterez jamais de cravate au travail. Cest curieux lorsquon y pense : nouer un morceau de tissu autour de son cou peut magiquement vous obtenir un emploi. Dans la culture Perl, loprateur de liaison tie1 joue un rle similaire : il vous permet de crer une variable apparemment normale qui, derrire son dguisement, est en fait un objet Perl part entire dont on peut sattendre quelle ait sa propre personnalit intressante. Cest juste un drle de bout de magie, comme tirer Bugs Bunny dun chapeau. Formul autrement, les drles de caractres $, @, % ou * devant un nom de variable en disent long Perl et ses programmeurs ils sous-entendent chacun un ensemble spcifique de comportements caractristiques. Vous pouvez dformer ces comportements de diverses manires utiles avec tie en associant la variable une classe qui implmente un nouvel ensemble de comportements. Par exemple, vous pouvez crer un hachage Perl ordinaire et le lier avec tie une classe qui transforme le hachage en base de donnes, de sorte que quand vous lisez des valeurs du hachage, Perl va par magie chercher les donnes dans un fichier de donnes externe, et que quand vous affectez des valeurs au hachage, Perl stocke par magie les donnes dans le mme fichier. Ici, par magie signifie en effectuant de manire transparente quelque chose de trs compliqu . Vous connaissez le vieux dicton : toute technologie suffisamment avance est indiscernable dun script Perl. (Srieusement, les gens qui jouent avec les tripes de Perl utilisent magique comme terme technique dsignant toute smantique supplmentaire attache des variables telles que %ENV ou %SIG. Les variables lies nen sont quune extension.) Perl possde dj les fonctions internes dbmopen et dbmclose, qui lient magiquement des variables de hachage des bases de donnes, mais ces fonctions datent du temps o Perl

1. Note du traducteur : en anglais tie signifie lier ou attacher, et... cravate.

customer_8566

336

Chapitre 14 Variables lies

navait pas loprateur tie. Maintenant, tie fournit un mcanisme plus gnral. En fait, Perl lui-mme implmente dbmopen et dbmclose laide de tie. Vous pouvez lier avec tie un scalaire, un tableau, un hachage ou un handle de fichier (via son typeglob) toute classe qui fournit les mthodes nommes de manire approprie pour intercepter et simuler un accs normal ces variables. La premire de ces mthodes est invoque au moment de la liaison elle-mme : le fait de lier une variable invoque toujours un constructeur, qui retourne en cas de succs un objet que Perl stocke labri des regards, cach lintrieur de la variable normale . Vous pouvez toujours rcuprer cet objet plus tard en appliquant la fonction tied la variable normale :
tie VARIABLE, NOM_CLASSE, LISTE; # relie VARIABLE NOM_CLASSE $objet = tied VARIABLE;

Ces deux lignes sont quivalentes :


$objet = tie VARIABLE, NOM_CLASSE, LISTE;

Une fois quelle est lie, vous pouvez traiter la variable normale normalement, mais chaque accs invoque automatiquement une mthode de lobjet sous-jacent ; toute la complexit de la classe est cache derrire ces appels de mthodes. Si plus tard vous voulez rompre lassociation entre la variable et la classe, vous pouvez dlier la variable avec untie :
untie VARIABLE;

Vous pouvez presque considrer tie comme une espce de bless bizarre, ceci prs quil consacre une simple variable au lieu dune rfrence un objet. Il peut aussi prendre des paramtres supplmentaires, linstar dun constructeur ce qui nest pas terriblement surprenant, dans la mesure o il invoque un constructeur en interne, dont le nom dpend du type de la variable que vous liez : TIESCALAR, TIEARRAY, TIEHASH ou TIEHANDLE.2 Ces constructeurs sont invoqus en tant que mthodes de classe, avec NOM_CLASSE comme invoquant, plus tout paramtre additionnel que vous donnez dans LISTE. (La VARIABLE nest pas passe au constructeur.) Ces quatre constructeurs retournent chacun un objet de la faon habituelle. Ni les constructeurs, ni les autres mthodes de la classe ne se soucient vraiment de savoir sils ont t invoqus par tie, puisque vous pouvez toujours les invoquer directement si vous le souhaitez. En un sens, toute la magie se situe dans tie et non dans la classe implmentant le tie. La classe nest en ce qui la concerne quune classe ordinaire avec des drles de noms de mthode. (En effet, certains modules lis fournissent des mthodes supplmentaires qui ne sont pas visibles par la variable lie ; ces mthodes doivent tre appeles explicitement comme vous le feriez pour toute autre mthode dobjet. De telles mthodes supplmentaires pourraient fournir des services comme le verrouillage de fichiers, la protection de transactions, ou tout autre chose que pourrait faire une mthode dinstance.) Ainsi ces constructeurs consacrent (avec bless) et retournent une rfrence dobjet comme le ferait toute autre constructeur. Cette rfrence ne doit pas forcment rfren2. Comme les constructeurs ont des noms distincts, vous pourriez mme fournir une classe unique les implmentant tous. Cela vous permettrait de lier des scalaires, des tableaux, des hachages et des handles de fichiers la mme classe, bien que ce ne soit gnralement pas fait, car cela rendrait dlicat lcriture des autres mthodes magiques.

customer_8566

Liaison de scalaire

337

cer le mme type de variable que celle qui est lie ; elle doit simplement tre consacre afin que la variable lie puisse retrouver le chemin de votre classe en cas de besoin. Par exemple, notre long exemple de TIEARRAY utilise un objet bas sur un hachage afin quil puisse commodment contenir des informations supplmentaires sur le tableau quil mule. La fonction tie nexcutera pas votre place de use ou de require vous devez le faire vous-mme explicitement, avant dappeler le tie. (Cela dit, pour des raisons de compatibilit descendante, la fonction dbmopen tentera de faire un use de lune ou lautre implmentation DBM. Mais vous pouvez lempcher de choisir en faisant un use explicite, du moment que le module que vous spcifiez figure dans la liste des modules que peut choisir dbmopen. Voir la doc en ligne du module AnyDBM_File pour une explication plus complte.) Les mthodes appeles par une variable lie ont un nom prdtermin comme FETCH (rcuprer) et STORE (stocker), puisquelles sont invoques implicitement (cest--dire dclenches par des vnements spcifiques) de lintrieur de la machinerie de Perl. Ces noms sont en MAJUSCULES, suivant la convention courante pour les fonctions appeles implicitement. (Dautres noms spciaux qui suivent cette convention sont BEGIN, CHECK, INIT, END, DESTROY et AUTOLOAD, sans parler de UNIVERSAL->VERSION. En fait, presque toutes les variables prdfinies et les handles de fichiers de Perl sont en majuscules : STDIN, SUPER, CORE, CORE::GLOBAL, DATA, @EXPORT, @INC, @ISA, @ARGV et %ENV Bien entendu, les . oprateurs internes et les pragmas, lextrme oppos, nont pas du tout de majuscules.) La premire chose que nous traiterons est extrmement simple : comment lier une variable scalaire.

Liaison de scalaire
Afin dimplmenter un scalaire li, une classe doit dfinir les mthodes suivantes : TIESCALAR, FETCH et STORE (et ventuellement DESTROY). Lorsque vous liez une variable scalaire avec tie, Perl appelle TIESCALAR. Lorsque vous consultez la variable lie, il appelle FETCH, et lorsque vous affectez une valeur la variable, il appelle STORE. Si vous avez gard en main lobjet retourn par le tie initial (ou si vous le rcuprez plus tard avec tied), vous pouvez accder vous-mme lobjet sous-jacent ceci ne dclenche ni FETCH ni STORE. En tant quobjet, il nest pas du tout magique, et tout fait objectif. Sil existe une mthode DESTROY, Perl linvoque lorsque disparat la dernire rfrence lobjet li, comme pour tout autre objet. Cela se produit lorsque votre programme se termine ou lorsque vous appelez untie, ce qui limine la rfrence utilise par tie. Cependant, untie nlimine pas les rfrences existantes que vous pourriez avoir stockes ailleurs ; DESTROY est report jusqu ce que ces rfrences aient galement disparu. Les paquetages Tie::Scalar et Tie::StdScalar, situs tous les deux dans le module Tie::Scalar, fournissent des dfinitions de classe de base simples si vous ne souhaitez pas dfinir toutes ces mthodes vous-mme. Tie::Scalar fournit des mthodes lmentaires qui ne font quasiment rien, et Tie::StdScalar fournit des mthodes qui font se comporter un scalaire li comme un scalaire Perl ordinaire. (Ce qui semble particulirement inutile, mais parfois vous voulez juste un lger emballage autour de la smantique de scalaire ordinaire, comme par exemple pour compter le nombre de fois quune variable donne est affecte.)

customer_8566

338

Chapitre 14 Variables lies

Avant de vous montrer un exemple recherch et une description complte de toute la mcanique, voici juste un avant-got pour vous mettre en apptit et pour vous montrer quel point cest facile. Voici un programme complet :
#!/usr/bin/perl package Centime; sub TIESCALAR { bless \my $self, shift } sub STORE { ${ $_[0] } = $_[1] } # faire laction par dfaut sub FETCH { sprintf "%.02f", ${ my $self = shift } } # valeur arrondie package main; tie $francs, "Centime"; $francs = 45.00; $francs *= 1.0715; # taxe $francs *= 1.0715; # et double taxe ! print "Ce sera $francs francs, sil vous plat.\n";

lexcution, le programme affiche :


Ce sera 51.67 francs, sil vous plat.

Pour voir la diffrence, mettez lappel tie en commentaire. Vous obtiendrez :


Ce sera 51.66505125 francs, sil vous plat.

Reconnaissons que cela reprsente beaucoup defforts juste pour arrondir des nombres.

Mthodes de liaison de scalaire


Maintenant que vous avez vu un chantillon de ce qui va venir, dveloppons une classe de liaison de scalaire plus recherche. Au lieu dutiliser un paquetage prt lemploi pour la classe de base (et tant donn que les scalaires sont si simples), nous examinerons tour tour chacune des quatre mthodes en construisant une classe exemple nomme FichierScalaire. Les scalaires lis cette classe contiennent des chanes ordinaires, et chaque variable de ce type est implicitement associe au fichier dans lequel la chane est stocke. (Vous pourriez nommer vos variables de manire vous rappeler quel fichier vous faites rfrence.) Les variables sont lies la classe de la manire suivante :
use FichierScalaire; # charger FichierScalaire.pm tie $chameau, "FichierScalaire", "/tmp/camel.ide";

Une fois la variable lie, son contenu dorigine est cras, et la connexion interne entre la variable et son objet supplante la smantique normale de la variable. Lorsque vous demandez la valeur de $chameau, elle lit le contenu de /tmp/camel.ide, et lorsque vous affectez une valeur $chameau, elle crit le nouveau contenu dans /tmp/camel.ide, crasant tout occupant prcdent. La liaison est faite sur la variable et non sur sa valeur, donc la nature lie dune variable nest pas prserve par laffectation. Par exemple, supposons que vous copiiez une variable lie :
$dromadaire = $chameau;

Au lieu de lire la valeur comme lordinaire dans la variable scalaire $chameau, Perl invoque la mthode FETCH de lobjet associ sous-jacent. Cest comme si vous aviez crit

customer_8566

Liaison de scalaire
ceci :
$dromadaire = (tied $chameau)->FETCH():

339

Ou si vous retenez lobjet retourn par tie, vous pouvez utiliser cette rfrence directement, comme dans le code exemple suivant :
$cide = tie $chameau, "FichierScalaire", "/tmp/camel.ide"; $dromadaire = $chameau; # par linterface implicite $dromadaire = $cide->FETCH(); # pareil, mais explicitement

Si la classe fournit des mthodes autres que TIESCALAR, FETCH, STORE, et DESTROY, vous pouvez utiliser $cide pour les invoquer manuellement. Toutefois, ordinairement on soccupe de ses propres affaires et on laisse lobjet sous-jacent tranquille, ce qui explique quon utilise rarement la valeur de retour de tie. Vous pouvez toujours rcuprer lobjet avec tied si vous en avez besoin plus tard (par exemple, si la classe documente dautres mthodes dont vous avez besoin). Ne pas utiliser lobjet retourn limine aussi certains types derreur, ce que nous traiterons plus loin. Voici le prambule de notre classe, que nous mettrons dans FichierScalaire.pm :
package FichierScalaire; use Carp; use strict; use warnings; use warnings::register; my $compteur = 0; # Transmettre gentiment les messages derreur. # Simposer un peu de discipline. # Activer les avertissements de porte lexicale. # Permettre lutilisateur de dire # "use warnings FichierScalaire". # Compteur interne de FichierScalaires lis.

Le module standard Carp exporte les fonctions carp, croak, et confess, que nous utiliserons dans le code plus loin. Comme dhabitude, voir le chapitre 32, Modules standards, ou la doc en ligne pour plus de dtails sur Carp. Les mthodes suivantes sont dfinies par la classe : NOM_CLASSE->TIESCALAR(LISTE) La mthode TIESCALAR de la classe est dclenche lorsque vous liez une variable avec tie. La LISTE en option contient les paramtres ncessaires pour initialiser lobjet correctement. (Dans notre exemple, il ny a quun seul paramtre : le nom du fichier.) La mthode doit retourner un objet, mais celui-ci nest pas ncessairement une rfrence un scalaire. Mais il lest dans notre exemple.
sub TIESCALAR { # dans FichierScalaire.pm my $classe = shift; my $nom_fichier = shift; $compteur++; # Une lexicale visible dans le fichier, # prive pour la classe return bless \$nom_fichier, $classe; }

Comme il ny a pas dquivalent scalaire des compositeurs de tableau et de hachage anonymes [] et {}, nous consacrons simplement le rfrent de la variable lexicale, qui devient de fait anonyme ds la sortie de la porte lexicale du nom. Ceci fonctionne bien (vous pourriez faire de mme avec les tableaux et les hachages) tant que la variable est rellement lexicale. Si vous tentiez cette astuce avec une variable globale, vous pourriez croire vous en sortir jusqu ce que vous tentiez de crer un

customer_8566

340

Chapitre 14 Variables lies

autre camel.ide. Ne soyez pas tent dcrire quelque chose comme ceci :
sub TIESCALAR { bless \$_[1], $_[0] } # FAUX, pourrait rfrencer # une variable globale

Un constructeur crit de manire plus robuste pourrait vrifier que le fichier est accessible. Nous vrifions dabord que le fichier est lisible, comme nous ne souhaitons pas craser la variable existante. (En dautres termes, il ne faut pas supposer que lutilisateur commence par crire dans le fichier. Il pourrait garder prcieusement son ancien fichier camel.ide produit par une excution antrieure du programme.) Si nous ne pouvons pas ouvrir ou crer le fichier spcifi, nous indiquons lerreur gentiment en retournant undef et en affichant en option un avertissement avec carp. (Au lieu de cela nous pourrions moins gentiment faire un croak cest une affaire de got.) Nous utilisons le pragma warnings pour dterminer si lutilisateur sintresse ou non notre avertissement :
sub TIESCALAR { # dans FichierScalaire.pm my $classe = shift; my $nom_fichier = shift; my $hf; if (open $hf, "<", $nom_fichier or open $hf, ">", $nom_fichier) { close $hf; $compteur++; return bless \$nom_fichier, $classe; } carp "Impossible de lier $nom_fichier: $!" if warnings::enabled(); return; }

tant donn un tel constructeur, nous pouvons prsent associer le scalaire $chaine au fichier camel.ide :
tie ($chaine, "FichierScalaire", "camel.ide") or die;

(Nous faisons encore des suppositions que nous ne devrions pas faire. Dans une version en production, nous nouvririons probablement quune fois le fichier, en retenant le handle de fichier ainsi que le fichier pour la dure de la liaison, et en gardant tout ce temps un verrouillage exclusif sur le handle laide de flock. Sans cela nous risquons des situations de concurrence (race conditions) voir Gestion des problmes de synchronisation dans le chapitre 23, Scurit.) SELF->FETCH Cette mthode est invoque chaque fois que vous accdez une variable lie (cest--dire, que vous la lisez). Elle ne prend pas de paramtre hormis lobjet li la variable. Dans notre exemple, cet objet contient le nom de fichier :
sub FETCH { my $self = shift; confess "Je ne suis pas une mthode de classe" unless ref $self; return unless open my $hf, $$self; read($hf, my $valeur, -s $hf); # NB: nutilisez pas -s avec # les tubes ! return $valeur; }

customer_8566

Liaison de scalaire

341

Cette fois nous avons dcid dexploser (lever une exception) si FETCH reoit autre chose quune rfrence. (Soit elle tait invoque comme mthode de classe, soit quelquun la appele par erreur en tant que fonction.) Nous navons pas dautre moyen de retourner une erreur, donc cest probablement la raction approprie. En fait, Perl aurait de toute faon lev une exception ds que nous aurions tent de drfrencer $self ; nous sommes simplement polis en utilisant confess pour dverser une trace arrire complte de la pile sur lcran de lutilisateur. (Si lon peut considrer cela poli.) Nous pouvons maintenant voir le contenu de camel.ide lorsque nous disons :
tie($chaine, "FichierScalaire", "camel.ide"); print $chaine;

SELF->STORE(VALEUR) Cette mthode est excute lorsquune valeur est affecte la variable lie. Le premier paramtre, SELF, est comme toujours lobjet associ la variable ; VALEUR est ce qui est affect la variable. (Nous utilisons le terme affect au sens large toute opration qui modifie la variable peut appeler STORE.)
sub STORE { my($self,$valeur) = @_; ref $self or confess "pas une mthode de classe"; open my $hf, ">", $$self or croak "impossible dcraser $$self: $!"; syswrite($hf, $valeur) == length $valeur or croak "impossible dcrire dans $$self: $!"; close $hf or croak "impossible de fermer $$self: $!"; return $valeur; }

Aprs avoir affect la nouvelle valeur, nous la retournons car cest ce que fait laffectation. Si laffectation na pas russi, nous affichons lerreur avec croak. Parmi les causes ventuelles dchec : nous navions pas la permission dcrire dans le fichier associ, ou le disque sest rempli, ou des malins gnies ont infest le contrleur de disque. Parfois vous contrlez la magie, et parfois cest elle qui vous contrle. Nous pouvons maintenant crire dans camel.ide en disant ceci :
tie($chaine, "FichierScalaire", "camel.ide"); $chaine = "Voici la premire ligne de camel.ide\n"; $chaine .= "Et voici une deuxime ligne, rajoute automatiquement.\n";

SELF->DESTROY Cette mthode est dclenche lorsque lobjet associ la variable lie est sur le point dtre recycl par le ramasse-miettes, au cas o il devrait faire quelque chose de spcial pour nettoyer autour de lui. Comme pour les autres classes, cette mthode est rarement ncessaire, puisque Perl vous libre automatiquement la mmoire de lobjet moribond. Ici, nous dfinissons une mthode DESTROY qui dcrmente notre compteur de fichiers lis :
sub DESTROY { my $self = shift; confess "mauvais type" unless ref $self; $compteur--; }

customer_8566

342

Chapitre 14 Variables lies

Nous pourrions alors aussi fournir une mthode de classe supplmentaire pour rcuprer la valeur courante du compteur. vrai dire, elle ignore si elle est appele comme mthode de classe ou dobjet, mais vous navez plus dobjet aprs le DESTROY, non ?
sub count { # my $invoquant = shift; $compteur; }

Vous pouvez lappeler comme mthode de classe tout moment comme ceci :
if (FichierScalaire->count) { warn "Il reste des FichierScalaires lis quelque part...\n"; }

Cest peu prs tout ce quil y a faire. vrai dire, cest plus que tout ce quil y a faire, puisque nous avons fait quelques choses gentilles pour tre complets, robustes, et esthtiques (ou pas). Il est certainement possible de faire des classes TIESCALAR plus simples.

Variables compteur magiques


Voici une classe Tie::Counter simple, inspire du module CPAN de mme nom. Les variables lies cette classe sincrmentent de 1 chaque fois quelles sont utilises. Par exemple :
tie my $compte "Tie::Counter", 100; @tableau = qw /Rouge Vert Bleu/; for my $couleur (@tableau) { # Affiche : print " $compteur $couleur\n"; # 100 Rouge } # 101 Vert # 102 Bleu

Le constructeur prend en option un paramtre supplmentaire spcifiant la valeur initiale du compteur, par dfaut 0. Laffectation au compteur lui donne une nouvelle valeur. Voici la classe :
package Tie::Counter; sub FETCH { ++ ${ $_[0] } } sub STORE { ${ $_[0] } = $_[1] } sub TIESCALAR { my ($classe, $valeur) = @_; $valeur = 0 unless defined $valeur; bless \$valeur => $classe; } 1; # ncessaire dans un module

Vous voyez comme cest court ? Nul besoin de beaucoup de code pour assembler une classe comme celle-ci.

Bannir $_ par magie


Cette classe de liaison curieusement exotique permet dinterdire les emplois non localiss de $_. Au lieu dintgrer un module avec use, qui invoque la mthode import de la

customer_8566

Liaison de scalaire

343

classe, ce module doit tre charg avec no pour appeler la mthode unimport rarement utilise. Lutilisateur dit :
no Souligne;

Alors toutes les utilisations de $_ comme variable globale non localise lvent une exception. Voici une suite de tests pour le module :
#!/usr/bin/perl no Souligne; @tests = ( "Affectation" "Lecture" "Comparaison" "Chop" "Test fichier" "Embot" );

=> => => => => =>

sub sub sub sub sub sub

{ { { { { {

$_ = "Mal" }, print }, $x = /mauvais/ }, chop }, -x }, for (1..3) { print } },

while ( ($nom, $code) = splice(@tests, 0, 2) ) { print "Tester $nom : "; eval { &$code }; print $@ ? "dtect" : " rat !"; print "\n"; }

qui affiche ce qui suit :


Tester Tester Tester Tester Tester Tester Affectation : dtect Lecture : dtect Comparaison : dtect Chop : dtect Test fichier : dtect Embot : 123 rat !

Ce dernier est rat parce quil est localis correctement par la boucle for et donc sr daccs. Voici le module curieusement exotique Souligne lui-mme. (Avons-nous mentionn quil est curieusement exotique ?) Il fonctionne car la magie lie est de fait cache par un local. Le module fait le tie dans son propre code dinitialisation pour le cas o il serait appel par un require.
package Souligne; use Carp; sub TIESCALAR { bless \my $toto => shift } sub FETCH { croak Accs en lecture $_ interdit } sub STORE { croak Accs en criture $_ interdit } sub unimport { tie($_, __PACKAGE__) } sub import { untie $_ } tie($_, __PACKAGE__) unless tied $_; 1;

customer_8566

344

Chapitre 14 Variables lies

Il est difficile de mler de manire utile dans votre programme des appels use et no pour cette classe, car ils se produisent tous la compilation, et non lexcution. Vous pourriez appeler Souligne->import et Souligne->unimport directement, comme le font use et no. Mais normalement, pour vous permettre dutiliser $_ librement, vous lui appliqueriez simplement local, ce qui est tout lintrt de la manipulation.

Liaison de tableau
Une classe qui implmente un tableau li doit dfinir au moins les mthodes TIEARRAY, FETCH, et STORE. Il y a aussi beaucoup de mthodes optionnelles : la mthode DESTROY omniprsente, bien entendu, mais aussi les mthodes STORESIZE et FETCHSIZE, qui donnent accs $#tableau et scalar(@tableau). De plus, CLEAR est dclenche lorsque Perl doit vider un tableau, et EXTEND lorsque Perl aurait par avance allou plus de mmoire pour un vrai tableau. Vous pouvez aussi dfinir les mthodes POP PUSH, SHIFT, UNSHIFT, SPLICE, DELETE, et EX, ISTS si vous voulez que les fonctions Perl correspondantes fonctionnent avec le tableau li. La classe Tie::Array peut servir de classe de base pour implmenter les cinq premires de ces fonctions partir de FETCH et de STORE. (Limplmentation par dfaut dans Tie::Array de DELETE et de EXISTS appelle simplement croak.) Tant que vous dfinissez FETCH et STORE, le type de structure de donnes contenu par votre objet na pas dimportance. Dun autre ct, la classe de base Tie::StdArray (dfinie dans le module standard Tie::Array module) fournit des mthodes par dfaut qui supposent que lobjet contient un tableau ordinaire. Voici une simple classe de liaison de tableau qui en fait usage. Parce quelle utilise Tie::StdArray comme classe de base, seules sont dfinir les mthodes qui doivent tre traites dune manire non standard.
#!/usr/bin/perl package TableauHorloge; use Tie::Array; our @ISA = Tie::StdArray; sub FETCH { my($self,$emplacement) = @_; $self->[ $emplacement % 12 ]; } sub STORE { my($self,$emplacement,$valeur) = @_; $self->[ $emplacement % 12 ] = $valeur; } package main; tie my @tableau, TableauHorloge; @tableau = ( "a" ... "z" ); print "@tableau\n";

Lorsquil est excut, le programme affiche "y z o p q r s t u v w x". Cette classe implmente un tableau ne comportant que douze cases, comme les heures du cadran dune horloge, numrotes de 0 11. Si vous demandez le 15e lment du tableau, vous obtenez en ralit le 3e. Vous pouvez voir la classe comme une aide pour les gens qui nont pas appris lire lheure sur une horloge 24 heures.

customer_8566

Liaison de tableau

345

Mthodes de liaison de tableau


Ctait la mthode simple. Voyons maintenant les menus dtails. Pour illustrer notre propos, nous implmenterons un tableau de taille limite la cration. Si vous tentez daccder quelque chose au-del de cette limite, une exception est leve. Par exemple :
use TableauLimite; tie @tableau, "TableauLimite", 2; $tableau[0] $tableau[1] $tableau[2] $tableau[3] = = = = "bon"; "bien"; "super"; "oula";

# Interdit : affiche un message derreur

Le code en prambule de cette classe est le suivant :


package TableauLimite; use Carp; use strict;

Pour viter de devoir dfinir SPLICE plus tard, nous lhriterons de la classe Tie::Array :
use Tie::Array; our @ISA = ("Tie::Array");

NOM_CLASSE->TIEARRAY(LISTE) En tant que constructeur de la classe, TIEARRAY doit retourner une rfrence consacre qui mulera le tableau li. Dans cet exemple, juste pour vous montrer que vous ne devez pas ncessairement retourner une rfrence de tableau, nous choisissons de reprsenter notre objet avec une rfrence de hachage. Un hachage fonctionne bien comme type gnrique denregistrement : la valeur de la clef LIMITE du hachage stocke la limite maximale autorise, et sa valeur DONNEES contient les donnes relles. Si quelquun lextrieur de la classe tente de drfrencer lobjet retourn (en pensant sans doute quil sagit dune rfrence un tableau), une exception est leve.
sub TIEARRAY { my $classe = shift; my $limite = shift; confess "usage: tie(\@tableau, TableauLimite, index_max)" if @_ || $limite =~ /\D/; return bless { LIMITE => $limite, DONNEES => [] }, $classe; }

Maintenant nous pouvons dire :


tie(@tableau, "TableauLimite", 3); # lindex maximum autoris est 3

pour nous assurer que le tableau naura jamais plus de quatre lments. chaque fois quun lment du tableau est consult ou enregistr, FETCH ou STORE sera appele tout comme elle ltait pour les scalaires, mais avec lindex en paramtre supplmentaire. SELF->FETCH(INDEX) Cette mthode est excute chaque fois que lon accde un lment du tableau li. Elle prend un paramtre aprs lobjet : lindex de la valeur que nous tentons de rcuprer.

customer_8566

346

Chapitre 14 Variables lies


sub FETCH { my ($self, $index) = @_; if ($index > $self->{LIMITE}) { confess "Dpassement de limite du tableau : $index > $self->{LIMITE}"; } return $self->{DONNEES}[$index]; }

SELF->STORE(INDEX,VALEUR) Cette mthode est invoque chaque fois que lon affecte une valeur un lment du tableau. Elle prend deux paramtres aprs lobjet : lindex de la case o nous tentons de stocker quelque chose et la valeur que nous tentons dy mettre.
sub STORE { my($self, $index, $valeur) = @_; if ($index > $self->{LIMITE} ) { confess "Dpassement de limite du tableau : $index > $self->{LIMITE}"; } return $self->{DONNEES}[$index] = $valeur; }

SELF->DESTROY Perl appelle cette mthode lorsque la variable lie doit tre dtruite et sa mmoire rcupre. Ceci nest presque jamais utile dans un langage avec un ramasse-miettes, donc cette fois-ci nous la laissons de ct. SELF->FETCHSIZE La mthode FETCHSIZE devrait retourner le nombre total dlments dans le tableau li associ SELF. Cest lquivalent de scalar(@tableau), qui est habituellement gal $#tableau + 1.
sub FETCHSIZE { my $self = shift; return scalar @{$self->{DONNEES}}; }

SELF->STORESIZE(NOMBRE) Cette mthode spcifie le NOMBRE total dlments dans le tableau li associ SELF. Si le tableau rtrcit, vous devez supprimer les lments au-del de NOMBRE. Si le tableau grandit, vous devez vous assurer que les nouvelles positions sont indfinies. Dans notre classe TableauLimite, nous empchons aussi que le tableau ne grandisse au-del de la limite spcifie initialement.
sub STORESIZE { my ($self, $nombre) = @_; if ($nombre > $self->{LIMITE}) { confess "Dpassement de limite du tableau : $nombre > $self->{LIMITE}"; } $#{$self->{DONNEES}} = $nombre; }

customer_8566

Liaison de tableau
SELF->EXTEND(NOMBRE)

347

Perl se sert de la mthode EXTEND pour indiquer que le tableau risque daugmenter pour accommoder NOMBRE lments. Ainsi vous pouvez tout de suite allouer la mmoire en un gros morceau au lieu de lallouer plus tard et petit petit avec de nombreux appels successifs. Comme notre TableauLimite possde une taille limite fixe, nous ne dfinissons pas cette mthode. SELF->EXISTS(INDEX) Cette mthode vrifie lexistence dans le tableau li de llment situ la position INDEX. Pour notre TableauLimite, nous ne faisons quemployer la fonction interne exists de Perl aprs avoir vrifi quil ne sagit pas dune tentative de regarder audel de la limite suprieure fixe.
sub EXISTS { my ($self, $index) = @_; if ($index > $self->{LIMITE}) { confess "Dpassement de limite du tableau : $index > $self->{LIMITE}"; } exists $self->{DONNEES}[$index]; }

SELF->DELETE(INDEX) La mthode DELETE supprime llment la position INDEX du tableau li SELF. Dans notre classe TableauLimite, la mthode est presque identique EXISTS, mais ceci nest pas toujours le cas.
sub DELETE { my ($self, $index) = @_; print STDERR "suppression !\n"; if ($index > $self->{LIMITE}) { confess "Dpassement de limite du tableau : $index > $self->{LIMITE}"; } delete $self->{DONNEES}[$index]; }

SELF->CLEAR Cette mthode est appele lorsque le tableau doit tre vid. Cela se produit lorsquon affecte une liste de nouvelles valeurs (ou une liste vide) au tableau, mais pas lorsquil est soumis la fonction undef. Comme un TableauLimite vid satisfait toujours la limite suprieure, nous navons rien vrifier ici.
sub CLEAR { my $self = shift; $self->{DONNEES} = []; }

Si vous affectez une liste au tableau, CLEAR sera dclenche mais ne verra pas les valeurs de la liste. Donc si vous passez outre la limite suprieure ainsi :
tie(@tableau, "TableauLimite", 2); @tableau = (1, 2, 3, 4);

customer_8566

348

Chapitre 14 Variables lies

la mthode CLEAR retournera quand mme avec succs. Lexception ne sera leve que lors du STORE qui suit. Laffectation dclenche un CLEAR et quatre STORE. SELF->PUSH(LISTE) Cette mthode ajoute les lments de LISTE la fin du tableau. Voici quoi elle pourrait ressembler pour notre classe TableauLimite :
sub PUSH { my $self = shift; if (@_ + $#{$self->{DONNEES}} > $self->{LIMITE}) { confess "Tentative dajouter trop dlments"; } push @{$self->{DONNEES}}, @_; }

SELF->UNSHIFT(LISTE) Cette mthode insre les lments de LISTE au dbut du tableau. Dans notre classe TableauLimite, la fonction ressemblerait PUSH. SELF->POP La mthode POP enlve le dernier lment du tableau et le retourne. Pour TableauLimite, cest une ligne :
sub POP { my $self = shift; pop @{$self->{DONNEES}} }

SELF->SHIFT La mthode SHIFT enlve le premier lment de la liste et le retourne. Pour TableauLimite, cest similaire POP . SELF->SPLICE(POSITION,LONGUEUR,LISTE) Cette mthode vous permet dpisser (splice) le tableau SELF. Pour imiter la fonction interne splice de Perl, POSITION devrait tre en option et zro par dfaut, et compter en arrire partir de la fin du tableau sil est ngatif. LONGUEUR devrait galement tre en option, et par dfaut la longueur du reste du tableau. LISTE peut tre vide. Si elle imite correctement la fonction interne, la mthode retournera une liste des LONGUEUR lments partir de POSITION (cest--dire la liste des lments devant tre remplacs par LISTE). Comme lpissage est une opration assez complexe, nous ne la dfinirons pas du tout ; nous ne ferons quutiliser la fonction SPLICE du module Tie::Array dont nous disposons sans rien faire en hritant de Tie::Array. De cette manire nous dfinissons SPLICE en fonction dautres mthodes de TableauLimite, et donc la vrification de limites aura tout de mme lieu. Ceci complte notre classe TableauLimite. Elle ne fait que lgrement dformer la smantique des tableaux. Mais nous pouvons faire mieux, et plus court.

Commodit de notation
Une des choses bien avec les variables cest quelles interpolent. Une des choses moins bien avec les fonctions cest quelles ne le font pas. Vous pouvez utiliser un tableau li pour faire une fonction qui peut tre interpole. Supposons que vous vouliez interpoler des nombres alatoires dans une chane. Vous pouvez juste dire :

customer_8566

Liaison de hachage
#!/usr/bin/perl package InterpAleat; sub TIEARRAY { bless \my $self }; sub FETCH { int rand $_[1] }; package main; tie @rand, "InterpAleat"; for (1,10,100,1000) { print "Un entier alatoire plus petit que $_ serait $rand[$_]\n"; } $rand[32] = 5; # Cela va-t-il reformater notre disque systme ?

349

Lorsquil est excut, ce programme affiche :


Un entier alatoire Un entier alatoire Un entier alatoire Un entier alatoire Cant locate object plus petit que plus petit que plus petit que plus petit que method "STORE" 1 serait 0 10 serait 5 100 serait 81 1000 serait 765 via package "InterpAleat" at foo line 11.

Comme vous le voyez, ce nest pas si grave de ne pas avoir implment STORE. Cela explose simplement de faon normale.

Liaison de hachage
Une classe qui implmente un hachage li doit dfinir huit mthodes. TIEHASH construit de nouveaux objets. FETCH et STORE donnent accs aux couples clef/valeur. EXISTS indique si une clef est prsente ou non dans le hachage, et DELETE supprime une clef et sa valeur associe.3 CLEAR vide le hachage en supprimant tous les couples clef/valeur. FIRSTKEY et NEXTKEY itrent sur les couples clef/valeur lorsque vous appelez keys, values ou each. Et comme dhabitude, si vous voulez excuter des actions spcifiques lorsque lobjet est dsallou, vous pouvez dfinir une mthode DESTROY. (Si ceci vous semble un grand nombre de mthodes, vous navez pas lu avec attention la section prcdente sur les tableaux. En tout cas, nhsitez pas hriter de mthodes par dfaut du module standard Tie::Hash, en ne redfinissant que les mthodes intressantes. Ici aussi, Tie::StdHash sattend ce que limplmentation soit aussi un hachage.) Par exemple, supposons que vous vouliez crer un hachage pour lequel, chaque fois que vous affectez une valeur une clef, au lieu dcraser la valeur dorigine, la nouvelle valeur soit ajoute la fin dun tableau de valeurs existantes. Comme cela lorsque vous dites :
$h{$c} = "un"; $h{$c} = "deux";

Cela fait en ralit :


push @{ $h{$c} }, "un"; push @{ $h{$c} }, "deux";
3. Souvenez-vous que Perl distingue entre une clef absente du hachage et une clef prsente dans le hachage mais ayant undef comme valeur associe. Les deux possibilits peuvent tre testes avec exists et defined, respectivement.

customer_8566

350

Chapitre 14 Variables lies

Cela nest pas une ide trs complique, donc vous devriez pouvoir employer un module assez simple, ce que vous pouvez faire en utilisant Tie::StdHash comme classe de base. Voici une classe Tie::HachageRajout qui fait prcisment cela :
package Tie::HachageRajout; use Tie::Hash; our @ISA = ("Tie::StdHash"); sub STORE { my ($self, $clef, $valeur) = @_; push @{$self->{$clef}}, $valeur; } 1;

Mthodes de liaison de hachage


Voici un exemple intressant de classe de liaison de hachage : elle vous donne un hachage qui reprsente les fichiers point dun utilisateur (cest--dire les fichiers dont le nom commence avec un point, ce qui est une convention de nommage des fichiers de configuration sous Unix). Vous indexez dans le hachage avec le nom du fichier (sans le point) et vous rcuprez le contenu du fichier point. Par exemple :
use FichiersPoint; tie %dot, "FichiersPoint"; if ( $point{profile} =~ /MANPATH/ or $point{login} =~ /MANPATH/ or $point{cshrc} =~ /MANPATH/ ) { print "il semble que vous spcifiez votre MANPATH\n"; }

Voici une autre manire dutiliser notre classe lie :


# Le troisime paramtre est le nom de lutilisateur # dont nous examinerons les fichiers point. tie %lui, "FichiersPoint", "daemon"; foreach $f (keys %lui) { printf "le fichier point %s de daemon est de taille %d\n", $f, length $lui{$f}; }

Dans notre exemple FichiersPoint nous implmentons le hachage avec un hachage ordinaire comportant plusieurs champs importants, dont seul le champ {CONTENU} contient ce que voit lutilisateur comme son hachage. Voici les vrais champs de lobjet :
Champ UTILISATEUR REPERTOIRE ECRASER CONTENU Contenu Celui dont lobjet reprsente les fichiers point. O se situent ces fichiers point. Si lon a le droit de modifier ou dcraser ces fichiers point. Le hachage de couples nom de fichier point et contenu.

customer_8566

Liaison de hachage
Voici le dbut de FichiersPoint.pm :
package FichiersPoint; use Carp; sub quietaisje { (caller(1))[3] . "()" } my $DEBOGUAGE = 0; sub deboguage { $DEBOGUAGE = @_ ? shift : 1 }

351

Dans notre exemple, nous voulons pouvoir dclencher laffichage de messages de dbogage pendant le dveloppement de la classe, do lutilit de $DEBOGUAGE. Nous gardons aussi sous la main en interne une fonction pratique pour afficher les avertissements : quietaisje retourne le nom de la fonction ayant appel la fonction courante (la fonction grand-mre de quietaisje). Voici les mthodes pour le hachage li FichiersPoint : NOM_CLASSE->TIEHASH(LISTE) Voici le constructeur de FichiersPoint :
sub TIEHASH { my $self = shift; my $utilisateur = shift || $>; my $rep_point = shift || ""; croak "usage: @{[ &quietaisje ]} [UTILISATEUR [REP_POINT]]" if @_; $utilisateur = getpwuid($utilisateur) if $utilisateur =~ /^\d+$/; my $rep = (getpwnam($utilisateur))[7] or croak "@{ [&quietaisje] }: pas dutilisateur $utilisateur"; $rep .= "/$rep_point" if $rep_point; my $noeud = { UTILISATEUR REPERTOIRE CONTENU ECRASER };

=> => => =>

$utilisateur, $rep, {}, 0,

opendir REP, $rep or croak "@{[&quietaisje]}: impossible douvrir $rep: $!"; for my $point ( grep /^\./ && -f "$rep/$_", readdir(REP)) { $point =~ s/^\.//; $noeud->{CONTENU}{$point} = undef; } closedir REP; return bless $noeud, $self; }

Cela vaut sans doute la peine de mentionner que si vous allez appliquer des tests de fichier sur les valeurs retournes par le readdir ci-dessus, vous avez intrt les prfixer avec le rpertoire concern (comme nous le faisons). Sans quoi, en labsence dun chdir, vous risqueriez de ne pas tester le bon fichier.

customer_8566

352
SELF->FETCH(CLEF)

Chapitre 14 Variables lies

Cette mthode implmente la lecture dun lment du hachage li. Elle prend un paramtre aprs lobjet : la clef dont nous tentons de rcuprer la valeur. Cette clef est une chane, et vous pouvez faire ce que vous voulez avec (qui soit cohrent avec sa nature de chane). Voici le fetch de notre exemple FichiersPoint :
sub FETCH { carp &quietaisje if $DEBOGUAGE; my $self = shift; my $point = shift; my $rep = $self->{REPERTOIRE}; my $fichier = "$rep/.$point"; unless (exists $self->{CONTENU}->{$point} || -f $fichier) { carp "@{[&quietaisje]}: pas de fichier $point" if $DEBOGUAGE; return undef; } # Implmenter un cache. if (defined $self->{CONTENU}->{$point}) { return $self->{CONTENU}->{$point}; } else { return $self->{CONTENU}->{$point} = `cat $rep/.$point`; } }

Nous avons un peu trich en excutant la commande Unix cat(1), mais il serait plus portable (et plus efficace) douvrir le fichier nous-mmes. Dun autre ct, comme les fichiers point sont un concept unixien, nous ne sommes pas tellement concerns. Ou nous ne devrions pas ltre. Ou quelque chose comme a... SELF->STORE(CLEF,VALEUR) Cette mthode fait ce quil faut lorsquun lment du hachage li est modifi (crit). Elle prend deux paramtres aprs lobjet : la clef sous laquelle nous stockons la nouvelle valeur, et la valeur elle-mme. Dans notre exemple FichiersPoint, nous ne permettons pas un utilisateur dcrire un fichier sans dabord invoquer la mthode ecraser sur lobjet dorigine retourn par tie :
sub STORE { carp &quietaisje if $DEBOGUAGE; my $self = shift; my $point = shift; my $valeur = shift; my $fichier = $self->{REPERTOIRE} . "/.$point"; croak "@{[&quietaisje]}: $fichier non crasable" unless $self->{ECRASER}; open(F, "> $fichier") or croak "impossible douvrir $fichier: $!"; print F $valeur; close(F); }

customer_8566

Liaison de hachage
Si quelquun souhaite craser quelque chose, il peut dire :
$ob = tie %points_daemon, "daemon"; $ob->ecraser(1); $points_daemon{signature} = "Un vrai dmon\n";

353

Mais il pourrait galement modifier {ECRASER} laide de tied :


tie %points_daemon, "FichiersPoint", "daemon"; tied(%points_daemon)->ecraser(1);

ou en une instruction :
(tie %points_daemon, "FichiersPoint", "daemon")->ecraser(1);

La mthode ecraser est simplement :


sub ecraser { my $self = shift; $self->{ECRASER} = @_ ? shift : 1; }

SELF->DELETE(CLEF) Cette mthode traite les tentatives de suppression dun lment du hachage. Si votre hachage mul utilise quelque part un vrai hachage, vous pouvez simplement appeler le vrai delete. De nouveau, nous prenons la prcaution de vrifier que lutilisateur souhaite rellement craser des fichiers :
sub DELETE { carp &quietaisje if $DEBOGUAGE; my $self = shift; my $point = shift; my $fichier = $self->{REPERTOIRE} . "/.$point"; croak "@{[&quietaisje]}: ne supprime pas le fichier $fichier" unless $self->{ECRASER}; delete $self->{CONTENU}->{$point}; unlink $fichier or carp "@{[&quietaisje]}: impossible de supprimer $fichier: $!"; }

SELF->CLEAR Cette mthode est excute lorsque le hachage entier doit tre vid, habituellement en lui affectant la liste vide. Dans notre exemple, cela supprimerait tous les fichiers point de lutilisateur ! Cest une chose tellement dangereuse que nous exigerons que ECRASER soit suprieur 1 avant que cela ne puisse se produire :
sub CLEAR { carp &quietaisje if $DEBOGUAGE; my $self = shift; croak "@{[&quietaisje]}: ne supprime pas tous les fichiers point de $self->{UTILISATEUR}" unless $self->{ECRASER} > 1; for my $point ( keys %{$self->{CONTENU}}) { $self->DELETE($point); } }

customer_8566

354
SELF->EXISTS(CLEF)

Chapitre 14 Variables lies

Cette mthode est excute lorsque lutilisateur invoque la fonction exists sur un hachage donn. Dans notre exemple, nous examinons le hachage {CONTENU} pour trouver la rponse :
sub EXISTS { carp &quietaisje if $DEBOGUAGE; my $self = shift; my $point = shift; return exists $self->{CONTENU}->{$point}; }

SELF->FIRSTKEY Cette mthode est appele lorsque lutilisateur commence itrer sur le hachage, comme lors dun appel keys, values ou each. En appelant keys dans un contexte scalaire, nous rinitialisons son tat interne pour nous assurer que le prochain each utilis dans linstruction return obtiendra bien la premire clef.
sub FIRSTKEY { carp &quietaisje if $DEBOGUAGE; my $self = shift; my $temp = keys %{$self->{CONTENU}}; return scalar each %{$self->{CONTENU}}; }

SELF->NEXTKEY(CLEF_PRECEDENTE) Cette mthode est litrateur dune fonction keys, values ou each. CLEF_PRECEDENTE est la dernire clef laquelle on a accd, ce que sait fournir Perl. Ceci est utile si la mthode NEXTKEY doit connatre ltat prcdent pour calculer ltat suivant. Dans notre exemple, nous utilisons un vrai hachage pour reprsenter les donnes du hachage li, ceci prs que ce hachage est stock dans le champ CONTENU du hachage plutt que dans le hachage lui-mme. Donc nous pouvons compter sur loprateur each de Perl :
sub NEXTKEY { carp &quietaisje if $DEBOGUAGE; my $self = shift; return scalar each %{ $self->{CONTENU} } }

SELF->DESTROY Cette mthode est dclenche lorsque lobjet du hachage li est sur le point dtre dsallou. Elle nest vraiment utile que pour le dbogage et le nettoyage. En voici une version trs simple :
sub DESTROY { carp &quietaisje if $DEBOGUAGE; }

Maintenant que nous vous avons donn toutes ces mthodes, voici un exercice faire la maison : reprendre tout par le dbut, trouver les endroits o nous avons interpol @{[&quietaisje]}, et les remplacer par un simple scalaire li nomm $quietaisje qui fait la mme chose.

customer_8566

Liaison de handle de fichier

355

Liaison de handle de fichier


Une classe qui implmente un handle de fichier li doit dfinir les mthodes suivantes : TIEHANDLE, et lune au moins de PRINT, PRINTF, WRITE, READLINE, GETC, ou READ. La classe peut galement fournir une mthode DESTROY, et la dfinition des mthodes BINMODE, OPEN, CLOSE, EOF, FILENO, SEEK, TELL, READ et WRITE permet au handle de fichier li dmuler les fonctions internes Perl correspondantes. (Enfin, ce nest pas tout fait vrai : WRITE correspond syswrite et na rien voir avec la fonction Perl interne write, qui fait de laffichage laide de dclarations format.) Les handles de fichier lis sont particulirement utiles lorsque Perl est intgr dans un autre programme (comme Apache ou vi) et que laffichage par STDOUT ou STDERR doit tre redirig de manire spciale. Mais il nest en fait mme pas ncessaire que les handles de fichier soient lis un fichier. Vous pouvez utiliser des instructions de sortie pour construire une structure de donnes en mmoire, et des instructions dentre pour la rcuprer. Voici une manire simple dinverser une srie dinstructions print et printf sans inverser chaque ligne :
package InversePrint; use strict; sub TIEHANDLE { my $classe = shift; bless [], $classe; } sub PRINT { my $self = shift; push @$self, join , @_; } sub PRINTF { my $self = shift; my $fmt = shift; push @$self, sprintf $fmt, @_; } sub READLINE { my $self = shift; pop @$self; } package main; my $m = "--MORE--\n"; tie *INV, "InversePrint"; # Faire des print et des printf. print INV "Le juge blond est soudainement trs malade.$m"; printf INV <<"END", int rand 10000000; Portez %d vieux whiskys au juge blond qui fume ! END

customer_8566

356
print INV <<"END"; Portez ce vieux whisky au juge blond qui fume. END # Maintenant on lit partir du mme handle. print while <INV>;

Chapitre 14 Variables lies

Ceci affiche :
Portez ce vieux whisky au juge blond qui fume. Portez 7387770 vieux whiskys au juge blond qui fume ! Le juge blond est soudainement trs malade.--MORE--

Mthodes de liaison de handle de fichier


Pour notre exemple dtaill, nous crerons un handle de fichier qui met en majuscules les chanes qui lui sont soumises. Pour nous amuser un peu, nous ferons commencer le fichier avec <CRIER> lorsquil est ouvert, et nous le fermerons avec </CRIER> lorsquil est ferm. Comme a nous pourrons divaguer en XML bien form. Voici le dbut du fichier Crier.pm qui implmente la classe :
package Crier; use Carp; # Pour pouvoir signaler les erreurs avec croak

Listons prsent les dfinitions de mthode de Crier.pm. NOM_CLASSE->TIEHANDLE(LISTE) Ceci est le constructeur de la classe, qui comme dhabitude doit retourner une rfrence consacre :
sub TIEHANDLE { my $classe = shift; my $forme = shift; open my $self, $forme, @_ or croak "impossible douvrir $forme@_: $!"; if ($forme =~ />/) { print $self "<CRIER>\n"; $$self->{ECRITURE} = 1; # Se souvenir dcrire la balise #de fin } return bless $self, $classe; # $self est une rfrence de glob }

Ici, nous ouvrons un nouveau handle de fichier selon le mode et le nom de fichier passs loprateur tie, nous crivons <CRIER> dans le fichier, et nous retournons une rfrence consacre. Il se passe beaucoup de choses dans cette instruction open, mais nous indiquerons simplement que, en plus de lidiome habituel open or die , le my $self passe un scalaire non dfini open, qui sait comment lautovivifier en un typeglob. Sa nature de typeglob est galement intressante, car le typeglob contient non seulement le vritable objet entre/sortie du fichier, mais aussi

customer_8566

Liaison de handle de fichier

357

diverses autres structures de donnes pratiques, comme un scalaire ($$$self), un tableau (@$$self), et un hachage (%$$self). (Nous ne mentionnerons pas la fonction, &$$self.) La $forme est un paramtre indiquant soit le nom de fichier, soit le mode. Si cest un nom de fichier, @_ est vide, donc cela se comporte comme un open deux paramtres. Autrement, $forme est le mode pour les paramtres restants. Aprs louverture, nous faisons un test pour dterminer si nous devons crire la balise ouvrante, auquel cas nous le faisons. Et immdiatement nous utilisons une de ces structures de donnes susmentionnes. Ce $$self->{ECRITURE} est un exemple dutilisation du glob pour stocker une information intressante. Dans ce cas, nous retenons si nous avons crit la balise ouvrante afin de savoir si nous devons crire la balise fermante correspondante. Nous utilisons le hachage %$$self, donc nous pouvons donner au champ un nom comprhensible. Nous aurions pu utiliser le scalaire $$$self, mais une telle utilisation ne se documenterait pas elle-mme. (Ou elle ne ferait que se documenter elle-mme, selon votre point de vue.) SELF->PRINT(LISTE) Cette mthode implmente le print sur le handle li. La LISTE contient ce qui a t pass print. Notre mthode ci-dessous met en majuscules chaque lment de la LISTE :
sub PRINT { my $self = shift; print $self map {uc} @_; }

SELF->READLINE Cette mthode fournit les donnes lorsque le handle de fichier est lu avec loprateur angle (<HF>) ou avec readline. La mthode doit retourner undef lorsquil ny a plus de donnes.
sub READLINE { my $self = shift; return <$self>; }

Ici, nous faisons simplement return <$self> pour que la mthode se comporte correctement selon quelle est appele en contexte scalaire ou en contexte de liste. SELF->GETC Cette mthode sexcute chaque fois quest appele getc sur le handle de fichier li.
sub GETC { my $self = shift; return getc($self); }

Comme plusieurs des mthodes dans notre classe Crier, la mthode GETC ne fait quappeler sa fonction interne Perl correspondante et retourner le rsultat. SELF->OPEN(LISTE) Notre mthode TIEHANDLE ouvre elle-mme le fichier, mais un programme qui utilise la classe Crier et appelle ensuite open dclenche cette mthode.

customer_8566

358

Chapitre 14 Variables lies


sub OPEN { my $self = shift; my $forme = shift; my $nom = "$forme@_"; $self->CLOSE; open($self, $forme, @_) or croak "impossible de rouvrir $nom: $!"; if ($forme =~ />/) { print $self "<CRIER>\n" or croak "impossible de commencer le print: $!"; $$self->{ECRITURE} = 1; # Se souvenir dcrire la balise de fin } else { $$self->{ECRITURE} = 0; # Se souvenir de ne pas crire # la balise de fin } return 1; }

Nous invoquons notre propre mthode CLOSE pour fermer le fichier explicitement au cas o lutilisateur ne se serait pas souci de le faire lui-mme. Ensuite nous ouvrons un nouveau fichier avec le nom de fichier spcifi dans le open, et nous crions dedans. SELF->CLOSE Cette mthode gre les requtes de fermeture du handle. Ici, nous faisons un seek jusqu la fin du fichier et, sil russit, nous affichons </CRIER> avant dappeler le close interne de Perl.
sub CLOSE { my $self = shift; if ($$self->{ECRITURE}) { $self->SEEK(0, 2) $self->PRINT("</CRIER>\n") } return close $self; }

or return; or return;

SELF->SEEK(LISTE) Lorsque vous faites un seek sur un handle de fichier li, la mthode SEEK est appele.
sub SEEK { my $self = shift; my ($position, $depart) = @_; return seek($self, $position, $depart); }

SELF->TELL Cette mthode est invoque lorsque tell est appele sur le handle de fichier li.
sub TELL { my $self = shift; return tell $self; }

customer_8566

Liaison de handle de fichier


SELF->PRINTF(LISTE)

359

Cette mthode est excute lorsque printf est appele sur le handle de fichier li. La LISTE contient le format et les lments afficher.
sub PRINTF { my $self = shift; my $format = shift; return $self->PRINT(sprintf $format, @_); }

Ici, nous employons sprintf pour produire la chane formate et nous la passons PRINT pour la mise en majuscules. Mais rien ne vous oblige utiliser la fonction interne sprintf. Vous pourriez interprter les codes pour-cent votre manire. SELF->READ(LISTE) Cette mthode rpond lorsque le handle est lu avec read ou sysread. Notez que nous modifions le premier paramtre de LISTE sur place , imitant comment read peut remplir le scalaire fourni comme deuxime paramtre.
sub READ { my ($self, undef, $taille, $position) = @_; my $ref_tampon = \$_[1]; return read($self, $$ref_tampon, $taille, $position); }

SELF->WRITE(LISTE) Cette mthode est invoque lorsquon crit au handle avec syswrite. Ici, nous mettons en majuscules la chane crite.
sub WRITE { my $self = shift; my $chaine = uc(shift); my $taille = shift || length $chaine; my $position = shift || 0; return syswrite $self, $chaine, $taille, $position; }

SELF->EOF Cette mthode retourne une valeur boolenne lorsque ltat fin-de-fichier du handle de fichier li la classe Crier est test avec eof.
sub EOF { my $self = shift; return eof $self; }

SELF->BINMODE(DISC) Cette mthode indique la discipline entre/sortie qui doit tre utilise sur le handle de fichier. Si rien nest spcifi, elle met le handle de fichier en mode binaire (la discipline :raw), pour les systmes de fichiers qui distinguent entre les fichiers texte et les fichiers binaires.
sub BINMODE { my $self = shift; my $disc = shift || ":raw";

customer_8566

360
return binmode $self, $disc; }

Chapitre 14 Variables lies

Voil comment vous lcririez, mais elle est en fait inutilisable dans notre cas car open a dj crit sur le handle. Donc nous devrions probablement lui faire dire :
sub BINMODE { croak("Trop tard pour utiliser binmode") }

SELF->FILENO Cette mthode doit retourner le descripteur de fichier (fileno) associ au handle de fichier par le systme dexploitation.
sub FILENO { my $self = shift; return fileno $self; }

SELF->DESTROY Comme pour les autres types de liaison, cette mthode est dclenche lorsque lobjet li est sur le point dtre dtruit. Ceci est utile pour permettre lobjet de faire du nettoyage. Ici, nous nous assurons que le fichier est ferm, au cas o le programme aurait oubli dappeler close. Nous pourrions simplement dire close $self, mais il est prfrable dinvoquer la mthode CLOSE de la classe. De cette manire si le concepteur de la classe dcide de modifier la faon dont les fichiers sont ferms, cette mthode DESTROY na pas tre modifie.
sub DESTROY { my $self = shift; $self->CLOSE; # Fermer le fichier avec la mthode CLOSE de Crier }

Voici une dmonstration de notre classe Crier :


#!/usr/bin/perl use Crier; tie(*FOO, Crier::, ">nom_fichier"); print FOO "bonjour\n"; # Affiche BONJOUR. seek FOO, 0, 0; # Repart du dbut. @lines = <FOO>; # Appelle la mthode READLINE. close FOO; # Ferme le fichier explicitement. open(FOO, "+<", "nom_fichier"); # Rouvre FOO, appelant OPEN. seek(FOO, 8, 0); # Saute "<CRIER>\n". sysread(FOO, $tampon, 7); # Lit 7 octets de FOO dans $tampon. print "trouv $tampon\n"; # Devrait afficher "BONJOUR". seek(FOO, -7, 1); # Recule par-dessus "bonjour". syswrite(FOO, "ciao!\n", 6); # Ecrit 6 octets dans FOO. untie(*FOO); # Appelle la mthode CLOSE implicitement.

Aprs lexcution de ceci, le fichier contient :


<CRIER> CIAO! </CRIER>

Voici dautres choses tranges et merveilleuses faire avec le glob interne. Nous employons le mme hachage que prcdemment, mais avec les nouvelles clefs

customer_8566

Liaison de handle de fichier

361

CHEMIN_FICHIER et DEBOGUAGE. Dabord nous installons une surcharge de conversion en chane pour que laffichage de nos objets rvle le nom de fichier (voir le chapitre 13, Surcharge) :
# Ceci est vraiment trop gnial ! use overload q("") => sub { $_[0]->chemin_fichier }; # Ceci doit tre mis dans chaque fonction que vous voulez tracer. sub trace { my $self = shift; local $Carp::CarpLevel = 1; Carp::cluck("\nmthode magique trace") if $self->deboguage; } # Handler de surcharge pour afficher le chemin daccs au fichier. sub chemin_fichier { my $self = shift; confess "je ne suis pas une mthode de classe" unless ref $self; $$self->{CHEMIN_FICHIER} = shift if @_; return $$self->{CHEMIN_FICHIER}; } # Deux modes. sub deboguage { my $self = shift; my $var = ref $self ? \$$self->{DEBOGUAGE} : \our $Deboguage; $$var = shift if @_; return ref $self ? $$self->{DEBOGUAGE} || $Deboguage : $Deboguage; }

Ensuite nous appelons trace lentre de toutes nos mthodes ordinaires, comme ceci :
sub GETC { $_[0]->trace; my($self) = @_; getc($self); } # NOUVEAU

Nous stockons le chemin daccs du fichier dans les mthodes TIEHANDLE et OPEN :
sub TIEHANDLE { my $classe = shift; my $forme = shift; my $nom = "$forme@_"; # NOUVEAU open my $self, $forme, @_ or croak "impossible douvrir $nom : $!"; if ($forme =~ />/) { print $self "<CRIER>\n"; $$self->{ECRITURE} = 1; # Se souvenir dcrire la balise de fin } bless $self, $classe; # $self est une rfrence de glob $self->chemin_fichier($nom); # NOUVEAU return $self; } sub OPEN { $_[0]->trace; # NOUVEAU

customer_8566

362

Chapitre 14 Variables lies


my $self = shift; my $forme = shift; my $nom = "$forme@_"; $self->CLOSE; open($self, $forme, @_) or croak "impossible de rouvrir $nom : $!"; $self->chemin_fichier($nom); # NOUVEAU if ($forme =~ />/) { print $self "<CRIER>\n" or croak "impossible de commencer le print : $!"; $$self->{ECRITURE} = 1; # Se souvenir dcrire la balise de fin } else { $$self->{ECRITURE} = 0; # Se souvenir de ne pas crire la # balise de fin } return 1;

Il faut aussi appeler $self->deboguage(1) quelque part pour dmarrer le dbogage. Lorsque nous faisons cela, tous les appels Carp::cluck produiront des messages informatifs. En voici un que nous obtenons pendant la rouverture ci-dessus. Il nous situe trois niveaux de profondeur dappels de mthode, alors que nous fermons lancien fichier en prparation pour louverture du nouveau :
mthode magique trace at foo line 87 Crier::SEEK(>nom_fichier, >nom_fichier, 0, 2) called at foo line 81 Crier::CLOSE(>nom_fichier) called at foo line 65 Crier::OPEN(>nom_fichier, +<, nom_fichier) called at foo line 141

Handles de fichier originaux


Vous pouvez lier un mme handle de fichier lentre et la sortie dun tube (pipe) deux bouts. Supposons que vous vouliez excuter le programme bc(1) (calculateur prcision arbitraire) de cette manire :
use Tie::Open2; tie *CALC, Tie::Open2, "bc -l"; $somme = 2; for (1 .. 7) { print CALC "$somme * $somme\n"; $somme = <CALC>; print "$_: $somme"; chomp $somme; } close CALC;

Vous vous attendriez ce quil affiche ceci :


1: 4 2: 16 3: 256

customer_8566

Liaison de handle de fichier


4: 5: 6: 7: 65536 4294967296 18446744073709551616 340282366920938463463374607431768211456

363

Vous auriez raison de vous attendre cela si vous aviez le programme bc(1) sur votre ordinateur, et si vous aviez dfini Tie::Open2 de la manire suivante. Cette fois-ci nous utiliserons un tableau consacr comme objet interne. Il contient nos deux handles de fichier pour la lecture et pour lcriture. (La tche difficile douverture dun tube deux bouts est faite par IPC::Open2 ; nous ne faisons que la partie amusante.)
package Tie::Open2; use strict; use Carp; use Tie::Handle; # ne pas hriter de ceci ! use IPC::Open2; sub TIEHANDLE { my ($classe, @cmd) = @_; no warnings once; my @paire_hf = \do { local(*LECTURE, *ECRITURE) }; bless $_, Tie::StdHandle for @paire_hf; bless(\@paire_hf => $classe)->OPEN(@cmd) || die; return \@paire_hf; } sub OPEN { my ($self, @cmd) = @_; $self->CLOSE if grep {defined} @{ $self->FILENO }; open2(@$self, @cmd); } sub FILENO { my $self = shift; [ map { fileno $self->[$_] } 0,1 ]; } for my $meth_sortie ( qw(PRINT PRINTF WRITE) ) { no strict refs; *$meth_sortie = sub { my $self = shift; $self->[1]->$meth_sortie(@_); }; } for my $meth_entree ( qw(READ READLINE GETC) ) { no strict refs; *$meth_entree = sub { my $self = shift; $self->[0]->$meth_entree(@_); }; }

customer_8566

364

Chapitre 14 Variables lies

for my $meth_double ( qw(BINMODE CLOSE EOF)) { no strict refs; *$meth_double = sub { my $self = shift; $self->[0]->$meth_double(@_) && $self->[1]->$meth_double(@_); }; } for my $meth_morte ( qw(SEEK TELL)) { no strict refs; *$meth_morte = sub { croak("impossible dappliquer $meth_morte un tube"); }; } 1;

Les quatre dernires boucles sont incroyablement chouettes, notre avis. Pour une explication de ce qui se passe, voir la section Fermetures comme modles de fonctions au chapitre 8. Voici un ensemble de classes encore plus bizarres. Les noms de paquetages devraient vous donner une ide de ce quelles font :
use strict; package Tie::DevNull; sub TIEHANDLE { my $classe = shift; my $hf = local *HF; bless \$hf, $classe; } for (qw(READ READLINE GETC PRINT PRINTF WRITE)) { no strict refs; *$_ = sub { return }; } package Tie::DevAleatoire; sub READLINE { rand() . "\n"; } sub TIEHANDLE { my $classe = shift; my $hf = local *HF; bless \$hf, $classe; } sub FETCH { rand() } sub TIESCALAR { my $classe = shift; bless \my $self, $classe; } package Tie::Tee;

customer_8566

Liaison de handle de fichier

365

sub TIEHANDLE { my $classe = shift; my @handles; for my $chemin (@_) { open(my $hf, ">$chemin") || die "impossible dcrire $chemin"; push @handles, $hf; } bless \@handles, $classe; } sub PRINT { my $self = shift; my $ok = 0; for my $hf (@$self) { $ok += print $hf @_; } return $ok == @$self; }

La classe Tie::Tee mule le programme standard Unix tee(1) qui envoie un f lux en sortie vers plusieurs diffrentes destinations. La classe Tie::DevNull mule le priphrique nul /dev/null des systmes Unix. La classe Tie::DevRandom produit des nombres alatoires soit comme handle, soit comme scalaire, selon que vous appelez TIEHANDLE ou TIESCALAR ! Voici comment vous les appelez :
package main; tie tie tie tie *DISPERSE, *ALEATOIRE, *NULL, my $alea, "Tie::Tee", qw(tmp1 - tmp2 >tmp3 tmp4); "Tie::DevAleatoire"; "Tie::DevNull"; "Tie::DevAleatoire";

for my $i (1..10) { my $ligne = <ALEATOIRE>; chomp $ligne; for my $hf (*NULL, *DISPERSE) { print $hf "$i: $ligne $alea\n"; } }

Ce qui produit quelque chose comme ceci sur votre cran :


1: 0.124115571686165 0.20872819474074 2: 0.156618299751194 0.678171662366353 3: 0.799749050426126 0.300184963960792 4: 0.599474551447884 0.213935286029916 5: 0.700232143543861 0.800773751296671 6: 0.201203608274334 0.0654303290639575 7: 0.605381294683365 0.718162304090487 8: 0.452976481105495 0.574026269121667 9: 0.736819876983848 0.391737610662044 10: 0.518606540417331 0.381805078272308

customer_8566

366

Chapitre 14 Variables lies

Mais ce nest pas tout ! Le programme a crit sur votre cran cause du - dans le tie de *DISPERSE ci-dessus. Mais cette ligne lui a galement dit de crer les fichiers tmp1, tmp2, et tmp4, et dajouter la fin de tmp3. (Nous avons aussi crit au handle de fichier *NULL dans la boucle, mais bien sr cela nest apparu nulle part dintressant, moins que vous vous intressiez aux trous noirs.)

Un pige subtil du dliement


Si vous avez lintention de vous servir de lobjet retourn par tie ou par tied, et que la classe dfinit un destructeur, il y a un pige subtil contre lequel vous devez vous protger. Examinez cet exemple (tordu, avouons-le) dune classe qui utilise un fichier pour tenir un log de toutes les valeurs affectes un scalaire :
package Souvenir; sub TIESCALAR { my $classe = shift; my $nom_fichier = shift; open(my $handle, ">", $nom_fichier) or die "Impossible douvrir $nom_fichier: $!\n"; print $handle "Le Dbut\n"; bless {HF => $handle, VALEUR => 0}, $classe; } sub FETCH { my $self = shift; return $self->{VALEUR}; } sub STORE { my $self = shift; my $valeur = shift; my $handle = $self->{HF}; print $handle "$valeur\n"; $self->{VALEUR} = $valeur; } sub DESTROY { my $self = shift; my $handle = $self->{HF}; print $handle "La Fin\n"; close $handle; } 1;

Voici un exemple qui se sert de notre classe Souvenir :


use strict; use Souvenir;

customer_8566

Un pige subtil du dliement


my $fred; tie $fred, "Souvenir", "chameau.log"; $fred = 1; $fred = 4; $fred = 5; untie $fred; system "cat chameau.log";

367

Voici ce quil affiche lorsquil est excut :


Le Dbut 1 4 5 La Fin

Jusquici tout va bien. Rajoutons une mthode supplmentaire la classe Souvenir qui permet les commentaires dans le fichier disons, quelque chose comme ceci :
sub commenter { my $self = shift; my $message = shift; print { $self->{HF} } $handle $message, "\n"; }

Et voici lexemple prcdent, modifi pour utiliser la mthode commenter :


use strict; use Souvenir; my ($fred, $x); $x = tie $fred, "Souvenir", "chameau.log"; $fred = 1; $fred = 4; commenter $x "change..."; $fred = 5; untie $fred; system "cat chameau.log";

Maintenant le fichier risque dtre vide ou incomplet, ce qui nest probablement pas ce que vous souhaitiez faire. Voici pourquoi. Lier une variable lassocie lobjet retourn par le constructeur. Cet objet na normalement quune rfrence : celle cache derrire la variable lie. Appeler untie rompt lassociation et limine cette rfrence. Comme il ne reste pas de rfrence lobjet, la mthode DESTROY est dclenche. Cependant, dans lexemple ci-dessus nous avons stock dans $x une deuxime rfrence lobjet li. Cela veut dire quil reste une rfrence valide lobjet aprs le untie. DESTROY nest pas dclenche, et le fichier nest ni enregistr, ni ferm. Cest pour cela que rien nest sorti : le tampon du handle de fichier tait encore en mmoire. Il natteindra le disque qu la sortie du programme. Pour dtecter ceci, vous pourriez utiliser loption de ligne de commande -w ou inclure le pragma use warnings "untie" dans la porte lexicale courante. Lune ou lautre technique dclerait un appel untie pendant quil reste des rfrences lobjet li. Dans ce cas, Perl affiche cet avertissement :
untie attempted while 1 inner references still exist

customer_8566

368

Chapitre 14 Variables lies

Pour faire marcher correctement le programme et faire taire lavertissement, liminez les rfrences supplmentaires lobjet li avant dappeler untie. Vous pouvez le faire explicitement :
undef $x; untie $fred;

Souvent vous pouvez rsoudre le problme en vous assurant simplement que vos variables quittent leur porte au bon moment.

Modules de liaison sur CPAN


Avant de devenir tout inspir lide dcrire votre propre module de liaison, vous devriez vrifier que quelquun ne la pas dj fait. Il y a beaucoup de modules de liaison sur CPAN, et il y en a des nouveaux tous les jours. (Enfin, chaque mois, en tout cas.) Le tableau 14-1 en liste quelques-unes. Tableau 14-1. Modules de liaison sur CPAN
Module IO::WrapTie MLDBM Net::NISplusTied Tie::Cache::LRU Tie::Const Tie::Counter Tie::CPHash Tie::DB_FileLock Tie::DBI Tie::DB_Lock Tie::Dict Tie::Dir Tie::DirHandle Tie::FileLRUCache Tie::FlipFlop Tie::HashDefaults Tie::HashHistory Tie::IxHash Description Emballe les objets lis avec une interface IO::Handle. Stocke de manire transparente des donnes complexes, pas juste de simples chanes, dans un fichier DBM. Lie des hachages des tables NIS+. Implmente un cache utilisant lalgorithme Least Recently Used (moins rcemment utilis). Fournit des scalaires et des hachages constants. Enchante une variable scalaire pour quelle sincrmente chaque fois quon y accde. Implmente un hachage insensible la casse mais qui prserve la casse. Fournit un accs verrouill aux bases de donnes Berkeley DB 1.x. Lie des hachages aux bases de donnes relationnelles DBI. Lie des hachages aux bases de donnes avec des verrouillages exclusifs et partags. Lie un hachage un serveur dict RPC. Lie un hachage pour lire des rpertoires. Lie des handles de rpertoire. Implmente un cache LRU lger, bas sur le systme de fichiers. Implmente une liaison qui alterne entre deux valeurs. Permet un hachage davoir des valeurs par dfaut. Garde lhistorique de toutes les modifications dun hachage. Fournit Perl des tableaux associatifs ordonns.

GnuPG::Tie::Encrypt Lie une interface de handle de fichier avec GNU Privacy Guard.

customer_8566

Modules de liaison sur CPAN


Tableau 14-1. Modules de liaison sur CPAN
Module Tie::LDAP Tie::Persistent Tie::Pick Tie::RDBM Tie::SecureHash Tie::STDERR Tie::Syslog Tie::TextDir Tie::TransactHash Tie::VecArray Tie::Watch Win32::TieRegistry Description Implmente une interface une base de donnes LDAP . Fournit des structures de donnes persistantes via tie.

369

Choisit (et supprime) alatoirement un lment dun ensemble. Lie des hachages aux bases de donnes relationnelles. Permet lencapsulation avec les espaces de noms. Envoie la sortie de votre STDERR un autre processus tel quun systme denvoi de courrier. Lie un handle de fichier pour automatiquement enregistrer sa sortie avec syslog. Lie un rpertoire de fichiers. Modifie un hachage par transactions sans changer lordre pendant la transaction. Donne un vecteur de bits une interface de tableau. Place des tmoins sur les variables Perl. Fournit des manires faciles et puissantes de manipuler la base de registres de Microsoft Windows.

customer_8566

customer_8566

Technique Perl

III

customer_8566

customer_8566

15

Unicode

Si vous ne savez pas encore ce quest Unicode, vous le saurez bientt mme si vous ne lisez pas ce chapitre car travailler avec Unicode devient indispensable. (Certains pensent que cest une ncessit malfique mais cest bien davantage une ncessit bnfique. Dans tous les cas, cest un mal ncessaire.) Historiquement, les gens ont construit des jeux de caractres qui ref ltaient ce quils devaient faire dans le contexte de leur propre culture. Comme les gens de toutes les cultures sont naturellement paresseux, ils ont eu tendance ninclure que les symboles dont ils avaient besoin en excluant ceux qui ne leur taient pas utiles. Cela fonctionnait merveille aussi longtemps que nous ne communiquions quavec dautres gens appartenant notre propre culture, mais maintenant que nous commenons utiliser lInternet pour des communications interculturelles, nous nous heurtons des problmes du fait de cette approche exclusive. Il est dj difficile dimaginer comment taper des caractres accentus sur un clavier amricain. Comment dans le monde (littralement) peuton crire une page web multilingue ? Unicode est la solution, ou tout au moins une partie de la solution (voir galement XML). Unicode est un jeu de caractres inclusif plutt quexclusif. Alors que les gens peuvent chicaner, et ne sen privent pas, sur les divers dtails dUnicode (et il y a une grande quantit de dtails sur lesquels chicaner), lintention gnrale est de contenter tout le monde de manire suffisante1 avec Unicode pour quils utilisent de leur propre gr Unicode comme le mdium international dchange de donnes textuelles. Personne ne vous force utiliser Unicode, tout comme personne ne vous force lire ce chapitre (du moins, nous lesprons). Les gens pourront toujours utiliser leurs anciens jeux de caractres exclusifs dans leur propre culture. Mais dans ce cas (comme on dit), la portabilit en souffrira. La loi de la conservation de la souffrance dit que si nous rduisons la souffrance quelque part, elle doit augmenter autre part. Dans le cas dUnicode, nous devons souffrir de la migration dune smantique doctet vers une smantique de caractre. Puisque, par un
1. Ou dans certains cas, de mcontenter tout le monde de manire insuffisante.

customer_8566

374

Chapitre 15 Unicode

accident de lhistoire, il a t invent par un Amricain, Perl a historiquement confondu les notions doctet et de caractre. En migrant vers Unicode, Perl ne doit plus les confondre dune manire ou dune autre. Paradoxalement, en amenant Perl ne plus confondre les octets et les caractres, nous permettons aux programmeurs Perl de les confondre car ils savent que Perl rtablira la distinction, exactement comme ils peuvent confondrent confondre les nombres et les chanes et sen remettre Perl pour convertir autant que ncessaire les uns vers les autres et rciproquement. Autant que possible, Perl a une approche dUnicode semblable son approche de tout le reste : Faire Ce Quil Faut Faire. Idalement, nous aimerions parvenir ces quatre objectifs : Objectif n 1 Les anciens programmes orients octet ne devraient pas spontanment se planter avec les anciennes donnes orientes octet avec lesquelles ils travaillaient. Objectif n 2 Les anciens programmes orients octet devraient par magie commencer fonctionner avec les nouvelles donnes orientes caractre lorsque cest appropri. Objectif n 3 Les programmes devraient tourner aussi vite avec les nouvelles donnes orientes caractre quavec les anciennes donnes orientes octet. Objectif n 4 Perl devrait rester un langage unifi plutt que se scinder en un Perl orient octet et un Perl orient caractre. Pris ensemble, ces objectifs sont pratiquement impossibles atteindre. Mais nous nous en approchons relativement bien. Ou plutt, nous sommes toujours dans le processus de rapprochement, puisquil sagit dune tche en cours de ralisation. Perl continue dvoluer en mme temps quUnicode. Mais notre plan denvergure est doffrir une voie de migration qui soit sre et qui puisse nous amener l o nous voulons aller en rencontrant le minimum daccidents en cours de route. Comment y arriver est le sujet du prochain paragraphe.

Construction dun caractre


Dans les versions de Perl antrieures 5.6, toutes les chanes taient vues en tant que squences doctets. Dans les versions 5.6 et suivantes, une chane peut toutefois contenir des caractres dune taille suprieure un octet. Nous voyons maintenant les chanes, non plus en tant que squences doctets, mais en tant que squences de numros compris dans lintervalle 0 .. 2**32-1 (ou dans le cas dordinateurs 64 bits, 0 .. 2**64-1). Ces numros reprsentent des caractres abstraits et, dans un certain sens, plus grand est le numro, plus la taille du caractre est grande ; mais au contraire de beaucoup de langages, Perl nest pas li une taille particulire de la reprsentation dun caractre. Perl utilise un encodage de taille variable (bas sur UTF8), ainsi ces numros de caractres abstraits peuvent tre empaquets, ou non, raison dun numro par octet. videmment, le numro de caractre 18 446 744 073 709 551 515 (cest--dire, \x{ffff_ffff_ffff_ffff} ) ne tiendra jamais dans un octet (en fait, il prend 13 oc-

customer_8566

Construction dun caractre

375

tets) mais si tous les caractres de votre chane se situent dans lintervalle 0..127 en dcimal, alors ils seront certainement empaquets raison dun par octet, puisque lUTF8 est identique lASCII pour les sept premiers bits de poids faible. Perl utilise de lUTF8 lorsquil pense que cest bnfique, ainsi, si tous les caractres de votre chane sont dans lintervalle 0..255, il y a une grande chance que les caractres soient empaquets dans des octets mais en labsence dautre informations connues, vous ne pouvez tre sr car Perl fait en interne une conversion entre les caractres 8 bits et les caractres UTF8 de taille variable si ncessaire. Lessentiel est que vous ne devriez pas vous en soucier la plupart du temps car la smantique de caractre est prserve un niveau abstrait indpendamment de la reprsentation. Dans tous les cas, si votre chane contient des numros de caractres suprieurs 255 en dcimal, la chane est certainement stocke en UTF8. Plus exactement, elle est stocke dans la version tendue dUTF8 de Perl que nous appelons utf8, en hommage au pragma du mme nom, mais surtout parce que cest plus simple taper. (Et de plus, lUTF8 rel nest autoris contenir que des numros de caractres consacrs par le Consortium Unicode. Lutf8 de Perl est autoris contenir tous les caractres dont vous avez besoin pour accomplir votre travail. Perl se moque du fait que vos numros de caractres soient officiellement corrects ou juste corrects.) Nous avons dit que vous ne devriez pas vous en soucier la plupart du temps, mais les gens aiment de toute faon se faire du souci. Supposez que vous ayez une v-chane reprsentant une adresse IPv4 :
$adr_loc = v127.0.0.1; # Srement stocke en octets. $oreilly = v204.148.40.9; # Pourrait tre stocke en octets ou en utf8. $adr_nok = v2004.148.40.9; # Srement stocke en utf8.

Tout le monde peut sapercevoir que $adr_nok ne marchera pas en tant quadresse IP Il . est donc facile de penser que si ladresse rseau dOReilly est force une reprsentation UTF8, elle ne marchera plus. Mais les caractres dans la chane sont des numros abstraits, non des octets. Tout ce qui utilise une adresse IPv4, comme la fonction gethostbyaddr, devrait automatiquement forcer les numros de caractres abstrait tre reconvertis vers une reprsentation en octets (et chouer avec $adr_nok). Les interfaces entre Perl et le monde rel doivent saccommoder des dtails de la reprsentation. Jusqu un certain point, les interfaces existantes essaient de faire ce quil faut sans que vous ayez leur dire quoi faire. Mais de temps en temps, vous devez donner des instructions certaines interfaces (comme la fonction open) et si vous crivez votre propre interface vers le monde rel, elle aura besoin dtre soit assez astucieuse pour arriver comprendre les choses par elle-mme, soit au moins assez lgante pour suivre les instructions lorsque que vous voulez quelle se comporte diffremment de ce quelle aurait fait par dfaut.2
2. Sur certains systmes, il peut y avoir des moyens de basculer toutes vos interfaces en une seule fois. Si loption de la ligne de commande -C est utilise (ou la variable globale ${^WIDE_SYSTEM_CALLS} est positionne 1), tous les appels systme utiliseront les API de caractres larges (wide character). (Ceci nest actuellement implment que sur Microsoft Windows.) Le projet actuel de la communaut Linux est que toutes les interfaces basculeront en mode UTF8 si $ENV{LC_TYPE} est positionne UTF8 . Les autres communauts peuvent adopter dautres approches. Ce nest pas une rgle absolue.

customer_8566

376

Chapitre 15 Unicode

Puisque Perl se soucie de maintenir une smantique de caractre transparente lintrieur du langage lui-mme, la seule place o vous devez vous inquiter dune smantique doctet, oppose une smantique de caractre, est dans vos interfaces. Par dfaut, toutes vos anciennes interfaces Perl vers le monde extrieur sont orientes octet. Cest-dire qu un niveau abstrait, toutes vos chanes sont des squences de numros dans lintervalle 0..255, ainsi, si rien dans le programme ne les force des reprsentations en utf8, vos anciens programmes continueront fonctionner avec des donnes orientes octet comme ils le faisaient auparavant. Vous pouvez donc cocher lobjectif n1 ci-dessus. Si vous voulez que vos anciens programmes fonctionnent avec les nouvelles donnes orientes caractre, vous devez marquer vos interfaces orientes caractre de manire que Perl sattende recevoir des donnes orientes caractre de ces interfaces. Une fois que cest fait, Perl devrait automatiquement faire toutes les conversions ncessaires pour prserver labstraction des caractres. La seule diffrence est que vous devez introduire dans votre programme des chanes qui soient marques comme contenant potentiellement des caractres plus grands que 255, ainsi, si vous effectuez une opration entre une chane doctets et une chane utf8, Perl convertira en interne la chane doctets en une chane utf8 avant deffectuer lopration. Gnralement, les chanes utf8 ne sont reconverties en chanes doctets que lorsque vous les envoyez une interface oriente octet, auquel cas, si vous aviez une chane contenant des caractres plus grands que 255, vous aurez un problme qui peut tre rsolu de diverses manires selon linterface en question. Vous pouvez donc cocher lobjectif n2. Parfois, vous voulez mlanger du code comprenant une smantique de caractre avec du code devant tourner avec une smantique doctet, comme du code dentres/sorties qui lit ou crit des blocs de taille fixe. Dans ce cas, vous pouvez mettre une dclaration use bytes autour du code orient octet pour le forcer utiliser une smantique doctet mme sur les chanes marques en tant que chanes utf8. Les conversions sont alors sous votre responsabilit. Mais cest un moyen de renforcer une lecture locale plus stricte de lobjectif n1, au dpend dune lecture globale plus relche de lobjectif n2. Lobjectif n3 a largement t atteint, en partie en faisant des conversions paresseuses entre les reprsentations en octets et en utf8 et en partie en tant discret sur la manire dont nous avons implment potentiellement des fonctionnalits lentes dUnicode, comme la recherche des proprits de caractres dans des tables normes. Lobjectif n4 a t atteint en sacrifiant un peu de la compatibilit des interfaces la qute des autres objectifs. Dune certaine faon, nous navons pas bifurqu vers deux Perl diffrents ; mais en le considrant dune autre manire, la rvision 5.6 de Perl est une version bifurque de Perl au regard des versions antrieures et nous ne nous attendons pas ce que les gens migrent depuis leurs versions antrieures avant dtre srs que la nouvelle version fera bien ce quils veulent. Mais cest toujours le cas avec les nouvelles versions, nous nous permettrons donc de cocher galement lobjectif n4.

Consquences de la smantique de caractre


Le rsultat de tout ceci est quun oprateur interne typique manipulera des caractres sauf sil est dans la porte dun pragma use bytes. Toutefois, mme en dehors de la porte dun use bytes, si tous les oprandes de loprateur sont stocks en tant que carac-

customer_8566

Consquences de la smantique de caractre

377

tres 8 bits (cest--dire quaucune oprande nest stocke en tant quutf8), alors la smantique de caractre se confond avec la smantique doctet et le rsultat de loprateur sera stock en interne dans un format 8 bits. Ceci prserve une compatibilit antrieure pourvu que vous napprovisionniez pas vos programmes avec des caractres plus larges quen Latin-1. Le pragma utf8 est avant tout un dispositif de compatibilit permettant la reconnaissance de lUTF8 dans les littraux et les identificateurs rencontrs par lanalyseur grammatical. Il peut galement tre utilis pour permettre certaines fonctionnalits des plus exprimentales dUnicode. Notre objectif long terme est de changer le pragma utf8 en une opration ne faisant rien (no-op). Le pragma use bytes ne sera jamais chang en une opration ne faisant rien. Non seulement il est ncessaire pour le code orient octet, mais un de ses effets de bords est galement de dfinir des enrobages orients octet autour de certaines fonctions pour les utiliser en dehors dune porte de use bytes. Au moment o nous crivons ceci, le seul enrobage dfini est pour la fonction length mais dautres sont susceptibles de ltre au fil du temps. Pour utiliser cet enrobage, crivez :
use bytes (); # Charge les enrobages sans importer la smantique doctet. ... $lg_car = length("\x{ffff_ffff}"); # Renvoie 1. $lg_oct = bytes::length("\x{ffff_ffff}"); # Renvoie 7.

En dehors de la porte dune dclaration use bytes, la version 5.6 de Perl fonctionne (ou du moins, est cense fonctionner) ainsi : Les chanes et les motifs peuvent maintenant contenir des caractres ayant une valeur ordinale suprieure 255 :
use utf8; $convergence = "+

-";

En supposant que vous ayez un diteur compatible avec Unicode pour diter votre programme, de tels caractres se prsenteront gnralement directement lintrieur de chanes littrales en tant que caractres UTF8. Pour le moment, vous devez dclarer un use utf8 au dbut de votre programme pour permettre lutilisation de lUTF8 dans les littraux. Si vous ne disposez pas dditeur Unicode, vous pouvez toujours spcifier un caractre particulier en ASCII avec une extension de la notation \x. Un caractre dans lintervalle Latin-1 peut tre crit comme \x{ab} ou comme \xab mais si le numro dpasse les deux chiffres hexadcimaux, vous devez utiliser des accolades. Les caractres Unicode sont spcifis en mettant le code hexadcimal lintrieur des accolades aprs le \x. Par exemple, un smiley Unicode vaut \x{263A}. Il ny a pas de construction syntaxique en Perl prsumant que les caractres Unicode fassent exactement 16 bits, vous ne pouvez donc pas utiliser \u263A comme dans certains langages ; \x{263A} est lquivalent le plus proche. Pour insrer des caractres nomms via \N{NOM_CAR}, voir le pragma use charnames au chapitre 31, Modules de pragmas. Les identificateurs lintrieur du script Perl peuvent contenir des caractres Unicode alphanumriques, y compris des idogrammes :
use utf8;

customer_8566

378
$ ++; # Un enfant est n.

Chapitre 15 Unicode

Ici encore, use utf8 est ncessaire (pour linstant) pour reconnatre de lUTF8 dans votre script. Vous tes actuellement livr vous-mme lorsquil sagit dutiliser les formes canoniques des caractres Perl ne tente pas (encore) de canoniser pour vous les noms de variable. Voir www.unicode.org pour le dernier rapport sur la canonisation. Les expressions rgulires correspondent des caractres au lieu doctets. Par exemple un point correspond un caractre au lieu de correspondre un octet. Si le Consortium Unicode arrive mme approuver lemploi du twengar, alors (malgr le fait que de tels caractres sont reprsents avec 4 octets en UTF8), ceci russi la correspondance :
"\N{TENGWAR LETTER SILME NUQUERNA}" =~ /^.$/

Le motif \C est fourni pour forcer une correspondance un seul octet ( char en C, do \C). Utilisez \C avec prudence, puisquil peut dsynchroniser des caractres dans votre chane et vous pouvez obtenir des erreurs Caractre UTF8 mal form . Vous ne pouvez pas utiliser \C dans des crochets, puisquil ne reprsente aucun caractre particulier, ni aucun ensemble de caractres. Les classes de caractres dans les expressions rgulires correspondent des caractres au lieu doctets et correspondent avec les proprits des caractres spcifies dans la base de donnes des proprits Unicode. Ainsi, \w peut tre utilis pour correspondre un idogramme :
" " =~ /\w/

Les proprits nommes dUnicode et les intervalles de blocs peuvent tre utiliss comme classes de caractres avec les nouvelles constructions \p (correspond la proprit) et \P (ne correspond pas la proprit). Par exemple, \p{Lu} correspond tout caractre ayant la proprit majuscule dUnicode, alors que \p{M} correspond tout caractre marqu. Les proprits dune seule lettre peuvent omettre les accolades, ainsi \pM peut galement correspondre des caractres marqus. Beaucoup de classes de caractres prdfinies sont disponibles, comme \p{IsMirrored} et \p{InTibetan} :
"\N{greek:Iota}" =~ /p{Lu}/

Vous pouvez galement utiliser \p et \P lintrieur des crochets des classes de caractres. (Dans la version 5.6.0 de Perl, vous avez besoin de faire use utf8 pour que les proprits des caractres fonctionnent bien. Cette restriction sera leve lavenir.) Voir le chapitre 5, Correspondance de motifs, pour plus de dtails sur la correspondance de proprits Unicode. Le motif spcial \X correspond toute squence Unicode tendue (une squence de caractres combins en langage standard), o le premier caractre est un caractre de base et les suivants des caractres marqus sappliquant au caractre de base. Cest quivalent (?:\PM\pM*) :
"o\N{COMBINING TILDE BELOW}" =~ /\X/

Vous ne pouvez pas utiliser \X lintrieur de crochets car il pourrait correspondre plusieurs caractres et il ne reprsente aucun caractre particulier, ni aucun ensemble de caractres.

customer_8566

Consquences de la smantique de caractre

379

Loprateur tr/// traduit des caractres au lieu doctets. Pour changer tous les caractres hors de lintervalle Latin-1 en points dinterrogation, vous pourriez crire :
tr/\0-\x{10ffff}/\0-\xff?/; # caractre utf8 vers latin1

Les oprateur de traduction de casse utilise des tables de traduction de casse Unicode lorsquon leur fournit des caractres en entre. Remarquer que uc traduit en majuscules, alors quucfisrt traduit linitiale en majuscule de titre (titlecase), pour les langages qui font la distinction. Naturellement les squences dantislashs correspondantes ont la mme smantique :
$x $x $x $x = = = = "\u$mot"; "\U$mot"; "\l$mot"; "\L$mot"; # # # # met met met met linitiale de $mot en majuscule de titre $mot en majuscules linitiale de $mot en minuscule $mot en minuscules

Soyez prudent, car les tables de traduction de casse Unicode ne tentent pas de fournir des tables de correspondance bijectives pour chaque instance, particulirement pour les langages utilisant un nombre de caractres diffrent pour les majuscules et les minuscules. Comme ils disent dans les standards, alors que les proprits de casse sont elles-mmes normatives, les tables de casse ne sont quinformelles. La plupart des oprateurs manipulant des positions ou des longueurs dans une chane basculeront automatiquement lutilisation de positions de caractres, ce qui comprend : chop, substr, pos, index, rindex, sprintf, write et length. Les oprateurs qui ne basculent pas dlibrment comprennent vec, pack et unpack. Les oprateurs qui sen moquent vraiment comprennent chomp, ainsi que tout autre oprateur traitant une chane comme un paquet de bits, tels que le sort par dfaut et les oprateurs manipulant des fichiers.
use bytes; $lg_octets = length("Je fais de l no bytes; $lg_caracs = length("Je fais de l "); # 15 octets "); # mais 9 caractres

Les lettres c et C de pack/unpack ne changent pas, puisquelles sont souvent utilises pour des formats orients octet. (Encore une fois, pensez char en langage C.) Toutefois, il existe un nouveau spcificateur U , qui fera les conversions entre les caractres UTF8 et les entiers :
pack("U*", 1, 20, 300, 4000) eq v1.20.300.4000

Les fonctions chr et ord fonctionnent avec des caractres :


chr(1).chr(20).chr(300).chr(4000) eq v1.20.300.4000

En dautres termes, chr et ord sont comme pack("U") et unpack("U") et non comme pack("C") et unpack("C"). En fait, ces derniers sont un moyen pour vous dmuler les fonctions chr et ord orientes octet si vous tes trop paresseux pour faire un use bytes. Enfin, un reverse en contexte scalaire inverse par caractre plutt que par octet :
"+

-"

eq reverse "-

+"

Si vous regardez dans le rpertoire CHEMIN_BIBLIOTHEQUE_PERL/unicode, vous trouverez de nombreux fichiers en rapport avec la dfinition des smantiques ci-dessus. La base de donnes des proprits Unicode provenant du Consortium Unicode se situe

customer_8566

380

Chapitre 15 Unicode

dans un fichier appel Unicode.300 (pour Unicode 3.0). Ce fichier a dj t trait par mktables.PL pour donner un tas de petits fichiers .pl dans le mme rpertoire (et dans les sous-rpertoires Is/, In/ et To/), dont certains sont automatiquement avals par Perl pour implmenter des choses comme \p (voir les rpertoires Is/ et In/) et uc (voir le rpertoire To/). Les autres fichiers sont avals par des modules comme le pragma use charnames (voir Name.pl). Mais au moment o nous crivons ceci, il reste encore de nombreux fichiers qui sont juste assis l sans rien faire, en attendant que vous leur criviez un module daccs : ArabLink.pl ArabLnkGrp.pl Bidirectional.pl Block.pl Category.pl CombiningClass.pl Decomposition.pl JamoShort.pl Number.pl To/Digit.pl Un rsum bien plus lisible dUnicode, avec beaucoup de liens hypertextes, se trouve dans CHEMIN_BIBLIOTHEQUE_PERL/unicode/Unicode3.html. Remarquez que lorsque le Consortium Unicode sort une nouvelle version, certains de ces noms de fichier sont susceptibles de changer, vous devrez donc fouiller un peu. Vous pouvez trouver CHEMIN_BIBLIOTHEQUE_PERL avec lincantation suivante :
% perl -MConfig -le print $Config{privlib}

Pour trouver tout ce que lon peut trouver sur Unicode, vous devriez consulter The Unicode Standard Version 3.0 (ISBN 0-201-61633-5).

Attention

au travail

Au moment o nous crivons ceci (cest--dire, en phase avec la version 5.6.0 de Perl), il existe encore des prcautions prendre pour utiliser Unicode. (Consultez votre documentation en ligne pour les mises jour.) Le compilateur dexpressions rgulires existant ne produit pas de codes doprations (opcodes) polymorphiques. Cela signifie que le fait de dterminer si un motif particulier correspondra ou non des caractres Unicode est ralis lorsque le motif est compil (bas sur le fait que le motif contient ou non des caractres Unicode) et non lorsque la correspondance arrive lexcution. Ceci doit tre chang pour correspondre de manire adapte de lUnicode si la chane sur laquelle se fait la correspondance est en Unicode. Il ny a actuellement pas de moyen facile de marquer une donne lue depuis un fichier ou depuis tout autre source externe comme tant en utf8. Ceci sera un domaine sur lequel se concentrer dans un futur proche et ce sera probablement dj corrig au moment o vous lirez ceci.

customer_8566

Attention au travail

381

Il ny a pas de mthode pour forcer automatiquement lentre et la sortie vers dautres encodages que UTF8. Ceci est toutefois prvu dans un futur proche, consultez donc votre documentation en ligne. Lutilisation de locales avec utf8 peut conduire dtranges rsultats. Actuellement, il existe quelques tentatives pour appliquer l information dune locale 8 bits des caractres dans lintervalle 0..255 mais ceci est de faon vidente incorrect pour des locales qui utilisent des caractres au-del de cet intervalle (lorsquils sont convertis en Unicode). Cela aura galement tendance tourner plus lentement. Le bannissement des locales est fortement encourag.

LUnicode est fun il faut juste que vous dfinissiez le fun correctement.

customer_8566

customer_8566

Communication interprocessus
Les processus peuvent communiquer de presque autant de faons que les personnes. Mais les difficults de la communication interprocessus ne devraient pas tre sous-estimes. Il ne vous sert rien dattendre une rplique verbale si votre partenaire nutilise que le langage des signes. De mme, deux processus ne peuvent se parler que lorsquils saccordent sur la mthode de communication et sur les conventions bties sur cette mthode. Comme avec tout type de communication, lventail des conventions sur lesquelles saccorder va du lexical au pragmatique : tout, depuis quel jargon vous utiliserez jusquau choix de celui dont cest le tour de parler. Ces conventions sont ncessaires car il est trs difficile de communiquer avec une smantique pure, dpouille de tout contexte. Dans notre jargon, la communication interprocessus spelle habituellement IPC (InterProcess Communication). Les fonctionnalits dIPC de Perl vont du trs simple au trs complexe. Votre choix dpend de la complexit des informations communiquer. La forme la plus simple dinformation est, dune certaine manire, aucune information, sinon lavertissement quun certain vnement sest produit un certain moment. En Perl, ces vnements sont communiqus par un mcanisme de signal inspir de celui du systme UNIX. lautre extrme, les fonctionnalits de socket de Perl permettent de communiquer avec nimporte quel autre processus de lInternet grce nimporte quel protocole mutuellement support. Cette libert a bien sr un prix : vous devez parcourir un certain nombre dtapes pour mettre en place la connexion et vous assurer que vous parlez le mme langage que le processus lautre bout. Ce qui peut vous forcer adhrer dtranges coutumes, selon les conventions culturelles en usage. Il se peut mme que pour tre correct au niveau du protocole, vous deviez mme vous mettre parler un langage comme XML, Java ou Perl. Quelle horreur ! Entre ces deux extrmes, on trouve des fonctionnalits intermdiaires conues lorigine pour faire communiquer des processus sur la mme machine. Il sagit notamment des bons vieux fichiers, des pipes (ou tubes), des FIFO et les divers appels systme dIPC System V Limplmentation de ces fonctionnalits varie selon les plates-formes ; les sys.

16

customer_8566

384

Chapitre 16 Communication interprocessus

tmes Unix modernes (y compris le MAC OS X dApple) devraient toutes les implmenter et, mis part les signaux et les IPC System V la plupart des autres sont implmentes , sur les systme dexploitation rcents de Microsoft, y compris les pipes, les forks, les verrouillages de fichiers et les sockets.1 Vous pouvez trouver de plus amples informations sur le portage en gnral dans lensemble de documentations standard de Perl (dans nimporte quel format affich par votre systme) sous perlport. Les informations spcifiques Microsoft peuvent tre trouves sous perlwin32 et perlfork, qui sont installs mme sur des systmes non-Microsoft. Pour les livres publis, nous vous suggrons les suivants : Perl en action, par Tom Christiansen et Nathan Torkington (OReilly Associates, 1998), chapitres 16 18. Advanced Programming in the UNIX Environment, par W. Richard Stevens (AddisonWesley, 1992). TCP/IP Illustrated, par W. Richard Stevens, Volumes I-III (Addison-Wesley, 19921996).

Signaux
Perl utilise un modle simple de gestion des signaux : le hachage %SIG contient des rfrences (quelles soient symboliques ou en dur) des gestionnaires de signaux dfinis par lutilisateur. Certains vnements entranent le systme dexploitation dlivrer un signal au processus affect. Le gestionnaire correspondant cet vnement est appel avec un argument contenant le nom du signal qui la dclench. Pour envoyer un signal un autre processus, utilisez la fonction kill. Pensez-y comme une information dun bit envoye lautre processus.2 Si ce processus a install un gestionnaire de signal pour le signal en question, il peut excuter du code lorsquil le reoit. Mais il ny a aucun moyen pour le processus metteur dobtenir une quelconque sorte de valeur de retour, autre que de savoir si le signal a t lgitimement envoy. Lmetteur ne reoit aucun retour lui disant ce que le processus rcepteur a fait du signal, sil en a fait quelque chose. Nous avons class cette fonctionnalit dans les IPC alors quen fait, les signaux peuvent provenir de diverses sources et pas seulement dautres processus. Le signal pourrait galement provenir du mme processus, ou bien il pourrait tre gnr lorsque lutilisateur tape au clavier une squence particulire comme Ctrl-C ou Ctrl-Z, ou il pourrait tre fabriqu par le noyau quand certains vnements se produisent, comme la fin dun processus fils, ou lorsque le processus na plus assez despace sur la pile, ou parce quun fichier a atteint sa taille limite en mmoire. Mais votre propre processus ne sait pas distinguer facilement ces diffrents cas. Un signal ressemble un paquet qui arrive mystrieusement sur le pas de la porte sans ladresse de lexpditeur. Vous feriez mieux dtre prudent au moment de louvrir. Puisque les entres dans le hachage %SIG peuvent tre des rfrences en dur, une tech-

1. Enfin, sauf les sockets AF_UNIX. 2. En fait, il sagit plus de cinq ou six bits, selon le nombre de signaux dfinis par votre systme dexploitation et si lautre processus utilise le fait que vous navez pas envoy un signal diffrent.

customer_8566

Signaux

385

nique courante est dutiliser des fonctions anonymes pour les gestionnaires de signaux simples :
$SIG{INT} = sub { die "\nIci\n" }; $SIG{ALRM} = sub { die "Votre minuterie a expir" };

Ou vous pourriez crer une fonction nomme et affecter son nom ou une rfrence lentre approprie du hachage. Par exemple, pour intercepter les signaux dinterruption et de sortie (souvent associs aux touches Ctrl-C et Ctrl-\ sur votre clavier), mettez en place un gestionnaire comme ceci :
sub intercepte { my $nom_sig = shift; our $ben_voyons++; die "Quelquun ma envoy un SIG$nom_sig !"; } $ben_voyons = 0; $SIG{INT} = intercepte; # signifie toujours &main::intercepte $SIG{INT} = \&intercepte; # la meilleure stratgie $SIG{QUIT} = \&intercepte; # en intercepte galement un autre

Remarquez que tout ce que nous faisons dans le gestionnaire de signaux est de positionner une variable globale et de lever une exception avec die. vitez autant que possible de faire quelque chose de plus compliqu que cela car sur la plupart des systmes, la bibliothque C nest pas rentrante. Les signaux sont dlivrs de manire asynchrone,3 ainsi, lappel une quelconque fonction print (voire tout ce qui a besoin dallouer plus de mmoire avec malloc(3)) pourrait en thorie dclencher une erreur de mmoire et engendrer un core dump si vous tiez dj dans une routine apparente de la bibliothque C lorsque le signal a t dlivr. (Mme la routine die est quelque peu dangereuse sauf si le processus est excut lintrieur dun eval, ce qui supprime les entres/ sorties depuis die et par consquent empche dappeler la bibliothque C. Probablement.) Une manire encore plus simple dintercepter les signaux est dutiliser le pragma sigtrap pour installer de simples gestionnaires de signaux par dfaut :
use sigtrap qw(die INT QUIT); use sigtrap qw(die untrapped normal-signals stack-trace any error-signals);

Le pragma est trs utile lorsque vous ne voulez pas vous embter crire votre propre gestionnaire mais que vous voulez toujours intercepter les signaux dangereux et tout fermer dans les rgles. Par dfaut, certains de ces signaux ont un caractre si fatal pour votre processus que votre programme sarrtera en pleine course lorsquil en recevra un. Malheureusement, cela signifie que les fonctions END grant la terminaison du programme et les mthodes DESTROY soccupant de lachvement dun objet ne seront pas appeles. Mais elles le seront sur des exceptions Perl ordinaires (comme lorsque vous appelez die), vous pouvez donc utiliser ce pragma pour convertir sans douleur les signaux en

3. La synchronisation de lmission de signaux avec les codes doprations (opcodes) au niveau de Perl est planifie pour une prochaine version de Perl, ce qui devrait rgler les questions de signaux et de core dumps.

customer_8566

386

Chapitre 16 Communication interprocessus

exceptions. Mme si vous ne manipulez pas de signaux vous-mme, votre programme devra bien se comporter quand mme. Voir la description de use sigtrap au Chapitre 31, Modules de pragmas, pour beaucoup plus de fonctionnalits de ce pragma. Vous pouvez galement choisir daffecter au gestionnaire de %SIG les chanes IGNORE ou DEFAULT , auquel cas Perl essayera dcarter le signal ou permettra que se produise laction par dfaut pour ce signal (bien que certains signaux ne peuvent tre ni intercepts ni ignors, comme les signaux KILL et STOP ; voir signal(3), sil est implment, pour obtenir une liste des signaux disponibles sur votre systme et leur comportement par dfaut). Le systme dexploitation voit les signaux comme des nombres plutt que comme des noms, mais Perl, comme la plupart des gens, prfre les noms symboliques aux nombres magiques. Pour trouver les noms des signaux, passez en revue les cls du hachage %SIG ou utilisez la commande kill -l si vous en disposez sur votre systme. Vous pouvez galement utiliser le module standard Config pour dterminer la correspondance que fait votre systme entre les noms et les numros des signaux. Voir Config(3) pour des exemples. Puisque %SIG est un hachage global, les affections que vous y effectuez se rpercutent sur tout votre programme. Il est souvent plus respectueux pour le reste de votre programme de confiner linterception des signaux une porte rduite. Faites cela avec une affectation en local du gestionnaire de signaux, ce qui na plus deffet une fois que lon sort du bloc lencadrant. (Mais souvenez-vous que les valeurs avec local sont visibles depuis les fonctions appeles depuis ce bloc.)
{ local $SIG{INT} = IGNORE; ... # Faites ce que vous voulez ici, en ignorant tous les SIGINT. fn(); # Les SIGINT sont galement ignors dans fn() ! ... # Et ici. } # La fin du bloc restaure la valeur prcdente de $SIG{INT}. fn(); # Les SIGINT ne sont pas ignors dans fn() (a priori).

Envoi de signaux des groupes de processus


Les processus (du moins sous Unix) sont organiss en groupes de processus, correspondant gnralement une tche complte. Par exemple, lorsque vous lancez une seule commande shell consistant en une srie de filtres envoyant les donnes de lun lautre travers des pipes, ces processus (et leurs fils) appartiennent au mme groupe. Ce groupe de processus possde un numro correspondant au numro du processus leader de ce groupe. Si vous envoyez un signal un numro de processus positif, il nest transmis qu ce processus ; mais si vous lenvoyez un numro ngatif, le signal est transmis tous les processus dont le numro de groupe est le nombre positif correspondant, cest-dire le numro de processus du leader de ce groupe. (De faon bien pratique, pour le leader du groupe, lID du groupe de processus est simplement $$.) Imaginez que votre programme veuille envoyer un signal hang-up tous ses processus fils, ainsi qu tous les petits-fils lancs par ces fils, ainsi qu tous les arrires-petitsfils lancs par ces petits-fils, ainsi qu tous les arrires-arrires-petits-fils lancs par ces arrires-petits-fils, et ainsi de suite. Pour faire cela, votre programme appelle dabord

customer_8566

Signaux

387

setpgrp(0,0) pour devenir le leader dun nouveau groupe de processus et tous les processus quil crera ensuite feront partie de ce nouveau groupe. Il importe peu que ces processus soient dmarrs manuellement via fork ou automatiquement via des open sur des pipes ou encore en tant que tches darrire-plan avec system("cmd &"). Mme si ces processus ont leurs propres fils, lenvoi dun signal hang-up au groupe de processus entier les trouvera tous (sauf pour les processus qui ont positionn leur propre groupe de processus ou chang leur UID pour sauto-accorder une immunit diplomatique envers vos signaux).
{ local $SIG{HUP} = IGNORE; kill(HUP, -$$); } # mexempte # envoie le signal mon propre # groupe de processus

Un autre signal intressant est le signal numro 0. En fait, ce dernier naffecte pas le processus cible mais vrifie plutt sil est toujours en vie et sil na pas chang son UID. Cest-dire quil vrifie sil est lgal de lui envoyer un signal sans le faire effectivement.
unless (kill 0 => $pid_fils) { warn "quelque chose daffreux est arriv $pid_fils"; }

Le signal numro 0 est le seul qui fonctionne de la mme faon sous les portages sur Microsoft comme il le fait sous Unix. Sur les systmes Microsoft, kill ne dlivre pas effectivement de signal. la place, il force le processus fils se terminer avec le statut indiqu par le numro de signal. Il se peut que cela soit corrig un jour. Cependant, le signal magique 0 a toujours le comportement par dfaut, non-destructeur.

Fossoyage des zombies


Lorsquun processus se termine, son pre reoit un signal CHLD envoy par le noyau et le processus devient un zombie4 jusqu ce que le parent appelle wait ou waitpid. Si vous dmarrez un autre processus en Perl en utilisant nimporte quoi dautre que fork, Perl soccupe de fossoyer vos fils zombies mais si vous utilisez un fork pur, vous tes censs nettoyer derrire vous. Sur la plupart des noyaux, mais pas tous, une bidouille simple pour fossoyer automatiquement les zombies consiste positionner $SIG{CHLD} IGNORE. Une approche plus souple (mais fastidieuse) est de les fossoyer vous-mmes. Comme il se peut quil y ait plus dun fils qui soit mort avant que vous ne vous en occupiez, vous devez rassembler vos zombies dans une boucle jusqu ce quil ny en ait plus :
use POSIX ":queue"; sub FOSSOYEUR { 1 until (waitpid(-1, WNOHANG) == -1) }

Pour lancer ce code comme il se faut, vous pouvez soit positionnez un gestionnaire pour le signal CHLD :
$SIG{CHLD} = \&FOSSOYEUR;

ou, si vous tes dans une boucle, arrangez-vous simplement pour appeler le fossoyeur
4. Si, si cest vraiment le terme technique consacr.

customer_8566

388

Chapitre 16 Communication interprocessus

de temps autre. Ceci est la meilleure approche car elle nest pas sujette au core dump occasionnel que les signaux peuvent parfois dclencher dans la bibliothque C. Toutefois, elle savre coteuse si on lappelle dans une boucle concise, un compromis raisonnable consiste donc utiliser une stratgie hybride dans laquelle vous minimisez le risque lintrieur du gestionnaire en en faisant le moins possible et en attendant sur lextrieur pour fossoyer les zombies :
our $zombies = 0; $SIG{CHLD} = sub { $zombies++ }; sub fossoyeur { my $zombie; our %Statut_Fils; # Stocke chaque code de retour $zombies = 0; while (($zombie = waitpid(-1, WNOHANG)) != -1) { $Statut_Fils{$zombie} = $?; } } while (1) { fossoyeur() if $zombies; ... }

Ce code prsume que votre noyau implmente des signaux fiables. Ce ntait traditionnellement pas le cas pour les anciens SysV ce qui rendait impossible lcriture de ges, tionnaires de signaux corrects. Depuis la version 5.003, Perl utilise, l o il est disponible, lappel systme sigaction(2), qui est bien plus digne de confiance. Cela signifie qu moins que vous ne tourniez sur un ancien systme ou avec un ancien Perl, vous naurez pas rinstaller vos gestionnaires et risquez de manquer des signaux. Heureusement, tous les systmes de la famille BSD (y compris Linux, Solaris et Mac OS X) et les systmes compatibles POSIX fournissent des signaux fiables, le comportement dgrad des anciens SysV est donc plus une remarque historique quun problme dactualit. Avec ces nouveaux noyaux, beaucoup dautres choses fonctionnent galement mieux. Par exemple, les appels systme lents (ceux qui peuvent bloquer, comme read, wait et accept) redmarreront automatiquement sils sont interrompus par un signal. Au mauvais vieux temps, le code de lutilisateur devait se souvenir de vrifier explicitement si chaque appel systme lent avait chou ou non, avec $! ($ERRNO) positionn EINTR et, si ctait le cas, le relancer. Ceci ne se produisait pas seulement avec les signaux INT ; mme des signaux inoffensifs comme TSTP (provenant dun Ctrl-Z) ou CONT (en passant la tche en premier plan) auraient fait avorter lappel systme. Perl redmarre maintenant lappel systme automatiquement pour vous si le systme dexploitation le permet. Ceci est gnralement dcrit comme tant une fonctionnalit. Vous pouvez vrifier si vous disposez ou non dun comportement des signaux plus rigoureux, dans le style de POSIX, en chargeant le module Config et en testant si $Config{d_sigaction} est vrai. Pour trouver si les appels systme lents sont redmarrables ou non, vrifiez la documentation de votre systme propos de sigaction(2) ou sigvec(3) ou dnichez SV_INTERRUPT ou SA_RESTART dans votre fichier C sys/signal.h. Si vous trouvez lun de ces symboles ou les deux, vous avez certainement des appels systme redmarrables.

customer_8566

Signaux

389

Minutage des oprations lentes


Une utilisation courante des signaux consiste imposer une limite de temps aux oprations sexcutant lentement. Si vous tes sur un systme Unix (ou sur tout autre systme compatible POSIX implmentant le signal ALRM), vous pouvez demander au noyau denvoyer un signal ALRM votre processus un moment venir prcis :
use Fcntl :flock; eval { local $SIG{ALRM} = sub { die "redmarrage de la minuterie" }; alarm 10; # planifie une alarme dans 10 secondes eval { flock(HF, LOCK_EX) # un verrou exclusif bloquant or die "flock impossible : $!"; }; alarm 0; # annule lalarme }; alarm 0; # protection contre une situation de concurrence die if $@ && $@ !~ /redmarrage de la minuterie/; # relance

Si lalarme est dclenche pendant que vous attendez le verrou et que vous ne faites quintercepter le signal avant de sortir, vous retournerez directement dans le flock car Perl relance automatiquement les appels systme l o cest possible. La seule solution est de lever une exception avec die et de laisser ensuite eval lintercepter. (Ceci fonctionne car lexception aboutit un appel de la fonction longjmp(3) de la bibliothque C et cest rellement ce qui vous dispense de relancer lappel systme.) La capture dexception imbrique existe car lappel de flock lverait une exception si flock ntait pas implment sur votre plate-forme et vous devez vous assurez dannuler lalarme dans tous les cas. Le second alarm 0 sert dans le cas o le signal arrive aprs avoir lanc le flock mais avant datteindre le premier alarm 0. Sans le second alarm 0, vous prendriez le risque davoir une lgre situation de concurrence (N.d.T. : race condition) mais le poids ne compte pas dans les situations de concurrence ; soit il y en a, soit il ny en a pas. Et nous prfrons quil ny en ait pas.

Blocage des signaux


De temps autre, vous aimeriez bien retarder la rception dun signal durant une section de code critique. Vous ne voulez pas ignorer le signal aveuglment mais ce que vous tes en train de faire est trop important pour tre interrompu. Le hachage %SIG de Perl nimplmente pas de blocage des signaux, contrairement au module POSIX, travers son interface lappel systme sigprocmask(2) :
use POSIX qw(:signal_h); $ensemble_signaux = POSIX::SigSet->new; $ensemble_bloques = POSIX::SigSet>new(SIGINT,SIGQUIT,SIGCHLD); sigprocmask(SIG_BLOCK, $ensemble_bloques, $ensemble_signaux) or die "Impossible de bloquer les signaux INT,QUIT,CHLD : $!\n";

Une fois que les trois signaux sont bloqus vous pouvez faire ce que vous voulez sans craindre dtre embt. Lorsque vous en avez fini avec votre section critique, dbloquez les signaux en restaurant lancien masque de signaux :

customer_8566

390

Chapitre 16 Communication interprocessus

sigprocmask(SIG_SETMASK, $ensemble_signaux) or die "Impossible de restaurer les signaux INT, QUIT, CHLD : $!\n";

Si lun de ces trois signaux tait arriv alors quils taient bloqus, ils sont dlivrs immdiatement. Si deux signaux ou plus sont en attente, lordre de dlivrance est indfini. De plus, on ne fait aucune distinction entre le fait de recevoir une seule fois un signal particulier que lon a bloqu et le recevoir plusieurs fois.5 Par exemple, si neuf processus fils se terminaient pendant que vous bloquiez les signaux CHLD, votre gestionnaire (si vous en aviez un) ne serait appel quune seule fois aprs avoir dbloqu les signaux. Cest pourquoi, lorsque vous fossoyez les zombies, vous devez toujours boucler jusqu ce quils soient tous partis.

Fichiers
Peut-tre naviez-vous jamais pens aux fichiers comme tant un mcanisme dIPC, mais ils se taillent la part du lion dans les communications interprocessus loin devant tous les autres procds runis. Lorsquun processus dpose ses prcieuses donnes dans un fichier et quun autre processus les extrait, ces processus ont communiqu entre eux. Les fichiers offrent quelque chose dunique parmi toutes les formes dIPC couvertes ici : comme un rouleau de papyrus enseveli dans le dsert et dterr aprs des millnaires, un fichier peut tre dterr et lu longtemps aprs le dcs de celui qui la crit.6 En travaillant sur la persistance tout en tant dune facilit dutilisation comparable, il nest pas surprenant que les fichiers soient toujours populaires. Lemploi de fichiers, pour transmettre des informations depuis un pass rvolu vers un futur incertain, amne quelques surprises. Vous crivez le fichier sur un mdium permanent, tel quun disque, et cest tout. (Vous pourriez dire un serveur web o le trouver, sil contient du HTML.) Cela devient un challenge intressant lorsque tous les protagonistes sont toujours en vie et essaient de communiquer entre eux. Sans une convention propos de celui dont le temps de parole est arriv, toute communication fiable est impossible ; laccord peut tre conclu via le verrouillage de fichier, qui sera abord dans le prochain paragraphe. Dans le paragraphe suivant, nous parlerons de la relation spciale existant entre un processus pre et ses fils, qui permet toutes les protagonistes dchanger de linformation via lhritage de laccs aux mmes fichiers. Les fichiers prsentent toutefois des limites quand il est question daccs distant, de synchronisation, de fiabilit et de suivi des sessions. Dautres paragraphes de ce chapitre prsentent divers mcanismes dIPC invents pour pallier ces limites.

Verrouillage de fichier
Dans un environnement multitche, vous devez faire attention ne pas rentrer en collision avec dautres processus essayant dutiliser le mme fichier que vous. Tant que tous les processus ne font que lire, il ny a aucun problme, mais ds quau moins un dentre
5. Cest--dire, traditionnellement. Les signaux comptabilisables seront peut-tre implments sur des systmes temps-rel daprs les dernires spcifications mais nous navons encore jamais vus de tels systmes. 6. Si tant est quun processus puisse dcder.

customer_8566

Fichiers

391

eux a besoin dcrire dans le fichier, il sen suit un chaos complet moins quun quelconque mcanisme de verrouillage ne vienne faire la police. Ne vous contentez pas de lexistence dun fichier (cest--dire, -e $fichier) comme une indication de verrouillage car il existe une situation de concurrence (race condition) entre le test de lexistence de ce nom de fichier et ce que vous avez prvu de faire avec (comme le crer, louvrir ou leffacer). Voir le paragraphe Grer les situations de concurrences au chapitre 23, Scurit, pour plus dinformations ce sujet. Linterface portable de Perl pour le verrouillage est la fonction flock(HANDLE, DRAPEAUX), dcrite au chapitre 29, Fonctions. Pour une portabilit maximale, Perl nutilise que les fonctionnalits de verrouillage les plus simples et les plus largement rpandues que lon puisse trouver sur le plus grand ventail de plates-formes. Cette smantique est suffisamment simple pour tre mule sur la plupart des systmes, y compris ceux qui nimplmentent pas lappel traditionnel du mme nom, comme System V ou Windows NT. (Cependant, si vous tournez sur un systme Microsoft antrieur NT, vous navez probablement aucune chance, vous nen auriez pas plus si vous tiez sur un systme Apple antrieur Mac OS X.) Il existe deux varits de verrous : les verrous partags (le drapeau LOCK_SH) et les verrous exclusifs (le drapeau LOCK_EX). Malgr le nom intimidant exclusif , les processus ne sont pas obligs dobir aux verrous sur les fichiers. Cest--dire que flock nimplmente quun verrouillage consultatif, signifiant que le verrouillage dun fichier nempche pas un autre processus de lire, ni mme dcrire dans ce fichier. Une demande de verrou exclusif nest quune manire pour un processus de permettre au systme dexploitation de bloquer cette demande jusqu ce quil ny ait plus de verrous, quils soient partags ou exclusifs. De mme, lorsquun processus demande un verrou partag, il ne fait que se bloquer lui-mme jusqu ce quil ny ait plus de verrous exclusifs. Un fichier en concurrence ne peut tre accessible de manire sre que lorsque tous les protagonistes utilisent le mcanisme de verrouillage de fichier. Ainsi, flock est une opration bloquante par dfaut. Cest--dire que si vous ne pouvez obtenir immdiatement le verrou que vous dsirez, le systme dexploitation bloque votre processus jusqu ce que ce soit possible. Voici comment obtenir un verrou partag, bloquant, gnralement utilis pour lire un fichier :
use Fcntl qw(:DEFAULT :flock); open(HF, "< nom_fichier") or die "impossible douvrir nom_fichier : $!"; flock(HF, LOCK_SH) or die "impossible de verrouiller nom_fichier : $!"; # maintenant, lisez le fichier

Vous pouvez essayer dacqurir un verrou de manire non-bloquante en incluant le drapeau LOCK_NB dans la requte flock. Sil est impossible de vous donner le verrou immdiatement, la fonction choue et renvoie instantanment faux. Voici un exemple :
flock(HF, LOCK_SH | LOCK_NB) or die "impossible de verrouiller nom_fichier : $!";

Vous pouvez dsirer quelque chose dautre que la leve dune exception comme nous lavons fait ici mais vous noserez certainement pas faire dentres/sorties sur le fichier. Si le verrou vous est refus, vous ne devriez pas accder au fichier jusqu ce que vous lobteniez. Qui sait dans quel tat de confusion vous pourriez trouver le fichier ? Lintrt principal du mode non-bloquant est de vous laisser sortir faire quelque chose dautre

customer_8566

392

Chapitre 16 Communication interprocessus

pendant lattente. Mais il peut galement savrer utile pour produire des interactions plus amicales en avertissant les utilisateurs que cela pourrait prendre du temps pour obtenir le verrou afin quils ne se sentent pas abandonns :
use Fcntl qw(:DEFAULT :flock); open(HF, "< nom_fichier") or die "impossible douvrir nom_fichier : $!"; unless (flock(HF, LOCK_SH | LOCK_NB)) { local $| = 1; print "Attente dun verrou sur nom_fichier..."; flock(HF, LOCK_SH) or die "impossible de verrouiller nom_fichier : $!"; print "obtenu.\n"; } # maintenant, lisez dans HF

Certains seront tents de mettre ce mode non-bloquant dans une boucle. Le problme majeur avec le mode non-bloquant est que, pendant que vous revenez pour vrifier nouveau, quelquun dautre a pu semparer du verrou parce que vous avez abandonn votre place dans la file dattente. Parfois vous navez qu vous mettre dans la file et patienter. Si vous avez de la chance, il y aura quelques magazines lire. Les verrous sappliquent sur les handles de fichiers, non sur les noms de fichiers.7 Lorsque vous fermez le fichier, le verrou se dissout automatiquement, que vous ayez ferm le fichier explicitement en appelant close ou implicitement en le rouvrant ou en quittant votre processus. Pour obtenir un verrou exclusif, gnralement utilis pour crire dans un fichier, vous devez faire attention. Vous ne pouvez pas utiliser pour cela un open ordinaire ; si vous utilisez un mode douverture de <, il chouera sur les fichiers qui nexistent pas encore et si vous utilisez >, il crasera les fichiers existant dj. Utilisez plutt sysopen sur le fichier afin quil puisse tre verrouill avant dtre cras. Une fois que vous avez ouvert le fichier en toute scurit pour y crire mais que vous ny avez pas encore touch, obtenez un verrou exclusif et alors seulement, tronquez le fichier. Maintenant vous pouvez lcraser avec les nouvelles donnes.
use Fcntl qw(:DEFAULT :flock); sysopen(HF, "nom_fichier", O_WRONLY | O_CREAT) or die "impossible douvrir nom_fichier : $!"; flock(HF, LOCK_EX) or die "impossible de verrouiller nom_fichier : $!"; truncate(HF, 0) or die "impossible de tronquer nom_fichier : $!"; # maintenant, crivez dans HF

7. En fait, les verrous ne sappliquent pas sur des handles de fichiers ils sappliquent sur les descripteurs de fichiers associs aux handles puisque le systme dexploitation ne connat pas les handles. Cela signifie que tous vos messages die portant sur lchec de lobtention dun verrou sur le non de fichier sont techniquement inapropris. Mais les messages derreur de la forme Je ne peux pas obtenir de verrou sur le fichier reprsent par le descripteur associ au handle ouvert lorigine avec le chemin nom_fichier, bien que nom_fichier puisse maintenant reprsenter un fichier totalement diffrent de celui que notre handle reprsente ne feraient que semer la confusion dans lesprit de lutilisateur (sans parler du lecteur).

customer_8566

Fichiers

393

Si vous voulez modifier le contenu dun fichier sur place, utilisez encore sysopen. Cette fois-ci, vous demandez un accs la fois en lecture et en criture, en crant le fichier si besoin. Une fois le fichier ouvert mais avant davoir fait la moindre lecture ou criture, obtenez le verrou exclusif et gardez-le durant toute votre transaction. Il vaut souvent mieux relcher le verrou en fermant le fichier car cela garantit que tous les tampons seront vids avant que le verrou ne soit relch. Une mise jour implique la lecture danciennes valeurs et lcriture de nouvelles. Vous devez accomplir ces deux oprations sous un seul verrou exclusif, de peur quun autre processus ne lise les valeurs (en passe de devenir incorrectes) aprs (voire avant) vous, mais avant que vous ncriviez. (Nous reverrons cette situation quand nous aurons parl de la mmoire partage, plus loin dans ce chapitre.)
use Fcntl qw(:DEFAULT :flock); sysopen(HF, "fichier_compteur", O_RDWR | O_CREAT) or die "impossible douvrir fichier_compteur : $!"; flock(HF, LOCK_EX) or die "impossible de verrouiller en criture fichier_compteur : $!"; $compteur = <HF> || 0; # serait indfini la premire fois seek(HF, 0, 0) or die "impossible de rembobiner fichier_compteur : $!"; print HF $compteur+1, "\n" or die "impossible dcrire dans fichier_compteur : $!"; # la prochaine ligne est superflue dans ce programme # mais est une bonne ide dans le cas gnral truncate(HF, tell(HF)) or die "impossible de tronquer fichier_compteur : $!"; close(HF) or die "impossible de fermer fichier_compteur : $!";

Vous ne pouvez pas verrouiller un fichier que vous navez pas encore ouvert et vous ne pouvez pas avoir un verrou unique sappliquant plus dun fichier. Cependant, ce quil vous est possible de faire est dutiliser un fichier totalement spar qui se comporterait comme une sorte de smaphore, comme un feu de signalisation, et qui fournirait un accs contrl quelque chose dautre travers des verrous partags et exclusifs sur ce fichier smaphore. Cette approche possde de multiples avantages. Vous pouvez avoir un fichier verrou qui contrle laccs de multiples fichiers, vitant le genre de verrou mortel (deadlock) survenant lorsquun processus essaie de verrouiller ces fichiers dans un certain ordre pendant quun autre processus essaie de les verrouiller dans un ordre diffrent. Vous pouvez utiliser un fichier smaphore pour verrouiller un rpertoire entier. Vous pouvez mme contrler laccs quelque chose dautre qui ne soit mme pas dans le systme de fichiers, comme un objet de mmoire partage ou une socket sur laquelle plusieurs serveurs prforks aimeraient appeler accept. Si vous avez un fichier DBM ne fournissant pas son propre mcanisme de verrouillage explicite, un fichier verrou auxiliaire est la meilleure faon de contrler les accs concurrents par de multiples agents. Sinon, le cache interne de votre bibliothque DBM peut se dsynchroniser du fichier sur disque. Avant dappeler dbmopen ou tie, ouvrez et

customer_8566

394

Chapitre 16 Communication interprocessus

verrouillez le fichier smaphore. Si vous ouvrez la base de donnes avec O_RDONLY, vous devrez utiliser LOCK_SH pour le verrou. Sinon, utilisez LOCK_EX, pour un accs exclusif lors des mises--jour dans la base. (Encore une fois, cela ne fonctionne que si tous les protagonistes sentendent pour accorder de lattention au smaphore.)
use Fcntl qw(:DEFAULT :flock); use DB_File; # seulement pour la dmonstration ; toute autre db convient $NOM_DB = "chemin/a/la/base"; $VERROU = $NOM_DB . ".verrou"; # utilisez O_RDWR si vous pensez mettre des donnes dans le fichier verrou sysopen(DB_VER, $VERROU, O_RDONLY | O_CREAT) or die "impossible douvrir $VERROU : $!"; # vous devez obtenir le verrou avant douvrir la base flock(DB_VER, LOCK_SH) or die "impossible de verrouiller $VERROU avec LOCK_SH : $!"; tie(%hachage, "DB_File", $NOM_DB, O_RDWR | O_CREAT) or die "impossible de lier $NOM_DB : $!";

Maintenant vous pouvez en toute scurit faire ce que vous voulez avec le %hachage li. Lorsque vous en avez fini avec votre base de donnes, assurez-vous de relcher explicitement ces ressources et dans lordre inverse de celui avec lequel vous les avez acquises :
untie %hachage; close DB_VER; # vous devez fermer la base avant le fichier verrou # maintenant le verrou peut partir en toute scurit

Si la bibliothque GNU DBM est installe, vous pouvez utiliser le verrouillage implicite du module standard GDBM_File. Sauf si le tie initial contient le drapeau GDBM_NOLOCK, la bibliothque sassure que seul un crivain la fois puisse ouvrir le fichier GDBM et que les lecteurs et les crivains naient pas la fois la base de donnes ouverte.

Passage de handles de fichiers


chaque fois que vous crez un processus fils en utilisant fork, ce nouveau processus hrite de tous les handles de fichiers ouverts de son pre. Lutilisation des handles de fichiers pour les communications interprocessus plus facile illustrer en utilisant tout dabord des fichiers. La comprhension de ce mcanisme est essentielle pour matriser les mcanismes plus labors des pipes et des sockets, dcrits plus loin dans ce chapitre. Lexemple le plus simple consiste ouvrir un fichier et dmarrer un processus fils. Le fils utilise alors le handle de fichier dj ouvert pour lui :
open(ENTREE, "< /etc/motd") or die "/etc/motd : $!"; if ($pid = fork) { waitpid($pid,0) } else { defined($pid) or die "fork : $!"; while (<ENTREE>) { print "$. : $_" } exit; # empche le fils de retomber dans le code principal } # le handle de fichier ENTREE se trouve maintenant EOF pour le pre

customer_8566

Fichiers

395

Une fois que laccs un fichier a t accord par open, il le reste jusqu la fermeture du handle de fichier ; la modification des permissions du fichier ou des privilges daccs na aucun effet sur son accessibilit. Mme si le processus altre ultrieurement son ID dutilisateur ou de groupe ou si le fichier est transfr un nouveau propritaire, cela naffecte pas les handles de fichiers dj ouverts. Les programmes tournant sous des permissions accrues (comme les programmes set-id ou les dmons du systme) ouvrent souvent un fichier sous leurs droits accrus et dlguent ensuite le handle de fichier un processus fils qui naurait pas pu ouvrir le fichier lui-mme. Bien que cette fonctionnalit soit trs pratique lorsquelle est utilise intentionnellement, elle peut galement poser des problmes de scurit si les handles de fichiers ont des fuites accidentelles dun programme lautre. Pour viter daccorder un accs implicite tous les handles de fichiers possibles, Perl ferme automatiquement tout handle de fichier quil a ouvert (y compris les pipes et les sockets) chaque fois que vous lancez avec exec un nouveau programme ou que vous en excutez un implicitement avec un open sur un pipe, avec system ou avec qx// (apostrophes inverses). Les handles de fichiers du systme STDIN, STDOUT et STDERR chappent cette rgle car leur fonction premire est de fournir un lien dans les communications entre programmes. Un moyen de passer un handle de fichier un nouveau programme consiste donc copier ce handle vers un des handles standard :
open(ENTREE, "< /etc/motd") if ($pid = fork) { wait } else { defined($pid) open(STDIN, "<&ENTREE") exec("cat", "-n") } or die "/etc/motd : $!";

or die "fork : $!"; or die "dup : $!"; or die "exec cat : $!";

Si vous voulez vraiment que le nouveau programme acquire laccs un handle de fichier autre que ces trois-l, cest possible mais vous devrez faire une ou deux petites choses. Lorsque Perl ouvre un nouveau fichier (ou un pipe, ou une socket), il vrifie la valeur courante de la variable $^F ($SYSTEM_MAX_FD). Si le descripteur numrique du fichier utilis par ce nouveau handle de fichier est suprieur $^F, il est marqu comme lun des descripteur quil faudra fermer. Sinon, Perl le laisse tranquille et les nouveaux programmes que vous lancerez avec exec hriteront de laccs. Il nest pas toujours aussi facile de prdire quel descripteur de fichier aura votre handle rcemment ouvert mais vous pouvez positionner de manire temporaire votre numro maximal pour les descripteurs de fichiers systme une valeur immodrment grande le temps de faire le open :
# ouvre le fichier et marque ENTREE comme devant tre # conserv entre les exec { local $^F = 10_000; open(ENTREE, "< /etc/motd") or die "/etc/motd : $!"; } # lancienne valeur de $^F est restaure lorsquon sort de la porte

Maintenant, tout ce quil vous reste faire est dobtenir que le nouveau programme accorde de lattention au numro de descripteur du handle de fichier que vous venez douvrir. La solution la plus propre (sur les systmes implmentant ceci) consiste pas-

customer_8566

396

Chapitre 16 Communication interprocessus

ser un nom de fichier spcial quivalant un descripteur de fichier. Si votre systme possde un rpertoire nomm /dev/fd ou /proc/$$/fd, contenant des fichiers numrots de 0 au numro maximal de descripteurs supports, vous pouvez probablement utiliser cette stratgie. (Beaucoup de systmes dexploitation Linux ont les deux mais seule la version /proc a tendance tre correctement peuple. Les systmes BSD et Solaris prfrent /dev/fd. Vous devrez fureter dans votre systme pour voir ce qui vous convient le mieux.) Ouvrez dabord votre handle de fichier et marquez-le comme tant lun de ceux laisser ouverts entre les exec comme dans le code prcdent, puis faites un fork comme ceci :
if ($pid = fork) { wait } else { defined($pid) or die "fork : $!"; $fichier_df = "/dev/fd/" . fileno(ENTREE); exec("cat", "-n", $fichier_df) or die "exec cat : $!"; }

Si votre systme implmente lappel systme fcntl, vous pouvez ajuster manuellement le drapeau de handle de fichier close-on-exec. Ceci est pratique pour les fois o vous navez pas ralis lorsque vous avez cr le handle de fichier que vous voudriez le partager avec vos fils.
use Fcntl qw/F_SETFD/; fcntl(ENTREE, F_SETFD, 0) or die "Impossible de mettre zro le flag close-on-exec pour ENTREE : $!\n";

Vous pouvez galement forcer un handle de fichier se fermer :


fcntl(ENTREE, F_SETFD, 1) or die "Impossible de positionner le flag close-on-exec pour ENTREE : $!\n";

Vous pouvez aussi demander le statut actuel :


use Fcntl qw/F_SETFD F_GETFD/; printf("ENTREE sera %s entre les exec\n", fcntl(ENTREE, F_GETFD, 1) ? "ferm" : "laiss ouvert");

Si votre systme nimplmente pas les descripteurs de fichiers nomms dans le systme de fichiers et que vous voulez passer un handle de fichier autre que STDIN, STDOUT ou STDERR, vous pouvez toujours le faire, mais vous devrez procder quelques arrangements spciaux dans votre programme. Les stratgies courantes pour ceci consistent passer le numro de descripteur par le biais dune variable denvironnement ou dune option de la ligne de commande. Si le programme excut est en Perl, vous pouvez utiliser open pour convertir un descripteur de fichier en un handle de fichier. Au lieu de spcifier un nom de fichier, utiliser "&=", suivi du numro de descripteur.
if (defined($ENV{no_df_entree}) && $ENV{no_df_entree} =~ /^d$/) { open(ENTREE, "<&=$ENV{no_df_entree}") or die "fdopen $ENV{no_df_entree} en entre impossible : $!"; }

customer_8566

Pipes

397

Cela devient encore plus facile que cela si vous allez lancer un sous-programme ou un programme Perl qui attend un nom de fichier comme argument. Vous pouvez utiliser la fonctionnalit douverture de descripteur de la fonction ordinaire open de Perl (et non sysopen ou la forme trois argument dopen) pour que cela se fasse automatiquement. Imaginez que vous ayez un simple programme Perl comme ceci :
#!/usr/bin/perl -p # nl - numro de lignes en entre printf "%6d ", $.;

En supposant que vous vous tes arrang pour que le handle ENTREE reste ouvert entre les exec, vous pouvez appeler ce programme de cette manire :
$df_spec = <&= . fileno(ENTREE); system("nl", $df_spec);

ou pour capturer la sortie :


@lignes = nl $df_spec; # les apostrophes empchent le # shell dinterpoler df_spec

Que vous fassiez ou non un exec dun autre programme, si vous utilisez les descripteurs de fichiers hrits travers un fork, il y a un petit ppin. Au contraire des variables copies travers un fork, qui deviennent en fait des copies dupliques mais indpendantes, les descripteurs de fichiers sont vraiment les mmes dans les deux processus. Si lun des processus lit des donnes depuis le handle, le pointeur de seek (reprsentant la position dans le fichier) avance galement dans lautre processus et ces donnes ne sont plus accessibles par les deux processus. Sils lisent chacun leur tour, ils joueront ensemble saute-mouton dans le fichier. Intuitivement, cela reste sens pour les handles attachs des priphriques sries, des pipes ou des sockets, puisque ceux-ci ont tendance tre des priphriques en lecture seule avec des donnes phmres. Mais ce comportement peut vous surprendre avec des fichiers sur disque. Si cest un problme, rouvrez tout fichier ayant besoin de traages spars aprs le fork. Loprateur fork est un concept tir dUnix, ce qui signifie quil peut ne pas tre correctement implment sur toutes les plates-formes non-Unix/non-POSIX. Notamment, fork ne fonctionne sur les systmes Microsoft que si vous lancer Perl 5.6 (ou une version suprieure) sur Windows 98 (ou une version ultrieure). Bien que fork soit implment sur ces systmes via de multiples f lux dexcution concurrents dans le mme programme, il ne sagit pas des types de tches (threads) o toutes les donnes sont partages par dfaut ; ici, seuls les descripteurs de fichiers le sont. Voir galement le chapitre 17, Threads.

Pipes
Un pipe est un canal dentres/sorties unidirectionnel pouvant transfrer un f lux doctets dun processus un autre. Il existe deux varits de pipes : les pipes nomms et les pipes anonymes. Il se peut que vous connaissiez mieux les pipes anonymes, dont nous commencerons donc par parler.

customer_8566

398

Chapitre 16 Communication interprocessus

Pipes anonymes
La fonction open de Perl ouvre un pipe plutt quun fichier lorsque vous ajouter un symbole de pipe au dbut ou la fin du deuxime argument dopen. Cela change le reste de largument en une commande, qui sera interprte en tant que processus (ou en tant quensemble de processus) depuis lequel vous voulez recevoir ou vers lequel vous voulez envoyer un f lux de donnes via un pipe. Voici comment dmarrer un processus fils auquel vous avez lintention dcrire :
open IMPRESSION, or die "fork local $SIG{PIPE} print IMPRESSION close IMPRESSION "| cat -v | lpr -h 2>/dev/null" impossible : $!"; = sub { die "pipe dimpression cass" }; "trucs\n"; or die "mauvaise impression : $! $?";

Cet exemple dmarre en fait deux processus, nous crivons directement dans le premier (effectuant cat). Le second processus (effectuant lpr) reoit ensuite la sortie du premier. Dans la programmation shell, on appelle frquemment ceci un pipeline. Un pipeline peut contenir autant de processus la suite que vous voulez, pourvu que ceux se trouvant au milieu sachent se comporter comme des filtres ; cest--dire quils sachent lire depuis lentre standard et crire dans la sortie standard. Perl utilise le shell par dfaut de votre systme (/bin/sh sur Unix) chaque fois quune commande de pipe comprend des caractres spciaux que le shell prend en compte. Si vous ne faites que dmarrer une commande et si vous navez pas besoin dutiliser un shell ou si vous ne voulez pas , vous pouvez plutt employer la forme plusieurs arguments dun open sur un pipe :
open IMPRESSION, "|-", "lpr", "-h" # exige Perl 5.6.1 or die "impossible de lancer lpr : $!";

Si vous rouvrez la sortie standard de votre programme en tant que pipe vers un autre programme, tout ce que vous afficherez ultrieurement avec print vers STDOUT deviendra lentre standard du nouveau programme. Ainsi, pour envoyer un pager la sortie de votre programme,8 vous devez utiliser :
if (-t STDOUT) { # my $pager = $ENV{PAGER} || open(STDOUT, "| $pager") } END { close(STDOUT) } seulement si stdout est un terminal more; or die "fork du pager impossible : $!";

or die "impossible de fermer STDOUT : $!"

Lorsque vous crivez dans un handle de fichier connect un pipe, fermez toujours ce handle explicitement avec close lorsque vous en avez fini avec lui. De cette manire, votre programme principal ne se terminera pas avant sa progniture. Voici comment dmarrer un processus fils dans lequel vous avez lintention de lire :
open STATUT, "netstat -an 2>/dev/null |"
8. Cest--dire, permettre de la consulter un cran par cran et non dclencher des bips alatoires.

customer_8566

Pipes
or die "fork impossible : $!"; while (<STATUT>) { next if /^(tcp|udp)/; print; } close STATUT or die "mauvais netstat: $! $?";

399

Vous pouvez ouvrir un pipeline sur plusieurs niveaux en entre exactement comme vous le pouvez en sortie. Et comme prcdemment, vous pouvez viter le shell en utilisant une autre forme dopen :
open STATUT, "-|", "netstat", "-an" # exige Perl 5.6.1 or die "impossible de lancer netstat : $!";

Mais dans ce cas, vous naurez pas de redirection des entres/sorties, ni dexpansion de jokers (wilcard), ni de pipes sur plusieurs niveaux, puisque Perl se base sur votre shell pour ces fonctionnalits. Vous pourriez avoir remarqu que vous pouvez utiliser des apostrophes inverses pour obtenir le mme effet quen ouvrant un pipe en lecture :
print grep { !/^(tcp|udp)/ } netstat -an 2>&1; die "mauvais netstat" if $?;

Si les apostrophes sont extrmement commodes, le programme lit tout en mmoire en une seule fois, il est donc souvent plus efficace douvrir votre propre handle de fichier sur un pipe et de traiter le fichier ligne par ligne ou enregistrement par enregistrement. Cela vous donne un contrle plus fin sur lensemble de lopration, en vous laissant tuer le processus fils plus tt si a vous plat. Vous pouvez galement tre plus efficace en traitant lentre au fur et mesure, puisque les ordinateurs savent intercaler diverses oprations lorsque deux processus ou plus tournent en mme temps. (Mme sur une machine avec une seule CPU, les oprations dentres/sorties peuvent survenir lorsque la CPU fait autre chose.) Comme vous lancez deux processus ou plus en concurrence, une catastrophe peut frapper le processus fils nimporte quel moment entre louverture avec open et la fermeture avec close. Cela signifie que le pre doit vrifier la valeur de retour des deux fonctions, open et close. La seule vrification dopen nest pas suffisante, puisquelle vous dirait seulement si la commande a t lance avec succs ou non. (Elle ne peut vous dire ceci que dans les versions rcentes de Perl et seulement si la commande est excute directement par le fils et non via le shell.) Le fils rapporte son pre les catastrophes qui interviennent aprs cela avec un statut de fin non nul. Lorsque la fonction close voit cela, elle sait renvoyer une valeur fausse, indiquant que le vritable statut devrait tre lu partir de la variable $? ($CHILD_ERROR). Vrifier la valeur renvoye par close est donc aussi important que celle renvoye par open. Si vous crivez dans un pipe, vous devriez galement vous prparer grer le signal PIPE, qui vous est envoy si le processus lautre extrmit meurt avant que vous ayez fini de lui transmettre des donnes.

Soliloque
Une autre approche de la communication interprocessus consiste faire soliloquer le programme, pour ainsi dire. En fait, votre processus discute avec une copie de lui-mme par le biais de pipes. Cela fonctionne largement comme lopen sur un pipe dont nous

customer_8566

400

Chapitre 16 Communication interprocessus

avons parl au paragraphe prcdent, hormis le fait que le processus fils continue excuter votre script plutt quune autre commande. Pour indiquer ceci la fonction open, utilisez une pseudo-commande compose dun signe moins. Le second argument dopen ressemble donc -| ou |- , selon que vous voulez transmettre des donnes depuis ou vers vous-mme. Comme avec une commande fork ordinaire, la fonction open renvoie lID du processus fils dans le processus pre, mais 0 dans le processus fils. Une autre asymtrie est que le handle de fichier cit dans lopen nest utilis que dans le processus pre. Lextrmit du pipe pour le fils est rattache soit STDIN, soit STDOUT, selon le cas. Cest--dire que si vous ouvrez un pipe vers le signe moins, vous pouvez crire des donnes dans le handle de fichier que vous avez ouvert et votre fils les lira dans STDIN :
if (open(VERS, "|-")) { print VERS $depuis_pere; } else { $vers_fils = <STDIN>; exit; }

Si vous ouvrez un pipe depuis le signe moins, vous pouvez lire dans le handle de fichier ouvert ce que le fils crit dans STDOUT :
if (open(DEPUIS, "-|")) $vers_pere = <DEPUIS>; } else { print STDOUT $depuis_fils; exit; }

Une application courante de cette construction est de court-circuiter le shell lorsque vous voulez ouvrir un pipe depuis une commande. Vous pourriez vouloir faire ceci car vous ne voulez pas que le shell interprte les mtacaractres ventuels dans les noms de fichiers que vous essayer de passer la commande. Si vous tournez sous la version 5.6.1 de Perl, ou une version suprieure, vous pouvez utiliser la forme plusieurs arguments dopen pour obtenir le mme rsultat. Une autre utilisation dun open sur un fork consiste ouvrir un fichier ou une commande en toute scurit alors que vous tournez sous un certain UID ou GID. Le fils que vous lancez avec fork abandonne tous les droits daccs spciaux, puis ouvre en toute scurit le fichier ou la commande et se comporte comme un intermdiaire, en passant les donnes entre son pre plus puissant et le fichier ou la commande quil a ouvert. Vous pouvez trouver des exemples dans la section Accder aux commandes et aux fichiers avec des privilges restreints, au chapitre 23. Une utilisation pleine de crativit dun open sur un fork est le filtrage de votre propre sortie. Certains algorithmes sont beaucoup plus faciles implmenter en deux passes spares plutt quen une seule. Voici un exemple simple dans lequel nous mulons le programme tee(1) dUnix en envoyant notre sortie ordinaire vers un pipe. Lagent lautre extrmit du pipe (lun de vos propres sous-programmes) distribue notre sortie vers tous les fichiers spcifis :

customer_8566

Pipes
tee("/tmp/truc", "/tmp/machin", "/tmp/bidule"); while (<>) { print "$ARGV la ligne $. => $_"; } close(STDOUT) or die "impossible de fermer STDOUT : $!"; sub tee { my @sortie = @_; my @handles = (); for my $chemin (@sortie) { my $hf; # open remplira ceci unless (open ($hf, ">", $chemin)) { warn "impossible dcrire dans $chemin : $!"; next; } push @handles, $hf; } # rouvre STDOUT dans le pre et renvoie return if my $pid = open(STDOUT, "|-"); die "fork impossible : $!" unless defined $pid; # traite STDIN dans le fils while (<STDIN>) { for my $hf (@handles) { print $hf $_ or die "chec de la sortie de tee : $!"; } } for my $hf (@handles) { close($hf) or die "chec de la fermeture de tee : $!"; } exit; # empche le fils de renvoyer au programme principal ! }

401

Cette technique peut tre applique en boucle pour mettre autant de filtres que vous le dsirez sur votre sortie. Continuez simplement dappeler les fonctions qui font un forkopen sur STDOUT, ayez le fils qui lit depuis son pre (quil voit en tant que STDIN) et passez la sortie triture la prochaine fonction de la chane. Une autre application intressante du soliloque avec fork-open consiste capturer la sortie dune fonction ayant de mauvaises manires en envoyant tous ses rsultats clabousser STDOUT. Imaginez Perl qui naurait quune fonction printf, sans fonction sprintf. Ce dont vous auriez besoin est dune fonction marchant comme les apostrophes inverses mais avec des fonctions Perl au lieu de commandes externes :
fonction_mechante("arg"); # zut, a nous a chapp ! $chaine = sub_fork(\&fonction_mechante, "arg"); # capturez-la dans une # chane @lignes = sub_fork(\&fonction_mechante, "arg"); # dans des lignes spares sub sub_fork {

customer_8566

402

Chapitre 16 Communication interprocessus


my $pid_fils = open my $self, "-|"; defined $pid_fils or die "fork impossible : $!"; shift->(@_), exit unless $pid_fils; local $/ unless wantarray; return <$self>; # ferme la sortie de la porte

Nous ne prtendons pas que ceci est efficace ; un handle de fichier li avec tie irait certainement bien plus vite. Mais cest beaucoup plus facile coder si vous tes plus press que votre ordinateur.

Communication bidirectionnelle
Bien que lemploi dopen, pour se connecter une autre commande via un pipe, fonctionne raisonnablement bien pour les communications unidirectionnelles, quid des communications bidirectionnelles ? Lapproche la plus vidente ne fonctionne pas :
open(PROG_EN_LECTURE_ECRITURE, "| un programme |") # MAUVAIS !

et si vous oubliez dactiver les avertissements, le message de diagnostic passera la trappe :


Cant do bidirectional pipe at mon_prog line 3.

La fonction open ne lautorise pas car cette approche est tout fait encline causer des verrous mortels (deadlocks) si vous ntes pas trs attentif. Mais si vous tes dtermin,vous pouvez utiliser le module standard de bibliothque IPC::Open2 pour rattacher deux pipes aux STDIN et STDOUT dun sous-processus. Il existe galement IPC::Open3 pour les entres/sorties tridirectionnelles (vous permettant galement de capturer le STDERR de votre fils fils) mais ce dernier exige soit une boucle select embarrasse, soit le module IO::Select, plus commode. Mais vous devrez alors viter les oprations dans le tampon dentre de Perl, comme <> (readline). Voici un exemple utilisant open2 :
use IPC::OPen2; local (*Lecteur, *Ecrivain); $pid = open2(\*Lecteur, \*Ecrivain, "bc -l"); $somme = 2; for (1 .. 5) { print Ecrivain "$somme * $somme\n"; chomp($somme = <Lecteur>); } close Ecrivain; close Lecteur; waitpid($pid, 0); print "La somme vaut $somme\n";

Vous pouvez galement autovivifier des handles de fichiers lexicaux :


my ($hf_lecture, $hf_ecriture); $pid = open2($hf_lecture, $hf_hf_ecriture, "cat -u -n");

Gnralement le problme avec ceci est que le vidage de tampon standard des entres/ sorties va vraiment gcher votre journe. Mme si votre handle de fichier de sortie est

customer_8566

Pipes

403

automatiquement vid (la bibliothque le fait pour vous) de sorte que le processus lautre extrmit recevra vos donnes de manire opportune, vous ne pouvez gnralement rien faire pour lobliger vous retourner la politesse. Dans ce cas particulier, nous avons de la chance : bc sattend manipuler un pipe et sait vider ( f lush) chaque ligne de sortie. Mais peu de commandes sont conues de la sorte, cela fonctionne donc rarement moins dcrire vous-mme le programme lautre extrmit du pipe bidirectionnel. Mme les simples programmes apparemment interactifs, comme ftp, chouent ici car ils ne videront pas leur tampon ligne par ligne dans un pipe. Il ne le feront que sur un priphrique tty. Les modules de CPAN IO::Pty et Expect peuvent vous venir en aide car ils fournissent un vrai tty (en fait, un vrai pseudo-tty mais se comportant comme un vrai). Cela vous donne un vidage de tampon ligne par ligne dans lautre processus, sans modifier son programme. Si vous clatez votre programme en plusieurs processus et que vous voulez quils aient tous ensemble une conversation allant dans les deux sens, vous ne pouvez pas utiliser les interfaces de haut niveau de Perl, car ces dernires sont toutes unidirectionnelles. Vous devrez utilisez deux appels de fonction pipe, de bas niveau, chacun manipulant une direction dans la conversation :
pipe(DEPUIS_PERE, VERS_FILS) or die "pipe : $!"; pipe(DEPUIS_FILS, VERS_PERE) or die "pipe : $!"; select((select(VERS_FILS), $| = 1))[0]); # vidage automatique select((select(VERS_PERE), $| = 1))[0]); # vidage automatique if ($pid = fork) { close DEPUIS_PERE; close VERS_PERE; print VERS_FILS "Pid $$ du pre envoie ceci\n"; chomp($ligne = <DEPUIS_FILS>); print "Pid $$ du pre vient de lire ceci : $ligne\n"; close DEPUIS_FILS; close VERS>FILS; waitpid($pid,0); } else { die "fork impossible : $!" unless defined $pid; close DEPUIS_FILS; close VERS_FILS; chomp($ligne = <DEPUIS_PERE>); print "Pid $$ du fils vient de lire ceci : $ligne\n"; print VERS_PERE "Pid $$ du fils envoie ceci\n"; close DEPUIS_PERE; close VERS_PERE; exit; }

Sur la plupart des systmes Unix, vous navez en fait pas faire deux appels pipe spars pour accomplir une communication bidirectionnelle complte ( full duplex) entre un pre et son fils. Lappel socketpair fourni des connexions bidirectionnelles entre des processus associs sur la mme machine. Ainsi, plutt que deux pipe, vous navez besoin que dun socketpair :
use Socket; socketpair(Fils, Pere, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die "socketpair: $!";

customer_8566

404

Chapitre 16 Communication interprocessus

# ou laissez Perl choisir les handles de fichiers pour vous my ($hf_fils, $hf_pere); socketpair($hf_fils, $hf_pere, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die "socketpair: $!";

Aprs le fork, le pre ferme le handle Pere, puis lit et crit via le handle Fils. Pendant ce temps, le fils ferme le handle Fils, puis lit et crit via le handle Pere.

Pipes nomms
Un pipe nomm (souvent appel FIFO) est un mcanisme pour mettre en place un conversation entre des processus sans rapport les uns avec les autres, sur la mme machine. Les noms en question existent dans le systme de fichiers, ce qui est une manire amusante de dire que vous pouvez mettre un fichier spcial dans le systme de fichiers, soustendant un processus plutt quun disque.9 Un FIFO est pratique lorsque vous voulez connecter un processus un autre qui na aucun rapport. Lorsque vous ouvrez un FIFO, votre processus bloquera jusqu ce quil y ait un processus lautre extrmit. Ainsi, si un lecteur ouvre en premier un FIFO, il bloquera jusqu ce que lcrivain apparaisse et vice-versa. Pour crer un pipe nomm, utilisez la fonction mkfifo de POSIX enfin, si vous tes sur un systme POSIX. Sur les systmes Microsoft, vous pourrez la place regarder le module Win32::Pipe, qui, malgr les apparences, cre des pipes nomms. (Les utilisateurs de Win32 crent des pipes anonymes en employant pipe, tout comme le reste dentre nous.) Par exemple, mettons que vous aimeriez que votre fichier .signature produise une rponse diffrente chaque fois quil est lu. Vous navez qu le mettre en pipe nomm avec un programme Perl lautre extrmit crachant des aphorismes au hasard. Maintenant, chaque fois quun programme quelconque (comme en logiciel envoyant des mails, un lecteur de forums de discussion, un programme finger, et ainsi de suite) essayera de lire dans ce fichier, ce programme se connectera au vtre et lira une signature dynamique. Dans lexemple suivant, nous utilisons loprateur de test de fichier -p, que lon rencontre rarement, pour dterminer si quelquun (ou quelque chose) a supprim accidentellement notre FIFO.10 Si cest le cas, il ny a aucune raison pour essayer de louvrir, nous traiterons donc ceci comme une demande de terminaison. Si nous utilisions une simple fonction open avec un mode valant +> $chemin_f , il y aurait une minuscule situation de concurrence (race condition) qui risquerait de crer la signature en tant que simple fichier sil disparaissait entre le test -p et louverture. Nous ne pourrions pas non plus utiliser un mode valant +< $chemin_f car louverture dune FIFO en lecturecriture est non-bloquante (ceci nest vrai que pour les FIFO). En utilisant sysopen et en omettant le drapeau O_CREAT, nous vitons ce problme en ne crant jamais de fichier

9. Vous pouvez utiliser la mme chose avec des sockets dans le domaine Unix mais vous ne pouvez pas utiliser open sur ces derniers. 10. Une autre utilisation consiste voir si un handle de fichier est connect un pipe, nomm ou anonyme, comme dans -p STDIN.

customer_8566

IPC System V
par accident.
use Fcntl; # pour sysopen chdir; # au rpertoire maison $chemin_f = .signature; $ENV{PATH} .= ":/usr/games"; unless (-p $chemin_f) { # pas un pipe if (-e _) { # mais quelque chose dautre die "$0 : ncrasera pas .signature\n"; } else { require POSIX; POSIX::mkfifo($chemin_f, 0666) or die "mknod $chemin_f impossible: $!"; warn "$0 : a cr $chemin_f en tant que pipe nomm\n"; } } while (1) { # quitte si le fichier signature est supprim manuellement die "Le fichier pipe a disparu" unless -p $chemin_f; # la prochaine ligne bloque sil ny a pas de lecteur sysopen(FIFO, $chemin_f, O_WRONLY) or die "Impossible dcrire dans $chemin_f: $!"; print FIFO "Grard Lambert (lambert\@machine.org)\n", fortune -s; close FIFO; select(undef, undef, undef, 0.2); # dort 1/5me de seconde }

405

La courte sieste aprs la fermeture du FIFO est ncessaire pour laisser au lecteur une chance de lire ce qui a t crit. Si nous avions recommenc la boucle immdiatement et rouvert le FIFO avant que notre lecteur ait fini de lire les donnes que nous venions denvoyer, nous naurions pas vu de fin de fichier (end-of-file) car il y aurait encore un crivain. Nous aurions boucl tous les deux encore et encore jusqu ce qu une itration donne, lcrivain arrive un peu aprs et que le lecteur voie cette fin de fichier insaisissable. (Et nous nous sommes inquits propos des situations de concurrence ?)

IPC System V
Tout le monde dteste les IPC System V Elles sont plus lentes que des cartes perfores, . se taillent de petits espaces de noms insidieux sans aucun rapport avec le systme de fichiers, utilisent des numros hostiles lentendement humain pour nommer leurs objets et perdent constamment le fil de leurs propres penses. Et de temps autre, votre administrateur systme doit se lancer dans une opration de ratissage pour rechercher et de dtruire ces objets perdus dIPC SysV avec ipcs(1) et les tuer avec ipcrm(1), avant que le systme nait plus de mmoire, si tout va bien. Malgr tous ces maux, les antiques IPC SysV ont toujours des applications valides. Les trois sortes dobjets dIPC sont la mmoire partage, les smaphores et les messages. Pour la transmission de messages, on prfrera de nos jours le mcanisme de sockets qui est en outre beaucoup plus portable. Pour les utilisations simples des smaphores, on a

customer_8566

406

Chapitre 16 Communication interprocessus

plutt tendance utiliser le systme de fichiers. Quant la mmoire partage en fait, vous avez maintenant un problme. Si vous lavez, lappel systme mmap(2), plus moderne, remplit ce contrat11 mais la qualit de limplmentation varie dun systme lautre. Il requiert en outre un peu dattention pour que Perl vite de rallouer vos chanes depuis lendroit o mmap(2) les a mises. Mais lorsque les programmeurs envisagent dutiliser mmap(2), ils entendent marmonner de manire incohrente les gourous locaux sur le fait que mmap souffre de problmes pineux avec la cohrence de cache sil manque quelque chose appel un cache de tampon unifi (unified buffer cache) moins que ce ne soit une tche dunit de canton ( flycatcher unibus) et, rf lchissant sur le fait que lon sait ce quon perd mais quon ne sait pas ce quon trouve, ils retournent vite aux IPC SysV quils connaissent et dtestent pour tous leurs besoins en mmoire partage. Voici un petit programme dmontrant laccs contrl un tampon en mmoire partag par une niche de processus apparents. Les objets dIPC SysV peuvent galement tre partags entre des processus sans rapport les uns avec les autres, sur le mme ordinateur, mais vous devez alors imaginer comment ils vont se trouver les uns les autres. Nous crerons un smaphore par entit, qui servira dintermdiaire pour un accs scuris.12 chaque fois que vous voulez rcuprer ou mettre une nouvelle valeur en mmoire partage, vous devez passer dabord par le smaphore. Ceci peut devenir un peu pnible, nous enroberons donc laccs dans une classe dobjets. Le module IPC::Shareable va encore plus loin en enrobant sa classe dobjets dans une interface tie. Ce programme tourne jusqu ce que vous linterrompiez avec un Ctrl-C ou un quivalent :
#!/usr/bin/perl -w use v5.6.0; # ou une version suprieure use strict; use sigtrap qw(die INT TERM HUP QUIT); my $PROGENITURE = shift(@ARGV) || 3; eval { main() }; # voir DESTROY ci-dessous pour comprendre pourquoi die if $@ && $@ !~ /^SIG reu/; print "\nFini.\n"; exit; sub main { my $mem = ShMem->allouer("Cration Originale " . localtime); my(@rejetons, $fils); $SIG{CHLD} = IGNORE; for (my $embryon = $PROGENITURE; $embryon > 0; $embryon--) {
11. Il y a mme un module Mmap sur CPAN. 12. Il serait plus raliste de crer une paires de smaphores pour chaque morceau de mmoire partage : un pour la lecture et lautre pour lcriture. Et, en fait, cest ce que fait le module de CPAN IPC::Shareable. Mais nous essayons ici de rester simples. Cependant il vaut mieux admettre quavec un couple de smaphores, vous pourriez alors faire usage d peu prs le seul bnfice des IPC SysV : vous pourriez excuter des oprations atomiques sur des ensembles entiers de smaphores comme sil sagissait dun seul lment, ce qui est parfois bien utile.

customer_8566

IPC System V
if ($fils = fork) { print "$$ engendra $fils\n"; next; } die "fork impossible : $!" unless defined $fils; eval { while (1) { $mem->verrouiller(); $mem->positionner("$$ " . localtime) unless $mem->consulter =~ /^$$\b/o; $mem->deverrouiller(); } }; die if $@ && $@ !~ /^SIG reu/; exit; # mort du fils } while (1) { print "Le tampon vaut ", $mem->recuperer, "\n"; sleep 1; } }

407

Et voici le paquetage ShMem, que ce programme utilise. Vous navez qu lpingler la fin du programme ou le mettre dans son propre fichier (avec un 1; la fin) et le charger avec require depuis le programme principal. (On trouve les deux modules dIPC quil utilise son tour dans la distribution standard de Perl.)
package ShMem; use IPC::SysV qw(IPC_PRIVATE IPC_RMID IPC_CREAT S_IRWXU); use IPC::Semaphore; sub MAXBUF() { 2000 } sub allouer { # constructeur my $classe = shift; my $valeur = @_ ? shift : ; my $clef = shmget(IPC_PRIVATE, MAXBUF, S_IRWXU) or die "shmget : $!"; my $sem = IPC::Semaphore->new(IPC_PRIVATE, 1, S_IRWXU | IPC_CREAT) or die "IPC::Semaphore->new : $!"; $sem->setval(0,1) or die "sem setval : $!"; my $obj = bless { PROPRIETAIRE => $$, SHMKEY => $clef, SEMA => $sem, } => $classe; $obj->mettre($valeur); return $obj; }

customer_8566

408

Chapitre 16 Communication interprocessus

Maintenant, passons aux mthodes de collecte et de stockage. Les mthodes recolter et mettre verrouillent le tampon, contrairement aux mthodes consulter et positionner, ces dernires ne devraient donc tre utilises que lorsque lobjet est verrouill manuellement ce que vous devez faire lorsque vous voulez aller chercher une ancienne valeur et remettre une version modifie, tout cela avec le mme verrou. Le programme de dmonstration fait ceci dans sa boucle while (1). La transaction complte doit se drouler avec le mme verrou sinon le test et le positionnement ne seraient pas atomiques et pourraient exploser.
sub recolter { my $obj = shift; $obj->verrouiller; my $valeur = $obj->consulter(@_); $obj->deverrouiller; return $valeur; } sub consulter { my $obj = shift; shmread($obj-&>{SHMKEY}, my $tampon=, 0, MAXBUF) or die "shmread : $!"; substr($tampon, index($tampon, "\0")) = ; return $tampon; } sub mettre { my $obj = shift; $obj->verrouiller; $obj->positionner(@_); $obj->deverrouiller; } sub positionner { my($obj,$msg) = @_; shmwrite($obj->{SHMKEY}, $msg, 0, MAXBUF) or die "shmwrite : $!"; } sub verrouiller { my $obj = shift; $obj->{SEMA}->op(0,-1,0) or die "semop : $!"; } sub deverrouiller { my $obj = shift; $obj->{SEMA}->op(0,1,0) or die "semop : $!"; }

Finalement, la classe a besoin dun destructeur pour que, lorsque lobjet disparat, nous puissions manuellement dsallouer la mmoire partage et le smaphore stock lintrieur de lobjet. Sinon, ils survivront leur crateur et vous devrez recourir ipcs et ipcrm (ou un administrateur systme) pour vous dbarrasser deux. Cest pourquoi nous somme passs par les enrobages labors dans le programme principal pour convertir les signaux en exceptions : pour que tous les destructeurs soient lancs, que tous les objets dIPC SysV soient dsallous et que les administrateurs systme ne soccupent pas de notre cas.

customer_8566

Sockets
sub DESTROY { my $obj = shift; return unless $obj->{PROPRIETAIRE} == $$;

409

# vite les dsallocations # redondantes shmctl($obj->{SHMKEY}, IPC_RMID, 0) or warn "shmctl RMID : $!"; $obj->{SEMA}->remove() or warn "sema->remove : $!";

Sockets
Les mcanismes dIPC dont nous avons discut auparavant souffrent tous dune importante restriction : ils sont conus pour un communication entre des processus tournant sur le mme ordinateur. (Mme si les fichiers peuvent parfois tre partags entre les machines travers des mcanismes comme NFS, le verrouillage choue lamentablement sur la plupart des implmentations de NFS, ce qui annihile une grande part des plaisirs des accs concurrents.) Pour des communications gnriques sur le rseau, les sockets sont la solution de choix. Bien que les sockets aient t inventes sur BSD, elles se sont rapidement rpandues aux autres formes dUnix et de nos jours, vous pouvez trouver une interface pour les sockets sur peu prs tous les systmes dexploitations viables icibas. Si vous navez pas de sockets sur votre machine, vous allez rencontrer dnormes difficults pour utiliser lInternet. Avec les sockets, vous pouvez communiquer la fois avec des circuits virtuels (les flux ou streams TCP) et avec des datagrammes (les paquets UDP). Votre systme vous permet peut-tre den faire plus encore. Mais le type de programmation socket le plus courant utilise TCP sur des sockets du domaine Internet, cest donc celui que nous dtaillerons ici. De telles sockets fournissent des connexions fiables fonctionnant un peu comme deux pipes bidirectionnels qui ne seraient pas limits une seule machine. Les deux applications reines (killer apps) de lInternet, lemail et le surf sur le Web, reposent presquexclusivement sur des sockets TCP . Vous utilisez aussi largement UDP sans le savoir. Chaque fois que votre machine essaie de trouver un site sur lInternet, elle envoie des paquets UDP votre serveur DNS pour lui demander la vritable adresse IP Vous pourriez utiliser UDP vous-mme lorsque . vous voulez envoyer et recevoir des datagrammes. Les datagrammes sont plus conomiques que les connexions TCP prcisment parce quils ne sont pas orients connexion ; cest--dire quils ressemblent moins un appel tlphonique qu un dpt de lettre dans une bote. Mais il manque galement UDP la fiabilit offerte par TCP ce qui le , rend plus appropri pour les situations o vous ne vous souciez pas si un ou deux paquets se retrouvent happs, broys et engloutis. Ou lorsque vous savez quun protocole de plus haut niveau fera respecter un certain degr de redondance ou dchec en douceur (ce que fait DNS). Dautres choix sont disponibles mais bien moins courants. Vous pouvez utilisez des sockets du domaine Unix mais elles ne fonctionnent que pour les communications locales. Divers systmes implmentent divers autres protocoles qui ne sont pas bass sur IP . Ceux-ci intressent sans doute quelquun quelque part pour faire quelque chose mais nous devons nous restreindre quelquefois. Les fonctions Perl soccupant des sockets ont les mmes noms que les appels systme

customer_8566

410

Chapitre 16 Communication interprocessus

correspondants en C, mais leurs arguments ont tendance diffrer pour deux raisons : premirement, les handles de fichiers de Perl fonctionnent diffremment des descripteurs C ; deuximement, Perl connat dj la longueur de ses chanes et il est donc inutile de passer cette information. Voir les dtails sur chaque appel systme relatif aux sockets au chapitre 29. Avec du code Perl ancien, on devait utiliser des valeurs codes en dur pour passer des constantes aux fonctions des sockets, ce qui annihilait la portabilit. Comme la plupart des appels systme, ceux relatifs aux sockets renvoient discrtement mais poliment undef lorsquils chouent, au lieu de lever une exception. Il est donc essentiel de vrifier les valeurs renvoyes par ces fonctions, puisque si vous les jetez la poubelle, elles niront pas crier cet chec sur les toits. Si jamais vous voyez du code faisant quelque chose comme positionner explicitement $AF_INET = 2, vous savez que vous tes dans les problmes jusquau cou. Une approche dune supriorit incommensurable consiste utiliser le module Socket ou le module encore plus sympathique IO::Socket, tous deux standard. Ces modules fournissent diverses constantes et des fonctions daide dont vous aurez besoin pour mettre en place des clients et des serveurs. Pour une russite optimale, vos programmes de sockets devraient toujours commencer ainsi (noubliez pas non plus dajouter loption de vrification de marquage -T sur la ligne shebang (commenant par #!) pour les serveurs) :
#!/usr/bin/perl -w use strict; use sigtrap; use Socket; # ou IO::Socket

Comme nous lavons fait remarquer ailleurs, Perl est la merci de vos bibliothques C pour la plupart de ses fonctionnalits concernant le systme, et tous les systmes nimplmentent pas toutes les sortes de sockets. Il est probablement plus sr de sen tenir avec les oprations sur les sockets normales TCP et UDP Par exemple, si vous voulez que . votre code ait une chance dtre portable vers des systmes auxquels vous navez pas pens, ne vous attendez pas ce quils implmentent un protocole fiable avec des paquets squencs. Ne vous attendez pas non plus passer des descripteurs de fichiers ouverts entre des processus nayant aucun rapport les uns avec les autres sur des sockets du domaine Unix. (Si, si, vous pouvez vraiment faire cela sur de nombreuses machines Unix voir recvmsg(2) dans votre page de manuel locale.) Si vous voulez juste utiliser un service standard de lInternet comme le mail, les forums de discussion, le service de noms de domaine, FTP Telnet, le Web et ainsi de suite, alors , plutt que de repartir de zro, essayez dutiliser les modules existants de CPAN. Les modules tout faits, conus pour cela, comprennent : Net::SMTP (ou Mail::Mailer), Net:NNTP Net::DNS, Net::FTP Net::Telnet et les divers modules relatifs HTTP Les fa, , . milles de modules libnet et libww comprennent toutes deux de nombreux modules individuels pour la communication en rseau. Les zones de modules sur CPAN qui peuvent vous intresser sont dans la section 5 sur la Communication en rseau et dans la section 15, sur les Utilitaires de serveurs et de dmons. Dans les paragraphes qui suivent, nous prsentons plusieurs exemples de clients et de serveurs sans grande quantit dinformations sur chaque fonction utilise car ce serait en grande partie une recopie pure et simple de ce que nous avons dj crit au chapitre 29, Fonctions.

customer_8566

Sockets

411

Clients en rseau
Utilisez les sockets du domaine Internet lorsque vous voulez une communication client/serveur fiable entre des machines potentiellement diffrentes. Pour crer un client TCP se connectant un serveur quelque part, il est dordinaire plus facile dutiliser le module standard IO::Socket::INET :
use IO::Socket::INET; $socket = IO::Socket::INET->new(PeerAddr => $hote_distant, PeerPort => $port_distant, Proto => "tcp", Type => SOCK_STREAM) or die "Na pas pu se connecter $hote_distant:$port_distant : $!\n"; # envoie quelque chose sur la socket, print $socket "Pourquoi ne mappelles-tu plus jamais ?\n"; # lit la rponse distante, $reponse = <$socket>; # et termine la connexion lorsque nous avons fini close($socket);

Un raccourci pour lappel est suffisant lorsque vous navez que lhte et le port auxquels se connecter et que vous voulez utiliser les valeurs par dfaut pour les autres champs :
$socket = IO::Socket::INET->new("www.google.org:80") or die "Na pas pu se connecter au port 80 de google: $!";

Pour se connecter en utilisant le module Socket :


use Socket; # cre une socket socket(Serveur, PF_INET, SOCK_STREAM, getprotobyname(tcp)); # construit ladresse de la machine distante $adr_internet = inet_aton($hote_distant) or die "Na pas pu convertir $hote_distant en adresse Internet : $!\n"; $adr_p = sockaddr_in($port_distant, $adr_internet); # se connecte connect(Serveur, $adr_p) or die "Na pas pu se connecter $hote_distant:$port_distant : $!\n"; select((select(Serveur), $| = 1)[0]); # active la mise en tampon # des commandes

# envoie quelque chose sur la socket print Serveur "Pourquoi ne mappelles-tu plus jamais ?\n"; # lit la rponse distante $reponse = <Serveur>;

customer_8566

412

Chapitre 16 Communication interprocessus

# et termine la connexion lorsque nous avons fini close(Serveur);

Si vous ne voulez fermer que votre ct de la connexion, pour que lextrmit distante reste reoive une fin de fichier mais que vous puissiez continuer lire les donnes venant du serveur, utilisez lappel systme syscall pour une demi-fermeture :
# plus dcriture vers le serveur shutdown(Serveur, 1); # constante Socket::SHUT_WR dans la v5.6

Serveurs en rseau
Voici le serveur correspondant qui va avec. Il est assez simple grce la classe standard IO::Socket::INET :
use IO::Socket::INET; $serveur = IO::Socket::INET->new(LocalPort => $port_serveur, Type => SOCK_STREAM, Reuse => 1, Listen => 10 ) # ou SOMAXCONN or die "Na pas pu tre un serveur TCP sur le port $port_serveur : $!\n"; while ($client = $serveur->accept()) { # $client est la nouvelle connexion } close($serveur);

Vous pouvez galement crire cela en utilisant le module Socket, de plus bas niveau :
use Socket; # cre la socket socket(Serveur, PF_INET, SOCK_STREAM, getprotobyname(tcp)); # pour pouvoir redmarrer rapidement notre serveur setsockopt(Serveur, SOL_SOCKET, SO_REUSEADDR, 1); # construit ladresse de la socket $mon_adr = sockaddr_in($port_serveur, INADDR_ANY); bind(Serveur, $mon_adr) or die "Na pas pu sattacher au port $port_serveur : $!\n"; # tablit une file pour connexions entrantes listen(Serveur, SOMAXCONN) or die "Na pas pu couter sur le port $port_serveur : $!\n"; # accepte et traite les connexions while (accept(Client, Serveur)) { # Fait quelque chose avec la nouvelle connexion Client } close(Server);

customer_8566

Sockets

413

Le client na pas besoin de sattacher avec bind une adresse particulire, par contre cest le cas pour le serveur. Nous avons spcifi son adresse en tant que INADDR_ANY, ce qui signifie que les clients peuvent se connecter depuis nimporte quelle interface rseau disponible. Si vous voulez vous placer devant une interface particulire (comme le ct externe dune passerelle ou dune machine pare-feux ( firewall)), utilisez plutt ladresse relle de cette interface. (Les clients peuvent galement faire cela mais en ont rarement besoin.) Si vous voulez savoir quelle machine sest connecte avec vous, appelez getpeername sur la connexion du client. Ceci renvoie une adresse IP que vous devrez convertir vous, mme vers un nom (si vous le pouvez) :
use Socket; $autre_extremite = getpeername(Client) or die "Na pas pu identifier lautre extrmit : $!\n"; ($port, $adr_i) = unpack_sockaddr_in($autre_extremite); $ip_reelle = inet_ntoa($adr_i); $nom_hote_pretendu = gethostbyaddr($adr_i, AF_INET);

Ceci tre usurp (spoofable) de manire triviale car le propritaire de cette adresse IP peut initialiser ses tables dinversion (reverse tables) pour quelles disent ce quil veut. Une petite mesure pour sassurer de la validit de ladresse IP consiste faire la conversion inverse :
@recherche_noms = gethostbyname($nom_hote_pretendu) or die "Na pas pu faire la conversion inverse de $nom_hote_pretendu : $!\n"; @ips_resolues = map{inet_ntoa($_)} $recherche_noms[ 4 .. $#recherche_noms ]; e eq $_ } @ips_resolues; $usurpation_potentielle = !gre

Une fois quun client sest connect votre serveur, ce dernier peut faire des entres/sorties la fois depuis et vers ce handle client. Mais pendant que le serveur est ainsi occup, il ne peut plus servir de requtes entrantes provenant dautres clients. Pour viter de rester bloqu sur un seul client la fois, de nombreux serveurs se clnent, avec fork, pour soccuper de chaque connexion entrante. (Dautres anticipent les fork ou multiplexent les entres/sorties entre plusieurs clients en utilisant lappel systme select.)
REQUETE: while (accept(Client, Serveur)) { if ($pid_fils = fork) { close Client; # le pre ferme le handle inutilis next REQUETE; } defined($pid_fils) or die "fork impossible : $!" ; close Serveur; select(Client); $| = 1; # le fils ferme le handle inutilis # nouveau handle par dfaut pour les affichages # vidage de tampon automatique

# le code par connexion des fils fait ses entres/sorties avec le # handle Client $entree = <Client>;

customer_8566

414
print Client "affichage\n";

Chapitre 16 Communication interprocessus


# ou STDOUT, cest la mme chose

open(STDIN, "<<&Client") or die "impossible de dupliquer le client : $!"; open(STDOUT, ">&Client") or die "impossible de dupliquer le client : $!"; open(STDERR, ">&Client") or die "impossible de dupliquer le client : $!"; # lance la calculatrice, ce nest quun exemple system("bc -l"); # ou ce que vous prfrez, pourvu # quil ny ait pas de squences # dchappement du shell ! print "fini\n"; # toujours au client close Client; exit; # empche le fils de retourner accept }

Ce serveur clne un fils avec fork pour chaque requte entrante. De cette manire, il peut soccuper de plusieurs requtes la fois, tant que vous pouvez crer dautres processus. (Il se pourrait que vous vouliez fixer une limite ceci.) Mme si vous ne faites pas de fork, le listen permettra davoir jusqu SOMAXCONN (gnralement cinq ou plus) connexions en attente. Chaque connexion utilise des ressources, toutefois moins quun processus. Les serveurs faisant des fork doivent prendre soin de nettoyer une fois que leurs fils (appels des zombies dans le jargon dUnix) ont termin sinon il rempliraient vite votre table de processus. Le code FOSSOYEUR, prsent au paragraphe Signaux sen occupera pour vous ou vous pouvez affecter $SIG{CHLD} = IGNORE. Avant de lancer une autre commande, nous connectons lentre et la sortie (et la sortie derreurs) standard la connexion du client. De cette manire, toute commande lisant depuis STDIN et crivant vers STDOUT peut galement parler la machine distante. Sans la raffectation, la commande ne pourrait pas trouver le handle du client qui, par dfaut, est de toute faon ferm aprs lexec. Lorsque vous crivez un serveur en rseau, nous vous encourageons fortement activer la vrification du marquage par -T mme si vous ne tournez pas sous setuid ou setgid. Cest toujours une bonne ide pour les serveurs et tout autre programme qui est lanc pour le compte de quelquun dautre (comme tous les scripts CGI) car cela rduit les chances que des trangers soient capables de compromettre votre systme. Voir la section Grer des donnes non sres au chapitre 23, Scurit, pour plus dinformations ce sujet. Une autre chose prendre en considration lors de lcriture de programme Internet : plusieurs protocoles spcifient que la fin de ligne devrait tre CRLF, ce qui peut se spcifier de diffrentes faons : "\015\012" ou "\xd\xa" ou mme chr(13).chr(10). Depuis la version 5.6 de Perl, crire v13.10 produit galement la mme chane. (Sur plusieurs machines, vous pouvez galement employer "\r\n" pour signifier CRLF mais ne le faites pas si vous voulez tre portable vers les Mac car la signification de \r et de \n est inverse !) Plusieurs programmes Internet accepte en fait un simple "\012" comme fin de ligne mais cest parce que les programmes Internet essaient en gnral dtre tolrants dans ce quils acceptent et rigides dans ce quils mettent. (Si seulement nous arrivions pousser les gens agir de la sorte...)

customer_8566

Sockets

415

Passage de message
Comme nous lavons voqu auparavant, les communications UDP impliquent une surcharge bien moindre mais ne fournisse aucune fiabilit, puisquil ny a aucune promesses que les messages arriveront dans lordre ou mme quil arriveront tout court. On dit souvent quUDP signifie Unreliable Datagram Protocol (protocole de datagrammes non fiable). Nanmoins, UDP apporte des avantages par rapport TCP y compris la capacit de faire , de la diffusion large (broadcast) ou multiple (multicast) un ensemble complet dhtes destinataires en une seule fois (gnralement utilise sur votre sous-rseau local). Si vous vous trouvez excessivement soucieux propos de la fiabilit et que vous commencez construire des vrifications dans votre systme de messages, vous devriez probablement commencer par utiliser TCP Il est vrai quil est plus coteux de mettre en place et . de se sparer dune connexion TCP mais si vous pouvez amortir cela sur plusieurs messages (ou un message trs long), cela importe peu. De toute faon, voici un exemple dun programme UDP Il contacte le port UDP time . des machines passes comme paramtres dans la ligne de commande ou toutes les personnes quil peut trouver en utilisant ladresse universelle de broadcast si aucun argument na t donn.13 Toutes les machines nont pas de serveur dhorloge activ mais celles pour qui cest le cas vous renverront un entier de 4 octets, empaquet dans lordre rseau , reprsentant le nombre de secondes depuis 1900. Vous devez soustraire le nombre de secondes entre 1900 et 1970 pour fournir cette date au fonctions de conversion localtime ou gmtime.
#!/usr/bin/perl # retardhorloge - compare les horloges dautres systmes avec celle-ci # sans arguments, broadcast quiconque est lcoute. # attend une rponse pendant une demi-seconde. use use use use v5.6.0; # or une version suprieure warnings; strict; Socket;

unshift(@ARGV, inet_ntoa(INADDR_BROADCAST)) unless @ARGV; socket(my $sock_mess, PF_INET, SOCK_DGRAM, getprotobyname("udp")) or die "socket : $!"; # Certains machines ont besoin de ceci. a ne devrait pas faire de # mal aux autres. setsockopt($sock_mess, SOL_SOCKET, SO_BROADCAST, 1) or die "setsockopt : $!";

13. Si cela ne fonctionne pas, lancez ifconfig -a pour trouv ladresse de broadcast locale approprie.

customer_8566

416

Chapitre 16 Communication interprocessus

my $no_port = getservbyname("time", "udp") or die "pas de port udp time"; for my $cible (@ARGV) { print "Envoi $cible:$no_port\n"; my $adr_dest_p = sockaddr_in($no_port, inet_aton($cible)); send($sock_mess, "x", 0, $adr_dest_p) or die "send : $!"; } # le service dhorloge renvoie une heure sur 32 bits en secondes # depuis 1900 my $DEPUIS_1900_A_ORIGINE = 2_208_988_800; my $fmt_heure = "N"; # et ceci en format binaire my $lg_heure = length(pack($fmt_heure, 1)); # nimporte quel nombre # convient my $masque_entree = ; # chane pour stocker les bits de fileno bits # pour le select vec($masque_entree, fileno($sock_mess), 1) = 1; # nattend une entre quune demi-seconde while (select(my $masque_sortie = $masque_entree, undef, undef, 0.5)) { defined(my $adr_src_p = recv($sock_mess, my $heure_bin, $lg_heure, 0)) or die "recv : $!"; my($port, $adr_ip) = sockaddr_in($adr_src_p); my $hote_emet = sprintf "%s [%s]", gethostbyaddr($adr_ip, AF_INET) || UNKNOWN, inet_ntoa($adr_ip); my $delta = unpack($fmt_heure, $heure_bin) $DEPUIS_1900_A_ORIGINE - time(); print "Lhorloge sur $hote_emet est en avance de $delta secondes sur celle-ci.\n"; }

customer_8566

17

Threads

La programmation parallle est beaucoup plus complique quelle ne semble ltre. Imaginez que vous preniez une recette dans un livre de cuisine et que vous la convertissiez en quelque chose sur lequel plusieurs douzaines de chefs cuisiniers pourraient travailler en mme temps. Vous pouvez adopter deux approches. La premire consiste donner chaque chef sa cuisine prive, compltement quipe avec son propre matriel et ses propres ustensiles. Pour les recettes qui peuvent tre facilement dcomposes et pour les aliments qui peuvent tre transports dune cuisine une autre, cette approche fonctionne bien car elle empche chaque chef dempiter sur la cuisine de son voisin. Sinon, il vous suffit de mettre tous les chefs dans une seule cuisine et de les laisser se dbrouiller en dcidant qui utilise le mixer et quand. Cela peut se transformer en pagaille, surtout lorsque les couteaux de boucher commencent voler. Ces deux approches correspondent deux modles de programmation parallle sur les ordinateurs. Le premier est le modle multiprocessus, typique des systmes Unix traditionnels, dans lequel chaque thread1 de contrle possde son propre jeu de ressources. Le second modle est le modle multithread, dans lequel chaque thread de contrle partage des ressources avec tous les autres threads de contrle. Ou ne les partage pas, comme cela peut parfois arriver (et comme cela doit parfois arriver). Nous savons tous que les chefs aiment prendre le contrle ; a ne pose pas de problme car les chefs ont besoin de prendre le contrle pour accomplir ce que nous voulons quils accomplissent. Mais les chefs doivent sorganiser, dune manire ou dune autre. Perl implmente les deux modles dorganisation. Dans ce chapitre nous les appellerons le modle de processus et le modle de thread.
1. N.d.T. : La traduction franaise dun thread est une tche lgre ou une unit lmentaire de processus, mais comme le terme est gnralement connu de tous les programmeurs et que les programmeurs Perl sont particulirement impatients, paresseux et orgueilleux, nous emploierons littralement le mot thread dans cet ouvrage, ce qui nous permet daller plus vite, den crire moins et den tre particulirement fiers !

customer_8566

418

Chapitre 17 Threads

Le modle de processus
Nous ne nous tendrons pas trop sur le modle de processus ici, simplement parce quil est dominant tout au long du reste de ce livre. Perl est issu des systmes Unix, il a donc adopt la notion que chaque processus accomplit son propre travail. Si un processus veut dmarrer un traitement parallle, il doit logiquement dmarrer un processus parallle ; cest--dire quil doit faire un fork pour avoir un nouveau processus poids lourd, qui ne partage par dfaut que trs peu de choses avec son processus pre, si ce nest certains descripteurs de fichiers. (Le pre et le fils peuvent sembler partager beaucoup plus, mais une grande partie de ltat du processus pre est duplique dans le processus fils que rellement partage au sens logique du terme. Le systme dexploitation peut bien entendu faire preuve de paresse quand il sagit de forcer cette sparation logique, auquel cas nous appelons cela une smantique de copie lors dcritures (copy-on-write) mais nous ne ferions pas de copie du tout, sil ny avait pas en premier lieu de sparation logique.) Historiquement, cette vision industrielle du traitement multiprocessus a pos de petits problmes sur les systmes Microsoft car Windows navait pas de modle multiprocessus bien dvelopp (et il ne se reposait pas souvent sur ce quil avait cet gard pour la programmation parallle). Il a typiquement adopt la place une approche multithread. Toutefois, au prix defforts hroques, la version 5.6 de Perl implmente maintenant lopration fork sur Windows en clnant un nouvel objet interprteur lintrieur du mme processus. Cela signifie que la plupart des exemples utilisant fork dans le reste de ce livre fonctionneront maintenant sur Windows. Linterprteur cln partage du code immuable avec les autres interprteurs mais reoit sa propre copie des donnes avec lesquelles il samusera. (Bien entendu, il peut toujours y avoir des problmes avec les bibliothques C qui ne comprennent pas les threads.) Cette approche du traitement multiprocessus a t baptise ithreads, comme raccourci pour threads dinterprteurs . Lmulation de fork pour les systmes Microsoft a dclench limplmentation des ithreads. Toutefois, nous avons rapidement ralis que, bien les autres interprteurs tournaient sous des threads distincts, ils tournaient dans le mme processus, il serait donc facile de faire partager des donnes ces interprteurs spars, mme sils ne les partageaient pas par dfaut. Cest exactement linverse du modle multithread typique, dans lequel tout est partag par dfaut et o vous devez vous chiner ne pas partager quelque chose. Mais vous ne devriez pas voir ces deux modles comme tant compltement distincts lun de lautre car ils essaient tous deux de construire un pont au-dessus de la mme rivire ; ils ne font que le construire sur des berges opposes. La vritable solution tout problme de traitement parallle est de mler un certain degr de partage dans un certain degr dgosme. Ainsi, le but long terme est dtendre le modle dithreads pour permettre autant de partage que vous avez besoin ou que vous voulez. Toutefois, lheure o nous crivons ces lignes, la seule interface pour les ithreads visible par lutilisateur est lappel fork sous les portages Microsoft de Perl. Nous pensons que cette approche produira ventuellement des programmes plus propres que lapproche multithread standard. la base, il est plus facile de grer une conomie o vous prsumez que chacun possde ce quil a, plutt que de prsumer que tout le monde possde tout. Ce nest pas que lon attend des gens quils ne partagent pas dans une conomie capitaliste, ou quils ne dtournent pas

customer_8566

Le modle de thread

419

de fonds publics2 dans une conomie communiste. Ces choses tendent squilibrer. Il arrive que lon soit dans une conomie socialiste. Mais avec dinportant groupes de personnes, le partage de tout par dfaut ne fonctionne que si vous avez un chef en chef avec un grand couteau de boucher, pensant que tout lui appartient. Bien entendu, le vritable gouvernement de tout ordinateur est gr par un dictateur fasciste connu sous le nom de systme dexploitation. Mais un dictateur avis sait lorsquil faut faire croire aux gens quils sont capitalistes et lorsquil faut leur faire croire quils sont communistes.

Le modle de thread
Le modle de thread pour le traitement parallle a tout dabord t introduit dans Perl comme une fonctionnalit exprimentale dans la version 5.005. (Nous voulons dire par modle de thread , des threads partageant des ressources de donne par dfaut, non les nouveaux ithreads de la version 5.6.) Par certains cts, ce modle de thread est toujours une fonctionnalit exprimentale mme en 5.6 car Perl est un langage riche et le traitement multithread peut mettre un fouillis mme dans le plus simple des langages. Il existe toujours des coins et recoins de la smantique de Perl qui ninteragissent pas trs bien avec la notion que tout soit partag. Le nouveau modle des ithreads est une tentative pour contourner ces problmes et, un moment lavenir, il se peut que le modle de thread actuel soit englob dans le modle dithread (lorsque nous aurons une interface aux ithreads qui dira partagez tout ce que vous pouvez par dfaut ). Mais malgr ses problmes, lactuel modle de thread exprimental continue dtre trs utile dans plusieurs situations du mode rel o il est prfrable dtre un cobaye plutt que de ne pas avoir de threads. Des applications raisonnablement robustes peuvent tre crites en Perl avec des threads mais vous devez faire trs attention. Vous devriez au moins envisager dutiliser plutt fork, si vous pouvez trouver un moyen de rsoudre votre problme avec des pipes la place de structures de donnes partages. Mais certains algorithmes sont plus simples exprimer si de multiples tches peuvent accder facilement et efficacement au mme jeu de donnes.3 Cela produit du code plus petit et plus simple. Et puisque le noyau na pas copier des tableaux de pages pour les donnes (mme sil fait de la copie lors dcriture (copy-on-write)) lors de la cration de thread, il devrait tre plus rapide de dmarrer une tche de cette manire. De mme, le changement de contexte peut tre plus rapide si le noyau na pas besoin dchanger (swap) des tableaux de pages. (En fait, pour les threads au niveau de lutilisateur, le noyau nest pas impliqu du tout bien que les threads au niveau de lutilisateur aient bien entendu des problmes que les threads du noyau nont pas.) Voici pour les bonnes nouvelles. Maintenant, passons dautres plus sujettes rclamations. Nous avons dj mentionn que le traitement des threads tait quelque peu exprimental en Perl mais, mme sil ne ltait pas, la programmation avec des threads est
2. Dtourner des fonds publics : piquer la proprit publique dans les fonds au milieu de la nuit ; dtourner du public quelque chose qui nest pas forcment de largent, cf. adopter, tendre, GPL. 3. Le modle de mmoire partage des IPC System V dont nous avons parl dans le chapitre , prcdent, ne peut pas tre qualifi exactement comme tant facile et efficace .

customer_8566

420

Chapitre 17 Threads

assez tratre. La capacit dun f lux dexcution placer, quon le veuille ou non, des trous dans lespace des donnes dun autre, est susceptible de provoquer des dsastres, plus que vous ne pouvez limaginer. Vous pourriez vous dire : Cest facile corriger, je nai qu mettre des verrous sur les donnes partages. Daccord, le verrouillage des donnes partages est indispensable mais disposer de protocoles de verrouillages qui soient corrects est une difficult de notorit publique, avec des erreurs gnrant des verrous mortels (deadlocks) ou des rsultats non dterministes. Si vous avez des problmes de synchronisation dans votre programme, lemploi de threads va non seulement les aggraver mais les rendra galement plus difficiles localiser. Vous tes non seulement responsable de lhonntet de vos propres donnes partages, mais galement de celle des modules Perl et des bibliothques C que vous appelez. Votre code Perl a beau tre scuris au niveau des threads 100 %, si vous appelez un module ou un sous-programme C qui ne soit pas sr au niveau des threads, vous tes grill. Vous devriez prsumer quaucun module nest sr au niveau des threads moins de le prouver. Ceci inclut mme certains des modules standard. Peut-tre mme la plupart dentre eux. Nous ne vous avons pas dj dcourag ? Non ? Alors nous mettrons laccent sur le fait que vous tes quelque peu la merci des bibliothques de votre systmes dexploitation pour le traitement des threads lorsquil sagit de politiques dordonnancement et de premption. Certaines bibliothques de thread ne font du basculement de thread que sur les appels systme bloquants. Certaines bloquent le processus entier si un seul thread fait un appel systme bloquant. Certaines ne basculent les threads que sur lexpiration dun dlai quantifiable (soit dun thread, soit dun processus). Certaines ne basculent les threads quexplicitement. Oh, et pendant quon y est, si votre processus reoit un signal, dterminer quel thread ce signal est dlivr est compltement dpendant du systme. Pour faire de la programmation de thread en Perl, vous devez compilez une version spciale de Perl en suivant les instructions fournies dans le fichier README.threads dans le rpertoire des sources de Perl. Il est peu prs garanti que ce Perl spciale tournera moins vite que votre excutable Perl standard. Ne prsupposez pas que, puisque vous savez comment les threads sont programms dans dautres modles (POSIX, DEC, Microsoft, etc.), vous savez comment les threads fonctionnent en Perl. Comme avec dautres choses en Perl, Perl est du Perl, non du C++ ou du Java ou quoi que ce soit dautre. Par exemple, il ny a pas de priorits de thread en temps rel (et aucun moyen de contourner leur absence). Il ny a pas non plus de verrous dexclusion mutuelle (mutex). Utilisez simplement le verrouillage ordinaire ou peut-tre le module Thread::Semaphore ou les mcanismes de cond_wait. Toujours pas dcourag ? Bien ! Car les threads sont vraiment sympas. Vous pouvez prvoir de vous amuser.

Le module Thread
Linterface actuelle pour les threads en Perl est dfinie par le module Thread. De plus, un nouveau mot-cl de Perl a t ajout, loprateur lock. Nous parlerons de lock ultrieurement dans ce chapitre. Les autres modules standard de thread sont construits partir de cette interface de base.

customer_8566

Le modle de thread
Le module Thread fournit ces mthodes de classe :
Mthode new self list Utilisation Construit un nouvel objet Thread. Renvoie mon objet Thread courant. Renvoie la liste des objets Thread.

421

Et pour les objets Thread, il fournit ces mthodes dobjet :


Mthode join eval equal tid Utilisation Moissonne un thread (propage les erreurs). Moissonne un thread (capture les erreurs). Compare lidentit de deux threads. Renvoie lID de thread interne.

De plus, le module Thread fournit ces fonctions que lon peut importer :
Fonction yield async cond_signal cond_broadcast cond_wait Utilisation Dit lordonnanceur de lancer un thread diffrent. Construit un nouveau thread via une fermeture. Rveille exactement un thread qui fait un cond_wait() sur une variable. Rveille tous les threads qui font un cond_wait() sur une variable. Attend sur une variable jusqu tre rveill par un cond_signCal() ou un cond_broadcast() sur cette variable.

Cration de thread
Vous pouvez engendrer un thread de deux manires, soit en utilisant la mthode de classe Thread->new, soit en utilisant la fonction async. Dans tous les cas, la valeur renvoye est un objet Thread. Thread->new prend une rfrence de code indiquant la fonction lancer et des arguments passe cette fonction :
use Thread; ... $t = Thread->new(\&fonc, $arg1, $arg2);

Vous vous retrouvez souvent vouloir passer une fermeture comme premier argument sans fournir darguments supplmentaires :
my $quelque_chose; $t = Thread->new( sub { dit($quelque_chose) } );

Dans ce cas spcial, la fonction async donne un relief dans lcriture (cest--dire du sucre de syntaxe) :
use Thread qw(async);

customer_8566

422
... my $quelque_chose; $t = async { dit($quelque_chose); };

Chapitre 17 Threads

Vous remarquerez que nous avons import explicitement la fonction async. Bien entendu, vous pouvez galement utiliser le nom pleinement qualifi Thread::async la place, mais alors votre sucre de syntaxe nest plus aussi doux. Puisquasync ne prend quune fermeture, tout ce que vous voulez lui passer doit tre une variable lexicale qui soit ce moment dans la porte.

Destruction de thread
Une fois commenc et sujet aux lubies de votre bibliothque de thread le thread continuera tourner tout seul jusqu ce que sa fonction de plus haut niveau (celle que vous avez passe au constructeur) renvoie un rsultat. Si vous voulez terminer un thread plus tt, il vous suffit de faire return depuis lintrieur de cette fonction de plus haut niveau.4 Maintenant, tout est parfait pour que votre thread se termine en renvoyant un rsultat, mais qui le renvoyer ? Le thread qui a engendr ce thread-ci est vraisemblablement parti faire dautres choses et nattend plus de rponse lappel de la mthode. La rponse est assez simple : le thread attend jusqu ce que quelquun mette un appel de mthode qui fasse lattente dune valeur de retour. Cet appel de mthode sappelle join (joindre) car il fait se rejoindre de manire conceptuelle deux threads en un seul :
$val_ret = $t->join(); # moissonne le thread $t

Lopration join est une rminiscence de waitpid sur un processus fils. Si le thread a dj termin, la mthode join rend la main immdiatement avec la valeur valeur renvoye par la fonction principale du thread. Si le thread na pas fini, join se comporte comme un appel bloquant qui interrompt le thread appelant indfiniment. (Il ny a pas de mcanisme de minuterie (time-out).) Lorsquventuellement le thread sachve, le join renvoie une valeur. Toutefois, au contraire de waitpid, qui ne peut moissonner que les propres fils dun processus, nimporte quel thread peut faire un join sur nimporte quel autre thread lintrieur du processus. Cest--dire quil nest pas ncessaire que le thread qui fait le join soit le thread principal ou le thread parent. La seule restriction est quun thread ne peut pas faire de join sur lui-mme (ce qui reviendrait officier pour vos propres funrailles) et quun thread ne peut pas faire de join sur un thread qui a dj rpondu un join (ce qui quivaudrait deux directeurs des pompes funbres se battant au-dessus de la dpouille). Si vous essayez de faire lune de ces choses, une exception sera leve. La valeur de retour de join ne doit pas forcment tre une valeur scalaire elle peut galement tre une liste :
4. Nappelez pas exit ! Cela essayerait de quitter votre processus entier et y arriverait peut-tre. Mais en fait, le processus ne se terminera pas avant que tous les threads ne le fassent et certains dentre eux peuvent refuser de se terminer sur un exit. Nous donnerons plus dinformations ldessus plus tard.

customer_8566

Le modle de thread
use Thread async; $t1 = async { my @trucs = getpwuid($>); return @trucs; }; $t2 = async { my $mess = cat /etc/motd; return $mess; }; @liste_ret = $t1->join(); $val_ret = $t2->join(); print "Le 1er fils a renvoy @liste_ret\n"; print "Le 2me fils a renvoy $val_ret\n";

423

En fait, lexpression renvoye par un thread est toujours value dans un contexte de liste, mme si join est appel dans un contexte scalaire, auquel cas la dernire valeur de la liste est renvoye.

Capture des exceptions avec join


Si un thread se termine avec une exception non capture, cela ne tuera pas immdiatement le programme entier. Cela serait embtant. la place, lorsquun join est lanc sur ce thread, le join lve lui-mme lexception. Lemploi de join sur un thread indique une volont de propager toute exception leve par ce thread. Si vous prfrez capturer lexception ce moment et cet endroit, utilisez la mthode eval, qui comme la fonction interne du mme nom, fait que lexception est mise dans $@ :
$val_ret = $t->eval(); # capture les erreurs lorsque les # threads se rejoignent

if ($@) { warn "chec du thread : $@"; } else { print "le thread a renvoy $ret_val\n"; }

Bien quil ny ait pas de rgle cet effet, vous pourriez vouloir adopter lhabitude de ne rejoindre un thread que depuis le thread qui a cr celui que vous rejoignez. Cest--dire que vous ne moissonnez un thread fils que depuis le thread pre qui la engendr. Cela rend plus facile la conservation dune trace indiquant quelles exceptions vous auriez besoin de capturer et quand le faire.

La mthode detach
Comme autre solution pour arrter les threads, si vous navez pas prvu de rejoindre un thread plus tard avec join pour obtenir sa valeur de retour, vous pouvez appeler la mthode detach sur ce thread pour que Perl le nettoie votre place. Cest un peu comme lorsquun processus est hrit par le programme init sur Unix, sauf que le seul moyen

customer_8566

424
de faire cela sur Unix est que le processus pre meure.

Chapitre 17 Threads

La mthode detach ne met pas le thread en arrire plan ; si vous essayez de sortir du programme principal et quun thread dtach est toujours en train de tourner, la fin du programme bloquera jusqu ce que le thread lui-mme se termine. Mais plutt, la mthode detach vous pargne les tches de nettoyage. Elle indique purement et simplement Perl de ne pas garder la valeur de retour, ni la valeur de sortie du thread aprs quil a fini. En un sens, detach dit Perl de faire un join implicite lorsque le thread finit puis de jeter les rsultats. Cela peut avoir de limportance : si vous navez jamais fait de join, ni de detach, sur un thread qui renvoie une liste trs grande, cet espace de stockage sera perdu jusqu la fin. En effet, Perl devrait sagripper lui dans la perspective lointaine (mais alors trs lointaine, dans ce cas), o quelquun voudrait faire un join sur ce thread un moment lavenir. Une exception leve dans un thread fils dtach ne se propage plus non plus durant un join, puisque les threads ne suniront jamais. Utilisez sagement eval {} dans la fonction de plus haut niveau et trouvez dautres moyens de rapporter les erreurs.

Identification des threads


Chaque thread de Perl possde un numro didentification de thread distinct, qui est celui que la mthode tid renvoie :
$son_num_tid = $t1->tid();

Un thread peut accder son propre objet thread par lintermdiaire de lappel Thread>self. Ne confondez pas cela avec lID du thread : pour calculer son propre ID, un thread fait ceci :
$mon_tid = Thread->self->tid(); Thread::equal($t1, $t2) $t1->equal($t2) $t1->tid() == $t2->tid() # $$ pour les threads, pour ainsi dire

Pour comparer un objet thread avec un autre, employez lune de ces techniques :

Liste des threads courants


Vous pouvez obtenir une liste des objets threads courants dans le processus courant en utilisant lappel de mthode de classe Thread->list. La liste comprend la fois les threads en train de tourner et ceux qui ont fini mais sur lesquels aucun join na encore t appliqu. Vous pouvez faire ceci depuis nimporte quel thread.
for my $t (Thread->list()) { printf "$t a un tid = %d\n", $t->tid(); }

Priorit au processeur
Le module Thread implmente une fonction, que vous pouvez importer, appele yield. Elle fait en sorte que le thread appelant abandonne le processeur. Malheureusement, les dtails de ce mcanisme sont compltement dpendants votre version dimplmentation des threads. Nanmoins, abandonner le contrle de la CPU occasionnellement est considre comme un geste damabilit :

customer_8566

Le modle de thread
use Thread yield; yield();

425

Lutilisation des parenthses nest pas une obligation. Cest mme encore plus sr, syntaxiquement parlant, car la faute de frappe apparemment invitable yeild est alors intercepte :
use strict; use Thread yield; yeild; # Le compilateur se dsole, puis arrte tout yield; # Ok.

Accs au donnes
Ce que nous savons pass en revue jusquici ntait pas bien compliqu; mais nous sommes sur le point dy remdier. Rien de ce que nous avons fait ne mettait en pratique la nature parallle des threads. Laccs aux donnes partages change tout cela. Le code mis dans un thread en Perl possde les mmes limites en ce qui concerne la visibilit des donnes que tout autre morceau de code en Perl. On a toujours accs aux variables globales via des tables de symboles globales et aux variables lexicales via une porte lexicale (mmoire de travail, scratchpad). Toutefois, le fait que de multiples threads de contrle existent dans le programme gnre des erreurs dans les travaux. Deux threads ne peuvent tre autoriss accder la mme variable globale simultanment ou ils peuvent scraser lun lautre. (Le rsultat de lcrasement dpend de la nature de laccs.) De mme, deux threads ne peuvent tre autoriss accder la mme variable lexicale simultanment car les variables lexicales se comportent galement comme les globales si elles sont dclares en dehors de la porte de fermetures utilises par des threads. Dmarrer des threads via des rfrences de sous-programmes (en utilisant Thread->new) plutt que via des fermetures (en utilisant async) peut aider limiter laccs aux variables lexicales, si cest ce que vous voulez. (Parfois ce nest cependant pas le cas.) Perl rsout le problme pour certaines variables spciales internes, comme $!, $_, @_ et les autres variables comme celles-ci, en en faisant des donnes spcifiques au thread. La mauvaise nouvelle est que toutes vos variables de paquetage, basiques, que vous utilisez quotidiennement, ne sont pas protges des crasements. La bonne nouvelle est que vous navez gnralement pas vous inquiter propos de vos variables lexicales, en supposant quelles soient dclares lintrieur du thread courant, puisque chaque thread instanciera lentre de sa propre porte lexicale, qui est distincte de celle de tout autre thread. Vous ne devez vous soucier des variables lexicales que si elles sont partages entre les threads, par exemple en passant des rfrences ou en rfrenant les variables lexicales lintrieur de fermetures utilises par de multiples threads.

Synchronisation des accs avec lock


Lorsque plusieurs agents peuvent accder au mme lment en mme temps, des collisions surviennent, exactement comme un carrefour. Le verrouillage du carrefour est votre seule dfense.

customer_8566

426

Chapitre 17 Threads

La fonction interne lock est le mcanisme de Perl correspondant un feu tricolore pour le contrle des accs. Bien que lock soit en quelque sorte un mot-cl, cest un mot-cl timide car la fonction interne nest pas utilise si le compilateur a dj vu un dfinition sub lock {} dans le code de lutilisateur. Ceci est destin assurer une compatibilit antrieure. Cependant, CORE::lock dsigne toujours la fonction interne. (Dans un perl qui na pas t compil pour le traitement des threads, lappel de lock nest pas une erreur ; cest une opration sans danger ne faisant rien (no-op), du moins dans les versions rcentes.) Exactement de la mme manire que loprateur flock ne bloque que dautres instances de flock, et non les vritables entres/sorties, loprateur lock galement, ne bloque que dautres instances de lock, et non les accs ordinaires aux donnes. Ce sont, en effet, des verrous consultatifs. Exactement comme les feux tricolores.5 Vous pouvez faire un lock sur des variables scalaires individuelles aussi bien que sur des tableaux ou des hachages entiers.
lock $var; lock @valeurs; lock %hachage;

Cependant, lemploi de lock sur des valeurs agrges ne verrouille pas implicitement les composants scalaires de ces valeurs agrges :
lock @valeurs; ... lock $valeurs[23]; # dans le thread 1 # dans le thread 2 --- ne verrouille pas !

Si vous verrouillez un rfrence, cela verrouille automatiquement laccs au rfrant. Cest--dire que vous obtenez gratuitement une drfrence. Ceci est bien commode car les objets sont toujours cachs derrire un rfrence et vous voulez souvent verrouiller des objets. (Et vous ne voulez presque jamais verrouiller des rfrences.) Le problme avec les feux tricolores, bien entendu, est quils sont rouge la plupart du temps et que vous devez attendre. De mme, lock est un appel bloquant votre thread sera suspendu cet endroit jusqu ce que le verrou soit accord. Il ny a pas de mcanisme de minuterie (time-out). Il ny a pas non plus de mcanisme de dverrouillage car les verrous ont une porte dynamique. Ils durent jusqu ce que leur bloc, leur fichier ou leur eval soit fini. Lorsquils sortent de la porte, il sont automatiquement librs. Les verrous sont galement rcursifs. Cela signifie que si vous verrouillez une variable dans une fonction et que cette fonction sappelle rcursivement pendant que vous dtenez le verrou, le mme thread pourra verrouiller avec succs la mme variable nouveau. Le verrou est finalement abandonn lorsque lon est sorti de tous les niveaux dtenant les verrous. Voici une dmonstration simple de ce qui peut se passer si vous navez pas verrouill. Nous forons un changement de contexte en utilisant yield pour montrer le genre de

5. Certains feux de passage niveau sont obligatoires (ceux avec une barrire) et certaines personnes pensent que les verrous devraient ltre galement. Mais imaginez seulement un monde dans lequel chaque carrefour aurait des armes se levant et se baissant lorsque les feux changeraient.

customer_8566

Le modle de thread

427

problme qui peut galement arriver accidentellement avec un ordonnanceur premptif :


use Thread qw/async yield/; my $var = 0; sub une_inflation { if ($var == 0) { yield; $var++; } } my $t1 = new Thread \&une_inflation; my $t2 = new Thread \&une_inflation; for my $t ($t1, $t2) { $t->join } print "var vaut $var\n";

Ce code affiche toujours 2 (pour une certaine dfinition de toujours ) car nous avons dcid de linf lation aprs avoir vu que la variable valait 0 mais avant que nous puissions le faire, un autre thread a dcid den faire autant. Nous pouvons rsoudre cette collision par lajout trivial dun verrou avant dexaminer $var. Maintenant ce code affiche toujours 1 :
sub une_inflation { lock $var; if ($var == 0) { yield; $var++; } }

Souvenez-vous quil ny a pas de fonction unlock explicite. Pour contrler le dverrouillage, vous navez qu ajouter un autre niveau de porte, qui soit imbriqu, pour que le verrou soit relch lorsque cette porte se termine :
sub une_inflation { { lock $var; if ($var == 0) { yield; $var++; } } # le verrou est relch ici ! # autre code avec $var dverrouille }

Verrous mortels (deadlocks)


Le verrou mortel (deadlock) est le f lau des programmeurs de threads car il est facile den crer par accident et difficile de lviter. Voici un exemple simple de verrou mortel :
my $t1 = async { lock $a; yield; lock $b; $a++; $b++

customer_8566

428
}; my $t2 = async { lock $b; yield; lock $a; $b++; $a++ };

Chapitre 17 Threads

La solution ici est que tous les protagonistes qui on besoin dun ensemble de verrous particulier sen saisissent dans le mme ordre. Cest galement une bonne chose de minimiser la dure pendant laquelle vous dtenez des verrous. (Au moins, cest une bonne chose de le faire pour des questions de performance. Mais si vous le faites pour rduire les risques de verrou mortel, tout ce que vous faites est de le rendre plus difficile reproduire et diagnostiquer le problme.)

Verrouillage des sous-programmes


Vous pouvez galement mettre un verrou sur un sous-programme :
lock &fonc;

Au contraire des verrous sur les donnes, qui ne sont que consultatifs, les verrous de sous-programmes sont obligatoires. Personne dautre que le thread dtenant le verrou peut entrer dans le sous-programme. Considrez le code suivant, qui contient des situations de concurrence (race conditions) impliquant la variable $fini. (Les yield ne sont mis qu titre de dmonstration.)
use Thread qw/async yield/; my $fini = 0; sub bricole { my $arg = shift; my $tid = Thread->self->tid; print "thread $tid : bricole $arg\n"; yield; unless ($fini) { yield; $fini++; bricole($arg + 10); } }

Si vous le lancez de cette faon :


my @t; for my $i (1..3) { push @t, Thread->new(\&bricole, $i); } for (@t) { $_->join } print "fini vaut $fini\n";

voici laffichage (enfin, certaines fois ce nest pas dterministe) :


thread thread thread thread 1 2 3 1 : : : : bricole bricole bricole bricole 1 2 3 11

customer_8566

Le modle de thread
thread 2 : bricole 12 thread 3 : bricole 13 fini vaut 3

429

Toutefois, si vous le lancez de cette faon :


for my $i (1..3) { push @t, async { lock &bricole; bricole($i); }; } for (@t) { $_->join } print "fini vaut $fini\n";

voici laffichage :
thread 1 : bricole thread 1 : bricole thread 2 : bricole thread 3 : bricole fini vaut 1 1 11 2 3

Lattribut locked
Bien quil soit obligatoire dobir un verrou de sous-programme, rien ne force personne les verrouiller en premier lieu. Mais certains sous-programmes aimeraient vraiment tre capables dexiger dtre verrouills avant dtre appels. Lattribut de sous-programme locked remplit cette fonction. Il est plus rapide que lappel lock &fonc car il est connu la compilation, non seulement lexcution. Mais le comportement est le mme que lorsque nous lavons verrouill explicitement auparavant. Voici la syntaxe :
sub bricole : locked { # comme avant }

Si vous avez un prototype de fonction, il vient entre le nom et tous les attributs :
sub bricole ($) : locked { # comme avant }

Verrouillage des mthodes


Le verrouillage automatique dun sous-programme est vraiment trs pratique mais il en fait parfois un peu trop. Lorsque vous invoquez une mthode dobjet, cela na gnralement aucune importance si de multiples mthodes sont lances simultanment pour autant quelles le sont toutes pour le compte dobjets diffrents. Vous aimeriez donc vraiment verrouiller plutt lobjet sur lequel cette mthode est appele. Lajout dun attribut method la dfinition du sous-programme fait ceci :
sub bricole : locked method { # comme avant }

customer_8566

430

Chapitre 17 Threads

Si ce code est appel en tant que mthode, lobjet qui linvoque est verrouill, fournissant un accs squentiel cet objet mais permettant la mthode dtre appele sur dautres objets. Si la mthode nest pas appele sur un objet, lattribut essaie toujours de faire ce quil faut : si vous appelez une mthode verrouille comme une mthode de classe (Paquetage->new plutt que $obj->new), la table de symboles du paquetage est verrouille. Si vous appelez une mthode verrouille comme un sous-programme normal, Perl lvera une exception.

Variables de condition
Une variable de condition permet un thread dabandonner le processeur jusqu ce quun certain critre soit satisfait. Les variables de conditions indiquent des points de coordination entre les threads lorsque vous avez besoin de plus de contrle que ce quun seul verrou fournit. Dun autre ct, vous navez pas vraiment besoin de plus de temps systme (overhead) quun verrou ne fournit et les variables de condition sont conues dans cet esprit. Vous navez qu utiliser des verrous ordinaires plus des conditions ordinaires. Si la condition choue, vous devrez alors prendre des mesures extraordinaires via la fonction cond_wait ; mais nous optimisons pour les chances de russite, puisque dans une application bien conue, nous ne devrions pas de toute faon nous trouver dans un goulot dtranglement sur la condition courante. Outre le verrouillage et le test, les opration de base sur les variables de condition consistent envoyer ou recevoir un vnement signal (non un signal rel au sens de %SIG). Soit, vous suspendez votre excution pour attendre la rception dun vnement, soit vous envoyez un vnement pour rveiller dautres threads attendant une condition particulire. Le module Thread fournit trois fonctions, que vous pouvez importer, pour faire cela : cond_wait, cond_signal et cond_broadcast. Ce sont les mcanismes primaires sur lesquels se basent des modules plus abstraits comme Thread::Queue et Thread::Semaphore. Il est souvent plus commode dutiliser ces abstractions, lorsque cest possible. La fonction cond_wait() prend une variable dj verrouille par le thread courant, dverrouille cette variable, puis bloque jusqu ce quun autre thread fasse un cond_signal ou un cond_broadcast pour la mme variable verrouille. La variable bloque par cond_wait est reverrouille aprs que le retour de cond_wait. Si de multiples threads font un cond_wait sur la mme variable, tous rebloquent sauf un car ils ne peuvent regagner le verrou sur la variable. Ainsi, si vous nutilisez que cond_wait pour la synchronisation, abandonnez le verrou ds que possible. La fonction cond_signal prend une variable dj verrouille par le thread courant et dbloque lun des threads qui tait actuellement dans un cond_wait sur cette variable. Si plus dun thread bloquait dans un cond_wait sur cette variable, un seul est dbloqu et vous ne pouvez pas prdire lequel. Si aucun thread ne bloquait dans un cond_wait sur cette variable, lvnement est limin. La fonction cond_broadcast fonctionne comme cond_signal mais elle dbloque toutes les threads bloqus dans un cond_wait sur la variable verrouille, non un seul thread. (Bien entendu, cest toujours le cas sil ny a quun seul thread dtenant le verrou.) La fonction cond_wait est destine tre le genre de chose quun thread nemploie en dernier ressort que si la condition quil veut nest pas remplie. Le cond_signal et le

customer_8566

Le modle de thread

431

cond_broadcast indiquent que la condition est en train de changer. Le droulement des actions est suppos tre le suivant : verrouillez, puis vrifiez pour voir si la condition que vous voulez est remplie ou non ; si cest le cas, cest bon, sinon, faites un cond_wait jusqu ce que ce soit bon. Laccent devrait tre mis sur le fait dviter de bloquer autant que possible. (Cest gnralement un bon conseil lorsque lon manipule des threads.) Voici un exemple o le contrle passe dun thread lautre. Ne soyez pas bluff par le fait que les conditions relles sont relgues dans la partie droite des modificateurs dinstruction ; cond_wait ne sera jamais appel sauf si la condition que nous attendons est fausse.
use Thread qw(async cond_wait cond_signal); my $var_wait = 0; async { lock $var_wait; $var_wait = 1; cond_wait $var_wait until $var_wait == 2; cond_signal($var_wait); $var_wait = 1; cond_wait $var_wait until $var_wait == 2; $var_wait = 1; cond_signal($wait_var); }; async { lock $var_wait; cond_wait $var_wait until $var_wait == 1; $var_wait = 2; cond_signal($var_wait); cond_wait $var_wait until $var_wait == 1; $var_wait = 2; cond_signal($wait_var); cond_wait $var_wait until $var_wait == 1; };

Autres modules de thread


Plusieurs modules sont construits au-dessus de la primitive cond_wait.

Files dattente (queues)


Le module standard Thread::Queue fournit deux moyens de passer des objets entre des threads sans sinquiter des verrous ou de la synchronisation. Cette interface est bien plus facile :
Mthode new enqueue dequeue Utilisation Construit un nouvel objet Thread::Queue. Pousse un ou plusieurs scalaires la fin de la file. Enlve le premier scalaire du dbut de la file. La mthode dequeue bloque sil ny a plus dlments.

customer_8566

432

Chapitre 17 Threads

Remarquez comme une file dattente est similaire un pipe ordinaire, sauf quau lieu denvoyer des octets, vous arrivez passer des scalaires purs et durs, y compris des rfrences et des objets consacrs avec bless. Voici un exemple driv de la page de manuel de perlthrtut :
use Thread qw/async/; use Thread::Queue; my $Q = Thread::Queue->new(); async { while (defined($donnee = $Q->dequeue)) { print "$donnee retir de la file\n"; } }; $Q->enqueue(12); $Q->enqueue("A", "B", "C"); $Q->enqueue($thr); sleep 3; $Q->enqueue(\%ENV); $Q->enqueue(undef);

Et voici ce que vous obtenez comme affichage :


12 retir de la file A retir de la file B retir de la file C retir de la file Thread=SCALAR(0x8117200) retir de la file HASH(0x80dfd8c) retir de la file

Remarquez comment $Q tait dans la porte lorsque le thread asynchrone a t lanc via une fermeture de async. Les threads respectent les mmes rgles concernant les portes que nimporte quoi dautre en Perl. Lexemple ci-dessus naurait pas fonctionn si $Q avait t dclar aprs lappel async.

Smaphores
Thread::Semaphore vous fournit des objets smaphores, srs vis--vis des threads et capables de compter, pour implmenter vos oprations favorites p() et v(). Comme la plupart dentre nous nassocient pas ces oprations avec les mots hollandais passeer ( passer ) et verlaat ( laisser ), le module appelle ces oprations down (diminuer) et up (augmenter), respectivement. (On trouvera dans la littrature, wait (attendre) ou signal (signaler).) Les mthodes suivantes sont implmentes :
Mthode new down up Utilisation Construit un nouvel objet Thread::Semaphore. Alloue un ou plusieurs lments. Dsalloue un ou plusieurs lments.

La mthode new cre un nouveau smaphore et initialise son compteur au nombre sp-

customer_8566

Le modle de thread

433

cifi. Si aucun nombre nest spcifi, le compteur du smaphore est positionn 1. (Le nombre reprsente une certaine rserve dlment qui peut spuiser si tous les lments sont dsallous.)
use Thread::Semaphore; $mutex = Thread::Semaphore->new($MAX);

La mthode down dcrmente le compteur du smaphore du nombre spcifi, ou de 1 si aucun nombre nest donn. Elle peut tre interprte comme une tentative dallocation dune partie ou de la totalit dune ressource. Si le compteur du smaphore descend en dessous de zro, cette mthode bloque jusqu ce quelle compteur soit suprieur ou gal la quantit que vous avez demande. Appelez-le comme ceci :
$mutex->down();

La mthode up incrmente le compteur du smaphore du nombre spcifi, ou de 1 si aucun nombre nest donn. Elle peut tre interprte comme une tentative de dsallocation dune certaine quantit dune ressource prcdemment alloue. Ceci dbloque au moins un thread qui tait bloqu en essayant de faire un down sur le smaphore, pourvu que le up augmente le compteur du smaphore au-dessus de ce que le down essaie de le diminuer. Appelez-le comme ceci :
$mutex->up();

Autres modules standard pour le traitement des threads


Thread::Signal vous permet de dmarrer un thread qui est dsign pour recevoir les signaux %SIG de votre processus. Ceci traite le problme toujours vexant des signaux qui ne sont pas fiables tels quils sont actuellement implments dans Perl et leur utilisation imprudente peut de temps en temps causer des core dumps. Ces modules sont toujours en dveloppement et peuvent ne pas entraner leffet escompt sur votre systme. Dun autre ct, ils peuvent produire les rsultats dsirs. Si ce nest pas le cas, cest parce que quelquun comme vous ne les a pas corrigs. Peut-tre que quelquun comme vous devrait se lancer et donner un coup de main.

customer_8566

customer_8566

Compilation

18

Si vous tes venu ici pour trouver un compilateur Perl, vous serez peut-tre surpris dapprendre que vous en avez dj un votre programme perl (gnralement /usr/bin/perl) renferme dj un compilateur Perl. Ce nest peut-tre pas ce que vous pensiez et si tel est le cas, vous serez heureux dapprendre que nous fournissons galement des gnrateurs de code (que certaines personnes bien pensantes appellent compilateurs ) et nous en discuterons vers la fin de ce chapitre. Mais nos voulons tout dabord parler de ce que nous pensons tre Le Compilateur. Il y aura invitablement dans ce chapitre, une certaine quantit de petits dtails qui intresseront certains et ennuieront dautres. Si vous pensez que vous ntes pas intress, considrez cela comme loccasion dentraner vos facults de lecture grande vitesse. Imaginez que vous tes un chef dorchestre ayant command la partition pour une uvre immense. Lorsque le coffret arrive, vous trouvez plusieurs douzaines de livrets, un pour chaque membre de lorchestre, ne contenant que sa propre partition. Mais il manque curieusement votre copie principale avec toutes les partitions. Encore plus curieusement, les partitions que vous avez crites vous-mme sont retranscrites en franais au lieu dtre en notation musicale. Avant que vous puissiez mettre en place un concert susceptible dtre prsent au public, ou mme simplement donner la musique jouer votre orchestre, il vous faudra traduire les descriptions en prose vers le systme normal de notes et de mesures. Puis vous aurez besoin de compiler les partitions individuelles en une seule gigantesque pour que vous ayez une ide du programme dans son ensemble. De mme, lorsque vous remettez le code source de votre script Perl lexcutable perl pour quil lexcute, il nest pas plus utile lordinateur que ne ltait la description en franais de la symphonie aux musiciens. Avant que votre programme puisse tourner, Perl a besoin de compiler1 ces directives ressemblant un langage naturel vers une reprsentation symbolique spciale. Votre programme ne tourne pourtant toujours pas car le compilateur ne fait que compiler. Comme la partition du chef dorchestre, mme

1. Ou traduire, ou transformer, ou transfigurer, ou transmuter, ou mtamorphoser.

customer_8566

436

Chapitre 18 Compilation

aprs que votre programme a t converti en un format dinstructions convenant linterprtation, il a encore besoin dun agent actif pour interprter ces instructions.

Cycle de vie dun programme Perl


Vous pouvez dcomposer le cycle de vie dun programme Perl en quatre phases distinctes, chacune avec ses propres tapes indpendantes. La premire et la dernire sont les plus intressantes et les deux du milieu sont optionnelles. Ces phases sont dcrite la figure 18-1.

Figure 18-1. Le cycle de vie dun programme Perl 1. La phase de compilation Durant la phase 1, la phase de compilation, le compilateur convertit votre programme vers une structure de donnes appele un arbre syntaxique. En plus des techniques traditionnelles danalyse syntaxique, Perl en emploie une bien plus puissante : il utilise les blocs BEGIN pour guider toute compilation plus approfondie. Les blocs BEGIN sont passs linterprteur pour tre lancs ds quils ont t analyss, ce qui les lance effectivement dans lordre du premier arriv (FIFO : first in, first out). Ceci comprend toutes les dclarations use et no ; celles-ci ne sont que des blocs BEGIN dguiss. Tous les blocs CHECK, INIT et END sont programms par le compilateur pour une excution diffre. Les dclarations lexicales sont notes mais leurs affectations ne sont pas excutes. Toutes les constructions eval BLOC, s///e et les expressions rgulires non interpoles sont compiles ici et les expressions constantes sont pr-values. Le compilateur a maintenant fini, moins quil ne soit rappel au travail plus tard. la fin de cette phase, linterprteur est nouveau appel pour excuter tous les blocs CHECK programms dans lordre du dernier arriv (LIFO : last in, first out). La prsence ou labsence dun bloc CHECK dtermine si nous allons ensuite la phase 2 ou si nous sautons directement la phase 4. 2. La phase de gnration de code (optionnelle) Les blocs CHECK sont installs par les gnrateurs de code ; cette phase optionnelle nintervient donc que si vous avez utilis explicitement lun de ces gnrateurs de code (dcrit plus tard dans Gnrateurs de codes). Ceux-ci convertissent le programme compil (mais non encore lanc) soit en code source en C, soit en bytecode

customer_8566

Compilation du code

437

Perl srialis une squence de valeurs exprimant des instructions Perl internes. Si vous choisissez de gnrer du code source en C, il peut ventuellement produire un fichier appel une image excutable en langage machine natif.2 Arriv ce point, votre programme se met en hibernation. Si vous avez fait une image excutable, vous pouvez directement aller la phase 4 ; sinon, vous devez reconstruire les bytecodes lyophiliss en phase 3. 3. La phase de reconstruction de larbre syntaxique (optionnelle) Pour ranimer le programme, son arbre syntaxique doit tre reconstruit. Cette phase nexiste que si la gnration de code a eu lieu et si vous avez choisi de gnrer du bytecode. Perl doit tout dabord reconstituer ses arbres syntaxiques partir de cette squence de bytecode avant que le programme puisse tre lanc. Perl ne se lance pas directement partir des bytecodes ; ce serait trop lent. 4. La phase dexcution Finalement, ce que vous attendiez tous : faire tourner votre programme.3 Linterprteur prend larbre syntaxique (quil obtient directement depuis le compilateur ou indirectement depuis la gnration de code et la reconstruction conscutive de larbre) et lexcute. (Ou, si vous avez gnr un fichier image excutable, il peut tre lanc en tant que programme indpendant puisquil contient un interprteur Perl intgr.) Au dbut de cette phase, avant que ce ne soit votre programme principal de se lancer, tous les blocs INIT programms sont excuts dans lordre du premier arriv (FIFO). Puis, votre programme principal est lanc. Linterprteur peut faire nouveau appel au compilateur comme cela est ncessaire lorsquil rencontre un eval CHANE, un do FICHIER ou une instruction require, une construction s///ee ou une reconnaissance de motif avec une variable interpole contenant une assertion de code valide. Lorsque votre programme principal a fini, tous les blocs END diffrs sont finalement excuts, cette fois-ci dans lordre du dernier arriv (LIFO). Le bloc vu en tout premier sera excut en dernier et ensuite vous aurez fini. (Les blocs END ne sont court-circuits que si vous appelez un exec ou si votre processus est balay par une erreur catastrophique non intercepte. Les exceptions ordinaires ne sont pas considres comme tant catastrophiques.) Maintenant nous allons discuter de ces phases plus en dtail et dans un ordre diffrent.

Compilation du code
Perl est toujours dans lun des deux modes dopration : soit il est en train de compiler votre programme, soit il est en train de lexcuter jamais les deux en mme temps.

2. Votre script original est galement un fichier excutable mais il nest pas en langage machine, nous ne lappelons donc pas une image. Un fichier image est appel ainsi car il sagit dune copie exacte des codes machine que votre CPU sait directement excuter. 3. N.d.T. : en anglais, faire tourner se dit run et par consquent, cette phase sappelle galement run phase.

customer_8566

438

Chapitre 18 Compilation

Tout au long de ce livre, nous nous rfrons certains vnements comme se droulant la compilation (compile time) ou alors nous disons que le compilateur Perl fait ceci ou cela . dautres endroits, nous mentionnons quautre chose se droule lexcution (run time) ou que linterprteur Perl fait ceci ou cela . Bien que vous pouvez continuer vivre en pensant que Perl dsigne la fois le compilateur et linterprteur, comprendre lequel de ces deux rles est en train de jouer Perl un moment donn est essentiel pour comprendre pourquoi certaines choses se droulent comme elles le font et non autrement. Lexcutable perl implmente les deux rles : tout dabord le compilateur, puis linterprteur. (Dautres rles sont galement possibles ; perl est aussi un optimisateur et un gnrateur de code. Parfois, cest mme un tricheur mais tout cela dans la joie et la bonne humeur.) Il est galement important de comprendre la distinction entre la phase de compilation et la compilation (compilation time) ainsi quentre la phase dexcution et lexcution (run time). Une phase est un concept grande chelle. Alors que la compilation et lexcution sont des concepts petite chelle. Une phase de compilation donne fait surtout des travaux de compilation, mais elle fait galement quelques travaux dexcution via les blocs BEGIN. Une phase dexcution donne fait surtout des travaux dexcution, mais elle fait galement quelques travaux de compilation par lintermdiaire doprateurs comme eval CHANE. Dans le droulement typique des vnements, le compilateur Perl lit le source de votre programme en entier avant que lexcution ne commence. Cest ici que Perl analyse les dclarations, les instructions et les expressions pour sassurer quelles sont syntaxiquement valides.4 Sil trouve une erreur de syntaxe, le compilateur tente de la corriger pour quil puisse rendre compte des erreurs suivantes dans le code source. Parfois, ceci fonctionne et parfois non ; les erreurs de syntaxe ont une tendance fcheuse dclencher une cascade de fausses alertes. Perl abandonne, avec un sentiment de frustration, aprs environ 10 erreurs. En plus de linterprteur qui traite les blocs BEGIN, le compilateur traite votre programme avec la connivence de trois agents notionnels. Ceux-ci sont parfois appels lexmes mais vous les rencontrerez plus souvent sous le nom de tokens dans les textes parlant des langages de programmation. Lanalyseur lexical est parfois appel un tokener ou un scanner et ce quil fait est parfois appel de la lexicalisation (lexing) ou de la tokenisation (tokening). Lanalyseur syntaxique (parser) essaie alors de dgager un sens des groupes de tokens en les assemblant dans des constructions plus larges, comme des expressions et des instructions, bases sur la grammaire du langage Perl. Loptimisateur rarrange et rduit ces regroupements plus larges en squences plus efficaces. Il choisit ses optimisations prcautionneusement, sans perdre de temps sur des optimisations marginales car le compilateur Perl doit tre rapide comme lclair puisquil est utilis en mode load-and-go (cest--dire que lexcution dun programme est toujours prcde de sa compilation).

4. Non, il ny a pas de diagramme de syntaxe formelle comme en syntaxe BNF (Backus-Naur Form), mais nous vous invitons lire attentivement, dans larborescence des sources de Perl, le fichier perly.y, qui contient la grammaire yacc(1) que Perl utilise. Nous vous recommandons de vous tenir le plus loin possible de lanalyseur lexical, qui est connu pour avoir provoqu des troubles alimentaires chez des rats de laboratoire.

customer_8566

Compilation du code

439

Ceci ne se produit pas dans des tapes indpendantes mais dun seul coup avec normment de dialogues croiss entre les agents. Lanalyseur lexical a parfois besoin dindications de la part de lanalyseur syntaxique pour lever les ambiguts sur les diffrents types possibles des tokens quil regarde. (Curieusement, la porte lexicale est lune des choses que lanalyseur lexical ne comprend pas car cest lautre sens de lexique .) Loptimisateur a galement besoin de garder une trace de ce que lanalyseur syntaxique est en train de faire car certaines optimisations ne peuvent tre faites avant que lanalyseur syntaxique nait atteint un certain point, tel que la fin dune expression, dune instruction, dun bloc ou dun sous-programme. Vous pouvez trouver trange que le compilateur Perl fasse toutes ces choses en une fois plutt que les unes aprs les autres mais il sagit certainement du mme processus confus que lorsque vous essayez de comprendre un langage naturel la vole alors que vous tes en train de lcouter ou de le lire. Vous nattendez pas la fin dun chapitre pour comprendre ce que la premire phrase voulait dire. Vous pourriez pensez aux correspondances suivantes :
Langage informatique Caractre Token Terme Expression Instruction Bloc Fichier Programme Langage naturel Lettre Morphme Mot Proposition Phrase Paragraphe Chapitre Histoire

En supposant que lanalyse syntaxique se passe bien, le compilateur estime que ce que vous lui avez pass en entre est une histoire valide heu, pardon, un programme valide. Si vous utilisez loption -c lorsque vous lancez votre programme, il affiche un message syntax OK et se termine. Sinon, le compilateur passe les fruits de ses efforts aux autres agents. Ces fruits se prsentent sous forme dun arbre syntaxique. Chaque fruit de larbre ou chaque nud, comme on les appelle reprsente lun des codes dopration (opcodes) internes de Perl et les branches de larbre reprsentent le schma dvolution de cet arbre. ventuellement, les nuds seront enchans de manire linaire, les uns aprs les autres, pour indiquer lordre dans lequel le systme dexcution devra les passer en revue. Chaque code dopration est la plus petite unit dinstruction excutable que Perl peut apprhender. Vous pourriez rencontrer une expression telle que $a = -($b + $c) comme tant une seule instruction mais Perl lapprhende comme six codes dopration spars. Prsent sous un format simplifi, larbre syntaxique pour cette expression ressemblerait la figure 18-2. Les numros reprsentent lordre de parcours que le systme dexcution de Perl suivra ventuellement. Perl nest pas un compilateur travaillant en une seule passe comme certains pourraient le penser. (Les compilateurs travaillant en une seule passe sont trs dous pour rendre

customer_8566

440

Chapitre 18 Compilation

Figure 18-2. Ordre de parcours des codes dopration de $a = -($b +$c) les choses faciles lordinateur et difficiles au programmeur.) Il sagit rellement dun compilateur multipasse, faisant des optimisations et consistant en au moins trois passes logiques diffrentes, qui dans la pratique sentremlent. Les passes 1 et 2 sont lances en alternance alors que le compilateur fait des allers-retours toute vitesse le long de larbre syntaxique durant sa construction ; la passe 3 se produit ds quun sous-programme ou quun fichier est entirement analys. Voici ces diffrentes passes : Passe 1 : Analyse ascendante (Bottom-up parsing) Durant cette passe, larbre syntaxique est construit par lanalyseur syntaxique yacc(1) en utilisant les tokens quon lui donne partir de lanalyseur lexical sousjacent (qui pourrait tre considr comme une autre phase logique titre individuel). Ascendante signifie seulement que lanalyseur syntaxique connat les feuilles de larbre avant ses branches et sa racine. Il calcule vraiment les choses de bas en haut dans la figure 18-2, puisque nous avons dessin la racine en haut, dans la pure tradition idiosyncratique des informaticiens. (Et des linguistes.) Alors que chaque nud contenant un code dopration est construit, une vrification de bon sens par code dopration est effectue pour contrler si la smantique est valide, comme le bon nombre et le type correct des arguments utiliss pour appeler les fonctions internes. Alors que chaque sous-section de larbre prend forme, loptimisateur estime les transformations quil peut appliquer au sous-arbre entier se trouvant maintenant sous son emprise. Par exemple, une fois quil sait quune liste de valeurs est passe une fonction prenant un certain nombre darguments, il peut se dfaire du code dopration qui enregistre le nombre darguments pour les fonctions en acceptant un nombre variable. Une optimisation plus importante, connue sous le nom de prcalcul des expressions constantes (constant folding), est dcrite plus loin dans ce paragraphe. Cette passe construit galement lordre de parcours des nuds utilis plus tard pour lexcution, ce qui est une astuce vraiment gniale car le dpart du parcours nest presque jamais le nud suprieur. Le compilateur ralise une boucle temporaire des codes dopration, avec le nud suprieur pointant sur le premier code dopration parcourir. Lorsque le nud suprieur est incorpor dans quelque chose de plus gros, cette boucle de codes dopration est brise, uniquement pour

customer_8566

Compilation du code

441

engendrer une boucle plus grosse avec le nouveau nud suprieur. La boucle est ventuellement brise pour de bon lorsque le nud de dpart est pouss dans une autre structure comme un descripteur de sous-programme. Lappelant du sous-programme peut toujours retrouver ce premier code dopration bien quil soit dans les profondeurs de larbre, comme cest le cas dans la figure 18-2. Linterprteur na aucun besoin de revenir en bas de larbre pour arriver comprendre par o commencer. Passe 2 : Optimisateur descendant (Top-down optimizer) Une personne lisant un extrait dun code Perl (ou dun code franais, pour ce qui nous proccupe ici) ne peut dterminer le contexte sans examiner les lments lexicaux lentourant. Vous ne pouvez parfois pas dcider ce qui se passe rellement jusqu ce que vous ayez plus dinformations. Que cela ne vous aff lige pas pour autant car vous ntes pas seul : le compilateur non plus. Dans cette passe, le compilateur redescend le sous-arbre quil vient de construire pour appliquer des optimisations locales, dont la plus remarquable est la propagation de contexte. Le compilateur marque les nuds avec les contextes appropris (vide, scalaire, liste, rfrence ou lvalue) imposs par le nud courant. Les codes dopration superf lus sont annuls, mais non supprims, car il est maintenant trop tard pour reconstruire lordre dexcution. Nous compterons sur la troisime passe pour les enlever de lordre dexcution provisoire dtermin par la premire passe. Passe 3 : Optimisateur lucarne (Peephole optimizer) Certaines units de code ont leur propre espace de stockage dans lequel elles conservent leurs variables de porte lexicale. (De tels espace sont appels mmoires de travail ou scratchpads dans le jargon de Perl.) Ces units comprennent les eval CHANE, les sous-programmes et les fichiers entiers. Dune manire importante du point de vue de loptimisateur, elles ont chacune leur propre point dentre, ce qui signifie qualors que nous connaissons lordre dexcution partir dici, nous ne pouvons pas connatre ce qui sest pass auparavant car la construction a pu tre appele de nimporte o. Ainsi, lorsque lune de ces units a fini dtre analyse, Perl lance un optimisateur regardant par une lucarne, sur ce code. Au contraire des deux passes prcdentes, qui parcouraient la structure de branche de larbre syntaxique, cette passe-ci parcours le code dans un ordre dexcution linaire, puisquelle constitue la base la dernire opportunit de le faire avant que nous isolions la liste de codes dopration de lanalyseur syntaxique. La plupart des optimisations ont dj t effectues dans les deux premires passes mais certaines ne le pouvaient pas. Des optimisations varies de dernire minute se produisent ici, y compris lassemblage de lordre dexcution final en court-circuitant les codes dopration nuls et le fait de dtecter lorsque diverses juxtapositions de codes dopration peuvent tre rduites quelque chose de plus simple. Lidentification dune srie de concatnations de chanes est une optimisation importante puisque vous aimeriez vraiment viter de copier la mme chane encore et encore chaque fois que vous ajoutez un petit quelque chose la fin. Cette passe ne fait pas que de loptimisation ; il ralise galement une grande quantit de travail rel : linterception de mots simples (barewords), la gnration davertissements sur des constructions douteuses, la recherche de code peu susceptible dtre atteint, la rsolution de clefs de pseudo-

customer_8566

442

Chapitre 18 Compilation

hachages et la recherche de sous-programmes appels avant que leurs prototypes naient t compils. Passe 4 : Gnration de code (Code generation) Cette passe est optionnelle ; elle nest pas utilise dans le droulement normal des vnements. Mais si lun des trois gnrateurs de code B::Bytecode, B::C ou B::CC est invoqu, on accde une dernire fois larbre syntaxique. Les gnrateurs de code mettent soit les bytecodes Perl srialiss utiliss plus tard pour reconstruire larbre syntaxique, soit du code littral C reprsentant ltat de larbre syntaxique la compilation. La gnration de code C est disponible en deux varits diffrentes. B::C reconstruit simplement larbre syntaxique et le lance en utilisant la boucle habituelle runops() que Perl lui-mme utilise durant lexcution. Tandis que B:CC produit un quivalent C linaris et optimis du chemin emprunt par le code dexcution (qui ressemble une table de branchements ( jump table) gante) et lexcute. Pendant la compilation, Perl optimise votre code de manires trs, trs, diverses. Il rarrange le code pour le rendre plus efficace lexcution. Il supprime le code qui ne pourra jamais tre atteint durant lexcution, comme un bloc if (0) ou les blocs elsif et else avec un bloc if (1). Si vous utilisez des variables lexicalement types, dclares avec my NomClasse $var ou our NomClasse $var et que le paquetage NomClasse avait t initialis avec le pragma use fields, les accs aux champs constants depuis le pseudohachage sous-jacent sont vrifis pour y dtecter des fautes de frappe et convertis en accs un tableau. Si vous donnez loprateur sort une routine de comparaison suffisamment simple, comme {$a <=> $b} ou {$b cmp $a}, celle-ci est remplace par un appel du code C compil. Loptimisation la plus impressionnante de Perl est probablement la manire dont il rsout les expressions constantes ds que possible. Considrez par exemple larbre syntaxique prsent la figure 18-2. Si les nuds et 2 avaient tous deux t des littraux ou des fonctions constantes, les nuds 1 4 auraient t remplacs par le rsultat de ce calcul, ce qui aurait donn quelque chose comme la figure 18-3.

Figure 18-3. Prcalcul de constantes On appelle ceci le prcalcul dexpressions constantes (constant folding). Ce prcalcul ne se limite pas des cas simples comme la conversion la compilation de 2**10 en 1024. Il rsout galement les appels de fonctions la fois les fonctions internes et les sousprogrammes dclars par lutilisateurs remplissant les critres de la section Inclure par rfrence les fonctions constantes au chapitre 6, Sous-programmes. En rminiscence des compilateurs FORTRAN, clbres pour leur connaissance de leurs propres fonctions intrinsques, Perl sait galement laquelle de ses fonctions internes appeler durant la compilation. Cest pourquoi lorsque vous essayez de prendre le log de 0.0 ou la racine

customer_8566

Excution du code

443

carre (sqrt) dune constante ngative, vous encourez une erreur de compilation et non dexcution, et linterprteur nest pas lanc du tout.5 Mme les expressions arbitrairement complexes sont rsolues trs tt, en dclenchant parfois la suppression de blocs entiers comme celui-ci :
if (2 * sin(1)/cos(1) < 3 && une_fonc() { n_importe_quoi() }

Aucun code nest gnr pour ce qui ne pourra jamais tre valu. Comme la premire partie est toujours fausse, ni une_fonc, ni n_importe_quoi ne seront jamais appels. (Ne vous attendez donc pas faire un goto sur des tiquettes lintrieur de ce bloc car il nexistera mme pas lexcution.) Si une_fonc tait une fonction constante susceptible dtre incluse par rfrence (inlinable), sa valeur aurait juste t insre comme si ctait une constante littrale. Vous auriez alors encouru un avertissement Useless use of a constant in void context (Utilisation inutile dune constante dans un contexte vide). Ceci pourrait vous surprendre si vous naviez pas ralis que ctait une constante. Toutefois, si n_importe_quoi tait la dernire instruction value dans une fonction appele dans un contexte non vide (tel que loptimisateur le dtermine), vous nauriez jamais vu lavertissement. Vous pouvez voir le rsultat final de larbre syntaxique construit aprs toutes les tapes doptimisation avec perl -Dx. (Loption -D exige une version spciale de Perl, permettant le dbogage) Voir galement le paragraphe sur B::Deparse dcrit ci-dessous. En fin de compte, le compilateur Perl travaille dur (mais pas trop dur) pour optimiser le code afin que, lorsquarrive le moment de lexcution, celle-ci soit acclre. Cest le moment o votre programme est lanc, alors occupons-nous en maintenant.

Excution du code
premire vue, les programmes Sparc ne tournent que sur des machines Sparc, les programmes Intel ne tournent que sur des machines Intel et les programmes Perl ne tournent que sur des machines Perl. Une machine Perl possde des qualits quun programme Perl trouverait idales dans un ordinateur : une mmoire qui salloue et se dsalloue automatiquement, des types de donnes fondamentaux qui sont des chanes, des tableaux et des hachages dynamiques et nont pas de limite de taille et des systmes qui se comportent peu prs toujours de la mme faon. Le travail de linterprteur Perl est de faire que nimporte quel ordinateur sur lequel il tourne, apparaisse comme lune de ces machines Perl idales. Cette machine fictive prsente lillusion dun ordinateur spcialement conu pour ne rien faire tourner dautre que des programmes Perl. Chaque code dopration (opcode) produit par le compilateur est une commande fondamentale dans cet ensemble dinstructions mules. Au lieu dun compteur de programme matriel, linterprteur ne garde que la trace du code dopration courant excuter. Au lieu dun pointeur de pile matriel, linterprteur possde sa propre pile virtuelle. Cette pile est trs importante

5. En fait, nous simplifions ici lextrme. Linterprteur est bien lanc car cest de cette manire que le prcalcul de constantes est implment. Mais il est immdiatement lanc la compilation, de la mme faon que les blocs BEGIN sont excuts.

customer_8566

444

Chapitre 18 Compilation

car la machine virtuelle Perl (que nous refusons dappeler une PVM6) est une machine reposant sur des oprations de pile. Les codes dopration de Perl sont appel en interne des codes PP (abrviation de codes push-pop , empiler-dpiler ) car ils manipulent la pile virtuelle de linterprteur pour trouver toutes les oprandes, traiter les valeurs temporaires et stocker tous les rsultats. Si vous avez jamais programm en Forth ou en PostScript ou utilis une calculatrice scientifique HP avec une saisie en RPN ( Reverse Polish Notation , notation polonaise inverse), vous savez comment fonctionne une machine base sur des oprations de pile. Mme si ce nest pas le cas, le concept est simple : pour ajouter 3 et 4, vous faites les choses dans lordre 3 4 + au lieu de lordre conventionnel 3 + 4. Ce qui signifie en termes doprations de pile que vous empilez 3, puis 4 et + dpile ensuite les deux arguments, les additionne et remet 7 dans la pile, o il restera jusqu ce que vous en fassiez quelque chose. Compar au compilateur Perl, linterprteur Perl est un programme rigoureux, presquennuyeux. Tout ce quil fait est de parcourir pas pas les codes dopration compils, un un, et de les acheminer vers lenvironnement dexcution de Perl, cest--dire, vers la machine virtuelle Perl. Cest juste un tas de code C, nest-ce pas ? En fait, ce nest pas du tout ennuyeux. Une machine virtuelle Perl garde la trace dune grande quantit de contextes dynamiques votre place pour que vous nayez pas le faire. Perl entretient un bon nombre de piles, que vous navez pas connatre, mais que nous numrerons ici, seulement pour vous pater : pile doprandes (operand stack) Il sagit de la pile dont nous avons dj parl. pile de sauvegardes (save stack) L o sont sauvegardes les valeurs dclares locales en attendant dtre restaures. Plusieurs routines internes dclarent galement des valeurs comme tant locales sans que vous le sachiez. pile de portes (scope stack) Le contexte dynamique poids plume, qui contrle le moment o la pile de sauvegardes doit tre dpile. pile de contextes (context stack) Le contexte dynamique poids lourd ; qui a appel qui pour en arriver l o vous tes. La fonction caller parcourt cette pile. Les fonctions de contrle de boucle examinent cette pile pour trouver quelle boucle contrler. Lorsque vous pluchez la pile de contexte, la pile de portes est pluche en consquence, ce qui restaure toutes vos variables locales partir de la pile de sauvegardes, mme si vous aviez quitt le contexte prcdent par le biais de procds infmes comme de lever une exception et sortir avec un longjmp(3). pile de changements denvironnement ( jumpenv stack) La pile des contextes de longjmp(3) qui nous permettent de lever des exceptions ou de quitter le programme de manire expditive.
6. N.d.T. : PVM est lacronyme habituel de Parallel Virtual Machine, machine parallle virtuelle.

customer_8566

Excution du code
pile de retours (return stack)

445

L do nous sommes partis lorsque nous sommes entrs dans ce sous-programme. pile de repre (mark stack) L o commence, dans la pile doprandes, la liste darguments courante pour les fonctions avec un nombre variable darguments (variadic). piles de mmoires de travail lexicales rcursives (recursive lexical pad stacks) L o sont stocks les variables lexicales et les autres registres de mmoires de travail (scratch register) lorsque les sous-programmes sont appels rcursivement. Bien entendu, il y a la pile C dans laquelle sont stockes toutes les variables C. Perl essaie en fait dviter de se reposer sur la pile du C pour le stockage de valeurs sauvegardes, puisque longjmp(3) court-circuite la restauration approprie de telles valeurs. Tout ceci pour dire que la vision habituelle que lon a dun interprteur, un programme qui en interprte un autre, est vraiment inadquate pour dcrire ce qui se passe ici. Oui, il existe du code C implmentant des codes dopration mais lorsque nous parlons d interprteur , nous voulons dire quelque chose de plus que cela, de la mme manire que lorsque nous parlons de musicien , nous voulons dire quelque chose de plus quun ensemble dinstructions dADN changeant les notes en sons. Les musiciens sont des organismes rels, vivants et ont une condition . Il en va de mme pour les interprteurs. En particulier, tout ce contexte dynamique et lexical, ainsi que les tables de symboles globales, plus larbre syntaxique, plus un thread dexcution, est ce que nous appelons un interprteur. En tant que contexte dexcution, un interprteur commence son existence avant mme que le compilateur ne dmarre et il peut se lancer dans une forme rudimentaire pendant mme que le compilateur est en train de construire le contexte de linterprteur. En fait, cest prcisment ce qui arrive lorsque le compilateur appelle linterprteur pour excuter des blocs BEGIN et dautres choses dans le mme genre. Et linterprteur peut se retourner et utiliser le compilateur pour se construire davantage. Chaque fois que vous dfinissez un autre sous-programme ou que vous chargez un autre module, la machine virtuelle Perl particulire que nous appelons un interprteur se redfinit elle-mme. Vous ne pouvez pas vraiment dire si cest le compilateur ou linterprteur qui a le contrle car ils cooprent pour contrler le processus damorage (bootstrap process) que nous appelons communment lancer un script Perl . Cest comme lorsquon amorce le cerveau dun enfant. Est-ce lADN qui le fait ou les neurones ? Un peu des deux, selon nous, avec quelques interventions de programmeurs externes. Il est possible de lancer de multiples interprteurs dans le mme processus ; ils peuvent ou non partager des arbres syntaxiques, selon quils ont dmarr en clnant un interprteur existant ou en construisant un nouvel interprteur partir de zro. Il est galement possible de lancer de multiples threads dans un seul interprteur, auquel cas ils ne partagent pas seulement des arbres syntaxiques mais galement les symboles globaux voir le chapitre 17, Threads. Mais la plupart des programmes Perl nutilisent quun seul interprteur Perl pour excuter leur code compil. Et alors que vous pouvez lancer de multiples interprteurs Perl

customer_8566

446

Chapitre 18 Compilation

indpendants dans un seul processus, lAPI actuelle pour ceci nest accessible quen C.7 Chaque interprteur Perl individuel joue le rle dun processus compltement spar mais ne cote pas autant que la cration dun nouveau processus complet. Cest ainsi que lextension mod_perl dApache obtient de telles performances : lorsque vous lancez un script CGI sous mod_perl, ce script a dj t compil en codes dopration Perl, vitant ainsi le besoin de le recompiler mais, ce qui est plus important encore, en vitant le besoin de dmarrer un nouveau processus, ce qui constitue le vritable goulot dtranglement. Apache initialise un nouvel interprteur Perl dans un processus existant et passe cet interprteur le code prcdemment compil pour quil lexcute. Bien entendu, cest un peu plus compliqu que cela cest toujours un peu plus compliqu. Pour plus dinformations sur mod_perl, voir Writing Apache Modules with Perl and C (OReilly, 1999). Plusieurs autres applications, comme nvi, vim et innd, peuvent intgrer des interprteurs Perl ; nous ne pouvons pas esprer les lister toutes ici. Il existe un bon nombre de produits commerciaux qui ne font mme pas la publicit pour le moteur Perl quils ont intgr. Ils lutilisent seulement en interne car il accomplit leur travail avec classe.

Sorties du compilateur
Ainsi, si Apache peut compiler un programme Perl maintenant et lexcuter plus tard, pourquoi pas vous ? Apache et dautres programmes contenant des interprteurs Perl intgrs le font facilement ils ne stockent jamais larbre syntaxique dans un fichier externe. Si cette approche vous convient et que vous cela ne vous embte pas dutiliser lAPI C pour en bnficier, vous pouvez faire la mme chose. Voir le paragraphe Intgrer du Perl au chapitre 21, Mcanismes internes et accs externes pour apprendre comment accder Perl depuis une infrastructure C lentourant. Si vous ne voulez pas prendre cette route ou si vous avez dautres besoins, vous disposez alors de plusieurs options. Au lieu dalimenter immdiatement linterprteur Perl avec les codes dopration issus du compilateur Perl, vous pouvez invoquer lune des nombreuses autres sorties (backends). Ces sorties peuvent srialiser et stocker les codes dopration compils dans un fichier externe ou mme les convertir en deux varits diffrentes de code C. Merci de bien prendre conscience que les gnrateurs de code sont tous des utilitaires extrmement exprimentaux qui ne devraient pas esprer fonctionner dans un environnement de production. En fait, ils ne devraient mme pas esprer fonctionner dans un environnement de non-production, sauf peut-tre une fois tous les 36 du mois. Maintenant que nous avons assez rabaiss vos illusions pour que toute russite les surpasse ncessairement, nous pouvons vous parler en toute scurit du fonctionnement des sorties du compilateur. Certains des modules de sortie (backend) sont des gnrateurs de code, comme B::Bytecode, B::C et B::CC. Les autres sont rellement des analyseurs de code et des outils de

7. Avec une exception jusquici : la version 5.6.0 de Perl peut cloner des interprteurs dans limplmentation de lmulation de fork sur Microsoft Windows. Il pourrait bien y avoir une API Perl pour les ithreads , comme on les appelle, au moment o vous lirez ceci.

customer_8566

Gnrateurs de code

447

dbogage, comme B::Deparse, B::Lint et B::Xref. Au-del de ces sorties, la distribution standard inclut plusieurs autres modules de bas niveau dun intrt potentiel pour ceux dsirant devenir auteurs doutils Perl de dveloppement de code. Dautres modules de sortie peuvent tre trouvs sur CPAN, comprenant (au moment ou ces lignes sont crites) B::Fathom, B::Graph, B::JVM::Jasmin et B::Size. Lorsque vous utilisez le compilateur Perl pour autre chose que lalimentation de linterprteur, le module O (cest--dire en utilisant le fichier O.pm) se tient entre le compilateur et les modules de sorties varis. Vous nappelez pas les sorties directement : vous appelez plutt la partie intermdiaire, qui son tour appelle la sortie dsigne. Ainsi, si vous aviez un module appel B::Backend, vous linvoqueriez dans un script donn de cette manire :
% perl -MO=Backend NOM_SCRIPT

Certaines sorties prennent des options, spcifies comme ceci :


% perl -MO=Backend OPTS NOM_SCRIPT

Certaines sorties ont dj leur propre frontal pour invoquer leurs parties intermdiaires pour vous afin que vous nayez pas vous souvenir de leur M.O. En particulier, perlcc(1) invoque ce gnrateur de code, qui peut tre encombrant lancer.

Gnrateurs de code
Les trois sorties actuelles qui convertissent des codes dopration Perl en un autre format sont toutes emphatiquement exprimentales. (Oui, nous lavons dj dit mais nous ne voulons pas que vous loubliiez.) Mme lorsquil arrive quils produisent en sortie quelque chose qui se lance correctement, les programmes rsultants peuvent prendre plus despace disque, plus de mmoire et plus de temps CPU quils ne le feraient dordinaire. Ceci est un sujet encore en recherche et dveloppement. Les choses vont samliorer.

Le gnrateur de bytecode
Le module B::Bytecode crit les codes dopration de larbre syntaxique dans un encodage indpendant de la plate-forme. Vous pouvez prendre un script Perl compil en bytecode et copier cela sur une autre machine o Perl est install. La commande standard, bien quactuellement exprimentale, perlcc(1) sait comment convertir du code source Perl en un programme Perl compil en bytecode. Tout ce que vous devez faire est :
% perlcc -B script_src > script_pby

Et vous devriez maintenant tre capable d excuter directement le script_pby rsultant. Le dbut de ce fichier ressemble quelque chose comme ceci :
#!/usr/bin/perl use ByteLoader 0.04; PLBCi386-linux^@0.04^@^D^@^@^@^D^@^@^@0x1234^@^G ^C^@^@^@^@^F^A^C^A^@^@^@^G^@^C^B^@^@^@^G^@^C^C^@^@^@^G^@^C^D^ ^@^@^G^@^C^E^@^@^@^G^@^C^F^@^@^@^G^@^C^G^@^@^@^G^@^C^H^@^@^@^ ...

customer_8566

448

Chapitre 18 Compilation

Vous devriez trouver un petit en-tte de script suivit par des donnes purement binaires. Cela peut ressembler de la pure magie mais son mystra, heu. . . mystre nest pas trs puissant. Le module ByteLoader utilise une technique appele filtre de source pour altrer le code source avant que Perl nait une chance de le voir. Un filtre de source est un genre de prprocesseur sappliquant tout ce qui se trouve en dessous de lui dans le fichier courant. Au lieu dtre limit des transformations simplistes comme les prprocesseurs de macros comme le sont cpp(1) et m4(1), il ny a ici aucune limitation. Les filtres de source ont t utiliss pour enrichir la syntaxe de Perl, pour compresser ou crypter du code source et mme pour crire des programmes Perl en latin. E perlibus unicode; cogito, ergo substr; carp dbm, et al. Heu, avertissement du scriptor, dsol, du scribe latin. Le module ByteLoader est un filtre de source qui sait comment dsassembler les codes dopration srialiss pour reconstruire larbre syntaxique original. Le code Perl reconstitu est intgr dans larbre syntaxique actuel sans utiliser le compilateur. Lorsque linterprteur rencontre ces codes dopration, il na qu les excuter comme sils taient ici depuis toujours, nattendant que a.

Les gnrateurs de code C


Les autres gnrateurs de codes, B::C et B::CC, produisent tous deux du code C au lieu de codes dopration Perl srialiss. Le code quils gnrent est loin dtre lisible et si vous essayez de le lire, vous risquez de devenir aveugle. Ce nest pas quelque chose que vous pouvez utiliser pour insrer quelques morceaux de code Perl traduit en C dans un programme C plus vaste. Pour faire cela, voir le chapitre 21. Le module B::C ne fait qucrire les structures de donnes C ncessaires pour recrer lenvironnement dexcution Perl complet. Vous obtenez un interprteur Perl ddi avec toutes les structures de donnes internes prinitialises. En un certain sens, le code gnr ressemble celui que produit B::Bytecode. Les deux sont une traduction littrale des arbres de codes dopration que construit le compilateur mais l o B::Bytecode les laisse sous forme symbolique pour tre recrs plus tard et branchs dans un interprteur Perl dj lanc, B::C laisse ces codes dopration en C. Lorsque vous compilez ce code C avec votre compilateur C et que vous faites ldition de liens avec la bibliothque Perl, le programme rsultant naura pas besoin dun interprteur Perl install sur le systme cible. (Il pourra cependant avoir besoin de bibliothques partages, si vous navez pas fait une dition de liens statique pour tous les objets.) Cependant, ce programme nest pas vraiment diffrent de linterprteur Perl normal qui lance votre script. Il est seulement pcompil dans une image excutable de manire isole. Le module B::CC essaie toutefois den faire plus. Le dbut du fichier source C quil gnre ressemble un peu ce que produit B::C8 mais, ventuellement, toute ressemblance sarrte l. Dans le code de B::C, vous avez une norme table de codes dopration en C qui est manipule exactement de la mme manire que linterprteur laurait fait tout seul, alors que dans le code C gnr par B::CC est prsent dans lordre correspondant au f lux dexcution de votre programme. Il possde mme une fonction C correspon8. Mais alors, comme cest le cas pour tout, une fois que vous tes devenu aveugle. Est-ce que nous ne vous avions pas prvenu de ne pas jeter de coup dil ?

customer_8566

Outils de dveloppement de code

449

dant chaque fonction de votre programme. Une certaine quantit doptimisations bases sur le type des variables est accomplie ; quelques benchmarks peuvent tourner deux fois plus vite que dans linterprteur standards. Ceci est le plus ambitieux des gnrateurs de code actuels, celui qui reprsente le plus grand espoir pour lavenir. Et ce nest pas une concidence si cest galement le moins stable des trois. Les tudiants en informatique recherchant des projets de thse nont pas besoin de chercher ailleurs. Il y a ici une montagne de diamants attendant dtre affins.

Outils de dveloppement de code


Le module O possde de nombreux modi operandi intressants autres que lalimentation des gnrateurs de codes dsesprment exprimentaux. En fournissant un accs relativement indolore la sortie du compilateur Perl, ce module facilite lcriture dautres outils ayant besoin de tout savoir propos dun programme Perl. Le module B::Lint est ainsi baptis daprs lint(1), le vrificateur de programmes C. Il inspecte les programmes la recherche de constructions douteuses qui garent souvent les dbutants mais qui, normalement, ne dclenchent pas davertissements. Appelez le module directement :
% perl -MO=Lint,all mon_prog

Seules quelques vrifications sont actuellement dfinies, comme lemploi dun tableau dans un contexte scalaire implicite, le fait de se fier des variables par dfaut et laccs des identificateurs dun autre paquetage, commenant par _ (normalement privs). Voir B::Lint(3) pour plus de dtails. Le module B::Xref gnre des listes avec les rfrences croises des dclarations et des utilisations de toutes les variables ( la fois globales et de porte lexicale), de tous les sous-programmes et des tous les formats dans un programme, rpartis par fichier et par sous-programme. Appelez le module de cette manire :
% perl -MO=Xref mon_prog > mon_prog.pxref

Voici, par exemple, un extrait de compte-rendu :


Subroutine analyse_argv Package (lexical) $allume i113, 114 $opt i113, 114 %config_getopt i107, 113 @args_config i112, 114, 116, 116 Package Getopt::Long $ignorecase 101 &GetOptions &124 Package main $Options 123, 124, 141, 150, 165, 169 %$Options 141, 150, 165, 169 &verifie_lecture &167 @ARGV 121, 157, 157, 162, 166, 166

Ceci montre que la routine analyse_argv avait quatre variables lexicales propres ; elle accdait galement des identificateurs globaux des paquetages main et Getopt::Long.

customer_8566

450

Chapitre 18 Compilation

Les nombres reprsentent les lignes o llment en question a t utilis : un i au dbut, indique que cet lment est utilis pour la premire fois ce numro de ligne et un & au dbut signifie quun sous-programme a t appel ici. Les drfrences sont listes sparment, cest pourquoi figurent la fois $Options et %$Options. B::Deparse est un module offrant un affichage agrable (pretty printer) pouvant dmystifier du code Perl et vous aidez comprendre quelles transformations loptimisateur a effectu sur votre code. Par exemple, ceci montre les valeurs utilises par dfaut par Perl pour diverses constructions :
% perl -MO=Deparse -ne for (1 .. 10) { print if -t } LINE: while (defined($_ = <ARGV>)) { foreach $_ (1 .. 10) { print $_ if -t STDIN; } }

Loption -p ajoute des parenthses pour que vous puissiez voir lide que Perl se fait de la prsance :
% perl -MO=Deparse,-p -e print $a ** 3 + sqrt(2) / 10 ** -2 ** $c print((($a ** 3) + (1.4142135623731 / (10 ** (-(2 ** $c))))));

Vous pouvez utiliser -q pour voir en quelle oprations lmentaires les chanes interpoles sont compiles :
% perl -MO=Deparse,-q -e "Un $nom et quelques @ARGV\n" Un . $nom . et quelques . join($", @ARGV) . "\n";

Et ceci montre comment Perl compile vraiment une boucle for avec trois arguments en une boucle while :
% perl -MO=Deparse,-x3 -e for ($i=0;$i<10;$i++) { $x++ } $i = 0; while ($i < 10) { ++$x; } continue { ++$i }

Vous pouvez mme appeler B::Deparse sur un fichier de bytecode Perl produit par perlcc -B et B::Deparse le dcompile alors pour vous. Cependant, lire des codes dopration Perl srialiss est peut-tre un jeu denfant mais ce nest pas le cas lorsquil sagit dun cryptage lev.

Compilateur davant-garde, interprteur rtro


Il y a un temps pour penser tout ; parfois ce temps est derrire nous et parfois il est devant. Parfois il se situe entre les deux. Perl ne prtend pas savoir quand penser, il offre donc au programmeur un certain nombre doptions pour quil lui dise quand il faut penser. Dautres fois, il sait quune certaine sorte de pense est ncessaire mais il na aucune ide de ce quil doit penser, il a donc besoin dun moyen de le demander votre programme. Votre programme rpond ce genre de questions en dfinissant des sousprogrammes avec des noms appropris ce que Perl essaie de trouver.

customer_8566

Compilateur davant-garde, interprteur rtro

451

Non seulement le compilateur peut appeler linterprteur lorsquil veut avancer dans sa pense mais linterprteur peut galement appeler le compilateur en retour lorsquil veut rviser lhistoire. Votre programme peut utiliser plusieurs oprateurs pour rappeler le compilateur. Comme le compilateur, linterprteur peut galement appeler des sous-programmes nomms lorsquil veut se renseigner sur certaines choses. cause de tous ces changes entre le compilateur, linterprteur et votre programme, vous devez tre conscient des choses qui se passent et quand elles se passent. Nous parlerons tout dabord du moment o les sous-programmes nomms sont dclenchs. Au chapitre 10, Paquetages, nous avons vu comment un sous-programme AUTOLOAD dun paquetage tait dclench lorsquune fonction indfinie dans ce paquetage tait appele. Au chapitre 12, Objets, nous avons fait connaissance avec la mthode DESTROY qui est invoque lorsque la mmoire occupe par un objet est sur le point dtre rcupre par Perl. Enfin au chapitre 14, Variables lies, nous avons abord plusieurs fonctions appeles implicitement lorsquon accdait une variable lie. Ces sous-programmes suivent tous la convention selon laquelle, si un sous-programme est dclench automatiquement par le compilateur ou linterprteur, nous crivons son nom en majuscules. Associs avec les diffrentes tapes de la vie de votre programme, il existe quatre autres sous-programmes de ce type, appels BEGIN, CHECK, INIT et END. Le mot-cl sub est optionnel devant leurs dclarations. Peut-tre devraient-ils tre plutt appels blocs car dune certaine manire ils ressemblent plus des blocs nomms qu de vritables sous-programmes. Par exemple, au contraire des sous-programmes ordinaires, il ny a aucun mal dclarer ces blocs plusieurs fois, puisque Perl garde une trace du moment o les appeler, vous navez donc pas les appeler par leur nom. (Ils se diffrencient galement des sous-programmes ordinaires en ce que shift et pop se comportent comme si vous tiez dans le programme principal et manipulent donc @ARGV par dfaut et non @_.) Ces quatre types de blocs sexcutent dans cet ordre : BEGIN Sexcute ASAP (as soon as parsed9) chaque fois quon les rencontre pendant la compilation et avant de compiler le reste du fichier. CHECK Sexcute lorsque la compilation est acheve mais avant que le programme ne dmarre. (CHECK peut vouloir dire checkpoint (point de contrle) ou doublecheck (double vrification) ou mme simplement stop .) INIT Sexcute au dbut de lexcution, juste avant que le f lux principal de votre programme ne commence. END Sexcute la fin de lexcution, juste aprs que le programme a fini.

9. N.d.T. : ds que parss, analyss, jeu de mot avec la signification habituelle dASAP : as soon as possible, ds que possible.

customer_8566

452

Chapitre 18 Compilation

Si vous dclarez plus dun de ces blocs avec le mme nom, mme dans des modules spars, les BEGIN sexcutent tous avant les CHECK, qui eux-mmes sexcutent tous avant les INIT, qui leur tour sexcutent tous avant les END qui finalement sont les derniers sexcuter avant de mourir, aprs que votre programme a fini. De multiples BEGIN et INIT sexcutent dans lordre dans lequel ils ont t dclars (FIFO, first in, first out : premier arriv, premier servi) et les CHECK et END sexcutent dans lordre inverse dans lequel ils ont t dclars (LIFO, last in, first out : dernier arriv, premier servi). Ceci est probablement plus clair avec une dmonstration :
#!/usr/bin/perl -l print "dmarre lexcution principale ici\n"; die "lexcution principale meurt ici\n"; die "XXX: jamais atteint\n"; END { print "1er END: fini dexcuter" } CHECK { print "1er CHECK: fini de compiler" } INIT { print "1er INIT: commence excuter" } END { print "2me END: fini dexcuter" } BEGIN { print "1er BEGIN: toujours en train de compiler" } INIT { print "2me INIT: commence excuter" } BEGIN { print "2me BEGIN: toujours en train de compiler" } CHECK { print "2me CHECK: fini de compiler" } END { print "3me END: fini dexcuter" }

Lorsquil sexcute, ce programme de dmonstration affiche ceci :


1er BEGIN: toujours en train de compiler 2me BEGIN: toujours en train de compiler 2me CHECK: fini de compiler 1er CHECK: fini de compiler 1er INIT: commence excuter 2me INIT: commence excuter dmarre lexcution principale ici lexcution principale meurt ici 3me END: fini dexcuter 2me END: fini dexcuter 1er END: fini dexcuter

Puisquun bloc BEGIN sexcute immdiatement, il peut entrer dans les dclarations, les dfinitions et les importations de sous-programmes avant mme que le reste du fichier ne soit compil. Ceci peut altrer la manire dont le compilateur analyse le reste du fichier courant, tout particulirement si vous importez des dfinitions de sous-programmes. Du moins, dclarer un sous-programme lui permet dtre utilis comme un oprateur de liste, rendant les parenthses optionnelles. Si le sous-programme import est dclar avec un prototype, les appels ce sous-programme peuvent tre analyss comme les fonctions internes et peuvent mme supplanter les fonctions internes du mme nom afin de leur donner une smantique diffrente. La dclaration use nest quun bloc BEGIN qui sy croit. Les blocs END, par contraste, sexcutent aussi tard que possible : lorsque votre programme quitte linterprteur Perl, mme si cest le rsultat dun die non intercept ou dune autre exception fatale. Il existe deux situations dans lesquelles un bloc END (ou une mthode DESTROY) est court-circuit. Il ne sexcute pas si, au lieu de se terminer, le proces-

customer_8566

Compilateur davant-garde, interprteur rtro

453

sus courant se mtamorphose dun programme un autre via exec. Un processus balay de la surface de la terre par un signal non intercept court-circuite galement ses routines END. (Voir le pragma use sigtrap dcrit au chapitre 31, Modules de pragmas, pour un moyen facile de convertir les signaux interceptables en exceptions. Pour des informations gnrales sur les signaux, voir la section Signaux au chapitre 16, Communication inter-processus.) Pour viter le traitement de tous les END, vous pouvez appeler POSIX::_exit ou faire un kill -9, $$ ou simplement exec de nimporte quel programme inoffensif, comme /bin/true sur les systmes Unix. lintrieur dun bloc END, $? contient le statut avec lequel le programme va sortir en faisant exit. Vous pouvez modifier $? depuis lintrieur du bloc END pour changer la valeur de sortie du programme. Faites attention au changement accidentel de $? en lanant un autre programme avec system ou des apostrophes inverses. Si vous avez plusieurs blocs END lintrieur dun fichier, ils sexcutent dans lordre inverse de leur dfinition. Cest--dire que le dernier bloc END dfini est le premier sexcuter lorsque votre programme a fini. Cette inversion permet aux blocs BEGIN et END correspondants dtre imbriqus comme vous le souhaiteriez, si vous les aviez associs par paires. Par exemple, si le programme principal et un module quil charge ont leur propre paire de sous-programmes BEGIN et END, comme ceci :
BEGIN { print "le programme principal a commenc" } END { print "le programme principal a fini" } use Module;

et dans ce module, vous avez ces dclarations :


BEGIN { print "le module a commenc" } END { print "le module a fini" }

alors le programme principal sait que son BEGIN arrivera toujours en premier et son END toujours en dernier. (Oui, BEGIN est vraiment un bloc la compilation mais des arguments identiques sappliquent des paires de blocs INIT et END lexcution.) Ce principe est vrai rcursivement pour tout fichier qui en inclut un autre lorsque les deux ont des dclarations comme celles-ci. Cette proprit dimbrication implique que ces blocs fonctionnent bien en tant que constructeurs et destructeurs. Chaque module peut avoir ses propres fonctions dinitialisation et de dmolition que Perl appellera automatiquement. De cette manire, le programmeur na pas se se rappeler si une bibliothque particulire est utilise, ni quelle initialisation spciale ou quel code de nettoyage doit tre invoqu, ni quand linvoquer. Les dclarations du module soccupent de ces vnements. Si vous pensez un eval CHANE comme un rappel (cest--dire, un appel en arrire) du compilateur par linterprteur, alors vous pourriez penser un BEGIN comme un appel en avant de linterprteur par le compilateur. Les deux suspendent temporairement lactivit et basculent le mode dopration. Lorsque nous disons quun bloc BEGIN sexcute aussi tt que possible, nous voulons dire quil sexcute ds quil est compltement dfini, avant mme que le reste du fichier qui le contient ne soit analys. Les blocs BEGIN sont par consquent excuts la compilation, jamais lexcution. Une fois quun bloc BEGIN sest excut, il devient immdiatement indfini et le code quil a utilis est renvoy lespace mmoire de Perl. Vous ne pourriez pas appeler un bloc BEGIN comme un sous-programme mme si vous essayiez car lheure o vous le feriez, il serait dj parti.

customer_8566

454

Chapitre 18 Compilation

De mme que les blocs BEGIN, les blocs INIT sexcutent juste avant que lexcution de Perl ne commence, dans un ordre FIFO ( first in, first out : premier arriv, premier servi). Par exemple, les gnrateurs de codes documents dans perlcc utilisent des blocs INIT pour initialiser et rsoudre les pointeurs vers les XSUB. Les blocs INIT sont vraiment comme les blocs BEGIN, sauf quils permettent au programmeur de distinguer les constructions qui se droulent la compilation de celles qui se produisent lexcution. Lorsque vous lancez un script directement, ceci nest pas extrmement important car le compilateur est de toute faon invoqu chaque fois ; mais lorsque la compilation est spare de lexcution, la distinction peut devenir cruciale. Le compilateur peut ntre invoqu quune seule fois et lexcutable rsultant peut ltre plusieurs fois. De mme que les blocs END, les blocs CHECK sexcutent ds que la phase de compilation de Perl se finit mais avant que la phase dexcution ne commence, dans un ordre LIFO (last in, first out : dernier arriv, premier servi). Les blocs CHECK sont utiles pour librer le compilateur tout comme les blocs END sont utiles pour librer votre programme. En particulier, les sorties (backends) utilisent toutes des blocs CHECK comme le point partir duquel invoquer leurs gnrateurs de code respectifs. Tout ce quelles ont besoin de faire est de mettre un bloc CHECK dans leur propre module et il sexcutera au moment appropri, vous navez donc pas installer de CHECK dans votre programme. Pour cette raison, vous ncrirez que trs rarement un bloc CHECK vous-mme, moins que vous ncriviez de tels modules. Rcapitulant tout ceci, le tableau 18-1 numre les diverses constructions en dtaillant le moment o elles compilent le code reprsent par . . . et celui o elles lexcutent. Tableau 18-1.
Bloc ou expression use ... no ... BEGIN {...} CHECK {...} INIT {...} END {...} eval {...} eval "..." truc(...) sub truc {...} eval "sub {...}" s/motif/.../e s/motif/"..."/ee Compile Capture les pendant la erreurs de phase de compilation C C C C C C C E C C E C E Non Non Non Non Non Non Non Oui Non Non Oui Non Oui Excute Capture les pendant la erreurs phase de dexcution C C C C E E E E E E E E E Non Non Non Non Non Non Oui Oui Non Non Non Non Oui Politique de dclenchement dappel Maintenant Maintenant Maintenant Tard Tt Tard Inclus (inline) Inclus (inline) Inclus (inline) Appel nimporte quand Appel plus tard Inclus (inline) Inclus (inline)

Maintenant que vous connaissez la partition, nous esprons que vous serez capable de composer et de jouer vos morceaux de Perl avec plus dassurance.

customer_8566

Linterface de la ligne de commande


Ce chapitre montre comment faire pointer Perl dans la bonne direction avant douvrir le feu avec. Il existe diverses faon de faire viser Perl mais les deux moyens primaires sont par le biais doptions (switches) dans la ligne de commande et par le biais de variables denvironnement. Les options sont le moyen le plus immdiat et le plus prcis dajuster une commande particulire. Les variables denvironnement sont plus souvent employes pour mettre en place la politique globale.

19

Traitement des commandes


Il est heureux que Perl se soit dvelopp dans le monde Unix, car cela signifie que sa syntaxe dappel fonctionne assez bien sous les interprteurs de commandes des autres systmes dexploitation. La plupart des interprteurs de commandes savent comment traiter une liste de mots en arguments, et ne voient pas dinconvnient ce quun argument commence par un signe moins. Bien entendu, il existe cependant quelques cas o vous vous faites piger lorsque vous passez dun systme lautre. Vous ne pouvez pas utiliser les apostrophes sous MS-DOS comme vous le faites sous Unix, par exemple. Et sur les systmes comme VMS, il est ncessaire demployer un emballage logiciel (wrapper) sautant travers divers cerceaux pour muler lindirection des entres/sorties dUnix. Nous posons notre joker quant linterprtation des jokers (wildcards). Mais une fois ces problmes rsolus, Perl traite ses options et ses arguments peu prs de la mme manire sur nimporte quel systme dexploitation. Mme lorsque vous ne disposez pas dun interprteur de commandes per se, il est assez facile dexcuter un programme Perl depuis un autre programme, crit dans nimporte quel langage. Le programme appelant peut non seulement passer des arguments de la manire traditionnelle, mais il peut galement passer des informations via des variables denvironnement et, si votre systme dexploitation limplmente, des descripteurs de fichiers hrits (voir Passage de handles de fichiers au chapitre 16, Communication inter-processus). Mme des mcanismes de passage dargument plus exotiques peuvent facilement tre encapsuls dans un module, amens ensuite dans votre programme Perl via une simple directive use.

customer_8566

456

Chapitre 19 Linterface de la ligne de commande

Perl analyse les options de la ligne de commande de la manire standard.1 Cest--dire quil sattend ce que les options (les mots commenant par un moins) viennent en premier sur la ligne de commande. Le nom du script vient gnralement ensuite, suivi par les arguments additionnels passer au script. Certains de ces arguments supplmentaires peuvent eux-mmes ressembler des options, auquel cas ils doivent tre traits par le script car Perl abandonne lanalyse des options ds quil voit une non-option, ou loption spciale -- qui vaut dire Je suis la dernire option . Perl vous procure une certaine souplesse en ce qui concerne ce que vous fournissez au programme. Pour les petites tches rapides et brouillonnes, vous pouvez programmer Perl entirement depuis la ligne de commande. Pour les travaux plus importants, plus permanents, vous pouvez fournir un script Perl dans un fichier spar. Perl recherche compiler et lancer un script que vous pouvez spcifier avec lune de ces trois manires : 1. Spcifi ligne par ligne via des options -e sur la ligne de commande. Par exemple :
% perl -e "print Salut, tout le monde." Salut, tout le monde.

2. Contenu dans le fichier spcifi par le premier nom de fichier sur la ligne de commande. Les systmes supportant la notation #! sur la premire ligne dun script excutable invoquent les interprteurs de cette faon votre insu. 3. Pass implicitement via lentre standard. Cette mthode ne fonctionne que sil ny a pas de noms de fichier en argument ; pour passer des arguments un script en entre standard, vous devez utiliser la mthode 2, spcifier explicitement un - pour le nom du script. Par exemple :
% echo "print qq(Salut, @ARGV.)" | perl - tout le monde Salut, tout le monde.

Avec les mthodes 2 et 3, Perl commence par analyser le fichier dentre depuis le dbut moins davoir spcifi loption -x, ce qui lui fait rechercher la premire ligne commenant par #! contenant le mot perl , do il dmarre. Cela sert lancer un script inclus dans un message plus grand. En ce cas, vous pourriez indiquer la fin du script par le token __END__. Que vous utilisiez ou non -x, la ligne #! est toujours examine pour y trouver des options au moment de lanalyse syntaxique de la ligne. Ainsi, si vous vous trouvez sur une plate-forme qui nautorise quun argument sur la ligne #! ou pis, qui ne reconnat mme pas la ligne #! comme tant spciale, vous pouvez toujours conserver un comportement cohrent des options quelle que soit la manire dont Perl est invoqu, mme si -x a t utilis pour trouver le dbut du script. Attention : comme les versions plus anciennes dUnix interrompent sans rien dire linterprtation par le noyau de la ligne #! aprs 32 caractres, certaines options peuvent traiter votre programme correctement ou non ; vous pourriez mme obtenir un - sans sa lettre, si vous ntes pas prudent. Assurez-vous que tous vos scripts tombent avant ou aprs cette limite de 32 caractres. La plupart des options ne se soucient pas dtre traites plusieurs fois mais un - au lieu dune option complte pousserait Perl essayer de lire son code source depuis lentre standard plutt que depuis votre script. Et

1. En supposant que vous tes daccord avec le fait quUnix soit standard et manir.

customer_8566

Traitement des commandes

457

une option -I tronque pourrait galement provoquer des rsultats tranges. Toutefois, certaines options tiennent compte du fait quelles soient traites deux fois, comme les combinaisons de -l et de -0. Mettez toutes les options aprs la limite de 32 caractres (le cas chant) ou remplacez lemploi de -0CHIFFRES par BEGIN{$/ = "\0CHIFFRES";}. videmment, si vous ntes pas sur un systme UNIX, vous tes sr de ne pas avoir ce genre de problme. Lanalyse des options sur la ligne #! dmarre aprs que perl est mentionn pour la premire fois. Les squences -* et - sont spcifiquement ignores au bnfice des utilisateurs demacs et, si vous vous en sentez lenvie, vous pouvez crire :
#!/bin/sh -- # -*- perl -*- -p eval exec perl $0 -S ${1+"$@"} if 0;

et Perl ne verra que loption -p. La jolie squence -*- perl -*- indique emacs de dmarrer en mode Perl ; elle nest pas ncessaire si vous nutilisez pas emacs. Le sale -S est expliqu plus loin dans la description de cette option. Une astuce identique met en jeu le programme env(1), si vous en disposez :
#!/usr/bin/env perl

Les exemples prcdents utilisent un chemin relatif jusqu linterprteur Perl, obtenant ainsi la version trouve en premier dans le chemin de lutilisateur. Si vous voulez une version particulire de Perl, crivez, perl5.6.1 et placez ceci directement dans le chemin de la ligne #!, soit avec le programme env, soit avec le sale -S, soit avec un traitement ordinaire de #!. Si la ligne #! ne contient pas le mot perl , le programme cit aprs le #! est excut la place de linterprteur Perl. Par exemple, supposons que vous ayez ici un script ordinaire pour le Bourne shell qui dirait :
#!/bin/sh echo "Je suis un script shell"

Si vous donnez ce fichier Perl, celui-ci lancera /bin/sh pour vous. Cest un peu bizarre, mais cela facilite la vie ceux dont les machines ne reconnaissent pas #!, parce quils peuvent en positionnant leur variable denvironnement SHELL indiquer un programme (comme un gestionnaire de courrier) que leur shell est /usr/bin/perl et Perl enverra le programme linterprteur qui leur convient, mme si leur noyau est trop stupide pour le faire tout seul. Mais revenons aux scripts Perl qui sont vraiment des scripts Perl. Aprs avoir localis votre script, Perl compile le programme complet sous une forme interne (voir le chapitre 18, Compilation). Sil y a une erreur de compilation, lexcution du script nest mme pas lance. (Au contraire du script shell typique ou du fichier de commande, qui pourrait sexcuter partiellement avant de trouver une erreur de syntaxe.) Si le script est syntaxiquement correct, il est excut. Sil arrive la fin sans avoir rencontr un oprateur exit ou die, un exit(0) implicite est fourni par Perl pour indiquer le succs de lopration celui qui vous appelait. (Au contraire du programme C typique, o vous tes susceptible dobtenir un statut de sortie alatoire si votre programme ne fait que se terminer de la manire normale.)

customer_8566

458

Chapitre 19 Linterface de la ligne de commande

#! et isolement (quotation) sur les systmes non-Unix


La technique #!, propre Unix, peut tre simule sur dautres systmes : Macintosh Un programme Perl sur Macintosh aura la paire Type/Creator approprie, de faon ce quun double clic invoque lapplication Perl. MS-DOS Crez un fichier batch pour lancer votre programme et codifiez-le dans ALTERNATIVE_SHEBANG. Voir le fichier dosish.h dans les sources de la distribution Perl pour plus dinformations ce sujet. OS/2 Ajoutez cette ligne :
extproc perl -S -vos_options

en tant que premire ligne des fichiers *.cmd (-S contourne un bogue dans la manire dont cmd.exe gre extproc ). VMS Mettez ces lignes :
$ perl -mesopt f$env("procedure") p1 p2 p3 p4 p5 p6 p7 p8 ! $ exit++ + ++$status != 0 and $exit = $status = undef;

au dbut de votre programme, o -mesopt reprsente toutes les options de ligne de commande que vous voulez passer Perl. Vous pouvez dsormais invoquer le programme directement en tapant perl programme, en tant que procdure DCL en disant @programme ou implicitement via DCL$PATH en utilisant juste le nom du programme. Cette incantation est un peu difficile mmoriser mais Perl laffichera pour vous si vous tapez perl "-V:startperl". Si vous narrivez pas vous souvenir de a h bien, cest la raison pour laquelle vous avez achet ce livre. Win?? Lorsque vous utilisez la distribution ActiveState de Perl, sous certaines variantes de la suite de systmes dexploitation Windows de Microsoft (cest--dire, Win95, Win98, Win00,2 WinNT, mais pas Win3.1), la procdure dinstallation de Perl modifie la base de registre de Windows pour associer lextension .pl avec linterprteur Perl. Si vous installez un autre portage de Perl, y compris celui du rpertoire Win32 de la distribution de Perl, vous devrez alors modifier vous-mme la base de registre de Windows. Remarquez que lutilisation dune extension .pl implique que vous ne pourrez plus faire la diffrence entre un programme excutable Perl et un fichier de bibliothque Perl ( perl library ). Vous pourriez plutt utiliser .plx pour un programme Perl afin dviter ceci. Ce nest plus trs ennuyeux aujourdhui que la plupart des modules Perl se trouvent dans des fichiers .pm.
2. Heu, veuillez excuser ces problmes techniques...

customer_8566

Traitement des commandes

459

Les interprteurs de commandes les systmes non-Unix ont des ides extraordinairement diffrentes des shells Unix concernant lisolement (quoting). Il vous faudra apprendre quels sont les caractres spciaux de votre interprteur de commandes (on trouve couramment *, \ et ") et comment protger les espaces et ces caractres spciaux pour lancer des scripts sur une seule ligne (one-liners) via loption -e. Vous pourriez galement avoir changer un seul % en %% ou le protger avec une squence dchappement, sil sagit dun caractre spcial pour votre shell. Sur certains systmes, vous devrez peut-tre changer les apostrophes en guillemets. Mais ne faites pas cela sur les systmes Unix ou Plan9 ou nimporte quel systme o tourne un shell la Unix, comme les systmes du MKS Toolkit ou du paquetage Cygwin produit par les gens de chez Cygnus, appartenant maintenant Redhat. Le nouvel mulateur dUnix, Interix, produit par Microsoft, commence galement devenir, hum, hum, intrixant. Par exemple, sur Unix et Mac OS X, utilisez :
% perl -e print "Salut tout le monde\n"

Sur Macintosh (avant MAC OS X), utilisez :


print "Salut tout le monde\n"

puis lancez Mon_script ou Shift-Command-R. Sur VMS, utilisez :


$ perl -e "print ""Salut tout le monde\n"""

ou encore, avec qq// :


$ perl -e "print qq(Salut tout le monde\n)"

Et sur MS-DOS, etc., utilisez :


A:> perl -e "print \"Salut tout le monde\n\""

ou utilisez qq// pour choisir vos propre caractres disolement :


A:> perl -e "print qq(Salut tout le monde\n)"

Le problme est quaucun de ces exemples nest fiable : cela dpend de linterprteur de commandes que vous utilisez. Si le shell tait 4DOS, ceci fonctionnerait probablement mieux :
perl -e "print <Ctrl-x>"Salut tout le monde\n<Ctrl-x>""

Le programme CMD.EXE dans Windows NT semble avoir rcupr beaucoup de fonctionnalits du shell standard Unix lorsque tout le monde avait le dos tourn mais essayez de trouver de la documentation sur ses rgles concernant lisolement (quoting rules) ! Sur Macintosh,3 tout ceci dpend de lenvironnement que vous utilisez. MPW, qui peut tre utilis comme un shell pour MacPerl, est trs proche des shells Unix pour son support de diffrentes variantes disolement, si ce nest quil utilise allgrement les caractres non ASCII de Macintosh comme caractres de contrle.

3. Du moins, sur les versions antrieures Mac OS X, qui, de manire assez heureuse, est un systme driv de BSD.

customer_8566

460

Chapitre 19 Linterface de la ligne de commande

Il ny a pas de solution gnrale tout ceci. Cest tout bonnement une belle pagaille. Si vous ntes pas sur un systme Unix mais que vous voulez faire des choses avec la ligne de commande, vous avez plus vite fait dacqurir un meilleur interprteur de commandes que celui que votre constructeur vous a fourni, ce qui ne devrait pas poser trop de difficults. Ou crivez le tout en Perl et oubliez les scripts sur une seule ligne.

Emplacement de Perl
Bien que cela puisse paratre vident, Perl nest utile que lorsque les utilisateurs peuvent facilement le trouver. Autant que possible, il est bon davoir la fois /usr/bin/perl et /usr/ local/bin/perl comme liens symboliques vers le vritable binaire. Si cela nest pas possible, les administrateurs systme sont fortement encourags mettre Perl et les utilitaires associs dans un rpertoire gnralement prsent dans le PATH standard dun utilisateur ou dans un quelconque autre endroit qui soit vident et pratique. Dans ce livre, nous utilisons la notation standard #!/usr/bin/perl sur la premire ligne dun programme, pour dsigner le mcanisme fonctionnant sur votre systme, quel quil soit. Si vous avez besoin de lancer une version particulire de Perl, utilisez un chemin spcifique :
#!/usr/local/bin/perl5.6.0

Si vous voulez juste utiliser une version au moins gale un certain numro de version mais que vous vous fichez des versions suprieures, placez une instruction telle que celle-ci vers le dbut de votre programme :
use v5.6.0;

(Remarque : les versions plus anciennes de Perl utilisaient des numros comme 5.005 ou 5.004_05. De nos jours, nous les verrions plutt comme 5.5.0 et 5.4.5 mais les versions de Perl antrieures 5.6.0 ne comprendraient pas cette notation.)

Options
Une option de la ligne de commande ne comportant quun seul caractre sans son argument peut toujours tre combine (relie) avec loption suivante.
#!/usr/bin/perl -spi.bak # comme -s -p -i.bak

Les options sont galement appeles des flags ou des drapeaux ou des switchs (au singulier switch). Peu importe le nom que vous leur donnez, voici celles que Perl reconnat : -Termine le traitement des options, mme si largument suivant commence par un moins. Il na aucun autre effet. -0NUM_OCT -0 Spcifie le sparateur denregistrements ($/) comme tant un nombre octal. Si NUM_OCT nest pas prsent, le sparateur est le caractre nul (cest--dire le caractre 0, soit "\0" en Perl). Dautres options peuvent prcder ou suivre le nombre octal.

customer_8566

Traitement des commandes

461

Par exemple, si vous disposez dune version de find(1) pouvant afficher les noms de fichier termins par le caractre nul, vous pouvez crire ceci :
% find . -name *.bak -print0 | perl -n0e unlink

La valeur spciale 00 fait que Perl lira les fichiers en mode paragraphe, ce qui est quivalent positionner la variable $/ "". La valeur 0777 fait que Perl gobera des fichiers entiers dun seul coup. Cela revient indfinir la variable $/. Nous employons 0777 puisquil nexiste pas de caractre ASCII de cette valeur. (Malheureusement, il existe un caractre Unicode de cette valeur, \N{LATIN SMALL LETTER O WITH STROKE AND ACUTE}, mais quelque chose nous dit que vous ne lutiliserez pas comme sparateur pour vos enregistrements.) -a Active le mode autosplit mais seulement lorsque cette option est utilise avec un -n ou un -p. Une commande split implicite est dabord excute sur le tableau @F dans la boucle while implicite produite par le -n ou le -p. Ainsi :
% perl -ane print pop(@F), "\n";

est quivalent :
while (<>) { @F = split( ); print pop(@F), "\n"; }

Un sparateur de champ diffrent peut tre spcifi en passant une expression rgulire pour split loption -F. Par exemple, ces deux appels sont quivalents :
% awk -F: $7 && $7 !~ /^\/bin/ /etc/passwd % perl -F: -lane print if $F[6] && $F[6] !~ m(^/bin) /etc/passwd

-c Fait vrifier par Perl la syntaxe du script avant de sortir sans excuter ce quil vient de compiler. Techniquement, Perl en fera un peu plus que a : il excutera tous les blocs BEGIN ou CHECK et toutes les directives use, puisque ceux-ci sont censs se produire avant lexcution du programme. Cependant, les blocs END ou INIT ne sont plus excuts. Lancien comportement, toutefois rarement utile, peut toujours tre obtenu en mettant :
BEGIN { $^C = 0; exit; }

la fin de votre script principal. -C Active lutilisation par Perl des API de caractres larges (wide-character) sur le systme cible, si elles sont implmentes (avec la version 5.6.0, cela ne fonctionne que sur les plates-formes Microsoft). La variable spciale ${^WIDE_SYSTEM_CALLS} ref lte ltat de cette option. -d Lance le script sous le dbogueur Perl. Voir le chapitre 20, Le dbogueur Perl. -d:MODULE Lance le script sous le contrle dun module de dbogage ou de traage install dans la bibliothque Perl sous le nom de Devel::MODULE. Par exemple, -d:DProf

customer_8566

462

Chapitre 19 Linterface de la ligne de commande

excute le script avec le profileur Devel::DProf. Voir galement le paragraphe sur le dbogage au chapitre 20. -DLETTRES -DNOMBRE Active les drapeaux de dbogage. (Ceci ne fonctionne que si le dbogage est compil dans votre Perl, comme dcrit ci-dessous.) Vous pouvez spcifier soit un NOMBRE valant la somme des bits dsirs, soit une liste de LETTRES. Pour voir comment il excute votre script, employez, par exemple, -D14 ou -Dslt. Une autre valeur utile est -D1024 ou -Dx, qui liste larbre syntaxique compil. Et -D512 ou -Dr affiche les expressions rgulires compiles. La valeur numrique est disponible en interne grce la variable spciale $^D. Le tableau 19-1 liste les valeurs de bits assignes : Tableau 19-1. Options de -D
Bit 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536 Lettre p s l t o c p m f r x u L H X D S Signification Mise en tokens et analyse syntaxique. Instantans de la pile. Traitement de la pile dtiquettes. Trace de lexcution. Rsolution des mthodes et des surcharges. Conversions chanes/numrique. Affichage des commandes de prprocesseur pour -P . Allocation mmoire. Traitements des formats. Analyse et excution dexpressions rgulires. Vidage mmoire (dump) de larbre syntaxique. Vrification du marquage. Fuites de mmoire (ncessite de compiler Perl avec -DLEAKTEST). Vidage mmoire (dump) de hachage usurpe values(). Allocation de mmoires de travail (scratchpad). Nettoyage. Synchronisation de threads.

Tous ces drapeaux exigent un excutable Perl ayant t spcialement compil pour le dbogage. Toutefois, comme ce nest pas le cas par dfaut, vous serez incapable dutiliser loption -D sauf si votre administrateur systme ou vous-mme avez compil cette version spciale de Perl pour le dbogage. Voir le fichier INSTALL dans le rpertoire des sources de Perl pour plus de dtails mais, pour rsumer, vous devez passer -DDEBUGGING votre compilateur C lorsque vous compilez Perl lui-mme. Ce drapeau est automatiquement positionn si vous incluez loption -g lorsque Configure vous pose des questions propos des drapeaux de loptimisateur et du dbogueur. Si vous essayez seulement dobtenir une impression de chaque ligne de code Perl au fur et mesure quil sexcute (de la mme manire que sh -x le fait pour les

customer_8566

Traitement des commandes

463

scripts shell), vous ne ne pouvez pas utiliser loption -D de Perl. la place, faites ceci :
# Syntaxe du Bourne shell $ PERLDB_OPTS="NonStop=1 AutoTrace=1 frame=2" perl -dS programme # Syntaxe de csh % (setenv PERLDB_OPTS "NonStop=1 AutoTrace=1 frame=2"; perl -dS programme)

Voir le chapitre 20 pour les dtails et dautres possibilits. -e CODE_PERL Peut tre utilis pour entrer une ou plusieurs lignes de script. Si -e est utilis, Perl ne cherchera pas le nom du programme dans la liste darguments. Largument CODE_PERL est trait comme sil se terminait par un saut de ligne, ainsi, plusieurs commandes -e peuvent tre donnes pour former un programme de plusieurs lignes. (Assurez-vous de mettre des points-virgules comme vous le feriez dans un programme normal stock dans un fichier.) Ce nest pas parce que -e fournit un saut de ligne chaque argument que vous devez utiliser plusieurs options -e ; si votre shell autorise lisolement (quoting) sur plusieurs lignes, comme sh, ksh ou bash, vous pouvez alors passer un script sur plusieurs lignes comme un seul argument de -e :
$ perl -e print "Salut, "; print "@ARGV !\n"; la compagnie Salut, la compagnie !

Avec csh, il vaut probablement mieux utiliser plusieurs options -e :


% perl -e print "Salut, "; \ -e print "@ARGV !\n"; la compagnie Salut, la compagnie !

Les sauts de ligne, quils soient implicites ou explicites, sont pris en compte dans la numrotation des lignes, ainsi, le second print se trouve la ligne 2 du script de -e, dans les deux cas. -FMOTIF Spcifie le motif selon lequel seffectue lclatement (split) lorsque le mode autosplit est activ via loption -a (sinon, na aucun effet). Le motif peut tre entour par des slash (//), des guillemets ("") ou des apostrophes (). Si ce nest pas le cas, il sera automatiquement mis entre apostrophes. Souvenez-vous que pour passer des apostrophes ou des guillemets disolement via un shell, vous devrez isoler ces apostrophes et la manire dont vous pouvez le faire dpend du shell. -h Affiche un rsum des options de ligne de commande de Perl. -iEXTENSION -i Spcifie que les fichiers traits par la construction <> doivent tre dits sur place. Ceci est ralis en renommant le fichier dentre, en ouvrant le fichier de sortie daprs le nom dorigine et en slectionnant ce fichier de sortie comme fichier par

customer_8566

464

Chapitre 19 Linterface de la ligne de commande

dfaut pour les appels print, printf et write.4 LEXTENSION est utilise pour modifier le nom de lancien fichier afin den faire une copie de sauvegarde. Si aucune EXTENSION nest fournie, aucune sauvegarde nest effectue et le fichier actuel est cras. Si lEXTENSION ne contient pas de *, la chane est alors ajoute la fin du nom de fichier actuel. Si lEXTENSION contient un ou plusieurs caractres *, chaque * est alors remplac par le nom du fichier actuellement en cours de traitement. En termes de Perl, vous pourriez penser ceci comme :
($sauvegarde = $extension) =~ s/\*/$nom_fichier/g;

Ceci vous permet dutiliser un prfixe pour le fichier de sauvegarde, au lieu ou mme en complment dun suffixe :
% perl -piorig_* -e s/truc/machin/ xyz # sauvegarde dans orig_xyz

Vous pouvez mme mettre les copies de sauvegarde des fichiers originaux dans un autre rpertoire ( condition que le rpertoire existe dj) :
% perl -piancien/*.orig -e s/truc/machin/ xyz # sauvegarde dans ancien/xyz.orig

Les scripts sur une seule ligne sont quivalents dans chaque paire :
% perl -pi -e s/truc/machin/ xyz % perl -pi* -e s/truc/machin/ xyz # crase le fichier actuel # crase le fichier actuel

% perl -pi.orig -e s/truc/machin/ xyz # sauvegarde dans xyz.orig % perl -pi*.orig -e s/truc/machin/ xyz # sauvegarde dans xyz.orig

Depuis le shell, crire :


% perl -p -i.orig -e "s/truc/machin/;"

revient au mme que dutiliser le programme :


#!/usr/bin/perl -pi.orig s/truc/machin/;

Ce qui est un raccourci pratique pour le programme minemment plus long :


#!/usr/bin/perl $extension = .orig; LIGNE: while (<>) { if ($ARGV ne $ancien_argv) { if ($extension !~ /\*/) { $sauvegarde = $ARGV . $extension; } else { ($sauvegarde = $extension) =~ s/\*/$ARGV/g; } unless (rename($ARGV, $sauvegarde)) { warn "impossible de renommer $ARGV en $sauvegarde : $!\n"; close ARGV; next; } open(ARGV_SORTIE, ">$ARGV");
4. Techniquement, il ne sagit pas vraiment dun dition sur place . Il sagit du mme nom de fichier, mais dun fichier physique diffrent.

customer_8566

Traitement des commandes


select(ARGV_SORTIE); $ancien_argv = $ARGV; } s/truc/machin/; } continue { print; # ceci crit dans le fichier de nom original } select(STDOUT);

465

Ce code un peu long est virtuellement identique au simple code sur une seule ligne avec loption -i, hormis le fait que la forme -i na pas besoin de comparer $ARGV $ancien_argv pour savoir quand le nom de fichier a chang. Mais elle utilise bien ARGV_SORTIE pour le handle de fichier slectionn et restaure, aprs la boucle, lancien STDOUT comme handle de fichier de sortie par dfaut. Comme le code cidessus, Perl cre le fichier de sauvegarde sans tenir compte du fait que la sortie ait rellement chang ou non. Voir la description de la fonction eof sans parenthses pour des exemples sur la manire de dtecter la fin de chaque fichier dentre, au cas o vous voudriez ajouter des lignes chaque fichier ou remettre zro la numrotation des lignes. Si, pour un fichier donn, Perl est incapable de crer le fichier de sauvegarde comme lEXTENSION le spcifie, il mettra un avertissement cet effet et continuera traiter les autres fichiers. Vous ne pouvez pas utiliser -i pour crer des rpertoires ou pour enlever des extensions des fichiers. Vous ne pouvez pas non plus lutiliser avec un ~ indiquant le rpertoire maison (home directory) ce qui est dautant mieux car certaines personnes aiment utiliser ce caractre pour leurs fichiers de sauvegarde :
% perl -pi~ -e s/truc/machin/ fichier1 fichier2 fichier3...

Enfin, loption -i narrte pas lexcution de Perl si aucun nom de fichier nest donn sur la ligne de commande. Lorsque cela arrive, aucune sauvegarde nest effectue puisquon ne peut pas dterminer quel est le fichier original et le traitement sapplique de STDIN vers STDOUT comme on pouvait sy attendre. -IREPERTOIRE Les rpertoires spcifis par -I sont ajouts au dbut de @INC, qui contient le chemin de recherche des modules. -I dit aussi au prprocesseur o il faut chercher les fichiers dinclusion. Le prprocesseur C est invoqu par -P ; il recherche par dfaut dans /usr/include et /usr/lib/perl. moins que vous ne soyez sur le point dutiliser le prprocesseur C (ce que quasiment plus personne ne fait), vous feriez mieux dutiliser la directive use lib dans votre script. Cependant, comme use lib, loption -I ajoute implicitement les rpertoires spcifiques la plate-forme. Voir use lib au chapitre 31, Modules de pragmas pour plus de dtails. -lNUM_OCT -l Active le traitement de fin de ligne automatique. Son effet est double : premirement, il fait automatiquement un chomp sur la terminaison de ligne quand il est employ avec -n ou -p et deuximement, il positionne $\ la valeur de NUM_OCT afin que toute instruction daffichage ajoute un terminateur de ligne de valeur

customer_8566

466

Chapitre 19 Linterface de la ligne de commande

ASCII NUM_OCT. Si NUM_OCT est omis, -l positionne $\ la valeur actuelle de $/, gnralement un saut de ligne. Par exemple, pour couper les lignes quatre-vingt colonnes, crivez ceci :
% perl -lpe substr($_, 80) = ""

Remarquez que laffectation $\ = $/ est faite lorsque loption est traite, le sparateur denregistrements dentre peut donc tre diffrent de celui de sortie si loption -l est suivie dune option -0 :
% gnufind / -print0 | perl -ln0e print "trouv $_" if -p

Cela positionne $\ la valeur saut de ligne, puis $/ au caractre nul. (Remarquez que 0 aurait t interprt comme faisant partie de loption -l sil avait suivi immdiatement le -l. Cest pourquoi nous avons insr loption -n entre les deux.) -m et -M Ces options chargent un MODULE comme si vous aviez excut un use, moins que vous nayez spcifi -MODULE au lieu de MODULE, auquel cas no est invoqu. Par exemple, -Mstrict est identique use strict, alors que -M-strict est identique no strict. -mMODULE Excute use MODULE() avant dexcuter votre script. -MMODULE -MMODULE... Excute use MODULE avant dexcuter votre script. La commande est forme par simple interpolation du reste de largument suivant le -M, vous pouvez donc isoler largument par des apostrophes pour ajouter du code supplmentaire aprs le nom du module, par exemple, -Mmodule qw(truc machin). -MMODULE=arg1,arg2... Un peu de sucre de syntaxe vous permet dcrire galement -Mmodule=truc,machin comme raccourci pour -Mmodule qw(truc machin). Cette possibilit dispense des apostrophes lorsquon importe des symboles. Le code rellement gnr par -Mmodule=truc,machin est :
use module split(/,/, q{truc,machin})

Remarquez que la forme avec = limine la distinction entre -m et -M, mais il vaut mieux utiliser la forme en majuscules pour viter toute confusion. Vous ne pouvez utiliser les options -M et -m que depuis une vritable invocation de Perl depuis la ligne de commande, non comme des options trouves sur la ligne #!. (H, si vous alliez le mettre dans un fichier, pourquoi ne pas simplement crire la place le use ou le no quivalent?) -n Pousse Perl se comporter comme si la boucle suivante encadrait le script, ce qui le fait itrer sur les noms de fichiers en argument la manire de sed -n ou de awk :
LINE: while (<>) { ... }

# le script vient ici

customer_8566

Traitement des commandes

467

Vous pouvez utiliser LINE (LIGNE en anglais) comme une tiquette de boucle depuis lintrieur de votre script, mme si vous ne pouvez pas voir la vritable tiquette dans votre fichier. Remarquez que les lignes ne sont pas affiches par dfaut. Voir -p pour ce faire. Voici un moyen efficace de dtruire tous les fichiers datant de plus dune semaine :
find . -mtime +7 -print | perl -nle unlink;

Cette opration est plus rapide que loption -exec de find(1) car vous navez pas lancer un processus chaque nom de fichier trouv. Par une concidence stupfiante, les blocs BEGIN et END peuvent tre utiliss pour prendre le contrle avant ou aprs la boucle implicite, exactement comme dans awk. -p Pousse Perl se comporter comme si la boucle suivante encadrait le script, ce qui le fait itrer sur les noms de fichier en argument la manire de sed :
LINE: while (<>) { ... # le script vient ici } continue { print or die "-p destination: $!\n"; }

Vous pouvez utiliser LINE (LIGNE en anglais) comme tiquette de boucle depuis lintrieur de votre script, mme si vous ne pouvez pas voir la vritable tiquette dans votre fichier. Si un fichier dsign par un argument ne peut pas tre ouvert pour une raison ou pour une autre, Perl vous en avertit et passe au fichier suivant. Remarquez que les lignes sont affiches automatiquement. Toujours par une concidence stupfiante, les blocs BEGIN et END peuvent tre utiliss pour prendre le contrle avant ou aprs la boucle implicite, exactement comme dans awk. -P Pousse votre script passer par le prprocesseur C avant la compilation par Perl. (Comme les commentaires et les directives de cpp(1) commencent tous par le caractre #, il vaut mieux viter de commencer les commentaires par des mots-cls du prprocesseur C comme if , else ou define .) Que vous utilisiez loption -P ou non, Perl accorde toujours de lattention aux directives #line pour contrler le numro de ligne et le nom de fichier, nimporte quel prprocesseur peut donc informer Perl sur de telles choses. Voir la section Gnrer du Perl dans dautres langages au chapitre 24, Techniques couramment employes. -s Permet une analyse rudimentaire de la ligne de commande afin de rechercher les options suivant le nom du script, mais prcdant tout nom de fichier ou une terminaison doptions --. Toute option trouve est limine de @ARGV et une variable du mme nom que loption est positionne dans Perl. Aucun accolement doptions nest permis car les options de plusieurs caractres sont autorises. Le script suivant affiche vrai si, et seulement si, le script est invoqu avec une option -truc.

customer_8566

468

Chapitre 19 Linterface de la ligne de commande


#!/usr/bin/perl -s if ($truc) { print "vrai\n"; }

Si loption est de la forme -xxx=yyy, la variable $xxx est positionne ce qui suit ce signe gal dans largument ( yyy en loccurrence). Le script suivant affiche vrai si et seulement si le script est invoqu avec une option -truc=machin.
#!/usr/bin/perl -s if ($truc eq machin) { print "vrai\n"; }

-S Pousse Perl utiliser la variable denvironnement PATH pour rechercher le script ( moins que le nom du script ne contienne des sparateurs de rpertoires). Gnralement, cette option est utilise pour muler le dmarrage par #! sur les plates-formes qui ne limplmentent pas. Sur de nombreuses plates-formes disposant dun shell compatible avec le Bourne Shell ou le C shell, vous pouvez utiliser ceci :
#!/usr/bin/perl eval "exec /usr/bin/perl -S $0 $*" if $lance_sous_un_shell;

Le systme ignore la premire ligne et donne le script /bin/sh, qui essaye dexcuter le script Perl comme un shell script. Le shell excute la seconde ligne comme une commande shell normale et dmarre donc linterprteur Perl. Sur certains systmes, $0 ne contient pas toujours le nom de chemin complet et le -S indique alors Perl de rechercher le script si ncessaire. Aprs que Perl la trouv, il analyse les lignes et les ignore car la variable $lance_sous_un_shell nest jamais vraie. ${1+"$@"} vaudrait mieux que $* mais cette expression ne fonctionne pas si le script est interprt par csh. Afin de lancer sh au lieu de csh, certains systmes doivent remplacer la ligne #! par une ligne ne contenant quun deux-points, qui sera poliment ignor par Perl. Dautres systmes ne peuvent contrler cela et ont besoin dun montage totalement dviant pouvant fonctionner sous csh, sh ou perl, comme ce qui suit :
eval (exit $?0) && eval exec /usr/bin/perl -S $0 ${1+"$@"} & eval exec /usr/bin/perl -S $0 $argv:q if 0;

Oui. Cest laid, tout autant que les systmes qui fonctionnent5 ainsi. Sur certaines plates-formes, loption -S pousse galement Perl ajouter des suffixes au nom de fichier pendant quil le recherche. Par exemple, sur les plates-formes Win32, les suffixes .bat et .cmd sont ajouts si la recherche du fichier original choue et que le nom ne se termine pas dj par lun de ces deux suffixes. Si votre version de Perl a t construite avec le dbogage activ, vous pouvez utiliser loption -Dp de Perl pour suivre la progression de la recherche. Si le nom de fichier fourni contient des sparateurs de rpertoires (mme simplement en tant que nom de chemin relatif, et non un chemin absolu) et si le fichier nest pas trouv, les plates-formes ajoutant implicitement des extensions de fichiers (non Unix) le feront et chercheront le fichier avec lajout de ces extensions, lune aprs lautre.

5. Nous utilisons le terme en connaissance de cause.

customer_8566

Traitement des commandes

469

Sur les plates-formes comme DOS, si le script ne contient pas de sparateur de rpertoires, il sera tout dabord recherch dans le rpertoire actuel avant de ltre dans le PATH. Sur les plates-formes Unix, le script sera recherch strictement dans PATH, cause des problmes de scurit engendrs par lexcution accidentelle de quelque chose dans le rpertoire de travail courant sans en faire explicitement la demande. -T Force lactivation des vrifications de marquage afin que vous puissiez les tester. Ces vrifications ne sont gnralement lances quen excutant en setuid ou setgid. Il vaut mieux les activer explicitement pour les programmes qui tournent sous le nom de quelquun dautre, comme les programmes CGI. Voir le chapitre 23, Scurit. Remarquez que, pour des raisons de scurit, Perl doit voir cette option assez tt ; cela signifie habituellement quelle doit se trouver au dbut de la ligne de commande ou de la ligne #!. Si elle nest pas trouve assez tt, Perl sen plaint. -u Provoque un core dump de Perl aprs avoir compil le script. Vous pouvez alors, en thorie, prendre ce core dump et le transformer en fichier excutable grce au programme undump (qui nest pas fourni). Le dmarrage est ainsi acclr au dtriment de lespace disque (que vous pouvez minimiser en faisant strip sur lexcutable). Si vous voulez excuter une partie du script avant le vidage, utilisez plutt loprateur dump de Perl. Remarque : la disponibilit de undump dpend des plates-formes ; il peut ne pas exister pour certains portages de Perl. Il a t remplac par le nouveau gnrateur de code Perl-vers-C, qui est bien plus portable (mais toujours exprimental). -U Permet Perl deffectuer des oprations dangereuses. Actuellement, les seules oprations dangereuses sont la suppression de rpertoires en tant que super-utilisateur et le lancement de programmes en setuid alors que les vrifications fatales de marquage sont transformes en avertissements. Remarquez que les avertissements doivent tre activs pour engendrer les avertissements de vrifications de marquage. -v Affiche la version et le niveau de correctif (patch level) de votre excutable Perl, ainsi que quelques informations supplmentaires. -V Affiche un rsum des principales valeurs de configuration de Perl et la valeur actuelle de @INC. -V:NOM Affiche sur STDOUT la valeur de la variable de configuration indique. Le NOM peut contenir des caractres dexpressions rgulires, comme . pour correspondre nimporte quel caractre ou .* pour correspondre toute squence de caractres optionnelle.

customer_8566

470

Chapitre 19 Linterface de la ligne de commande


% perl -V:man.dir man1dir=/usr/local/man/man1 man3dir=/usr/local/man/man3 % perl -V:.*threads d_oldpthreads=undef use5005threads=define useithreads=undef usethreads=define

Si vous demandez une variable de configuration qui nexiste pas, sa valeur sera rapporte comme UNKNOWN (INCONNUE). Les informations de configuration sont accessibles depuis lintrieur dun programme en utilisant le module Config, bien que les motifs ne soit pas implments pour les indices des hachages :
% perl -MConfig -le print $Config{man1dir} /usr/local/man/man1

Voir le module Config au chapitre 32, Modules standard. -w Affiche des messages davertissement concernant les variables qui ne sont mentionnes quune fois et sur les valeurs scalaires qui sont utilises avant dtre positionnes. Prvient galement des redfinitions de sous-programme et des rfrences des handles de fichier indfinis ou de ceux, ouverts en lecture seule, sur lesquels vous essayez dcrire. Avertit galement si vous utilisez des valeurs en tant que nombres alors quelles ne semblent pas numriques ou si vous utilisez un tableau comme sil sagissait dun scalaire ou si vos sous-programmes rentrent dans plus de 100 rcursions, ainsi que dinnombrables choses du mme genre. Voir toutes les entres marques (W) au chapitre 33, Messages de diagnostic. Cette option ne fait que positionner la variable globale $^W. Elle na pas deffet sur les avertissements lexicaux voir pour cela les options -W et -X. Vous pouvez activer ou dsactiver des avertissements spcifiques via le pragma use warnings, dcrit au chapitre 31. -W Active de manire inconditionnelle et permanente tous les avertissements tout au long du programme, mme si les avertissements taient dsactivs localement en utilisant no warnings ou $^W = 0. Ceci comprend tous les fichiers chargs par use, require ou do. Pensez-y comme lquivalent Perl de la commande lint(1). -xREPERTOIRE -x Indique Perl dextraire un script qui est inclus dans un message. Les lignes rsiduelles du dbut sont limines jusqu la premire commenant par #! et contenant la chane perl . Toutes les options significatives de cette ligne aprs le mot perl seront appliques. Si un nom de rpertoire est spcifi, Perl basculera vers ce rpertoire avant de lancer le script. Loption -x permet seulement dliminer les lignes superf lues du dbut, pas les lignes superf lues de la fin. Le script doit se terminer par __END__ ou par __DATA__ sil y a des lignes superf lues ignorer aprs la fin du script. (Le script peut traiter au besoin tout ou partie des rsidus restants via

customer_8566

Variables denvironnement

471

le handle de fichier DATA. Il pourrait mme en thorie se dplacer avec seek au dbut du fichier et traiter les rsidus du dbut.) -X Dsactive de manire inconditionnelle et permanente tous les avertissements, exactement loppos de ce que fait loption -W.

Variables denvironnement
En plus des diverses options modifiant explicitement le comportement de Perl, vous pouvez positionner diverses variables denvironnement pour inf luencer divers comportements sous-jacents. La manire de positionner ces variables denvironnement est dpendante du systme, mais une astuce que vous devriez connatre si vous employez sh, ksh ou bash, est que vous pouvez positionner temporairement une variable denvironnement pour une seule commande, comme sil sagissait dune drle de sorte doption. Elle doit tre positionne devant la commande :
$ PATH=/bin:/usr/bin perl ma_programmette

Vous pouvez faire quelque chose de similaire avec un sous-shell dans csh ou tcsh :
% (setenv PATH=/bin:/usr/bin; perl ma_programmette)

Sinon, vous auriez gnralement positionn les variables denvironnement dans un fichier dont le nom ressemblerait .cshrc ou .profile dans votre rpertoire maison. Sous csh et tcsh, vous auriez crit :
% setenv PATH=/bin:/usr/bin

Et sous sh, ksh et bash, vous auriez crit :


$ PATH=/bin:/usr/bin; export PATH

Dautres systmes auront dautres moyens pour les positionner dune manire semi-permanente. Voici les variables denvironnement auxquelles Perl accorde de lattention : HOME Utilise si chdir est appel sans argument. LC_ALL, LC_CTYPE, LC_COLLATE, LC_NUMERIC, PERL_BADLANG Variables denvironnement contrlant comment Perl gre les donnes spcifiques aux langages naturels particuliers. Voir la documentation en ligne de perllocale. LOGDIR Utilise si chdir est appel sans argument et si HOME nest pas positionne. PATH Utilise lors de lexcution de sous-processus et dans la recherche du programme si loption -S est utilise. PERL5LIB Une liste de rpertoires, spars par des deux-points, dans lesquels rechercher les fichiers de bibliothque de Perl avant de les chercher dans la bibliothque standard et dans le rpertoire courant. Tous les rpertoires spcifiques larchitecture aux

customer_8566

472

Chapitre 19 Linterface de la ligne de commande

endroits spcifis sont automatiquement inclus sils existent. Si la variable denvironnement PERL5LIB nest pas dfinie, on consulte PERLLIB pour assurer une compatibilit antrieure avec les versions plus anciennes. Lors dune excution avec vrification du marquage (soit parce que le programme sexcutait en setuid ou setgid, soit parce que loption -T tait utilise), aucune des deux variables de recherche de bibliothque nest utilise. De tels programmes doivent employer le pragma use lib dans cet objectif. PERL5OPT Options de ligne de commande par dfaut. Les options dans cette variable sont considres comme faisant partie de toute ligne de commande Perl. Seules les options -[DIMUdmw] sont autorises. Lors dune excution avec vrifications de marquage (car le programme sexcutait en setuid ou setgid ou si loption -T tait utilise), cette variable est ignore. Si PERL5OPT commence par -T, le marquage sera activ et toutes les options suivantes seront ignores. PERL5DB La commande utilise pour charger le code du dbogueur. La valeur par dfaut est :
BEGIN { require perl5db.pl }

Voir le chapitre 20 pour dautres utilisations de cette variable. PERL5SHELL (seulement sur les portages Microsoft) Peut tre positionne une possibilit de shell que Perl doit utiliser en interne pour excuter les commandes via des apostrophes inverses ou via system. La valeur par dfaut est cmd.exe /x/c sur WinNT et command.com /c sur Win95. La valeur est considre comme tant dlimite par des espaces. Prfixez tout caractre devant tre isol (comme un espace ou une antislash) par un antislash. Remarquez que Perl nutilise pas COMSPEC pour cela car COMSPEC a un haut degr de variabilit entre les utilisateurs, ce qui amne des soucis de portabilit. De plus, Perl peut utiliser un shell qui ne convienne pas un usage interactif et le fait de positionner COMSPEC un tel shell peut interfrer avec le fonctionnement correct dautres programmes (qui regardent habituellement COMSPEC pour trouver un shell permettant lutilisation interactive). PERLLIB Une liste de rpertoires, spars par des deux-points, dans lesquels rechercher les fichiers de bibliothque de Perl avant de les chercher dans la bibliothque standard et dans le rpertoire courant. Si PERL5LIB est dfinie, PERLLIB nest pas utilise. PERL_DEBUG_MSTATS Approprie seulement si Perl est compil avec la fonction malloc incluse dans la distribution de Perl (cest--dire si perl -V:d_mymalloc vaut define ). Si elle est positionne, cela provoque un affichage de statistiques sur la mmoire aprs lexcution. Si sa valeur est un entier suprieur un, les statistiques sur la mmoire sont galement affiches aprs la compilation. PERL_DESTRUCT_LEVEL Approprie seulement si votre excutable perl a t construit en activant le dbo-

customer_8566

Variables denvironnement

473

gage, ceci contrle le comportement de la destruction globale des objets et autres rfrences. part celles-ci, Perl lui-mme nutilise pas dautres variables denvironnement, sauf pour les rendre disponibles au programme sexcutant et aux processus fils que lance ce programme. Certains modules, standard ou autres, peuvent se soucier dautres variables denvironnement. Par exemple, le pragma use re utilise PERL_RE_TC et PERL_RE_COLORS, le module Cwd utilise PWD et le module CGI utilise les nombreuses variables denvironnement positionnes par votre dmon HTTP (cest--dire, votre serveur Web) pour passer des informations au script CGI. Les programmes excuts en setuid feraient bien dexcuter les lignes suivantes avant de faire quoi que ce soit dautre, simplement pour que les gens restent honntes :
$ENV{PATH} = /bin:/usr/bin; # ou ce dont vous avez besoin $ENV{SHELL} = /bin/sh if exists $ENV{SHELL}; delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};

Voir le chapitre 23 pour plus de dtails.

customer_8566

customer_8566

Le dbogueur Perl

20

Avant tout, avez-vous essay le pragma use warnings? Si vous invoquez Perl avec loption -d, votre programme tournera sous le dbogueur Perl. Celui-ci fonctionne comme un environnement Perl interactif, offrant une invite (prompting) pour des commandes de dbogage qui vous permettent dexaminer le code source, de positionner des points darrt, dafficher la pile de vos appels de fonctions, de changer la valeur des variables et ainsi de suite. Toute commande non reconnue par le dbogueur est directement excute (en utilisant eval) en tant que code Perl dans le paquetage du code actuellement en train dtre dbogu. (Le dbogueur utilise le paquetage DB pour ses propres informations dtat, afin dviter de pitiner les vtres.) Cest si formidablement pratique que les gens lancent souvent le dbogueur tout seul pour tester des constructions Perl interactivement pour voir ce quelles font. Dans ce cas, le programme que vous dites Perl de dboguer na pas dimportance, nous en choisirons donc un sans grande signification :
% perl -de 42

En Perl, le dbogueur nest pas un programme spar de celui qui est dbogu, comme il lest dhabitude dans un environnement de programmation typique. Loption -d indique plutt au compilateur dinsrer des informations sur le source dans les arbres syntaxiques quil est sur le point de passer linterprteur. Cela signifie que votre code doit dabord compiler correctement pour que le dbogueur puisse sen occuper. Puis si cest le cas, linterprteur prcharge un fichier de bibliothque Perl spcial contenant le dbogueur lui-mme.
% perl -d /chemin/du/programme

Le programme sarrtera immdiatement avant la premire instruction lexcution (mais voir la section Utilisation du dbogueur concernant les instructions la compilation) et vous demande dentrer une commande de dbogueur. Chaque fois que le dbogueur sarrte et vous montre une ligne de code, il affiche la ligne quil est sur le point dexcuter, non celle quil vient dexcuter. Lorsque le dbogueur rencontre une ligne, il vrifie dabord sil y a un point darrt, affiche la ligne (si le dbogueur est en mode trace), accomplit toutes les actions (cres

customer_8566

476

Chapitre 20 Le dbogueur Perl

avec la commande a dcrite plus loin dans Commandes du dbogueur) et finalement affiche une invite (prompt) lutilisateur sil existe un point darrt ou si le dbogueur est en mode pas--pas. Sinon, il value la ligne normalement et continue avec la ligne suivante.

Utilisation du dbogueur
Linvite du dbogueur ressemble :
DB<8>

ou mme :
DB< <17> >

o le numro indique combien de commandes vous avez effectues. Un mcanisme dhistorique ressemblant celui de csh permet daccder des commandes antrieures par leur numro. Par exemple, !17 rpterait la commande numro 17. Le nombre de signes infrieur/suprieur indique la profondeur du dbogueur. Vous en obtenez plus dun, par exemple, si vous vous trouvez dj un point darrt et que vous affichez ensuite le rsultat dun appel de fonction qui comporte elle-mme un point darrt. Si vous voulez entrer une commande multiligne, comme une dfinition de sous-programme comportant plusieurs instructions, vous pouvez protger le saut de ligne qui termine normalement la commande du dbogueur par un antislash. En voici un exemple :
DB<1> for (1..3) { \ cont: print "ok\n"; \ cont: } ok ok ok

Admettons que vous vouliez dmarrer le dbogueur sur un petit programme de votre cru (appelons-le puce_du_chameau1) et arrtons-le ds quil arrive sur une fonction appele infeste. Voici comment vous feriez cela :
% perl -d puce_du_chameau Loading DB routines from perl5db.pl version 1.07 Editor support available. Enter h or h h for help, or man perldebug for more help. main::(puce_du_chameau:2): parasite(bacterie, 4); DB<1>
1. N.d.T. : En anglais, bogue se dit bug, qui signifie galement punaise , insecte , coloptre ou microbe , ce qui explique les diffrentes allusions des parasites dans les exemples de ce chapitre. Nous aurions pu adapter ces exemples lenveloppe de la chtaigne (sens premier de bogue en franais) mais avouez quun bogue informatique est aussi nuisible que certains insectes !

customer_8566

Utilisation du dbogueur

477

Le dbogueur arrte votre programme juste avant la premire instruction lexcution (mais voir ci-dessous les instructions la compilation) et vous demande dentrer une commande. Encore une fois, ds que le dbogueur sarrte pour vous montrer une ligne de code, il affiche celle qui est sur le point dtre excute, non celle qui vient de ltre. La ligne affiche peut ne pas ressembler exactement celle prsente dans votre fichier source, particulirement si vous lavez lanc par lintermdiaire dun prprocesseur. Vous aimeriez maintenant vous arrter ds votre programme arrive la fonction infeste, vous y tablissez donc un point darrt comme ceci :
DB<1> b infeste DB<2> c

Le dbogueur continue maintenant jusqu ce quil tombe sur cette fonction, o il affiche ceci :
main::infeste(puce_du_chameau:8): my $microbes = int rand(3);

Pour examiner une fentre de code source autour du point darrt, utilisez la commande w :
DB<2> w 5 } 6 7 sub infeste { 8==>b my microbes = int rand(3); 9: our $Maitre; 10: contaminer($Maitre); 11: warn "bain ncessaire" 12 if $Maitre && $Maitre->isa("Humain"); 13 14: print "$microbes attraps\n"; DB<2>

Comme vous pouvez le voir grce au marqueur ==>, votre ligne courante est la numro 8 et, grce au b qui sy trouve, vous savez quelle comporte un point darrt. Si vous aviez positionn une action, il y aurait galement eu un a. Les numros avec un deux-points peuvent comporter des points darrt, les autres ne le peuvent pas. Pour voir qui a appel qui, demandez la trace arrire de la pile (stack backtrace) en utilisant la commande T :
DB<2> T $ = main::infeste called from file Deplacement.pm line 4 @ = Deplacement::pattes(1, 2, 3, 4) called from file puce_du_chameau line 5 . = main::parasite(bacterie, 4) called from file puce_du_chameau ligne 2

Le premier caractre ($, @ ou .) indique si la fonction a t appele respectivement dans un contexte scalaire, de liste ou vide. Il y a trois lignes car vous tiez une profondeur de trois fonctions lorsque vous avez lanc la trace arrire de la pile. Voici ce que signifie chaque ligne : La premire ligne dit que vous vous trouviez dans la fonction main::infeste lorsque vous avez lanc la trace de la pile. Elle vous indique que la fonction a t appele dans un contexte scalaire depuis la ligne numro 4 du fichier Deplacement.pm.

customer_8566

478

Chapitre 20 Le dbogueur Perl

Elle montre galement quelle a t appele sans aucun argument, ce qui veut dire quelle a t appele en tant que &infeste au lieu de la manire normale infeste(). La deuxime ligne montre que la fonction Deplacement::pattes a t appele dans un contexte de liste depuis la ligne numro 5 du fichier puce_du_chameau, avec ces quatre arguments. La troisime ligne montre que main::parasite a t appele dans un contexte vide depuis la ligne numro 2 de puce_du_chameau.

Si vous avez des instructions excutables lors de la phase de compilation, comme du code venant de blocs BEGIN ou CHECK ou des instructions use, elles ne seront pas stoppes de manire ordinaire par le dbogueur, alors que les require et les blocs INIT le sont, puisquils interviennent aprs la transition vers la phase dexcution (voir le chapitre 18, Compiler). Les instructions de la phase de compilation peuvent tre traces avec loption AutoTrace positionne dans PERLDB_OPTS. Vous pouvez exercer un lger contrle sur le dbogueur Perl depuis lintrieur de votre programme Perl lui-mme. Vous pourriez faire ceci en positionnant, par exemple, un point darrt automatique un certain sous-programme lorsquun programme particulier sexcute sous le dbogueur. Cependant, depuis votre propre code Perl, vous pouvez transfrer de nouveau le contrle au dbogueur en utilisant linstruction suivante, qui est inoffensive si le dbogueur nest pas lanc :
$DB::single = 1;

Si vous positionnez $DB::single 2, cela quivaut la commande n, tandis quune valeur de 1 mule la commande s. La variable $DB::trace devrait tre mise 1 pour simuler le t. Une autre faon de dboguer un module consiste positionner un point darrt au chargement :
DB<7> b load c:/perl/lib/Carp.pm Will stop on load of c:/perl/lib/Carp.pm.

puis de redmarrer le dbogueur en utilisant la commande R. Pour un contrle plus fin, vous pouvez utiliser b compile nom_sous_programme pour sarrter aussitt quun sousprogramme particulier est compil.

Commandes du dbogueur
Lorsque vous tapez des commandes dans le dbogueur, vous navez pas besoin de les terminer par un point-virgule. Utilisez un antislash pour continuer les lignes (mais uniquement dans le dbogueur). Puisque le dbogueur utilise eval pour excuter des commandes, les initialisations avec my, our et local disparatrons une fois la commande termine. Si une commande du dbogueur concide avec une quelconque fonction de votre propre programme, vous navez qu prfixer lappel de fonction avec quelque chose qui ne ressemble pas une commande du dbogueur, comme un ; ou un + au dbut. Si la sortie dune commande interne du dbogueur dfile au-del des limites de votre cran, vous navez qu prfixer la commande avec un symbole de pipe afin quelle passe

customer_8566

Commandes du dbogueur
par votre pager :
DB<1> |h

479

Le dbogueur comprend une grande quantit de commandes et nous les avons divises (quelque peu arbitrairement) dans les catgories suivantes : pas pas et lancement, points darrt, traage, affichage, localisation de code, excution automatique de commandes et, bien entendu, divers. La commande la plus importante est peut-tre h, qui fournit de laide. Si vous tapez h h linvite du dbogueur, vous obtiendrez une page daide compacte conue pour tenir sur un seul cran. Si vous tapez h COMMANDE, vous obtiendrez de laide sur cette COMMANDE du dbogueur.

Pas pas et lancement


Le dbogueur fonctionne en parcourant votre programme pas--pas (stepping), ligne par ligne. Les commandes suivantes vous permettent de contrler ce que vous court-circuitez et o vous vous arrtez. s s EXPR La commande s du dbogueur avance dans le programme dun seul pas. Cest--dire que le dbogueur excutera la prochaine ligne de votre programme jusqu atteindre une autre instruction, en descendant dans les appels de sous-programmes si ncessaire. Si la prochaine ligne excuter implique un appel de fonction, le dbogueur sarrte alors la premire ligne lintrieur de cette fonction. Si une EXPR est fournie et quelle comprend des appels de fonctions, celles-ci seront galement parcourues pas--pas. n n EXPR La commande n excute des appels de sous-programme, sans les parcourir pas pas, jusquau dbut de la prochaine instruction du mme niveau (ou dun niveau plus haut). Si une EXPR est fournie et quelle comprend des appels de fonctions, celles-ci seront excutes en sarrtant avant chaque instruction. <ENTRE> Si vous ne faites quappuyer sur la touche <ENTRE> linvite du dbogueur, la commande s ou n prcdente est rpte. . La commande . renvoie le pointeur interne du dbogueur vers la dernire ligne excute et affiche cette ligne. r Cette commande continue jusquau retour du sous-programme actuellement excut. Elle affiche la valeur renvoye si loption PrintRet est positionne, ce qui est le cas par dfaut.

customer_8566

480

Chapitre 20 Le dbogueur Perl

Points darrt
b b b b b b b b b b LIGNE CONDITION LIGNE CONDITION NOM_SOUS_PROGRAMME NOM_SOUS_PROGRAMME CONDITION postpone NOM_SOUS_PROGRAMME postpone NOM_SOUS_PROGRAMME CONDITION compile NOM_SOUS_PROGRAMME load NOM_FICHIER La commande b du dbogueur positionne un point darrt avant la LIGNE, indiquant au dbogueur darrter le programme cet endroit pour que vous puissiez fureter autour. Si LIGNE est omise, la commande positionne un point darrt sur la ligne qui est sur le point dtre excute. Si CONDITION est spcifie, elle est value chaque fois que linstruction est atteinte : un point darrt nest dclench que si la CONDITION est vraie. Les points darrt ne peuvent tre positionns que sur les lignes commenant par une instruction excutable. Remarquez que les conditions nemploient pas if :
b 237 $x > 30 b 237 ++$compteur237 < 11 b 33 /motif/i

La forme b NOM_SOUS_PROGRAMME positionne un point darrt (qui peut tre conditionnel) avant la premire ligne du sous-programme cit. NOM_SOUS_PROGRAMME peut tre une variable contenant une rfrence de code ; si cest le cas, CONDITION nest pas implmente. Il existe plusieurs manires de positionner un point darrt sur du code qui na mme pas encore t compil. La forme b postpone positionne un point darrt (qui peut tre conditionnel) la premire ligne de NOM_SOUS_PROGRAMME aprs quil a t compil. La forme b compile positionne un point darrt sur la premire instruction devant tre excute aprs que NOM_SOUS_PROGRAMME a t compil. Remarquez quau contraire de la forme avec postpone, cette instruction se trouve lextrieur du sousprogramme en question car ce dernier na pas encore t appel, il a seulement t compil. La forme b load positionne un point darrt sur la premire ligne excut du fichier. Le NOM_FICHIER devrait tre un nom de chemin complet tel quon laurait trouv dans les valeurs de %INC. d d LIGNE Cette commande supprime le point darrt de la LIGNE ; si celle-ci est omise, la commande supprime le point darrt sur la ligne qui est sur le point dtre excute. D Cette commande supprime tous les points darrt.

customer_8566

Commandes du dbogueur
L Cette commande liste tous les points darrt et toutes les actions. c C LIGNE

481

Cette commande continue lexcution, en insrant ventuellement un point darrt, actif une seule fois, la LIGNE spcifie.

Traage
T Cette commande produit une trace arrire de la pile (backtrace stack). t t EXPR Cette commande bascule lactivation ou la dsactivation du mode trace, qui imprime chaque ligne de votre programme au moment o elle est value. Voir galement loption AutoTrace, prsente plus loin dans ce chapitre. Si une EXPR est fournie, le dbogueur tracera son excution. Voir galement plus loin la section Excution autonome. W W EXPR Cette commande ajoute EXPR en tant quexpression globale de surveillance. (Une expression de surveillance est une expression qui provoquera un point darrt lorsque sa valeur changera.) Si aucune EXPR nest fournie, toutes les expressions de surveillance sont supprimes.

Affichage
Le dbogueur de Perl comprend plusieurs commandes pour examiner des structures de donnes pendant que votre programme est immobilis un point darrt. p p EXPR Cette commande est identique print DB::OUT EXPR dans le paquetage courant. En particulier, comme il sagit de la propre fonction print de Perl, les structures de donnes imbriques et les objets ne sont pas affichs utiliser la commande x pour ce faire. Le handle DB::OUT imprime sur votre terminal (ou peut-tre une fentre dditeur) quel que soit lendroit o la sortie standard a pu tre redirige. x x EXPR La commande x value son expression dans un contexte de liste et affiche le rsultat, agrablement prsent (pretty-printed). Cest--dire que les structures de donnes imbriques sont imprimes rcursivement et avec les caractres invisibles convenablement encods.

customer_8566

482
V V PAQUETAGE V PAQUETAGE VARS

Chapitre 20 Le dbogueur Perl

Cette commande affiche toutes les variables (ou quelques-unes, lorsque vous spcifiez VARS) dans le PAQUETAGE spcifi (main par dfaut) en utilisant une prsentation agrable (pretty printer). Les hachages affichent leurs cls et leurs valeurs, les caractres de contrles sont prsents lisiblement, les structures de donnes imbriques sont imprimes de manire lisible et ainsi de suite. Ceci est identique un appel de la commande x sur chaque variable possible, sauf que x fonctionne galement avec les variables lexicales. De plus, vous pouvez tapez ici les identificateurs sans spcificateur de type, tel que $ ou @, comme ceci :
V Animal::Chameau SPOT FIDO

Au lieu dun nom de variable dans VARS, vous pouvez utiliser ~MOTIF ou !MOTIF pour imprimer les variables existantes dont le nom correspond ou ne correspond pas au MOTIF spcifi. X X VARS Cette commande est identique V PAQUETAGE_COURANT, o PAQUETAGE_COURANT est le paquetage o la ligne courante a t compile. H H -NUMRO Cette commande affiche la dernire commande NUMRO. Seules les commandes de plusieurs caractres sont stockes dans lhistorique. (Sinon, la plupart dentre elles seraient des s ou des n.) Si NUMRO est omis, toutes les commandes sont listes.

Localisation de code
lintrieur du dbogueur, vous pouvez extraire et afficher des parties de votre programme avec ces commandes. l l l l l LIGNE NOM_SOUS_PROGRAMME MIN+INCR MIN-MAX La commande l liste quelques-unes des prochaines lignes de votre programme ou la LIGNE spcifie, si elle est fournie ou quelques lignes au dbut du sous-programme ou de la rfrence de code NOM_SOUS_PROGRAMME. La forme l MIN+INCR liste INCR+1 lignes, en commenant MIN. La forme l MIN-MAX liste les lignes MIN jusqu MAX. Cette commande liste quelques lignes au dbut de votre programme.

customer_8566

Commandes du dbogueur
w w LIGNE

483

Liste une fentre (quelques lignes) autour de la LIGNE de code source donne ou de la ligne courante, si aucune LIGNE nest fournie. f NOM_FICHIER Cette commande vous permet de visualiser un programme ou une instruction eval diffrent. Si le NOM_FICHIER nest pas un nom de chemin absolu tel quon laurait trouv dans les valeurs de %INC, il est interprt en tant quexpression rgulire pour trouver le nom de chemin que vous voulez. /MOTIF/ Cette commande recherche le MOTIF en avant dans votre programme ; le / final est optionnel. Le MOTIF entier est galement optionnel et sil est omis, la recherche prcdente est rpte. ?MOTIF? Cette commande recherche le MOTIF en arrire dans votre programme ; le / final est optionnel. La recherche prcdente est rpte si le MOTIF est omis. S S MOTIF S !MOTIF La commande S liste les sous-programmes dont le nom correspond (ou avec !, ne correspond pas) au MOTIF. Si aucun MOTIF nest fourni, tous les sous-programmes sont lists.

Actions et excution de commandes


Depuis lintrieur du dbogueur, vous pouvez spcifier des actions accomplir certains moments. Vous pouvez galement lancer des programmes externes. a a COMMANDE a LIGNE a LIGNE COMMANDE Cette commande positionne une action accomplir avant dexcuter la LIGNE ou la ligne courante si LIGNE est omise. Par exemple, ceci affiche $truc chaque fois que la ligne 53 est atteinte :
a 53 print "DB a trouv $truc\n"

Si aucune COMMANDE nest spcifie, laction la LIGNE spcifie est supprime. Sans LIGNE, ni ACTION, laction sur la ligne courante est supprime. A La commande A du dbogueur supprime toutes les actions.

customer_8566

484
< < ? < EXPR << EXPR

Chapitre 20 Le dbogueur Perl

La forme < EXPR spcifie une expression Perl valuer avant toute invite du dbogueur. Vous pouvez ajouter une autre expression avec la forme << EXPR, les lister avec < ? et toutes les supprimer avec un simple <. > > ? > EXPR >> EXPR Les commandes > se comportent exactement comme leur cousines < mais sont excutes aprs linvite du dbogueur plutt quavant. { { ? { COMMANDE {{ COMMANDE Les commandes { du dbogueur se comportent exactement comme < mais spcifient une commande du dbogueur excuter plutt quune expression Perl. Un avertissement est mis sil apparat que vous avez accidentellement entr un bloc de code la place. Si cest vraiment ce que vous voulez faire, crivez le avec ;{ ... } ou mme do { ... }. ! ! NUMRO ! -NUMRO !MOTIF Un ! isol rpte la commande prcdente. Le NUMRO spcifie quelle commande excuter depuis lhistorique ; par exemple, ! 3 excute la troisime commande tape dans le dbogueur. Si un signe moins prcde le NUMRO, on compte les commandes rebours : ! -2 excute lavant-dernire commande. Si un MOTIF (sans slash) est fourni la place dun NUMRO, la dernire commande commenant par ce MOTIF est excute. Voir galement loption du dbogueur recallCommand. !! CMD Cette commande du dbogueur lance la commande externe CMD dans un sous-processus, qui lira depuis DB::IN et crira vers DB::OUT. Voir galement loption du dbogueur shellBang. Cette commande emploie le shell cit dans $ENV{SHELL}, qui peut parfois interfrer avec une interprtation correcte des informations concernant les statuts, les signaux et les core dump. Si vous voulez une valeur de sortie cohrente, positionnez $ENV{SHELL} /bin/sh. | | CMD_DB || CMD_PERL La commande |CMD_DB lance la commande CMD_DB du dbogueur, en pipant DB::OUT vers $ENV{PAGER}. On emploie souvent ceci avec les commandes qui pro-

customer_8566

Commandes du dbogueur
duiraient sinon une sortie trop longue, comme :
DB<1> |V main

485

Remarquez que ceci est valable pour les commandes du dbogueur et non pour celles que vous auriez tapes depuis votre shell. Si vous vouliez envoyer la commande externe who vers votre pager, vous pourriez faire quelque chose comme ceci :
DB<1> !!who | more

La commande ||CMD_PERL est semblable |CMD_DB mais DB::OUT est galement temporairement slectionn (avec select), afin que toutes les commandes appelant print, printf ou write sans handle de fichier soient galement envoyes vers le pipe. Par exemple, si vous aviez une fonction gnrant des tonnes daffichages en appelant print, vous utiliseriez cette commande la place de la prcdente pour envoyer la sortie vers le pager :
DB<1> sub qui { print "Utilisateurs : ", who } DB<2> ||qui()

Commandes diverses
q et ^D Ces commandes quittent le dbogueur. Il sagit de la manire recommande de sortir du dbogueur, bien que taper deux fois exit fonctionne parfois. Positionnez loption inhibit_exit 0 si vous voulez tre capable de passer directement la fin du programme et de tout de mme rester dans le dbogueur. Vous pouvez galement avoir besoin de positionner $DB::finished 0 si vous voulez suivre la destruction globale. R Redmarre le dbogueur en lanant une nouvelle session avec exec. Le dbogueur essaie de maintenir votre historique entre les sessions mais quelques rglages internes et quelques options de la ligne de commande peuvent tre perdus. Les rglages suivant sont actuellement prservs : lhistorique, les points darrt, les actions, les options du dbogueur et les options -w, -I et -e de la ligne de commande de Perl. = = ALIAS = ALIAS VALEUR Cette commande affiche la valeur actuelle dALIAS si aucune VALEUR nest fournie. Avec une VALEUR, elle dfinit une nouvelle commande du dbogueur avec le nom ALIAS. Si ALIAS et VALEUR sont tous deux omis, tous les alias actuels sont lists. Par exemple :
= quit q

Un ALIAS devrait tre un simple identificateur et devait galement se convertir en un simple identificateur. Vous pouvez obtenir des mcanismes dalias plus sophistiqus en ajoutant directement vos propres entres %DB::aliases. Voir Personnalisation du dbogueur plus loin dans ce chapitre.

customer_8566

486
man man PAGE_DE_MANUEL

Chapitre 20 Le dbogueur Perl

Cette commande appelle la visionneuse de documentation par dfaut de votre systme pour la page donne ou la visionneuse elle-mme si PAGE_DE_MANUEL est omise. Si cette visionneuse est man, les informations courantes de %Config sont utilises pour linvoquer. Le prfixe perl sera automatiquement fourni votre place si ncessaire ; ceci vous permet de taper man debug et man op depuis le dbogueur. Sur les systmes ne disposant pas dordinaire de lutilitaire man, le dbogueur invoque perldoc ; si vous voulez changer ce comportement, positionnez $DB::doccmd avec la visionneuse que vous dsirez. Ceci peut tre initialis dans un fichier rc ou par lintermdiaire dune affectation directe. O O OPTION ... O OPTION? ... O OPTION=VALEUR ... La commande O vous permet de manipuler les options du dbogueur, qui sont numres au paragraphe Options du dbogueur plus loin dans ce chapitre. La form O OPTION positionne chacune des options listes 1. Si un point dinterrogation suit une OPTION, sa valeur actuelle est affiche. La forme O OPTION=VALEUR positionne la valeur ; si VALEUR contient des espaces, ils doivent tre isols (quoted). Par exemple, vous pouvez positionner O pager="less MQeicsNfr" pour utiliser less avec ces drapeaux spcifiques. Vous pouvez utiliser des apostrophes ou des guillemets, mais si cest le cas, vous devez isoler des instances imbriques avec un type de caractre de protection identique celui avec lequel vous avez commenc. Vous devez galement protger tout antislash prcdant immdiatement lapostrophe ou le guillemet mais ntant pas destin protger lapostrophe ou le guillemet lui-mme. En dautres termes, vous navez qu suivre les rgles de lisolement par apostrophes sans tenir compte du type de caractre disolement rellement utilis. Le dbogueur rpond en vous montrant la valeur de loption qui vient dtre positionne, en utilisant toujours la notation avec des apostrophes dans laffichage :
DB<1> O OPTION=ceci n\est pas mal OPTION = ceci n\est pas mal DB<2> O OPTION="\"Nest-ce pas ?\", dit-elle" OPTION = "N\est-ce pas ?", dit-elle

Pour des raisons historiques, le =VALEUR est optionnel, mais vaut 1 par dfaut, seulement l o cela peut tre fait en toute scurit cest--dire surtout pour les options boolennes. Il vaut mieux affecter une VALEUR spcifique en utilisant =. LOPTION peut tre abrge mais moins que vous ne soyez volontairement occulte, il vaudrait certainement mieux vous abstenir. Plusieurs options peuvent tre positionnes ensemble. Voir la section Options du dbogueur pour en avoir la liste.

customer_8566

Personnalisation du dbogueur

487

Personnalisation du dbogueur
Le dbogueur contient probablement assez de points dentre pour sa configuration, pour que vous nayez jamais le modifier vous-mme. Vous pouvez changer le comportement du dbogueur depuis lintrieur de ce dernier en utilisant sa commande O, depuis la ligne de commande via la variable denvironnement PERLDB_OPTS et en lanant lune des commandes prdfinies stockes dans des fichiers rc.

Implmentation de lditeur pour le dbogage


Le mcanisme dhistorique de la ligne de commande du dbogueur noffre pas de facilits ddition pour la ligne de commande comme le font de nombreux shells : vous ne pouvez pas accder aux lignes prcdentes avec ^p, ni vous dplacer au dbut de la ligne avec ^a, bien que vous puissiez excuter les lignes prcdentes en utilisant la syntaxe avec un point dexclamation, familire aux utilisateurs du shell. Toutefois, si vous installez les modules Term::Readkey et Term::ReadLine de CPAN, vous obtiendrez des fonctionnalits ddition compltes, similaires ce quoffre GNU readline(3). Si emacs est install sur votre systme, il peut interagir avec le dbogueur Perl pour fournir un environnement intgr de dveloppement logiciel, avec des rminiscences de ses interactions avec les dbogueurs C. Perl est distribu avec un fichier de dmarrage pour pousser emacs agir comme un diteur sensible la syntaxe qui comprenne la syntaxe (du moins, une partie) de Perl. Regardez dans le rpertoire emacs du code source de la distribution Perl. Les utilisateurs de vi devraient galement regarder vim (et gvim, la version fentre et souris) pour obtenir une coloration des mots-cls de Perl. Une configuration similaire, faite par lun des auteurs (Tom), pour interagir avec le vi de nimporte quel fabriquant et le systme de fentrage X11, est galement disponible. Ceci fonctionne comme limplmentation intgre multifentre fournie par emacs, o le dbogueur dirige lditeur. Toutefois, lheure o ces lignes sont crites, son emplacement ventuel dans la distribution de Perl reste incertain. Mais nous avons pens que vous deviez connatre cette possibilit.

Personnalisation avec des fichiers dinitialisation


Vous pouvez effectuer certaines personnalisations en configurant un fichier .perldb ou perldb.ini (selon votre systme dexploitation), contenant du code dinitialisation. Ce fichier dinitialisation contient du code Perl, et non des commandes du dbogueur, et il est trait avant de regarder la variable denvironnement PERLDB_OPTS. Par exemple, vous pourriez construire des alias en ajoutant des entres dans le hachage %DB::alias, de cette manire :
$alias{longueur} $alias{stop} $alias{ps} $alias{quit} $alias{aide} = = = = = s/^longueur(.*)/p length($1)/; s/^stop (at|in)/b/; s/^ps\b/p scalar /; s/^quit(\s*)/exit/; s/^aide\s*$/|h/;

Vous pouvez changer les options depuis votre fichier dinitialisation en utilisant les appels de fonctions dans lAPI interne du dbogueur :

customer_8566

488

Chapitre 20 Le dbogueur Perl

parse_options("NonStop=1 LineInfo=db.out AutoTrace=1 frame=2");

Si votre fichier dinitialisation dfinit la routine afterinit, cette fonction est appele aprs la fin de linitialisation du dbogueur. Le fichier dinitialisation peut se trouver dans le rpertoire courant ou dans le rpertoire maison. Comme ce fichier contient du code Perl arbitraire, il doit appartenir au super-utilisateur ou lutilisateur courant et ntre modifiable que par son propritaire, pour des raisons de scurit. Si vous voulez modifier le dbogueur, copiez perl5db.pl depuis la bibliothque Perl vers un autre nom et bidouillez-le selon votre inspiration. Vous voudrez alors peut-tre positionner votre variable denvironnement PERL5DB pour crire quelque chose comme ceci :
BEGIN { require "mon_perl5db.plx" }

En dernier ressort, vous pourriez galement utiliser PERL5DB pour personnaliser le dbogueur en positionnant directement les variables internes ou en appelant directement les fonctions internes du dbogueur. Toutefois, soyez bien conscient que toutes les variables et les fonctions qui ne sont documentes ni ici, ni dans les pages de manuels en ligne perldebug, perldebguts ou DB, sont considres comme tant rserves un usage interne et sont susceptibles dtre modifies sans pravis.

Options du dbogueur
Le dbogueur possde de nombreuses options que vous pouvez positionner avec la commande O, soit interactivement, soit depuis lenvironnement, soit depuis un fichier dinitialisation. recallCommand, ShellBang Les caractres utiliss pour rappeler une commande ou pour engendrer un shell. Par dfaut, les deux options sont positionnes !. pager Le programme utilis pour afficher les commandes envoyes sur un pager (celles commenant par un caractre |). Par dfaut, $ENV{PAGER} sera utilis. Comme le dbogueur utilise les caractristiques de votre terminal courant pour les caractres gras et le soulignement, si le pager choisi ne transmet pas sans changements les squences dchappement, laffichage de certaines commandes du dbogueur ne sera plus lisible aprs leur passage dans le pager. tkRunning Excute sous le module Tk lors de linvite (avec ReadLine). signalLevel, warnLevel, dieLevel Positionne le niveau de verbosit. Par dfaut, le dbogueur laisse tranquille vos exceptions et vos avertissements car leur altration peut empcher le bon fonctionnement des programmes. Pour dsactiver ce mode scuris par dfaut, placez ces valeurs une valeur suprieure 0. un niveau de 1, vous obtenez une trace arrire pour tous les types davertissements (cest souvent gnant) ou toutes les exceptions (cest souvent prcieux). Malheureusement, le dbogueur ne peut pas discerner les exceptions fatales

customer_8566

Personnalisation du dbogueur

489

et non fatales. Si dieLevel vaut 1, alors vos exceptions non fatales sont aussi traces et altres sans crmonie si elles proviennent de chanes values (avec eval) ou dun eval quelconque lintrieur des modules que vous essayez de charger. Si dieLevel est 2, le dbogueur ne se soucie pas de leur provenance : il usurpe vos gestionnaires dexceptions et affiche une trace, puis modifie toutes les exceptions avec ses propres embellissements. Ceci peut tre utile dans une optique de traage mais tend dsesprment semer la confusion dans tout programme prenant au srieux sa gestion des exceptions. Le dbogueur essayera dafficher un message lorsque des signaux INT, BUS ou SEGV arriveront sans tre traits. Mais si vous vous trouvez dans un appel systme lent (comme un wait, un accept ou un read depuis le clavier ou depuis une socket) et si vous navez pas positionn votre propre gestionnaire pour $SIG{INT}, vous ne serez alors pas capable de faire un Ctrl-C pour revenir dans le dbogueur car le propre gestionnaire du dbogueur pour $SIG{INT} ne comprend pas quil doit lever une exception et sortir des appels systme lents par un longjmp(3). AutoTrace Positionne le mode trace (similaire la commande t mais peut tre mise dans PERLDB_OPTS). LineInfo Affecte le fichier ou le pipe dans lequel crire les informations sur les numros de ligne. Sil sagit dun pipe (mettons, |visual_perl_db), alors un message court est utilis. Cest le mcanisme mis en oeuvre pour interagir avec un diteur esclave ou un dbogueur visuel, comme les points dentres spciaux de vi ou demacs ou le dbogueur graphique ddd. inhibit_exit Si cette option vaut 0, elle permet le passage direct la fin du script. PrintRet Affiche la valeur de retour aprs la commande r si cette option est active (ce qui est le cas par dfaut). ornaments Affecte lapparence lcran de la ligne de commande (voir les documentations en ligne de Term::ReadLine). Il ny a actuellement aucun moyen de dsactiver les ornements, ce qui peut rendre certains affichages illisibles sur certains crans ou avec certains pagers. Ceci est considr comme un bogue. frame Affecte laffichage des messages lentre et la sortie des sous-programmes. Si frame & 2 est faux, les messages ne sont affichs qu lentre. (Laffichage de messages la sortie pourrait savrer utile sils sont entrecroiss avec dautres messages). Si frame & 4 est vrai, les arguments des fonctions sont affichs en plus dinformations sur le contexte et sur lappelant. Si frame & 8 est vrai, les FETCH surchargs, chanifis (stringify) et lis (avec tie) sont activs sur les arguments affichs. Si frame & 16 est vrai, la valeur de retour du sous-programme est affiche. La longueur partir de laquelle la liste darguments est tronque est rgie par loption suivante.

customer_8566

490
maxTraceLen

Chapitre 20 Le dbogueur Perl

La longueur laquelle la liste darguments est tronque lorsque le bit 4 de loption frame est positionn. Les options suivantes affectent ce qui se produit avec les commandes V X, et x : , arrayDepth, hashDepth Affiche seulement les n premiers lments. Si n est omis, tous les lments seront affichs. compactDump, veryCompact Change le style de sortie des tableaux et des hachages. Si compactDump est activ, les tableaux courts peuvent tre affichs sur une seule ligne. globPrint Afficher le contenu des typeglobs. DumpDBFiles Affiche les tableaux contenant les fichiers dbogus. DumpPackages Affiche les tables de symboles des paquetages. DumpReused Affiche le contenu des adresses rutilises . quote, HighBit, undefPrint Change le style daffichage des chanes. La valeur par dfaut de quote est auto ; vous pouvez activer le format avec des guillemets ou avec des apostrophes en la positionnant " ou , respectivement. Par dfaut, les caractres dont le bit de poids fort est positionn sont affichs tels quels. UsageOnly Au lieu de montrer le contenu des variables de paquetage, vous obtenez lorsque cette option est active, un affichage rudimentaire de lusage de la mmoire par paquetage, bas sur la taille totale des chanes trouves dans les variables du paquetage. Puisque la table de symboles du paquetage est utilise, les variables lexicales sont ignores.

Excution autonome
Pendant le dmarrage, les options sont initialises partir de $ENV{PERLDB_OPTS}. Vous pouvez y placer les options dinitialisation TTY, noTTY, ReadLine et NonStop. Si votre fichier dinitialisation contient :
parse_options("NonStop=1 LineInfo=tperl.out AutoTrace");

alors votre script sexcutera sans intervention humaine, plaant les informations de trace dans le fichier tperl.out (Si vous linterrompez, vous avez intrt rinitialiser LineInfo /dev/tty si vous voulez voir quelque chose.) Les options suivantes peuvent tre spcifies uniquement au dmarrage. Pour les positionner dans votre fichier dinitialisation, appelez parse_options("OPT=VAL").

customer_8566

Personnalisation du dbogueur
TTY Le terminal utiliser pour les entres/sortie de dbogage. noTTY

491

Si cette option est positionne, le dbogueur entre en mode NonStop et ne se connectera pas un terminal. En cas dinterruption (ou si le contrle passe au dbogueur via un rglage explicite de $DB::signal ou de $DB::single depuis le programme Perl), il se connecte au terminal spcifi par loption TTY au dmarrage ou un terminal trouv lexcution en utilisant le module Term::Rendezvous de votre choix. Ce module devrait implmenter une mthode appele new, renvoyant un objet contenant deux mthodes : IN et OUT. Celles-ci devraient renvoyer deux handles de fichiers utiliser que le dbogueur utiliserait comme son entre et sa sortie, respectivement. La mthode new devrait inspecter un argument contenant la valeur de $ENV{PERLDB_NOTTY} au dmarrage ou de "/tmp/perldbtty$$" autrement. On ninspecte pas lappartenance approprie ni laccs grand ouvert en criture de ce fichier, des risques de scurit sont donc thoriquement possibles. ReadLine Si cette option est fausse, limplmentation de ReadLine dans le dbogueur est dsactive de faon pouvoir dboguer les applications utilisant elles-mmes le module ReadLine. NonStop Si cette option est mise, le dbogueur entre en mode non interactif jusqu ce quil soit interrompu ou que votre programme positionne $DB::signal ou $DB::single. Les options peuvent parfois tre abrges de manire unique par leur initiale mais nous vous recommandons de toujours les peler en entier, pour la lisibilit et la compatibilit future. Voici un exemple de lutilisation de la variable denvironnement $ENV{PERLDB_OPTS} pour positionner les options automatiquement.2 Il lance votre programme de faon non interactive, affichant les infos chaque entre dans un sous-programme et pour chaque ligne excute. La sortie de la trace du dbogueur est place dans le fichier tperl.out. Ceci permet votre programme de continuer utiliser son entre et sa sortie standards, sans que les informations de trace se mettent sur son chemin.
$ PERLDB_OPTS="NonStop frame=1 AutoTrace LineInfo=tperl.out" perl -d mon_prog

Si vous interrompez le programme, vous aurez besoin de rinitialiser rapidement O LineInfo=/dev/tty ou autre chose de sens sur votre plate-forme. Sinon, vous ne verrez plus linvite du dbogueur.

2. Nous utilisons la syntaxe du shell sh pour montrer la configuration des variables denvironnement. Les utilisateurs dautres shells feront les adaptations en consquence.

customer_8566

492

Chapitre 20 Le dbogueur Perl

Implmentation du dbogueur
Perl fournit des points dentre spciaux pour le dbogage, la fois la compilation et lexcution pour crer des environnements de dbogage, tels que le dbogueur standard. Ces points dentres ne doivent pas tre confondus avec les options perl -D, qui ne sont utilisables que si votre version de Perl a t compile avec limplmentation DDEBUGGING. Par exemple, chaque fois que vous appelez la fonction interne de Perl caller, depuis le paquetage DB, les arguments avec lesquels lenregistrement dactivation correspondant avait t appel, sont copis dans le tableau @DB::args. Lorsque vous invoquez Perl avec loption -d, les fonctionnalits supplmentaires suivantes sont actives : Perl insert le contenu de $ENV{PERL5DB} (ou, si cette variable est absente, BEGIN {require perl5db.pl}) avant la premire ligne de votre programme. Le tableau @{"_<$nom_fichier"} contient les lignes de $nom_fichier pour tous les fichiers compils par Perl. Il en va de mme pour les chanes values (avec eval) qui contiennent des sous-programmes ou sont actuellement en cours dexcution. Le $nom_fichier pour les chanes values ressemble (eval 34). Les affectations de code dans les expressions rgulires ressemblent (re_eval 19). Le hachage %{"_<$nom_fichier"} contient les points darrt et les actions avec le numro de la ligne comme clef. Vous pouvez positionner des entres individuelles, par opposition au hachage complet. Perl ne se soucie ici que de la vrit boolenne, bien que les valeurs utilises par perl5db.pl se prsentent sous la forme "$condition_d_arret\0$action". Les valeurs dans ce hachage sont magiques dans un contexte numrique : elles valent zro si lon ne peut pas placer de point darrt sur la ligne. Le mme hachage renferme les chanes values qui contiennent des sous-programmes ou sont actuellement en train dtre excutes. Le $nom_fichier pour les chanes values ressemble (eval 34) ou (re_eval 19). Le scalaire ${"_<$nom_fichier} contient "_<$nom_fichier". Ceci est galement le cas pour les chanes values qui contiennent des sous-programmes ou sont actuellement en cours dexcution. Le $nom_fichier pour les chanes values ressemble (eval 34) ou (re_eval 19). Aprs que chaque fichier charg par require est compil mais avant quil soit excut, DB::postponed(*{"_<$nom_fichier"}) est appel si le sous-programme DB::postponed existe. Ici, le $nom_fichier est le nom dvelopp du fichier charg par require, tel quon le trouve dans les valeurs de %INC. Aprs que chaque sous-programme nom_sous_programme est compil, lexistence de $DB::postponed{nom_sous_programme} est vrifie. Si cette clef existe, DB::postponed(nom_sous_programme) est appel si le sous-programme DB::postponed existe galement. Un hachage %DB::sub est maintenu, dont les clefs sont les noms des sous-programmes et dont les valeurs se prsentent sous la forme nom_fichier:ligne_debutligne_fin. nom_fichier se prsente sous la forme (eval 34) pour les sous-programmes dfinis lintrieur de chanes values ou (re_eval 19) pour ceux dfinis lintrieur daffectations de code dans les expressions rgulires.

customer_8566

Implmentation du dbogueur

493

Lorsque lexcution de votre programme atteint un certain point qui pourrait contenir un point darrt, le sous-programme DB::DB() est appel si lune des variables $DB::trace, $DB::single ou $DB::signal est vraie. Ces variables ne peuvent tre affectes par local. Cette fonctionnalit est dsactive lorsque lexcution se droule lintrieur de DB::DB(), y compris les fonctions appeles depuis l, sauf si $^D & (1< <30) est vrai. Lorsque lexcution du programme atteint un appel de sous-programme, un appel &DB::sub(args) est effectu la place, avec $DB::sub contenant le nom du sousprogramme appel. Ceci ne se produit pas si le sous-programme avait t compil dans le paquetage DB.

Remarquez que si &DB::sub a besoin de donnes externes pour fonctionner, aucun appel de sous-programme nest possible jusqu ce que ceci soit accompli. Pour le dbogueur standard, la variable $DB::deep ( combien de niveaux de profondeur de rcursion pouvez-vous aller avant darrter obligatoirement) donne un exemple dune telle dpendance.

criture de son propre dbogueur


Un dbogueur minimal en tat de fonctionner consiste en une ligne :
sub DB::DB {}

qui, puisquil ne fait rien de particulier, peut facilement tre dfini via la variable denvironnement PERL5DB :
% PERL5DB="sub DB::DB {}" perl -d votre_programme

Un autre dbogueur minuscule, lgrement plus utile, pourrait tre cr comme ceci :
sub DB::DB {print ++$i; scalar <STDIN>}

Ce petit dbogueur imprimerait le numro de ligne squentiel chaque instruction rencontre et attendrait que vous entriez un retour la ligne avant de continuer. Le dbogueur suivant, bien quil paraisse petit, est vraiment tout fait fonctionnel :
{ package DB; sub DB {} sub sub {print ++$i, " $sub\n"; &$sub} }

Il affiche le numro squentiel de lappel de sous-programme et le nom du sous-programme appel. Remarquez que &DB::sub doit tre compil dans le paquetage DB, tel que nous lavons fait ici. Si vous basez votre nouveau dbogueur sur le dbogueur courant, il y a quelques points dentre qui peuvent vous aider le personnaliser. Au dmarrage, le dbogueur lit votre fichier dinitialisation dans le rpertoire courant ou dans votre rpertoire maison. Aprs que le fichier est lu, le dbogueur lit la variable denvironnement PERLDB_OPTS et parcourt celle-ci comme le reliquat dune ligne O ..., telle que vous lauriez entre linvite du dbogueur. Le dbogueur maintient galement des variables internes magiques, comme @DB::dbline et %DB::dbline, qui sont des alias pour @{"::_<fichier_courant"} et

customer_8566

494

Chapitre 20 Le dbogueur Perl

%{"::_<fichier_courant"}. Ici, fichier_courant est le fichier actuellement slectionn, soit choisi explicitement avec la commande f du dbogueur, soit implicitement de par le f lux dexcution. Certaines fonctions peuvent faciliter la personnalisation. DB::parse_options(CHANE) analyse une ligne comme loption O. DB::dump_trace(SAUT[, COMPTEUR]) saute le nombre spcifi denregistrements dactivation dans la pile (stack frames) et renvoie une liste contenant des informations propos des enregistrements dactivation appelants (tous, si COMPTEUR est omis). Chaque entre est une rfrence vers un hachage avec les clefs context (., $ ou @), sub (nom du sous-programme ou informations sur un eval), args (undef ou une rfrence vers un tableau), file (nom du fichier) et line (numro de ligne). DB::print_trace(HF, SAUT[, COMPTEUR[, COURT]]) imprime des informations formates, concernant les enregistrements dactivation appelants de la pile, dans le handle de fichier donn. Les deux dernires fonctions peuvent savrer pratiques en tant quarguments des commandes < et << du dbogueur. Vous navez pas besoin dapprendre tout cela la plupart dentre nous ne lont pas fait. En fait, lorsque nous avons besoin de dboguer un programme, nous ne faisons gnralement quinsrer quelques instructions print ici et l avant de relancer le programme. Dans des jours meilleurs, nous nous rappellerons quil faut activer les avertissements en premier. Cela fait souvent disparatre le problme, en vitant de nous arracher les cheveux (pour ce quil en reste). Mais lorsque cela ne fonctionne pas, il est bon de savoir, en vous attendant patiemment derrire cette bonne vieille option -d, quil existe un adorable petit dbogueur qui peut raccommoder nimporte quoi sauf trouver les bogues votre place. Mais si vous devez vous rappeler une seule chose propos de la personnalisation du dbogueur, cest peut-tre celle-ci : ne restreignez pas la notion de bogue aux choses qui rendent Perl malheureux. Il sagit galement dun bogue si votre programme vous rend malheureux. Plus tt, nous vous avons montr quelques dbogueurs personnaliss trs simples. Dans le prochain paragraphe, nous allons vous montrer un exemple dune diffrente sorte de dbogueur personnalis, une sorte qui peut (ou peut ne pas) vous aider dboguer le bogue connu sous le nom de Est-ce que ce truc va sarrter un jour ? .

Le profileur Perl
Voulez-vous rendre votre programme plus rapide ? La rponse est oui, bien entendu. Mais vous devriez dabord vous arrter est vous demander, Ai-je vraiment besoin de passer du temps rendre ce programme plus rapide ? Loptimisation rcrative peut tre amusante,3 mais normalement, vous avez mieux faire de votre temps. Parfois, vous navez besoin que de planifier votre travail et de lancer le programme pendant que vous allez boire un caf. (Ou vous prenez ceci comme excuse pour en boire un.) Mais si votre programme a absolument besoin de tourner plus rapidement, vous devriez commencer par le profiler. Un profileur peut vous dire quelles parties de votre programme prennent le plus de temps sexcuter, afin que vous ne perdiez pas de temps optimiser un sous-programme dont les effets sont insignifiants par rapport au temps dexcution total.
3. Enfin, daprs Nathan Torkington, qui a contribu la version originale de ce paragraphe.

customer_8566

Le profileur Perl

495

Perl est livr avec un profileur, le module Devel::DProf. Vous pouvez lutiliser pour profiler le programme Perl de mon_code.plx en tapant :
perl -d:DProf mon_code.plx

Mme si nous lavons appel un profileur puisque cest ce quil fait le mcanisme employ par DProf est exactement le mme que celui dont nous avons parl auparavant dans ce chapitre. DProf nest quun dbogueur qui enregistre le temps entre le moment o Perl entre dans chaque sous-programme et celui o il en sort. Lorsque votre script profil se terminera, Dprof dversera les informations mesurant le temps dans un fichier nomm tmon.out. Le programme dprofpp, livr avec Perl, sait comment analyser tmon.out et produit un rapport. Vous pouvez galement utiliser dprofpp comme frontal pour le processus complet avec loption -p (voir la description plus loin). tant donn ce programme :
exterieur(); sub exterieur { for (my $i=0; $i < 100; $i++) { interieur() } } sub interieur { my $total = 0; for (my $i=0; $i < 1000; $i++) { $total += $i } } interieur();

la sortie de dprofpp est :


Total Elapsed Time = 0.158572 Seconds User+System Time = 0.158572 Seconds Exclusive Times %Time ExclSec CumulS #Calls sec/call Csec/c Name 88.2 0.140 0.140 101 0.0014 0.0014 main::interieur 0.00 0.000 0.139 1 0.0000 0.1393 main::exterieur

Remarquez que la somme des pourcentages nest pas gale 100. En fait, dans ce cas, elle en est assez loin, ce qui devrait tre un signe comme quoi vous avez besoin de lancer le programme plus longtemps. En rgle gnrale, plus vous pouvez collecter de donnes de profilage, meilleur sera votre chantillon statistique. Si nous augmentons la boucle extrieure pour tourner 1000 fois au lieu de 100, nous obtiendrons des rsultats plus justes :
Total Elapsed Time = 1.403988 Seconds User+System Time = 1.373988 Seconds Exclusive Times %Time ExclSec CumulS #Calls sec/call Csec/c Name 98.2 1.350 1.348 1001 0.0013 0.0013 main::interieur 0.58 0.008 1.357 1 0.0085 1.3570 main::exterieur

La premire ligne rapporte combien de temps le programme a mis sexcuter, du dbut la fin. La seconde ligne affiche la somme de deux nombres diffrents : le temps pris pour excuter votre code ( user , utilisateur) et le temps pris par le systme dex-

customer_8566

496

Chapitre 20 Le dbogueur Perl

ploitation excuter les appels systmes faits par votre code ( system , systme). (Nous devrons admettre un peu de mauvaise prcision dans ces nombres lhorloge de lordinateur na certainement pas des tics dun millionime de seconde. Elle peut avoir des tics dun centime de seconde si vous avez de la chance.) Les temps user+system peuvent tre changs avec les options de la ligne de commande de dprofpp. -r affiche le temps coul, -s le temps systme uniquement et -u le temps utilisateur seulement. Le reste du rapport est une analyse du temps pass dans chaque sous-programme. La ligne Exclusive Times (Temps exclusifs) indique que lorsque le sous-programme exterieur a appel le sous-programme interieur, le temps pass dans interieur na pas compt dans le calcul du temps de exterieur. Pour changer ceci et faire que le temps de interieur soit comptabilis dans celui dexterieur, donnez loption -I dprofpp. Pour chaque sous-programme, les informations suivantes sont rapportes : %Time, le pourcentage de temps pass dans lappel ce sous-programme ; ExclSec, le temps en secondes pass dans ce sous-programmes, en nincluant pas les sous-programmes appels depuis celui-ci ; CumulS, le temps en secondes pass dans ce sous-programme et dans ceux appels depuis celui-ci ; #Calls, le nombre dappels du sous-programme ; sec/ call, le temps moyen en secondes de chaque appel au sous-programme, en nincluant pas les sous-programmes appels depuis celui-ci ; Csec/c, le temps moyen en secondes de chaque appel au sous-programme et de ceux appels depuis celui-ci. De toutes ces valeurs, la plus utile est %Time, qui vous dira o passe votre temps. Dans notre cas, le sous-programme interieur prend le plus de temps, nous devrions donc essayer de loptimiser ou de trouver un algorithme qui lappellera moins souvent. :-) Les options de dprofpp fournissent un accs dautres informations ou modifient la manire dont les temps sont calculs. Vous pouvez galement pousser dprofpp lancer en premier lier le script votre place, afin que vous nayez pas vous souvenir de loption -d:DProf : -p SCRIPT Dit dprofpp quil devrait profiler le SCRIPT donn et ensuite interprter ses donnes de profilage. Voir galement loption -Q. -Q Utilise avec -p pour dire dprofpp de sortir aprs avoir profil le script, sans interprter les donnes. -a Trie la sortie dans lordre alphabtique des noms de sous-programme plutt que dans lordre dcroissant des pourcentages de temps. -R Compte sparment les sous-programmes anonymes dfinis dans le mme paquetage. Le comportement par dfaut est de compter tous les sous-programmes anonymes en un seul, appel main::__ANON__. -I Affiche les temps des sous-programmes en incluant les temps des sous-programmes fils.

customer_8566

Le profileur Perl
-l

497

Trie les sous-programmes par nombre dappels. Ceci peut faciliter la slection de candidats linclusion par rfrence (inlining). -O COMPTEUR Montre seulement le top COMPTEUR des sous-programmes. La valeur par dfaut est 15. -q Naffiche pas les en-ttes des colonnes. -T Affiche larbre dappel des sous-programmes sur la sortie standard. Les statistiques des sous-programmes ne sont pas affiches. Une fonction appele plusieurs fois (conscutivement) au mme niveau dappel, ne sera affiche quune seule fois, avec un compteur de rptition. -S Produit un affichage structur par la manire dont vos sous-programmes sappellent lun, lautre :
main::interieur x 1 0.00s main::exterieur x 1 1.35s = (0.01 + 1.35)s main::interieur x 1000 1.35s

Lisez ceci ainsi : le niveau suprieur de votre programme a appel interieur une fois et pendant une dure de 0.00 s et le niveau suprieur a appel exterieur une fois et il a tourn pendant 1.35 s inclusivement (0.01 s dans exterieur lui-mme, 1.35 s dans les sous-programmes appels depuis exterieur) en appelant interieur 1000 fois (ce qui a pris 1.35 s). Waouh, compris ? Les branches du mme niveau (par exemple, interieur appel une fois et exterieur appel une fois) sont tries dans lordre des temps inclusifs. -U Ne trie pas. Affiche dans lordre trouv dans le fichier de profilage tel quel. -v Trie dans lordre des temps moyens passs dans les sous-programmes chaque appel. Ceci peut faciliter lidentification de candidats pour une optimisation la main en incluant par rfrence (inlining) le corps des sous-programmes. -g SOUS_PROGRAMME Ignore les sous-programmes sauf SOUS_PROGRAMME et tous ceux qui sont appels depuis celui-ci. Dautres options sont dcrites dans dprofpp(1), sa page de manuel standard. DProf nest pas votre seul choix de profileur. CPAN contient galement Devel::SmallProf, qui rapporte les temps passs dans chaque ligne de votre programme. Cela peut vous aider vous faire une ide si vous utiliser une construction Perl particulire qui savre tonnamment coteuse. La plupart des fonctions internes sont assez efficaces mais il est facile dcrire accidentellement une expression rgulire dont le temps syst-

customer_8566

498

Chapitre 20 Le dbogueur Perl

me (overhead) crot exponentiellement avec la taille de lentre. Voir galement le paragraphe Efficacit au chapitre 24, Techniques couramment employes, pour dautres astuces utiles. Maintenant, allez boire un caf. Vous en aurez besoin pour le prochain chapitre.

customer_8566

Mcanismes internes et accs externes


Comme nous lavons expliqu au chapitre 18, Compilation, perl (le programme) contient la fois un compilateur et un interprteur pour les programmes crits en Perl (le langage). Le compilateur/interprteur Perl est lui-mme crit en C. Dans ce chapitre, nous allons esquisser la manire dont les programmes en C fonctionnent si lon se place dans la perspective de quelquun voulant soit tendre, soit insrer Perl. Lorsque vous tendez Perl, vous mettez un bout de code C (appel lextension) sous le contrle de Perl et lorsque vous insrez Perl, vous mettez un interprteur Perl1 sous le contrle dun programme C plus large. La couverture succinte que nous faisons ici ne remplace en aucun cas les documentations en ligne sur les tripes de Perl : perlguts, perlxs, perlxstut, perlcall, perlapi et h2xs, toutes livres avec Perl. Encore une fois, moins que vous ntendiez ou insriez Perl, vous naurez jamais besoin de connatre tout ceci. En supposant que vous avez besoin de savoir, ce que vous devez savoir en premier est un peu des entrailles de Perl. Vous aurez galement besoin de connatre C pour la plupart de ce qui suit. Vous aurez besoin dun compilateur C pour lancer les exemples. Si votre but final est de crer un module dont les autres gens se serviront, ils auront galement besoin dun compilateur C. Plusieurs de ces exemples ne tourneront que sur les systmes ressemblant Unix. Oh, et ces informations sont susceptibles de changer dans les futures versions de Perl. En dautres termes, nous pntrons en terra incognita, au risque de rencontrer des monstres marins.

21

1. Alors que nous prenons soin de distinguer le compilateur de linterprteur lorsque cette distinction est importante, cela devient un peu ennuyeux de persister dire compilateur/ interprteur , nous raccourcissons donc cela souvent en interprteur pour signifier la globalit du code et des donnes C fonctionnant comme une instance de perl (le programme) ; lorsque vous incluez du Perl, vous pouvez avoir plusieurs instances de linterprteur mais chacune se comporte en tant que son propre petit perl.

customer_8566

500

Chapitre 21 Mcanismes internes et accs externes

Comment fonctionne Perl


Lorsquon alimente le compilateur Perl avec un programme Perl, la premire tche quil effectue est lanalyse lexicale : dcomposer le programme en ses lments syntaxiques de base (souvent appels tokens). Si le programme est :
print "Salut, tout le monde !\n";

lanalyseur lexical le dcompose en trois tokens : print, "Salut, tout le monde !\n" et le point-virgule final. La squence de tokens est alors analyse syntaxiquement, en fixant les relations entre les tokens. En Perl, la frontire entre lanalyse lexicale et syntaxique est encore plus f loue que dans les autres langages. (Cest--dire, les autres langages informatiques. Si vous pensez toutes les significations que new Bestiau peut prendre selon quil sagit dun paquetage Bestiau ou dun sous-programme appel new, vous comprendrez alors pourquoi. Dun autre ct, nous passons notre temps lever les ambiguts de ce genre en franais.) Une fois quun programme a t analys syntaxiquement et compris (vraisemblablement), il est compil dans un arbre de codes doprations (opcodes), reprsentant les oprations de bas niveau et finalement, cet arbre doprations est excut sauf si vous aviez invoqu Perl avec loption -c ( contrle de la syntaxe ), qui sort aprs avoir termin la phase de compilation. Cest pendant la compilation, et non pendant lexcution, que les blocs BEGIN, les blocs CHECK et les instructions use sont excuts.

Types de donnes internes


Pendant que larbre de codes doprations, constituant un programme Perl, est excut, des valeurs Perl sont cres, manipules et dtruites. Les types de donnes avec lesquels vous tes familier en Perl ont tous leur types de donnes correspondant dans le C que Perl a sous le capot et vous aurez besoin de connatre ces types lorsque vous passerez des donnes entre les deux langages. Trois typedefs (dfinitions de type) C correspondent au trois types de donnes de base de Perl : SV (valeur scalaire), AV (valeur tableau) et HV (valeur hachage). De plus, IV est un type simple entier sign dont on est sr quil est assez grand pour contenir soit un pointeur, soit un entier ; et I32 et I16 sont des types dont est sr quils sont assez grands pour contenir respectivement 32 et 16 bits. Pour stocker les versions non signes des ces trois derniers typedefs, il existe galement UV U32 et U16. Tous ces typedefs peuvent tre ma, nipuls avec les fonctions C dcrites dans la documentation de perlguts. Nous esquissons le comportement de certaines de ces fonctions ci-dessous : Il existe quatre types de valeurs pouvant tre copies dans un SV : une valeur entire (IV), un double (NV), une chane (PV) et un autre scalaire (SV). Il existe des douzaines de fonctions pour les SV pour vous permettre de crer, de modifier, dagrandir , et de vrifier la vrit boolenne ou le fait que les scalaires Perl quils reprsentent soient dfinis. Les rfrences Perl sont implmentes en tant que RV un type spcial , de SV . Lorsquun AV est cr, il peut tre cr vide ou peupl de SV, ce qui est sens puisquun tableau est une collection de scalaires. Le HV possde des fonctions C associes pour stocker, rcuprer, supprimer et vrifier lexistence de paires clef/valeur dans le hachage que le HV reprsente.

customer_8566

tendre Perl (utiliser du C depuis du Perl)

501

Il existe galement un GV (valeur glob), pouvant contenir des rfrences vers nimporte laquelle des valeurs associes un identificateur de variable : une valeur scalaire, un valeur tableau, une valeur hachage, un sous-programme, un handle dentre/sortie ou un format.

Lorsque vous tendez Perl, vous aurez parfois besoin de connatre ces valeurs lorsque vous crerez les liaisons vers les fonctions C. Lorsque vous insrez Perl, vous aurez besoin de connatre ces valeurs lorsque vous changerez des donnes avec linterprteur Perl inclus dans votre programme C.

tendre Perl (utiliser du C depuis du Perl)


Si vous voulez utiliser du code source C (ou une bibliothque C) depuis Perl, vous devez crer une bibliothque qui puisse tre charge dynamiquement ou avec laquelle vous puissiez faire une dition de liens statique avec lexcutable perl. (On prfre dordinaire le chargement dynamique pour minimiser le nombre des diffrents excutables perl qui prennent place en tant diffrents.) Vous crez cette bibliothque en crant un fichier XS (avec un suffixe .xs) contenant une srie de sous-programmes denveloppe (wrapper). Les sous-programmes denveloppe ne sont toutefois pas des sous-programmes Perl ; ils sont crits en langage XS et nous appelons un tel sous-programme, une XSUB (pour eXternal SUBroutine , routine externe). Une XSUB peut envelopper une fonction C depuis une bibliothque externe, une fonction C ailleurs dans le fichier XS ou du code C brut dans la XSUB elle-mme. Vous pouvez alors utiliser lutilitaire xsubpp, livr avec Perl pour prendre le fichier XS et le traduire en code C qui puisse tre compil dans une bibliothque que Perl comprendra. En supposant que votre systme dexploitation implmente ldition de liens dynamique, le rsultat final sera un module Perl se comportant comme tout autre module crit 100 % en Perl pur mais contenant sous le capot du code C compil. Il fait ceci en enlevant des arguments depuis la pile darguments de Perl, en convertissant les valeurs Perl vers les formats attendus par une fonction C particulire (spcifis travers une dclaration de XSUB), en appelant la fonction C et en retransfrant finalement les valeurs renvoyes par la fonction C vers Perl. Ces valeurs de retour peuvent tre repasses Perl soit en les mettant dans la pile de Perl, soit en modifiant les arguments fournis depuis Perl. (Si votre systme nimplmente pas ldition de liens dynamique, il existe un autre cerceau dans lequel vous devrez sauter et nous en parlerons dans le prochain paragraphe.) La description prcdente est en quelque sorte une vision simplifie de ce qui se passe rellement. Puisque Perl autorise des conventions dappels plus f lexibles que C, les XSUB peuvent en faire bien plus en pratique, comme vrifier la validit des paramtres dentre, lever des exceptions, renvoyer undef ou une liste vide, appeler diffrentes fonctions C en se basant sur le nombre et le type des arguments ou fournir une interface oriente objet. Encore une fois, voir les pages de manuel de perlxs et perlxstut.

XS et XSUB
XS est un moyen pratique : il ny a rien qui vous empche dcrire du code de glu directement en C et de le lier dans votre excutable Perl. Toutefois, ceci serait pnible, parti-

customer_8566

502

Chapitre 21 Mcanismes internes et accs externes

culirement si vous devez crire la glu pour de multiples fonctions C ou si vous ntes pas familier avec la discipline de la pile de Perl et autres mystres. XS vous permet dcrire une description concise de ce qui devrait tre fait par la glu et le compilateur XS, xsubpp, soccupe du reste. Pour les gens qui ne trouvent pas XS assez pratique, le systme SWIG gnre automatiquement des XSUB simples. Voir http:://www.swig.org pour plus dinformations. Le langage XS vous permet de dcrire la correspondance entre une fonction C et une fonction Perl. Il vous permet galement dcrire une fonction Perl qui soit une enveloppe autour de code C pur que vous crivez vous-mme. Lorsque XS est utiliser uniquement pour faire la correspondance entre C et Perl, la dclaration dune XSUB est quasiment identique la dclaration dune fonction C. Dans de telles circonstances, un outils appel h2xs (livr avec Perl) est capable de traduire un fichier den-tte C entier vers un fichier XS correspondant, fournissant la glu vers les fonctions C et les macros. Loutil xsubpp cre les constructions ncessaires pour permettre une XSUB de manipuler des valeurs Perl et la glu ncessaire pour permettre Perl dappeler la XSUB. Un fichier XS commence par le code C que vous voulez inclure, ce qui nest souvent rien de plus quun ensemble de directives #include. Aprs un mot-cl MODULE, le reste du fichier devrait tre dans le langage XS, une combinaison de directives XS et de dfinitions de XSUB. Nous verrons bientt lexemple dun fichier XS complet mais en attendant, voici la dfinition dune XSUB simple, permettant un programme Perl daccder une fonction de bibliothque C, appele sin(3). La XSUB spcifie le type renvoy (un nombre en virgule f lottante double prcision), le nom de la fonction et une liste dargumentd (avec un argument traduit x), ainsi que le type de largument (un autre double) :
double sin(x) double x

Les XSUB plus compliques contiendront souvent dautres morceaux de code XS. Chaque section dune XSUB commence par un mot-cl suivi dun deux-points, tel que INIT: ou CLEANUP:. Cependant, les deux premires lignes dune XSUB contiennent toujours les mmes donnes : la description du type renvoy et le nom de la fonction avec ses paramtres. Tout ce qui suit immdiatement ceci est considr comme tant une section INPUT: sauf si on le marque explicitement avec un autre mot-cl. Les divers mots-cls sont tous expliqus dans la page de manuel perlxs, que vous devriez lire pour apprendre tout ce que vous pouvez faire avec les XSUB. Si votre systme nest pas capable de charger dynamiquement des bibliothques partages, vous pouvez toujours utiliser des XSUB mais vous devez faire une dition de liens statique des XSUB avec le reste de Perl, crant ainsi un nouvel excutable Perl (qui prend place en tant diffrent). Le mcanisme de construction dune XSUB vrifiera le systme et construira une bibliothque partage si possible, sinon une bibliothque statique. Optionnellement, il peut construire un nouvel excutable li statiquement avec cette bibliothque statique incluse. Mais vous pourriez vouloir attendre pour lier toutes vos nouvelles extensions dans un seul excutable (qui prend place en tant le mme, puisque cest ce quil est.) Si votre systme est capable de lier dynamiquement les bibliothques mais que vous

customer_8566

tendre Perl (utiliser du C depuis du Perl)

503

voulez toujours construire un excutable li statiquement, vous pouvez lancer make perl au lieu de make dans les exemples suivants. Vous devrez ensuite lancer make test_static au lieu de make test pour tester votre extension. Le programme xsubpp a galement besoin de savoir comment convertir des types de donnes Perl en types de donnes C. Il le devine souvent mais avec des types dfinis par lutilisateur, vous pouvez avoir besoin de laider en spcifiant la conversion dans un fichier typemap (littralement : carte des types). Les conversions par dfaut sont stockes dans CHEMIN-VERS-LA-BIBLIOTHQUE/ExtUtils/typemap. Le fichier typemap est dcoup en trois sections. La premire, tiquete TYPEMAP dit au , compilateur quels sont les fragments de code parmi ceux des deux sections suivantes devraient tre utilises pour faire la correspondance entre les types C et les valeurs Perl. La deuxime section, INPUT, contient du code C spcifiant comment les valeurs Perl devraient tre converties en types C. La troisime section, OUTPUT, contient du code C spcifiant comment traduire les types C en valeurs Perl.

Cration dextensions
Une extension convenable consiste en plusieurs fichiers : lun contenant le code XS, plus des fichiers implments qui aident Perl deviner quoi faire avec le code XS. Vous pouvez crer tous ces fichiers la main mais il est plus facile dutiliser loutil h2xs, qui cre un squelette dextension que vous pouvez ensuite complter :
h2xs -A -n Montest

Ceci cre un rpertoire nomm Montest, peut-tre sous ext/ si ce rpertoire existe dans le rpertoire courant. Six fichiers seront crs dans le rpertoire Montest : MANIFEST, Makefile.PL, Montest.pm, Montest.xs, test.pl et Changes. Nous dcrivons les quatre premiers ci-dessous. MANIFEST Le fichier MANIFEST contient le nom de tous les fichiers qui viennent dtre crs dans le rpertoire Montest. Si vous ajoutez dautres fichiers dans votre extension et que vous la distribuez au monde entier, ajouter le nom des fichiers ici. Ceci est test par certains systmes pour sassurer que votre distribution est complte. Makefile.PL Il sagit dun programme Perl gnrant un Makefile (qui est ensuite pass make ou un quivalent). Makefile.PL est dcrit plus en dtail dans Crer des modules CPAN au chapitre 22, CPAN . Montest.pm Les utilisateurs feront un use sur ce module lorsquils voudront charger votre extension. Vous tes supposs remplir les blancs du module squelette cr pour vous par h2xs2 :
package Montest;

2. N.d.T. : Le squelette gnr par h2xs contient des commentaires en anglais. Toutefois, nous les avons traduits ici pour une meilleure comprhension.

customer_8566

504
use strict; use warnings; require Exporter; require DynaLoader;

Chapitre 21 Mcanismes internes et accs externes

our @ISA = qw(Exporter DynaLoader); # lments exporter par dfaut dans les espaces de noms des appelants. # Remarque : Nexportez pas des noms par dfaut sans une trs bonne # raison. Utilisez plutt EXPORT_OK. Nexportez pas btement toutes vos # fonctions/mthodes/constantes. our @EXPORT = qw( ); our $VERSION = 0.01; bootstrap Montest $VERSION; # Les mthodes prcharges viennent ici. # Les mthodes autocharges viennent aprs __END__ et sont traites par # le programme autosplit. 1; __END__ # En-dessous se trouve une souche de documentation pour votre module. # Vous feriez mieux de lditer !

La plupart des modules dextension feront un require des extensions Exporter et DynaLoader. Aprs avoir aliment @ISA (pour lhritage) et @EXPORT (pour rendre les fonctions disponibles pour le paquetage utilisant le module), le code dinitialisation dit Perl damorcer (bootstrap) le code XS. Perl lie alors dynamiquement la bibliothque partage dans le processus perl lexcution. Montest.xs Le fichier Montest.xs contient les XSUB disant Perl comment passer les donnes aux routines C compiles. Initialement, Montest.xs ressemblera quelque chose comme ceci :
#include "EXTERN.h" #include "perl.h" #include "XSUB.h" MODULE = Montest PACKAGE = Montest

ditons le fichier XS en ajoutant ceci la fin :


void salut() CODE: printf("Salut, tout le monde !\n");

Lorsque vous lancez perl Makefile.PL, le Makefile dont make a besoin est cr :

customer_8566

tendre Perl (utiliser du C depuis du Perl)


% perl Makefile.PL Checking if your kit is complete... Looks good Writing Makefile for Montest

505

Le lancement de make produit maintenant un affichage qui ressemble ceci (certaines lignes trop longues ont t raccourcies pour plus de clart et certaines lignes accessoires ont t supprimes) :
% make umask 0 && cp Montest.pm ./blib/Montest.pm perl xsubpp -typemap typemap Montest.xs >Montest.tc && mv Montest.tc Montest.c cc -c Montest.c Running Mkbootstrap for Montest () chmod 644 Montest.bs LD_RUN_PATH="" ld -o ./blib/PA-RISC1.1/auto/Montest/Montest.sl -b Montest.o chmod 755 ./blib/PA-RISC1.1/auto/Montest/Montest.sl cp Montest.bs ./blib/PA-RISC1.1/auto/Montest/Montest.bs chmod 644 ./blib/PA-RISC1.1/auto/Montest/Montest.bs Manifying ./blib/man3/Montest.3

Nous supposons que le programme make que Perl utilise pour construire le programme est appel make. Au lieu de lancer make dans ces exemple, il se peut que vous deviez substituer un autre programme make que Perl a t configur pour utiliser. Vous pouvez trouver ce programme avec :
% perl -V:make

Le lancement de make a cr un rpertoire nomm blib (pour build library , bibliothque de construction) dans le rpertoire de travail courant. Ce rpertoire contiendra la bibliothque partage que nous construirons. Une fois que nous sommes srs que nous savons ce que nous faisons, nous pouvons linstaller depuis ce rpertoire vers son emplacement dfinitif. Jusqualors, nous devrons ajouter explicitement le rpertoire blib au tableau @INC de Perl en utilisant le module ExtUtils::testlib. Si nous crons maintenant un fichier appel salut, ressemblant ceci :
use ExtUtils::testlib; use Montest; Montest::salut(); % perl salut Salut, le monde ! # ajoute les rpertoires blib/* @INC

nous pouvons creuser un passage depuis Perl vers C :

Une fois que notre extension est acheve et quelle a pass tous ses tests, nous pouvons linstaller avec make install. Vous aurez besoin des permissions en criture pour votre bibliothque Perl. (Si ce nest pas le cas, vous pouvez spcifier un autre rpertoire comme indiqu dans Installation des modules de CPAN dans la bibliothque Perl au chapitre 22.)

customer_8566

506

Chapitre 21 Mcanismes internes et accs externes

Entres et sorties des XSUB


En poursuivant lexemple prcdent, nous ajouterons une seconde XSUB, prenant un seul argument numrique en entre et renvoyant 1 si le nombre est pair et 0 sil est impair :
int est_pair(x) int x CODE: RETVAL = (x %2 == 0); OUTPUT: RETVAL

La liste des paramtres de sortie arrive tout la fin de la fonction, juste aprs la directive OUTPUT:. Lutilisation de RETVAL indique Perl que vous souhaitez renvoyer cette valeur comme valeur de retour de la XSUB. Si nous avions voulu que la fonction modifie son paramtre dentre, nous aurions utilis x la place de RETVAL. Nous pouvons construire nouveau notre nouvelle bibliothque partage avec les mmes tapes quavant, en gnrant un Makefile partir du Makefile.PL et en lanant make. Pour tester que notre extension fonctionne, nous crerons une suite de tests dans test.pl. Ce fichier est initialis par h2xs pour imiter le script de test de Perl lui-mme. lintrieur de ce script, vous pouvez lancer des tests pour confirmer que lextension se comporte comme il faut, en affichant ok lorsque cest le cas et not ok dans le cas contraire. Changez linstruction daffichage dans le bloc BEGIN de test.pl en print "1..4\n"; et ajoutez le code suivant la fin de ce fichier :
print Montest::est_pair(0) == 1 ? "ok 2" : "not ok 2", "\n"; print Montest::est_pair(1) == 0 ? "ok 3" : "not ok 3", "\n"; print Montest::est_pair(2) == 1 ? "ok 4" : "not ok 4", "\n";

Le script de test sexcutera lorsque vous taperez make test.

Utilisation des fonctions venant dune bibliothque C externe


Jusquici, nos deux exemples ne reposaient sur aucun code C se trouvant lextrieur du fichier XS. Nous utiliserons maintenant quelques fonctions de la bibliothque mathmatique C :
void arrondi(arg) double arg CODE: if (arg > 0.0) { arg = floor(arg + 0.5); } else if (arg < 0.0) { arg = ceil(arg - 0.5); } else { arg = 0.0; }

customer_8566

Insrer Perl (utiliser Perl depuis C)


OUTPUT: arg

507

Remarquez que larrondi que nous dfinissons ci-dessus ne renvoie pas de valeur mais change plutt la valeur de son argument sur place. Les fonctions floor(3) et ceil(3) font partie de la bibliothque mathmatique C. Si vous compiliez un programme C et que vous aviez besoin de faire une dition de liens avec la bibliothque mathmatique, vous ajouteriez -lm la ligne de commande, cest donc ce que vous mettez dans la ligne LIBS du fichier Makefile.PL :
LIBS => [-lm], # Se lie avec la biblio mathmatique m

Gnrez le Makefile et lancez make. Changez le bloc BEGIN pour lancer neuf tests et ajouter ce qui suit dans test.pl :
$i $i $i $i $i = = = = = -1.5; Montest::arrondi($i); print $i == -2.0 -1.1; Montest::arrondi($i); print $i == -1.0 0.0; Montest::arrondi($i); print $i == 0.0 ? 0.5; Montest::arrondi($i); print $i == 1.0 ? 1.2; Montest::arrondi($i); print $i == 1.0 ? ? "ok 5" ? "ok 6" "ok 7" : "ok 8" : "ok 9" : : "not ok 5", "\n"; : "not ok 6", "\n"; "not ok 7", "\n"; "not ok 8", "\n"; "not ok 9", "\n";

Le lancement de make test devrait maintenant afficher que ces neuf tests sont ok. La documentation, perlxstut, livre avec Perl, prsente plusieurs autres exemples dextensions Perl, y compris un exemple utilisant h2xs pour rendre automatiquement disponible une bibliothque C entire Perl.

Insrer Perl (utiliser Perl depuis C)


Vous pouvez accder un interprteur Perl depuis du C en insrant Perl lintrieur de votre programme C. Puisque Perl est lui-mme un programme, linsertion consiste prendre les morceaux importants de Perl est les intgrer dans les vtres. Remarquez que linsertion nest pas ncessaire si votre seul but est dutiliser un programme Perl pouvant fonctionner de manire indpendante et que cela ne vous drange pas de lancer un processus spar. Vous pouvez utiliser une fonction comme popen(3) de C pour changer vos donnes entre votre programme C et tout programme Perl externe, exactement comme vous pouvez utiliser open(PIPE, "| programme") ou IPC::Open2 et IPC::Open3 de Perl pour changer des donnes entre votre programme Perl et tout autre programme. Mais si vous voulez viter le surcot du lancement dun processus spar, vous pouvez insrer un interprteur dans votre programme C. Lors du dveloppement dapplications devant tourner longtemps (par exemple pour linsertion dans un serveur web), cest une bonne ide de maintenir un seul interprteur persistant plutt que de crer et de dtruire des interprteurs encore et encore. La raison majeure est la vitesse, puisque Perl ne sera charg quune seule fois en mmoire. En utilisant un interprteur Perl persistant, le module mod_perl dApache vite de charger Perl en mmoire nouveau chaque fois que quelquun charge une page web dApache. La page de manuel perlembed donne un exemple dinterprteur persistant, ainsi quun exemple de la manire dont un programme Perl peut grer de multiples interprteurs simultans (un autre atout majeur pour les serveurs web).

customer_8566

508

Chapitre 21 Mcanismes internes et accs externes

Compilation des programmes insrs


Lorsque vous insrez Perl dans C, gnralement votre programme C allouera, excutera puis dsallouera un objet PerlInterpreter, qui est une struct C dfinie dans la bibliothque libperl qui a t construite dans le processus de configuration de Perl pour votre systme. La bibliothque libperl (ainsi que EXTERN.h et perl.h, dont vous aurez galement besoin) se trouve dans un rpertoire qui variera dun systme lautre. Vous devriez tre capable de trouver le nom de ce rpertoire avec :
% perl -MConfig -e "print $Config{archlib}"

Vous devriez compiler votre programme exactement de la mme manire que votre excutable perl a t compil. Tout dabord, vous aurez besoin de savoir quel compilateur C a t utilis pour construire Perl sur votre machine. Vous pouvez lapprendre avec :
% perl -MConfig -e "print $Config{cc}"

Vous pouvez deviner quoi mettre sur la ligne de commande avec le module standard ExtUtils::Embed. Si vous aviez un programme C appel interp.c et que votre compilateur C tait cc, vous pourriez le compiler pour linsrer comme ceci :
% cc -o interp interp.c perl -MExtUtils::Embed -e ccopts -e ldopts

Ajout dun interprteur Perl votre programme C


Comme perl (le programme C) savre tre un bon exemple dinsertion de Perl (le langage), une dmonstration simple de linsertion peut tre trouve dans le fichier miniperlmain.c, dans le code source de Perl. Voici une version non portable de miniperlmain.c, contenant les principes essentiels de linsertion :
#include <EXTERN.h> #include <perl.h> /* depuis la distribution de Perl */ /* depuis la distribution de Perl */

static PerlInterpreter *mon_perl; /*** Linterprteur Perl ***/ int main(int argc, char **argv, char **env) { mon_perl = perl_alloc(); perl_construct(mon_perl); perl_parse(mon_perl, NULL, argc, argv, (char **)NULL); perl_run(mon_perl); perl_destruct(mon_perl); perl_free(mon_perl); }

Lorsque ceci sera compil avec la ligne de commande donne plus haut, vous serez capable dutiliser interp exactement comme un interprteur perl ordinaire :
% interp -e "printf(%x, 3405707998)" cafefade

Vous pouvez galement utiliser des instructions Perl stockes dans un fichier en plaant le nom du fichier dans argv[1] avant dappeler perl_run.

customer_8566

Insrer Perl (utiliser Perl depuis C)

509

Appel dun sous-programme Perl depuis C


Si un programme Perl contient un sous-programme que vous voulez appeler depuis un programme C, vous pouvez crer un interprteur Perl, puis utiliser lune des fonctions commenant par call_, documentes dans la page de manuel perlcall, pour invoquer ce sous-programme. Supposons que ceci soit votre programme Perl, appel affiche_heure.plx :
print "Je peux pas tre affich."; sub affiche_heure { print time; }

Dans cet exemple, nous utiliserons call_argv pour invoquer le sous-programme affiche_heure depuis ce programme C appel affiche_heure.c :
#include <EXTERN.h>; #include <perl.h> static PerlInterpreter *mon_perl; int main(int argc, char **argv, char **env) { char *args[] = { NULL }; mon_perl = perl_alloc(); perl_construct(mon_perl); perl_parse(mon_perl, NULL, argc, argv, NULL); /*** court-circuite perl_run() ***/ call_argv("affiche_heure", G_DISCARD | G_NOARGS, args); perl_destruct(mon_perl); perl_free(mon_perl); }

Ici, nous supposons que affiche_heure est un sous-programme Perl qui ne prend pas dargument (cest le G_NOARGS) et pour lequel nous pouvons ignorer la valeur de retour (cest le G_DISCARD). Ces drapeaux, et dautres, sont prsents dans perlcall. Nous compilons et lanons affiche_heure comme ceci :
% cc -o affiche_heure affiche_heure.c perl -MExtUtils::Embed -e ccopts -e ldopts % affiche_heure affiche_heure.pl 996412873

Dans ce cas particulier, nous nappelons pas perl_run mais, en gnral, on considre que cest une bonne formule pour que les mthodes DESTROY et les blocs END soient excuts au bon moment. Si vous voulez passer des arguments au sous-programme Perl, vous pouvez ajouter des chanes la liste args, termine par un NULL, passe call_argv. Pour dautres types de donnes, ou pour examiner les valeurs de retour, vous aurez besoin de manipuler la pile

customer_8566

510

Chapitre 21 Mcanismes internes et accs externes

de Perl. Nous aborderons ceci un peu plus tard ; pour les rouages et le cambouis, lisez la page de manuel perlcall, livre avec Perl.

valuation dune instruction Perl depuis C


Perl fournit deux fonctions pour valuer des extraits de code Perl : eval_sv et eval_pv, dcrites dans la page de manuel perlapi. De faon discutable, celles-ci sont les seules routines dont vous aurez jamais besoin pour excuter du code Perl depuis votre programme C. Le code excut peut tre aussi long que vous le dsirez, contenir plusieurs instructions et employer use, require ou do pour inclure dautres fichiers Perl. eval_pv vous permet dvaluer des chanes Perl individuelles, puis dextraire des variables pour la coercition en type C. Le programme suivant, chaine.c, excute trois chanes Perl, en extrayant un int depuis la premire, un float depuis la deuxime et un char * depuis la troisime :
#include <EXTERN.h> #include <perl.h> static PerlInterpreter *mon_perl; main (int argc, char **argv, char **env) { STRLEN n_a; char *insertion[] = { "", "-e", "0" }; mon_perl = perl_alloc(); perl_construct( mon_perl ); perl_parse(mon_perl, NULL, 3, insertion, NULL); perl_run(mon_perl); /** Traite $a en tant quentier **/ eval_pv("$a = 3; $a **= 2", TRUE); printf("a = %d\n", SvIV(get_sv("a", FALSE))); /** Traite $a en tant que flottant **/ eval_pv("$a = 3.14; $a **= 2", TRUE); printf("a = %f\n", SvNV(get_sv("a", FALSE))); /** Traite $a en tant que chane **/ eval_pv("$a = lreP rueugnoM ertua nu erocnE; $a = reverse($a);", TRUE); printf("a = %s\n", SvPV(get_sv("a", FALSE), n_a)); perl_destruct(mon_perl); perl_free(mon_perl); }

Toutes les fonctions avec Sv dans le nom, convertissent des scalaires Perl en type de C. Elles sont dcrites dans les pages de manuel perlguts et perlapi. Si vous compilez et excutez ce programme, vous verrez ce quengendre, comme rsultats, lutilisation de SvIV

customer_8566

Insrer Perl (utiliser Perl depuis C)


pour crer un int, SvNV pour crer un float et SvPV pour crer une chane C :
a = 9 a = 9.9596000 a = Encore un autre Mongueur Perl

511

Dans lexemple prcdent, nous avons cr une variable globale pour stocker temporairement la valeur calcule de notre expression value. Il est galement possible (et dans la plupart des cas, cest une meilleure solution) dutiliser la valeur de retour deval_pv plutt que de sen dbarrasser :
SV *val = eval_pv("reverse lreP rueugnoM ertua nu erocnE", TRUE); printf("%s\n", SvPV(val,n_a));

La page de manuel perlembed, livre avec Perl, comprend une dmonstration de eval_sv vous permettant dutiliser les fonctionnalits dexpressions rgulires de Perl depuis votre programme C.

Bricolage de la pile de Perl depuis C


En essayant dexpliquer les piles, la plupart des manuels informatiques3 marmonnent quelque chose propos dune pile dassiettes de caftria : la dernire chose que vous avez pose sur la pile est la premire que vous retirez. a ira pour nos objectifs : votre programme C poussera des arguments sur la pile de Perl , fermera les yeux pendant que la magie opre, puis retirera les rsultats les valeurs renvoyes par votre sous-programme Perl de la pile. Nous allons prsenter ici un exemple sans trop dexplications. Pour vraiment comprendre ce qui se passe, vous aurez besoin de savoir comment faire des conversions entre les types C et les types Perl, avec newSVic, sv_setnv, newAV et tous leurs amis dcrits dans les pages de manuels perlguts et perlapi. Vous aurez ensuite besoin de lire perlcall pour apprendre comment manipuler la pile de Perl. Comme C ne possde pas de fonction interne pour lexponentiation dentiers, rendons loprateur ** de Perl accessible en C. (Ceci est moins utile quil ny parat, puisque Perl implmente ** avec la fonction pow(3) de C.) Tout dabord, nous allons crer une fonction dexponentiation dans un fichier de bibliothque appel puissance.pl :
sub expo { my ($a, $b) = @_; return $a ** $b; }

Maintenant, nous allons crer un programme C, puissance.c, avec une fonction appel PuissancePerl, poussant les deux arguments dans la pile, invoquant expo et retirant la valeur de retour :
#include <EXTERN.h> #include <perl.h> static PerlInterpreter *mon_perl;

3. Plus le livre Perl de circonstance.

customer_8566

512

Chapitre 21 Mcanismes internes et accs externes

/* "Les vrais programmeurs savent crire du code assembleur dans nimporte quel langage." */ static void PuissancePerl(int a, int b) { dSP; /* initialise un pointeur sur la pile */ ENTER; /* tout est cr aprs ceci */ SAVETMPS; /* ...est une variable temporaire. */ PUSHMARK(SP); /* se souvient du pointeur de pile */ XPUSHs(sv_2mortal(newSViv(a))); /* pousse la base sur la pile */ XPUSHs(sv_2mortal(newSViv(b))); /* pousse lexposant sur la pile */ PUTBACK; /* rend local le pointeur de pile global */ call_pv("expo", G_SCALAR); /* appelle la function */ SPAGAIN; /* rafrachit le pointeur de pile */ /* retire la valeur de retour de la pile */ printf ("%d la puissance %d vaut %d.\n", a, b, POPi); PUTBACK; FREETMPS; /* dsalloue la valeur de retour */ LEAVE; /* ...et les arguments mortels de XPUSH */ } int main (int argc, char **argv, char **env) { char *my_argv[] = { "", "puissance.pl" }; mon_perl = perl_alloc(); perl_construct( mon_perl ); perl_parse(mon_perl, NULL, 2, my_argv, (char **)NULL); perl_run(mon_perl); PuissancePerl(3, 4); perl_destruct(my_perl); perl_free(my_perl); } /*** Calcule 3 ** 4 ***/

Vous pouvez compiler puissance.c pour donner lexcutable puissance ainsi :


% cc -o puissance puissance.c perl -MExtUtils::Embed -e ccopts -e ldopts % puissance 3 la puissance 4 vaut 81.

Maintenant votre programme puissance peut prendre place en tant galement diffrent.

Morale de lhistoire
Vous pouvez parfois crire du code plus rapide en C mais vous pouvez toujours crire plus rapidement du code en Perl. Puisque vous pouvez utiliser lun depuis lautre (et inversement), vous navez qu combiner leurs forces comme il convient. (Et passez le bonjour aux monstres marins des terra incognita.)

customer_8566

Culture Perl

IV

customer_8566

customer_8566

22
Une fois dans le rpertoire principal de CPAN, vous verrez quelques sous-rpertoires : authors

CPAN

CPAN (Comprehensive Perl Archive Network, le rseau darchives dtailles de Perl) est le dpt central pour tout ce qui concerne Perl. Il contient la sagesse engrange par la communaut Perl tout entire : des centaines de modules et de scripts Perl, une documentation reprsentant la valeur de plusieurs livres et la distribution complte de Perl. Si quelque chose est crit en Perl, utile et libre, il est certainement sur CPAN. Il existe des miroirs de CPAN dans le monde entier et vous pouvez en trouver prs de chez vous grce au multiplexeur de CPAN, situ ladresse http://www.perl.com/CPAN. Le multiplexeur se souviendra du miroir que vous avez choisi pour que vous y soyez automatiquement redirig lorsque vous reviendrez sur http://www.perl.com/CPAN/ (faites attention au slash la fin). Vous pouvez galement commencer www.cpan.org. Linterface est diffrente mais les donnes sont les mmes.

Ce rpertoire contient de nombreux sous-rpertoires raison de un par contributeur de logiciel. Par exemple, si vous dsirez trouver le superbe module CGI de Lincoln Stein1 et que vous tes parvenus savoir de source sre quil en est lauteur, vous pouvez regarder dans authors/Lincoln_Stein. Si vous ne savez pas qui la crit, vous pouvez chercher dans le rpertoire modules, dcrit ci-dessous. doc Ce rpertoire contient toutes les formes de documentation de Perl, y compris toutes les pages de manuel officielles de Perl dans plusieurs formats et arrangement diffrents, comme du texte, du HTML, du PostScript et du pod, le format natif de Perl, document au chapitre 26. modules Ce rpertoire contient des modules crits soit en Perl, soit en combinant Perl et C. Voir la discussion propos du rpertoire modules ci-dessous.
1. Qui fait maintenant partie de la distribution standard de Perl.

customer_8566

516
ports

Chapitre 22 CPAN

Ce rpertoire contient le code source et galement quelques fois des images excutables prcompiles des portages de Perl vers des systmes dexploitations qui ne sont pas directement supports dans la distribution standard ou pour lesquels il est de notorit publique que les compilateurs sont difficiles se procurer. Ces portages rsultent des efforts individuels de leurs auteurs respectifs et peuvent ne pas fonctionner prcisment comme ce livre lindique. De nos jours, peu de systmes ncessitent un portage spcifique. Il est toutefois intressant de regarder le document dindex de ce rpertoire car il comprend galement des informations dtaillant le moment o chaque vendeur de systmes a commenc livrer Perl. scripts Ce rpertoire contient une petite collection de divers programmes Perl provenant du monde entier. Ils sont trs utiles en tant que programmes seuls et comme exemples (bien que le code ne soit pas assujetti aux vrifications de contrle de qualit). En ce moment, il ny a pas beaucoup de programmes rpertoris mais nous esprons que cette zone senrichira avec le temps. Le projet Perl Power Tool (PPT, Puissants outils en Perl) se trouve galement ici. Le projet PPT a pour but de recrer en Perl tous les utilitaires standards dUnix. La plupart des outils standards sont dj intgrs, plus quelques-uns qui ne sont pas standards. src Dans ce rpertoire, vous trouverez le code source de la distribution standard de Perl. En fait, de deux distributions standards de Perl. Lune est indique comme stable et lautre comme devel (version de dveloppement). (La page dindex de ce rpertoire explique tous les dtails.) Il sagit seulement de liens vers les versions appropries. Au moment o nous crivons, stable.tar.gz est un lien symbolique vers perl-5.6.1.tar.gz2, mais il est susceptible de pointer vers une version plus leve au moment o vous lirez ceci. Cet norme fichier contient le code source complet et la documentation de Perl. La configuration et linstallation devraient tre relativement simples sur la plupart des plates-formes. Si ce nest pas le cas, voyez le rpertoire ports dcrit prcdemment.

Le rpertoire modules de CPAN


Bien que CPAN contiennent le code source complet de Perl, plus quelques distributions binaires pour les systmes privs de compilateurs C, ainsi que quelques programmes, CPAN est surtout connu pour sa collection de modules. Lorsque nous parlons de modules , nous voulons dire trois choses : de purs modules Perl 100 % (dcrits aux chapitres 11 et 12), des extensions (des modules dpendant de code C, dcrits au chapitre 21) et des pragmas (des modules contenant des instructions spciales pour le compilateur de Perl, dcrits au chapitre 31). Il existe galement sur
2. Le schma gnral est que si le deuxime nombre de la version est pair, il sagit dune version maintenue ; sil est impair, il sagit dune version de dveloppement. Lextension .tar.gz, qui est parfois crite .tgz, indique quil sagit du format standard de lInternet pour une archive tar GNUzippe, couramment appele tarball .

customer_8566

Le rpertoire modules de CPAN

517

CPAN des bundles (groupements) de modules. Les bundles sont des collections de modules qui interagissent dune manire ou dune autre et qui sont gnralement la production dun dveloppeur de modules dsirant fournir une solution autonome un ensemble de problmes. Si un module dpend dun autre (et ventuellement dune version spcifique), les dveloppeurs grouperont souvent les modules dans un bundle. Voir par exemple Bundle-XML. Une faon de parcourir les modules de CPAN est de vous rendre ladresse http:// search.cpan.org, qui fournit un frontal de moteur de recherche pour CPAN. Une autre manire est de vous rendre sur votre miroir local de CPAN et dentrer dans le rpertoire modules, o vous verrez trois sous-rpertoires : by-authors, by-category et by-module (par auteur, par catgorie et par module). Le rpertoire by-module peut tre le plus utile si votre navigateur possde une fonctionnalit de recherche bien que (lamentablement) certains modules ne sont disponibles que dans les rpertoires sous author. Si vous recherchez par catgorie, vous obtiendrez les choix suivants : Perl core modules, langage extensions, and documentation tools (Modules centraux de Perl, extensions de langage et outils pour la documentation) Cette catgorie comprend des pragmas et dautres modules standards, des modules qui vous aident crire diffremment en Perl, des modules en rapport avec le compilateur de Perl, des filtres pour le code source et des modules en rapport avec pod, le format de documentation de Perl. Cette catgorie comprend galement des modules pour gnrer du bytecode Java. Development support (Support du dveloppement) Cette catgorie comprend des modules pour en crer dautres et examiner comment Perl lance des programmes. Operating system interfaces and hardware drivers (Interfaces de systmes dexploitation et pilotes matriels) Vous trouverez ici des modules pour interagir avec des entits tranges comme des systmes dexploitations, des PalmPilots ou des ports srie. Networking, device control and interprocess communication (Communication rseau, contrle de priphriques et communication interprocessus) Ceci comprend des modules implmentant des protocoles rseau, manipulant des donnes rseau, maniant des modems et contrlant les appareils lectro-mnagers de votre maison. Data types and data type utilities (Types de donnes et utilitaires pour les types de donnes) Cette catgorie contient des modules pour les maths, les statistiques, les algorithmes, les structures de donnes (et leurs sauvegardes persistante), les dates et les heures, la programmation oriente objet, le PDL (le langage de donnes de Perl (Perl Data Language)) et le POE (lenvironnement objet de Perl (Perl Object Environment), un ordonnanceur vnementiel orient objet).

customer_8566

518
Database interfaces

Chapitre 22 CPAN

(Interfaces de bases de donnes) Vous trouverez ici des modules vous permettant dexploitant plusieurs douzaines de systmes de bases de donnes en Perl, la plupart dentre elles avec le systme DBI de Perl. Cette catgorie inclut les modules DBD spcifiques chaque base de donnes. User interfaces (character and graphical) (Interfaces utilisateur (en mode caractres et graphique)) Cette catgorie comprend des modules pour manipuler les terminaux utilisateur (dition de la ligne de commande et graphiques en mode caractres dans le style de curses(3)), ainsi que Perl/Tk et les liens avec Gtk, Gnome, Sx et Qt pour crire vos propres interfaces graphiques en Perl. Interfaces to or emulations of other programming languages (Interfaces vers ou mulations dautres langages de programmation) Cette catgorie contient des modules pour utiliser dautres langages de programmation depuis Perl ou vous permettre de prtendre que Perl nest pas ce quil prtend tre. Si vous tes intresss par utiliser Perl en C ou C en Perl, voir le chapitre 21. Filenames, filesystems, and file locking (Noms de fichier, systmes de fichiers et verrous de fichier) Cette catgorie comprend des modules pour inspecter, crer, verrouiller et tout ce qui concerne la manipulation de fichiers et de rpertoires. String processing, language text processing, parsing, and searching (Traitement de chanes et traitement, analyse et recherche de langages textuels) Cette catgorie contient des modules pour manipuler du texte : placer des csures, enrober, analyser, rechercher des variations grammaticales et faire des recherches. Elle comprend des modules pour manipuler du PostScript, des fontes, du XML et du RTF. Option, argument, parameter, and configuration file processing (Traitement doptions, darguments, de paramtres et de fichiers de configuration) Cette catgorie contient des modules pour traiter les arguments de la ligne de commande (le -x dans mon_prog_perl -x) et pour grer des fichiers de configuration (comme les fichiers commenant par un point). Internationalization and locale (Internationalisation et locales) Cette catgorie comprend des modules pour tailler sur mesure vos programmes pour un pays et une langue particuliers. Authentication, security, and encryption (Authentification, scurit et cryptage) Vous trouverez ici des modules pour grer des mots de passe dutilisateurs, calculer des signatures de messages, crypter des donnes et authentifier des utilisateurs.

customer_8566

Le rpertoire modules de CPAN


World Wide Web, HTML, HTTP CGI, MIME ,

519

(N.d.T. : vous avez compris sans traduction, non ?) Cette catgorie contient des modules vous permettant de crer des pages web base de CGI, des arpenteurs web et des systmes de gestion de contenus bass sur le web. Dautres modules vous permettent de grer les cookies, danalyser du HTML et des messages MIME et de manipuler des caches web. Il existe galement une section spciale uniquement consacre aux modules Perl que vous pouvez intgrer dans le serveur web Apache. Server and daemon utilities (Utilitaires pour les serveurs et les dmons) Cette catgorie comprend des modules pour crer des serveurs de rseau et dvnements. Archiving, compression, and conversion (Archivage, compression et conversion) Vous trouverez ici des modules pour manipuler des fichiers zip et tar et pour faire des conversions entre des formats de fichiers (mme le format de fichier dApple II). Images, pixmap, and bitmap manipulation, drawing, and graphing (Manipulations dimages, de cartes de pixels et de bits, dessins et graphiques) Cette catgorie contient des modules pour crer des graphiques, des GIF, du VRML et travailler avec Gimp. Mail and Usenet news (N.d.T. : vous avez compris sans traduction, non ?) Dans cette catgorie, vous trouverez des modules pour envoyer, recevoir et filtrer les mails et les news. Control flow utilities (Utilitaires de contrle de f lux) Cette catgorie contient des modules pour excuter du code Perl de temps autre. Filehandle, directory handle, and input/output stream utilities (Utilitaires pour les handles de fichiers, les handles de rpertoires et les f lux dentres/sorties) Ici se trouvent des modules pour les entres depuis des fichiers et les sorties dans des fichiers, y compris des fichiers journaux (log). Ceci comprend tous les modules IO:: et un module Expect pour automatiser les dialogues avec des services rseaux ou dautres programmes interactifs. Microsoft Windows modules (N.d.T. : vous avez compris sans traduction, non ?) Cette catgorie comprend des modules pour manipuler la base de registre de Windows, ASP ODBC, OLE et dautres technologies spcifiques Windows. ,

customer_8566

520
Miscellaneous modules

Chapitre 22 CPAN

(Modules divers) Vous trouverez ici des modules pour lastronomie, la biologie, la chimie, la validation (ou linvalidation) de cartes de crdit, les amortissements dhypothques, laudio, la vido, la norme MIDI, la mto et les jeux.

Utilisation des modules de CPAN


La plupart des modules que vous trouverez sur CPAN sont dans un format tarball . Cest--dire quils possdent une extension de fichier en tar.gz et quils sont dcompresss dans un rpertoire avec le code du module et tous les fichiers annexes, comprenant gnralement un fichier README et un fichier Makefile.PL. Quatre tapes rendent accessibles les modules de CPAN depuis vos programmes : la dcompression, le dpaquetage, la construction et linstallation. La manire dont fonctionne chacune de ces tapes dpend de votre systme dexploitation et du module que vous installez, nous ne pouvons donc pas vous donner de recette toute preuve qui fonctionnerait chaque fois. Lorsque vous doutez, lisez les fichiers README et INSTALL qui sont, esprons-le, distribus avec le module. Lisez galement la page de manuel de perlmodinstall. Mais il se peut que vous nayez jamais rf lchir la procdure dinstallation si vous utilisez le module CPAN (livr avec la distribution de Perl) ou PPM (Perl Package Manager, le gestionnaire de paquetages Perl, livr avec la distribution ActiveState de Perl). Pour utiliser le module CPAN ( ne pas confondre avec CPAN, lui-mme), tapez :
% perl -MCPAN -e "shell"

sur votre ligne de commande pour commencer le processus de configuration. Aprs avoir rpondu une varit de question sur la manire dont vous prfrez rcuprer des fichiers, vous pouvez installer un module en tapant :
install Un::Module

dans le shell du module CPAN, ou en tapant :


% perl -MCPAN -e "install Un::Module"

sur votre ligne de commande ordinaire. Si vous ne disposez pas des avantages pratiques du module CPAN ou de PPM, vous devrez passer la main les tapes dcrites dans les paragraphes suivants. Les instructions sont donnes pour Unix, Windows et Macintosh ; pour dautres systmes dexploitation, consultez la page de manuel de perlmodinstall.

Dcompression et dpaquetage des modules de CPAN


La plupart des milliers dutilitaires sur CPAN sont compresss pour occuper moins de place. Une fois que vous avez rcupr le tarball dun module, vous devez tout dabord le transformer en une arborescence de rpertoires sur votre systme en dcompressant ( dzippant ) et en dpaquetant le tarball. Sur Unix, vous pouvez utiliser gzip et tar pour faire cela. (Sur la plupart des systmes, tar fera les deux.) Sur Windows, WinZip dcompressera et dpaquetera la fois les tarballs. Sur un Macintosh, vous pouvez utiliser StuffIt, DropStuff, MacGzip ou suntar.

customer_8566

Utilisation des modules de CPAN

521

Construction des modules de CPAN


Une minorit de modules de CPAN viennent avec du code C que vous devrez compiler pour votre systme, ce qui est naturellement un problme pour les systmes qui ne disposent pas dun compilateur C. La procdure standard pour construire un module de CPAN (avec ou sans code C) rside dans les trois commandes suivantes, excutes partir de la ligne de commande. (Si vous navez pas de ligne de commande ou dquivalent de make, vous devrez avoir recours des mesures plus drastiques et plus dpendantes du systme. Les utilisateurs de Windows possdent une ligne de commande mais peuvent avoir besoin dutiliser lutilitaire nmake la place de make.)
% perl Makefile.PL % make % make test

La commande perl Makefile.PL essayera de crer un Makefile, quutiliseront les commandes make qui suivent pour dterminer quels utilitaires doivent tre construits et dans quel ordre. La dernire commande, make test, lance la srie de tests que par bonheur lauteur du module a incluse.

Installation des modules de CPAN dans la bibliothque Perl


Si vous avez suivi les tapes prcdentes, vous avez maintenant un module qui a t construit et test mais pas encore install dans la bibliothque de Perl. Lorsque Perl a t install sur votre systme, un rpertoire lib a t cr pour contenir des modules, des pragmas et les fichiers qui sy rapportent. Il sagit de la bibliothque Perl, qui se situe gnralement un endroit comme /usr/local/lib/perl5 sur les systme Unix et C:\PERL\LIB par dfaut sur les systmes Windows. Les modules installs aprs que Perl a t construit sont stocks dans le sous-rpertoire site_perl de la librairie Perl. Vous pouvez voir les noms de tous les rpertoires de votre bibliothque (et un tas dautres choses) en crivant :
% perl -V

Pour installer le module, tapez :


% make install

Cela ncessite normalement dtre super-utilisateur, mme pour installer des modules dans les rpertoires de la bibliothque Perl spcifiques votre site. Avec un peu de travail, vous pouvez installer le module dans un rpertoire hors de votre bibliothque Perl (comme votre rpertoire maison). Au lieu de taper normalement perl Makefile.PL pour crer un Makefile, vous pouvez plutt utiliser cette incantation :
% perl Makefile.PL LIB=/mon/rep/perllib \ INSTALLMAN1DIR=/mon/rep/man/man1 \ INSTALLMAN3DIR=/mon/rep/man/man3 \ INSTALLBIN=/mon/rep/bin \ INSTALLSCRIPT=/mon/rep/scripts

customer_8566

522

Chapitre 22 CPAN

Ceci installera les modules quelque part dans le rpertoire /mon/rep/perllib et tous les fichiers restants l o ils doivent aller. (Si vous vous trouvez en train de taper cela souvent, vous pouvez mme crire un petit programme Perl pour le faire votre place. Perl est trs bon pour accomplir des choses comme celles-l.) Vous pouvez ensuite indiquer Perl de rechercher les modules dans votre rpertoire spcial en ajoutant :
use lib "/mon/rep/perllib";

avant que votre programme ne tente de charger le module. Vous pouvez galement positionner la variable denvironnement PERL5LIB ce rpertoire ou utiliser loption de Perl -I. Voir le pragma use lib au chapitre 31, qui donne des exemples pour faire cela.

Cration de modules pour CPAN


Si vous avez un module dont vous pensez quil puisse tre utile aux autres, envisagez de rendre le monde meilleur en le tlchargeant sur CPAN. Le serveur qui gre les soumissions de nouveaux modules est appel PAUSE (Perl Authors Upload Server, le serveur de tlchargement des auteurs Perl) et on peut le trouver sur https://pause.kbx.de/pause/. Avant de pouvoir tlcharger votre module, vous devrez obtenir un compte sur PAUSE. Cest un peu comme devenir un dveloppeur Perl rpertori . Si vous vous considrez vous-mme comme un dveloppeur Perl rpertori, vous devriez en savoir assez pour documenter vos modules. Perl possde une convention pour inclure la documentation lintrieur de votre code source. (De cette manire, vous ne lgarez jamais.) Cette documentation incluse se trouve dans un format appel pod (pour Plain Old Documentation, bonne vieille documentation) et est dcrite au chapitre 26. Vous devriez envisager de scuriser votre module du point de vue des threads. Voir le chapitre 17, Threads. Vous devriez galement vous inquiter quelque peu si votre joli petit module fait ou non des choses risquant de perturber la scurit des gens qui lutilisent, car les autres peuvent avoir de vritables bonnes raisons dtre plus concerns par la scurit que vous ne ltes (POUR LINSTANT). Voir le chapitre 23, Scurit, pour tout savoir comment viter dtre tenu responsable de la 3e Guerre Mondiale et dautres nuisances du mme acabit. Les modules destins tre distribus sur CPAN doivent inclure un programme Perl appel Makefile.PL qui, lorsquon le lance, gnre un Makefile, ainsi quun fichier README dcrivant brivement ce que fait le module et comment linstaller. Le Makefile sattend comporter galement une srie de tests. Vous pouvez crer tous ces fichiers dun coup grce lutilitaire h2xs :
h2xs -X -n Truc::Machin

(Remplacez -X par -A si vous construisez un module comprenant un composant XS. XS est dcrit au chapitre 21.) Le programme h2xs cre un seul rpertoire avec des squelettes de fichiers que vous devrez garnir de chair. Lorsque vous avez termin, vous pouvez tlcharger le rpertoire dans un tarball sur PAUSE. Le Makefile.PL gnr par h2xs ressemblera quelque chose comme ceci :
use ExtUtils::MakeMaker;

customer_8566

Cration de modules pour CPAN


# See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written.3 WriteMakefile( NAME => Mon_test, VERSION_FROM => Mon_test.pm, # finds $VERSION LIBS => [], # e.g., -lm DEFINE => , # e.g., -DHAVE_SOMETHING INC => , # e.g., -I/usr/include/other );

523

La premire chose que fait le Makefile.PL est de charger le module ExtUtils::MakeMaker. La fonction WriteMakefile de MakeMaker possde une plthore doptions (avec une plthore valant approximativement 88) pour vous aider personnaliser ce qui se passe aprs que lutilisateur a tlcharg votre module depuis CPAN et a tap perl Makefile.PL pour commencer sa construction. La bonne nouvelle propos de tout ceci est que, puisque lutilisateur est suppos lancer le perl qui sera utilis plus tard, vous disposez dune large tendue dinformations de configuration disponibles (via le module Config ou la variable spciale $^O) pour vous aider dcider comment diriger MakeMaker. Dun autre ct, MakeMaker est vraiment excellent pour trouver des valeurs par dfaut satisfaisantes pour presque tout, ainsi le fichier squelette crit par h2xs peut trs bien contenir tout ce dont vous avez besoin avec peut-tre un ou deux ajustements. Pour plus dinformations ce sujet, voir la documentation en ligne trs complte de ExtUtils::MakeMaker. Lorsque vous crivez un module Perl destin un usage gnral, vous devriez permettre que la version de Perl de lutilisateur diffre de la vtre. Vous devriez toujours inclure une description en anglais de toutes les dpendances (les versions particulires de Perl, des pr-requis du systme ou dautres modules) dans le fichier README. De tout faon, cela ne suffira peut-tre mme pas, puisque quelquun qui utilise le module CPAN pour tlcharger et installer automatiquement votre module ne verrait jamais cet avertissement. Vous devriez donc vrifier les dpendances dans le Makefile.PL. Voil comment vous pourriez vous assurer que la personne qui tlcharge votre module lance Perl 5.6 ou une version suprieure :
eval { require 5.6.0 } or die << FIN_DOC; ############ ### This module requires lvaluable subroutines, which are not available ### in versions of Perl earlier than 5.6. Please upgrade!4 ############ FIN_DOC

Tests internes
Les instructions standards pour installer un module disent lutilisateur de lancer make test aprs avoir construit le module avec make. Merci donc dinclure un script de test d3. N.d.T. : Voir /lib/ExtUtils/MakeMaker.pm pour les dtails sur comment inf luencer le contenu du Makefile gnr. 4. N.d.T. : ce module ncessite des sous-programmes pris comme lvalues, qui ne sont pas disponibles dans les versions de Perl antrieures 5.6. Merci de mettre niveau !

customer_8566

524

Chapitre 22 CPAN

cent avec tout module que vous tlchargez vers CPAN. Vous devriez muler le style ok/not ok que Perl emploie dans sa propre srie de tests, afin que lutilisateur dtermine facilement le rsultat de chaque test unitaire. Le fichier test.pl gnr par h2xs vous aidera dmarrer. Le chapitre 21 donne des exemple de tests que vous pouvez ajouter la fin de test.pl. Si vous avez beaucoup de tests unitaires, vous pouvez avoir envie de singer la srie de tests de Perl en crant un sous-rpertoire appel t/ dans le rpertoire du module et dajouter lextension .t au nom de vos diffrents scripts de test. Lorsque vous lancerez make test, tous les fichiers de tests seront excuts automatiquement.

Tests externes
Les modules tlchargs vers CPAN sont tests par une varit de volontaires sur diffrentes plates-formes. Ces testeurs de CPAN sont notifis par email de chaque tlchargement nouveau et rpondent la liste de diffusion par PASS, FAIL, NA (non applicable sur cette plate-forme) ou UNKNOWN (ne sait pas), avec les remarques appropries. Vous pouvez trouver la liste de diffusion des testeurs de CPAN sur cpan-testers@perl.org ; les rsultats des tests sont posts sur http:// testers.cpan.org/. Il ne sagit que de la phase de test prliminaire, bien entendu. La vritable phase de test commence lorsque quelquun branche votre petit module sur un serveur web qui croule sous un million de pages vues par jour. Ou lors de lutilisation de votre module pour mettre au point lavion que vous emprunterez un jour prochain. Alors foncez, sautez lcriture de ces petits tests minables. Et voyez si lon sen fiche...

customer_8566

23

Scurit

Que vous ayez affaire un utilisateur assis son clavier et tapant des commandes ou quelquun envoyant des informations sur le rseau, la prudence simpose pour ce qui est des donnes arrivant dans vos programmes car lautre personne peut, de manire malveillante ou accidentelle, vous envoyer des donnes qui feront plus de mal que de bien. Perl fournit un mcanisme spcial de vrification de la scurit, appel mode de marquage, permettant disoler des donnes marques (N.d.T. : comme tant douteuses) afin de ne pas les utiliser mal propos. Par exemple, si vous faites confiance par erreur un nom de fichier marqu, vous pouvez vous retrouver en train dajouter une entre votre fichier de mots de passe alors que vous pensiez le faire sur un fichier de journal. Le mcanisme de marquage est expos la section Gestion des donnes non sres. Dans les environnements multitches, des actions, dans les coulisses, par des acteurs que lon ne voit pas peuvent affecter la scurit de votre propre programme. Si vous prsupposez que vous tes propritaire exclusif dobjets externes (en particulier des fichiers) comme si vos processus taient les seuls sur le systme, vous vous exposez des erreurs substantiellement plus subtiles que celles provenant directement de la gestion de donnes ou de code dont la provenance est douteuse. Perl vous aide alors quelque peu en dtectant des situations hors de votre contrle. Mais pour celles dont vous avez le contrle, il vous faudra comprendre quelles sont les approches lpreuve des trangers invisibles. La section Gestion des problmes de synchronisation discute de ces questions. Si la donne que vous avez reue dun tranger savre tre un morceau de code source excuter, vous devez tre encore plus prudent que vous ne le seriez avec une donne. Perl fournit des vrifications pour intercepter du code furtif dguis en donne pour que vous ne lexcutiez pas votre insu. Si vous ne voulez pas excuter de code tranger, le module Safe vous permet pourtant de mettre le code suspect en quarantaine l o il ne peut plus faire aucun mal et o il pourrait mme faire du bien. Ce sont l les thmes de la section Gestion du code non sr.

customer_8566

526

Chapitre 23 Scurit

Gestion des donnes non sres


Perl facilite une programmation scurise mme lorsque le programme est utilis par quelquun de moins fiable que le programme lui-mme. Cest--dire que certains programmes ont besoin daccorder des privilges limits leurs utilisateurs, sans accorder inutilement dautres privilges. Les programmes setuid et setgid tombent dans cette catgorie sur Unix, comme dautres programmes tournant avec des modes de privilges varis sur dautres systmes dexploitation qui implmentent de telles notions. Mme sur les systmes o ce nest pas le cas, les mmes principes sappliquent aux serveurs rseaux et tout programme lanc par ces serveurs (comme les scripts CGI, les gestionnaires de listes de diffusion et les dmons rpertoris dans /etc/inetd.conf). Tous ces programmes exigent un niveau de vigilance plus lev que la moyenne. Mme les programmes lancs partir de la ligne de commande sont parfois de bons candidats pour le mode de marquage, tout particulirement sils sont destins tre lancs par un utilisateur privilgi. Les programmes agissant sur des donnes non fiables, comme ceux qui gnrent des statistiques partir de fichiers journaux ou qui utilisent LWP::* ou Net::* pour rcuprer des donnes distantes, devraient probablement tre lancs avec le marquage explicitement activ ; les programmes imprudents risquent dtre changs en chevaux de Troie . Puisque les programmes ne retirent aucune motion prendre des risques, il ny a pas de raison pour quils ne soient pas prcautionneux. Au regard des shells de la ligne de commande sur Unix, qui ne sont vritablement que des infrastructures pour appeler dautres programmes, Perl est facile programmer de manire scurise car il est direct et autonome. linverse de la plupart des langages de programmation shells, qui sont bass sur de nombreuses et mystrieuses passes de substitution sur chaque ligne du script, Perl emploie un modle dvaluation plus conventionnel comportant moins dinconvnients cachs. De plus, comme le langage intgre plus de fonctionnalits internes, il dpend moins de programmes externes (dont la fiabilit peut tre mise en doute) pour accomplir son devoir. Sous Unix, le berceau de Perl, le meilleur moyen de compromettre la scurit du systme est de couvrir de f latteries un programme privilgi pour quil fasse quelque chose pour lequel il nest pas prvu. Pour parer de telles attaques, Perl a dvelopp une approche unique pour faire face aux environnements hostiles. Perl active automatiquement le mode de marquage chaque fois quil dtecte que son programme tourne avec des ID dutilisateur ou de groupe rels et effectifs diffrents.1 Mme si le fichier contenant votre script Perl ne possde pas de bit setuid ou setgid activ, ce script peut toujours se retrouver lanc en mode de marquage. Cela se produit si votre script a t invoqu par un autre programme, qui lui-mme tait lanc sous des ID diffrents. Les programmes Perl qui ne sont pas conus pour fonctionner en mode de marquage tendent expirer prmaturment lorsquils sont surpris violer la politique de marquage de scurit. Perl nest pas si crdule.
1. Le bit setuid des permissions UNIX est le mode 04000, et le bit setgid est 02000 ; lun comme lautre peuvent tre positionns pour donner lutilisateur du programme certains des privilges de son (ou de ses) propritaire(s). Dautres systmes dexploitation peuvent confrer des privilges spciaux aux programmes par dautres moyens, mais le principe reste le mme.

customer_8566

Gestion des donnes non sres

527

Vous pouvez galement activer explicitement le mode de marquage en utilisant loption de la ligne de commande -T. Vous devriez le faire pour les dmons, les serveurs et les programmes qui tournent pour le compte de quelquun dautre, comme les scripts CGI. Les programmes qui se lancent distance et anonymement par quelquun sur le Net sont excuts dans le plus hostile des environnements. Vous ne devriez pas craindre de dire Non ! de temps en temps. Contrairement la croyance populaire, vous pouvez faire preuve dune grande prudence sans pour autant vous transformer en prude faussement effarouche. Sur les sites les plus consciencieux en matire de scurit, lancer tous les scripts CGI avec loption -T nest pas seulement une bonne ide : cest la rgle. Nous ne prtendons pas que lancer les scripts en mode de marquage est suffisant pour les rendre scuriss. Ce nest pas le cas et cela prendrait un livre entier pour seulement mentionner tout ce quil faudrait faire. Mais si vous nexcutez pas vos scripts CGI en mode de marquage, vous faites inutilement limpasse sur la protection la plus forte que Perl puisse vous offrir. Pendant quil se trouve en mode de marquage, Perl prend des prcautions particulires appeles vrifications du marquage (taint checks) pour se prmunir contre les piges quils soient triviaux ou subtils. Certaines de ces prcautions sont assez simples, comme de vrifier que les variables denvironnement dangereuses ne soient pas positionnes et que les rpertoires de votre PATH ne soient pas modifiables par quelquun dautre ; les programmeurs prudents ont toujours procd ainsi. Dautres vrifications sont toutefois mieux assures par le langage lui-mme et ce sont celles-l qui contribuent rendre un programme Perl privilgi plus sr que le programme C correspondant ou un script CGI en Perl plus scuris que le mme script dans un langage sans vrifications de marquage. (Cest--dire, pour autant que nous le sachions, tous les langages part Perl.) Le principe est simple : vous ne pouvez pas utiliser des donnes drives de lextrieur dun programme pour affecter quelque chose dautre en dehors de ce programme du moins, pas accidententellement. Tout ce qui provient de lextrieur du programme est marqu, ce qui comprend tous les arguments de la ligne de commande, les variables denvironnement et les fichiers en entre. Les donnes marques ne peuvent tre utilises directement ou indirectement dans toute opration invoquant un sous-shell ou modifiant des fichiers, des rpertoires ou des processus. Toute variable positionne dans une expression ayant prcdemment rfrenc une valeur marque devient elle-mme marque, mme sil est logiquement impossible que la valeur marque ait inf luenc la variable. Le marquage tant associ chaque valeur scalaire, certaines valeurs individuelles dun tableau ou dun hachage peuvent tre marqus et dautres non. (Seules les valeurs dans un hachage peuvent tre marques et non les clefs.) Le code suivant illustre comment le marquage fonctionnerait si vous excutiez toutes ces instructions dans lordre. Les instructions indiques Non sres lveraient une exception, contrairement celles qui sont OK .
$arg = shift(@ARGV); $cache = "$arg, truc"; $ligne = <>; $chemin = $ENV{PATH}; $perso = abc; system "echo $perso"; # # # # # $arg est maintenant marqu ( cause de @ARGV). $cache est aussi marqu ( cause de $arg). Marqu (lu partir dun fichier externe). Marqu cause de %ENV, mais voir plus loin. Non marqu.

# Non sr avant que le PATH ne soit positionn.

customer_8566

528
system "echo $arg"; system "echo", $arg; system "echo $cache"; # # # #

Chapitre 23 Scurit
Non sr : utilise sh avec $arg marqu. OK une fois que le PATH est positionn (nutilise pas sh). Non sr de deux faons : marqu et PATH.

$vieux_chemin = $ENV{PATH}; # $vieux_chemin est marqu ( cause de %ENV). on dautres programmes.) $ENV{PATH} = bin:/usr/bin; # (R $nouveau_chemin = $ENV{PATH}; # $nouveau_chemin nest PAS marqu. delete @ENV{qw{IFS CDPATH ENV BASH_ENV}}; system "echo $perso"; system "echo $cache"; open(OUF, "< $arg"); open(OUF, "> $arg");

# Rend %ENV plus sr.

# OK, est sr une fois que le PATH est rinitialis. # Non sr via $cache qui est marqu. # OK (ouvertures en lecture seule non vrifies). # Non sr (tentative dcriture dans arg qui est # marqu).

open(OUF, "echo $arg|") # Non sr via $arg qui est marqu, mais... or die "impossible de faire un pipe sur echo : $!"; open(OUF,"-|") # Considr OK : voir ci-dessous pour or exec echo, $arg # lexemption de marquage sur une liste or die "exec echo impossible : $!"; # exec-ute. open(OUF,"-|", "echo", $arg) # Comme prcdemment, considr OK. or die "impossible de faire un pipe sur un echo : $!"; $cri = echo $arg; $cri = echo abc; $cri2 = echo $cri; unlink $perso, $arg; umask $arg; # Non sr via $arg qui est marqu. # $cri est marqu cause des apostrophes inverses. # Non sr via $cri qui est marqu. # Non sr via $arg qui est marqu. # Non sr via $arg qui est marqu.

exec "echo $arg"; # Non sr via $arg qui est marqu et pass au shell. exec "echo", $arg; # Considr OK ! (Mais voir ci-dessous.) exec "sh", -c, $arg; # Considr OK, mais tort !

Si vous essayez de faire quelque chose de non sr, vous obtiendrez une exception (qui devient une erreur fatale si elle nest pas intercepte) comme Insecure dependency ou Insecure $ENV{PATH} ( Dpendance non sre ou $ENV{PATH} non sr . Voir la section Nettoyage de votre environnement plus loin. Si vous passez une LISTE un system, un exec ou un open de pipe, les arguments ne sont pas inspects pour vrifier sils sont marqus car, avec une LISTE darguments, Perl na pas besoin dinvoquer le shell, qui est potentiellement dangereux, pour lancer la commande. Vous pouvez toujours crire facilement un system, un exec ou un open de

customer_8566

Gestion des donnes non sres

529

pipe non sr en utilisant la forme avec LISTE, comme le dmontre le dernier exemple ci-dessus. Ces formes sont exemptes de vrification car vous tes supposs savoir ce que vous faites lorsque vous les employez. Parfois, vous ne pouvez toutefois pas dire combien darguments vous tes en train de passer. Si vous fournissez ces fonctions un tableau2 qui ne contient quun lment, cest alors exactement comme si vous passiez une chane en premier et le shell pourrait alors tre utilis. La solution est de passer un chemin explicite dans lemplacement pour un objet indirect :
system @args; # Nappellera pas le shell sauf si @args == 1. system { $args[0] } @args; # Court-circuite le shell mme avec une liste # dun seul argument.

Dtection et blanchiment des donnes marques


Pour tester si une variable scalaire contient ou non une donne marque, vous pouvez utiliser la fonction est_marquee suivante. Elle utilise le fait que eval CHAINE lve une exception si vous essayez de compiler des donnes marques. Cela ne fait rien que la variable $nada employe dans lexpression compiler soit toujours vide ; elle sera encore marque si $arg lest. Le eval BLOC extrieur neffectue aucune compilation. Il nest ici que pour intercepter lexception leve si lon donne une donne marque leval intrieur. Puisquil est garanti que la variable $@ nest pas vide aprs chaque eval si une exception a t leve et vide sinon, nous renvoyons le rsultat du test vrifiant si sa longueur tait nulle :
sub est_marquee { my $arg = shift; my $nada = substr($arg, 0, 0); # longueur nulle local $@; # prserve la version de lappelant eval { eval "# $nada" }; return length($@) != 0; }

Mais tester le marquage ne vous en dit pas plus. Gnralement, vous savez parfaitement quelles variables contiennent des donnes marques il vous suffit de nettoyer le marquage des donnes. Le seul moyen officiel de court-circuiter le mcanisme de marquage consiste rfrencer des variables de sous-motifs dtermins par une prcdente recherche de correspondance dexpression rgulire.3 Lorsque vous crivez un motif contenant des parenthses capturantes, vous pouvez accder aux sous-chanes captures par le biais des variables de correspondance comme $1, $2 et $+ ou en valuant le motif dans un contexte de liste. Quel que soit le moyen employ, on prsume que vous tiez au cou-

2. Ou une fonction produisant une liste. 3. Un moyen officieux consiste stocker une chane marque comme clef dun hachage et de rcuprer nouveau cette clef. Car les clefs ne sont pas des SV complets (nom interne des valeurs scalaires), elles ne portent pas sur elle la proprit du marquage. Ce comportement peut changer un jour ou lautre, ne comptez donc pas dessus. Soyez prudent lorsque vous manipulez des clefs, de peur que vous nenleviez accidentellement le marquage de vos donnes et que vous ne fassiez quelque chose de dangereux avec.

customer_8566

530

Chapitre 23 Scurit

rant de ce que vous tiez en train de faire lorsque vous avez crit le motif et que vous lavez crit de manire viter tout danger. Vous devez donc rf lchir un peu ne blanchissez jamais aveuglment ou cest tout le mcanisme qui sera invalid. Il vaut mieux vrifier que la variable ne contient que des caractres valides au lieu de regarder si elle contient des caractres invalides. Ceci car il est beaucoup trop facile den rater auxquels vous nauriez jamais pens. Par exemple, voici un test destin sassurer que $chaine ne contient que des caractres de mot (alphabtiques, numriques et souligns), des tirets, des signes et des points :
if ($chaine =~ /^([-\@\w.]+)$/) { $chaine = $1; # $chaine est maintenant non marque. } else { die "Mauvaises donnes dans $chaine"; # Enregistrez ceci quelque part. }

Ceci rend $chaine raisonnablement fiable pour lutiliser ensuite dans une commande externe, puisque /\w+/ ne correspond gnralement pas des mtacaractres du shell, et que les autres caractre ne veulent rien dire de particulier pour le shell.4 Il aurait t dangereux dutiliser /(.+)/ car ce motif laisse tout passer, ce que Perl ne vrifie pas. Au moment du nettoyage, soyez extrmement prudent avec vos motifs. Le blanchiment des donnes en utilisant des expressions rgulires reprsente le seul mcanisme interne approuv pour nettoyer de sales donnes. Et parfois, cette approche est entirement mauvaise. Si vous tes en mode de marquage car vous tournez avez set-id et non parce que vous avez intentionnellement activ -T, vous pouvez limiter les risques en lanant avec fork un fils avec des privilges moindres ; voir la section Nettoyage de votre environnement. Le pragma use re taint dsactive le nettoyage implicite de toutes les correspondances de motifs jusqu la fin de la porte lexicale courante. Vous pourriez utiliser ce pragma si vous vouliez seulement extraire quelques sous-chanes dune donne potentiellement marque ; mais puisque ne vous tes pas inquit de la scurit, vous feriez mieux de laisser les sous-chanes marques pour vous prserver des accidents malchanceux venir. Imaginez que vous trouviez une correspondance avec quelque chose comme ceci, avec $chemin_complet marqu :
($rep, $fichier) = $chemin_complet =~ m!(.*/)(.*)!s;

Par dfaut, $rep et $fichier seraient maintenant marqus. Mais vous ne vouliez probablement pas faire cela de manire si cavalire car vous navez jamais vraiment rf lchi aux problmes de scurit. Par exemple, vous ne seriez pas follement heureux si $fichier contenait la chane ; rm -rf * ; , pour ne citer quun exemple tout fait remarquable. Le code suivant laisse les deux variables renvoyes marques si $chemin_complet ltait :

4. moins que vous nutilisiez intentionnellement des locales corrompues. Perl prsuppose que les dfinitions de locales de votre systme sont potentiellement compromises. Ainsi, lorsque le pragma use locale est actif, les motifs contenant une classe de caractres symbolique, comme \\w ou [[:alpha:]], produisent des rsultats marqus.

customer_8566

Gestion des donnes non sres


{ use re taint; ($rep, $fichier) = $chemin_complet =~ m!(.*/)(.*)!s; }

531

Une bonne stratgie consiste laissez les sous-correspondances marques par dfaut dans le fichier source entier et de ne permettre denlever le marquage que slectivement dans des portes imbriques si le besoin sen fait sentir :
use re taint; # le reste du fichier laisse maintenant $1, etc. marqus { no re taint; # ce bloc enlve maintenant le marquage dans les # correspondances dexpressions rgulires if ($num =~ /^(\d+)$/) { $num = $1; } }

Une entre depuis un handle de fichier ou de rpertoire est automatiquement marque, sauf si elle provient du handle de fichier spcial DATA. Si vous le souhaitez, vous pouvez dsigner dautres handles comme des sources dignes de confiance via la fonction untaint du module IO::Handle :
use IO::Handle; IO::Handle::untaint(*UN_HF); UN_HF->untaint(); # Soit de manire procdurale # soit en utilisant un style OO.

Dsactiver le marquage sur un handle de fichier complet est un geste dangereux. Comment savez-vous vraiment quil est sr ? Si vous vous apprtez faire cela, vous devriez au moins vrifier que personne part le propritaire ne puisse crire dans le fichier.5 Si vous tes sur un systme de fichiers Unix (et un qui restreint prudemment chown(2) au super-utilisateur), le code suivant fonctionne :
use File::stat; use Symbol qualify_to_ref; sub handle_semble_sur(*) { my $hf = qualify_to_ref(shift, caller); my $info = stat($hf); return unless $info; # le propritaire nest ni le super-utilisateur, ni moi , # dont luid rel est dans la variable $< if ($info->uid != 0 && $info->uid != $<) { return 0; }

5. Bien que vous puissiez galement enlever le marquage dun handle de rpertoire, cette fonction ne marche que sur un handle de fichier. Car, tant donn un handle de rpertoire, il nexiste pas de manire portable dextraire son descripteur de fichier avec stat.

customer_8566

532

Chapitre 23 Scurit
# vrifie si le groupe ou les autres peuvent crire dans le fichier # utilise 066 pour dtecter galement la possibilit de lire if ($info->mode & 022) { return 0; } return 1;

} use IO::Handle; UN_HF->untaint() if handle_semble_sur(*UN_HF);

Nous avons appel stat sur le handle de fichier et non sur le nom de fichier pour viter une situation de concurrence (race condition) dangereuse. Voir la section Gestion des situations de concurrence plus loin dans ce chapitre. Remarquez que cette routine nest quun bon point de dpart. Un version lgrement plus paranoaque aurait galement vrifier tous les rpertoires parents, mme si vous ne pouvez pas faire un stat sur un handle de rpertoire de manire fiable. Mais si lun des rpertoires parents est en criture pour tout le monde, vous savez que vous tes en danger quil y ait ou non des situations de concurrence. Perl a ses propres notions en ce qui concerne les oprations qui sont dangereuses mais il est toujours possible de se plonger dans les ennuis avec dautres oprations qui se moquent dutiliser ou non des valeurs marques. Il ne suffit pas toujours dtre prudent avec les entres. Les fonctions de Perl pour les sorties ne testent pas si leurs arguments sont marqus ou non, mais, dans certains environnements, cela compte. Si vous ne faites pas attention ce que vous crivez en sortie, vous pourriez tout bonnement finir par cracher des chanes ayant une signification inattendue pour quiconque traitant la sortie. Si vous tournez sur un terminal, les squences dchappement spciales et les codes de contrle pourraient provoquer un affichage erratique sur le terminal. Si vous tes dans un environnement web et que vous recrachez sans prcaution tout ce que lon vous donne, vous pourriez produire de manire imprvisible des balises HTML qui dformeraient drastiquement lapparence de la page. Pire encore, certaines balises peuvent mme en retour excuter du code dans le navigateur. Imaginez le cas courant dun livre dor o les visiteurs entrent leurs propres messages afficher lorsque dautres viennent appeler. Un invit malicieux pourrait fournir des balises HTML disgracieuses ou mettre des squences <SCRIPT>...</SCRIPT> excutant du code (comme du JavaScript) en retour dans le navigateur des visiteurs suivants. Tout comme vous avez vrifi que tous les caractres sont autoriss, lorsque vous recevez une donne marque qui pourrait accder aux ressources de votre systme, vous pouvez effectuer une vrification analogue dans un environnement web lorsque vous recevez des donnes dun internaute. Par exemple, pour supprimer tous les caractres absentes de la liste des bons caractres, essayez quelque chose comme :
$nouvelle_entree_du_livre_d_or =~ tr[_a-zA-Z0-9 ,.!?()@+*-][]dc;

Vous nutiliseriez certainement pas cela pour nettoyer un nom de fichier, puisque vous ne voulez probablement pas de noms de fichiers avec des espaces ou des slashes, pour commencer. Mais il nest pas suffisant de prserver votre livre dor vierge de toute balise HTML sournoise et de toute entit perfide. Chaque cas de blanchiment de donne est quelque peu diffrent, passez donc toujours du temps dcider ce qui est permis et ce

customer_8566

Gestion des donnes non sres

533

qui ne lest pas. Le mcanisme de marquage est prvu pour intercepter les erreurs stupides, pas pour se dispenser de rf lchir.

Nettoyage de votre environnement


Lorsque vous excutez un autre programme depuis votre script Perl, peu importe comment, Perl vrifie pour sassurer que votre variable denvironnement PATH soit scurise. Puisquil provient de votre environnement, votre PATH commence par tre marqu, ainsi si vous essayez de lancer un autre programme, Perl lve une exception Insecure $ENV{PATH} . Lorsque vous le positionnez une valeur connue, non marque, Perl sassure que chaque rpertoire dans ce PATH ne soit pas accessible en criture par quelquun dautre que le propritaire et le groupe du rpertoire ; sinon, Perl lance une exception Insecure directory . Vous seriez surpris dapprendre que Perl se proccupe de votre PATH mme lorsque vous spcifiez le nom de chemin complet de la commande que vous voulez excuter. Il est vrai quavec un nom de fichier absolu, le PATH nest pas utilis pour localiser lexcutable. Mais Perl se mfie de ce que le programme excut pourrait en lancer un autre avec un PATH non sr. Perl vous force donc positionner un PATH scuris avant dappeler un autre programme, quelle que soit la manire dont vous lappelez. Le PATH nest pas la seule variable denvironnement pouvant causer du chagrin. Comme certains shells utilisent les variables IFS, CDPATH, ENV et BASH_ENV Perl sassure que toutes , celles-ci sont soit vides, soit sans marquage avant de lancer une autre commande. Positionnez ces variables quelque chose que lon sait tre sr ou alors supprimez-les de lenvironnement :
delete ENV{qw(IFS CDPATH ENV BASH_ENV)}; # Rend %ENV plus sr

Des fonctionnalits accommodantes dans un environnement normal peuvent devenir des problmes de scurit dans un environnement hostile. Mme si vous vous rappelez avoir interdit les noms de fichiers contenant des sauts de ligne, il est important de comprendre que open accde autre chose de plus que seulement des noms de fichiers. Avec les ornements appropris dans largument reprsentant le nom de fichier, les appels open avec un ou deux arguments peuvent galement lancer des commandes arbitraires externes via des pipes, forker des copies supplmentaires du processus courant, dupliquer des descripteurs de fichiers et interprter le nom de fichier spcial - comme un alias de lentre ou de la sortie standard. Il peut galement ignorer les espaces au dbut ou la fin qui peuvent masquer de tels argument fantaisistes vos motifs de test. Bien quil soit vrai que les vrifications de marquage de Perl intercepteront les arguments marqus utiliss dans les ouvertures de pipe (sauf si vous utilisez un argument de liste spar) et toutes les ouvertures de fichiers qui ne soient pas en lecture seule, lexception leve par ceci est toujours susceptible de faire que votre programme se conduise mal. Si vous avez lintention dutiliser une donne drive de lextrieur dans une partie dun nom de fichier ouvrir, incluez au moins un mode explicite spar par un espace. Cependant, le plus sr est certainement dutiliser un sysopen de bas niveau ou la forme trois arguments de open :
# Ouverture magique --- peut tre nimporte quoi open(HF, $fichier) or die "open $fichier magique, impossible : $!";

customer_8566

534

Chapitre 23 Scurit

# Garantit louverture dun fichier en lecture seule et non un pipe # ou un fork, mais interprte toujours les descripteurs de # fichiers et - et ignore les espaces aux extrmits du nom. open(HF, "< $fichier) or die "open $fichier, impossible : $!"; # Ouverture WYSIWYG : dsactive toutes les fonctionnalits accommodantes. open(HF, "<", $fichier) or die "open $fichier, impossible : $!"; # Mmes proprits que la version 3 arguments WYSIWYG. require Fcntl; sysopen(HF, $fichier, O_RDONLY) or die "sysopen $fichier, impossible : $!";

Et mme ces tapes ne sont pas assez bonnes. Perl ne vous empche pas douvrir des noms de fichiers marqus en lecture, vous devez donc tre prudent avec ce que vous montrez aux gens. Un programme qui ouvre en lecture un nom de fichier arbitraire, fourni par lutilisateur, pour ensuite rvler le contenu de ce fichier, est toujours un problme de scurit. Que se passe-t-il sil sagit dune lettre prive ? Et sil sagit du fichier de mots de passe de votre systme ? Ou des informations sur les salaires ou votre portefeuille dactions ? Examinez de prs les noms de fichier fournis par un utilisateur potentiellement hostile6 avant de les ouvrir. Par exemple, vous pourriez vouloir vrifier quil ny a pas de rpertoires sournois dans votre PATH. Les noms comme ../../../../../../../etc/ passwd sont des coups fourrs du genre qui sont de notorit publique. Vous pouvez vous protger en vous assurant quil ny a pas de slash dans le nom du chemin (en supposant quil sagit du sparateur de rpertoire de votre systme). Une autre astuce courante est de mettre des sauts de ligne ou des points-virgules dans les noms de fichiers qui seront interprts ensuite par de pauvres interprteurs de commandes simples desprit, pouvant tre bluffs en commenant une nouvelle commande au beau milieu du nom de fichier. Cest pourquoi le mode de marquage dconseille les commandes externes non inspectes.

Accs aux commandes et aux fichiers avec des privilges restreints


La discussion qui suit est relative des facilits astucieuses concernant la scurit sur les systmes Unix. Les utilisateurs dautres systmes peuvent en toute scurit (ou plutt en toute inscurit) passer ce paragraphe. Si vous tournez avec set-id, essayez darranger cela, chaque fois que cest possible, pour que les oprations dangereuses soient accomplies avec les privilges de lutilisateur et non ceux du programme. Cest--dire qu chaque fois que vous allez appeler open, sysopen, system, des apostrophes inverses et tout autre opration sur un fichier ou sur un processus, vous pouvez vous protgez en repositionnant votre UID ou votre GID effectif avec lUID ou le GID rel. En Perl, vous pouvez faire cela pour les scripts setuid en crivant $> = $< (ou $EUID = $UID si vous avez fait use English) et pour les scripts setgid en crivant $( = $) ($EGID = $GID). Si les deux ID sont positionns, vous devez rini6. Et sur le Net, les seuls utilisateurs que vous pouvez en toute confiance considrer comme ntant pas potentiellement hostiles sont plutt ceux qui sont activement hostiles.

customer_8566

Gestion des donnes non sres

535

tialiser les deux. De toute faon, cest parfois infaisable car vous pourriez encore avoir besoin de ces privilges accrus ultrieurement dans votre programme. Pour ces cas-l, Perl procure un moyen relativement sr douvrir un fichier ou un pipe depuis un programme set-id. Tout dabord, lancez un fils avec la syntaxe spciale de open qui connecte le pre et le fils par un pipe. Dans le fils, repositionnez ensuite ses ID dutilisateur et de groupe leur valeur originale ou des valeurs connues et sres. Vous devrez galement modifier tous les attributs de processus du fils sans affecter le pre, vous permettant de changer le rpertoire de travail courant, positionner le masque de cration de fichiers ou bricoler les variables denvironnement. Le processus fils, qui ne sexcute plus sous des privilges accrus, appelle finalement open et passe les donnes auxquelles il a accd sous couvert dun utilisateur ordinaire mais dment, son pre, puissant mais paranoaque de manire justifie. Bien que system et exec nutilisent pas le shell lorsque vous leur fournissez plus dun argument, loprateur apostrophes inverses nadmet pas de telle convention dappel alternative. En utilisant la technique lanant un processus fils, nous pouvons facilement muler les apostrophes inverses sans nous soucier des squences dchappements du shell et avec des privilges rduits (et donc plus srs) :
use English; # pour employer $UID, etc. die "open fork impossible : $!" unless defined ($pid = open(DEPUIS_FILS, "-|")); if ($pid) { # pre while (<DEPUIS_FILS>) { # faire quelque chose } close DEPUIS_FILS; } else { $EUID = $UID; # setuid(getuid()) $EGID = $GID; # setgid(getgid()) et initgroups(2) sur getgroups(2) chdir("/") or die "chdir / impossible : $!"; umask(077); $ENV{PATH} = "/bin:/usr/bin"; exec mon_prog, arg1, arg2; die "exec mon_prog impossible : $!"; }

Il sagit du meilleur moyen, et de loin, dappeler un programme depuis un script set-id. Vous tes sr de ne pas utiliser le shell pour excuter quoi que ce soit et vous abandonnez vos privilges avant dappeler vous-mme exec pour lancer le programme. (Mais puisque les formes avec liste de system, exec et open sur un pipe sont spcifiquement exemptes des vrifications de marquage, vous devez toujours prendre garde ce que vous leur passez.) Si nous navez pas besoin dabandonner vos privilges et voulez seulement implmenter les apostrophes inverses ou un open sur un pipe sans risquer que le shell intercepte vos arguments, il vous suffit dutiliser ceci :
open(DEPUIS_FILS, "-|") or exec("mon_prog", "arg1", "arg2") or die "impossible de lancer mon_prog : $!";

puis de lire dans DEPUIS_FILS dans le pre. Avec la version 5.6.1 de Perl, vous pouvez lcrire comme ceci :

customer_8566

536
open(DEPUIS_FILS, "-|", "mon_prog", "arg1", "arg2");

Chapitre 23 Scurit

La technique consistant lancer un fils nest pas seulement utile pour lancer des commandes depuis un programme set-id. Elle savre galement bonne pour ouvrir des fichiers sous lID de quiconque a lanc le programme. Imaginez que vous avez un programme setuid qui a besoin douvrir un fichier en criture. Vous ne voulez pas lancer le open avec vos privilges supplmentaires mais vous ne pouvez pas non plus les abandonner dfinitivement. Arrangez-vous alors pour avoir une copie forke qui abandonne ses privilges pour effectuer le open pour vous. Lorsque vous voulez crire dans le fichier, crivez au fils et ce dernier crira dans le fichier votre place.
use English; defined ($pid = open(ECRIVAIN_SUR, "|-")) or die "fork impossible : $!"; if ($pid) { # Vous tes dans le pre. # crivez les donnes au fils ECRIVAIN_SUR. print ECRIVAIN_SUR "donnes_en_sortie\n"; close ECRIVAIN_SUR or die $! ? "Erreur systme en fermant ECRIVAIN_SUR : $!" : "Statut dattente $? depuis ECRIVAIN_SUR"; } else { # Vous tes dans le fils. # Abandonnez donc vos privilges supplmentaires. ($EUID, $EGID) = ($UID, $GID); # Ouvrez le fichier avec les droits de lutilisateur original. open(HF, ">/un/chemin/de/fichier" or die "open /un/chemin/de/fichier en criture, impossible : $!"; # Copiez depuis le pre (maintenant stdin) vers le fichier. while (<STDIN>) { print HF, $_; } close(HF) or die "chec de close : $!"; exit; # Noubliez pas de faire disparatre ECRIVAIN_SUR. }

Lorsquil choue dans louverture du fichier, le fils affiche un message derreur et se termine. Lorsque le pre crit dans le handle de fichier du fils maintenant dcd, cela dclenche un signal de pipe bris (SIGPIPE) qui est fatal sil nest pas intercept ou ignor. Voir la section Signaux au chapitre 16, Communication interprocessus.

Gestion des problmes de synchronisation


Parfois, le comportement de vos programmes est trs sensible la synchronisation dvnements extrieurs hors de votre contrle. Il sagit toujours dun problme lorsque dautres programmes, particulirement ceux qui sont inamicaux, pourraient se battre avec votre programme pour les mmes ressources (comme des fichiers ou des priph-

customer_8566

Gestion des problmes de synchronisation

537

riques). Dans un environnement multitche, vous ne pouvez pas prdire lordre dans lequel les processus en attente dactivation vont tre autoriss accder au processeur. Les f lux dinstructions parmi tous les processus ligibles sentrecroisent, ainsi un processus dispose tout dabord dun peu de CPU, ensuite un autre, et ainsi de suite. Il semble alatoire de savoir celui dont cest le tour dtre actif et combien de temps il sera autoris ltre. Avec un seul programme, il ny a pas de problme mais avec plusieurs, partageant des ressources communes, cela peut en tre un. Les programmeurs de threads sont particulirement sensibles ces questions. Ils apprennent vite ne plus crire :
$var++ if $var == 0;

lorsquils veulent dire :


{ lock($var); $var++ if $var == 0; }

Le premier exemple donne des rsultats imprvisibles lorsque plusieurs threads dexcution tente de lancer ce code en mme temps. (Voir le chapitre 17, Threads.) Si vous pensez aux fichiers comme des objets partags et aux processus comme des threads candidats pour laccs ces objets partags, vous pourrez voir comment les mmes questions sont souleves. Un processus, aprs tout, nest en ralit quun thread qui sy croit. Ou vice versa. Limprvisibilit des synchronisations affecte la fois les situations privilgies et celles qui ne le sont pas. Nous dcrirons tout dabord comment se dbrouiller avec un bogue de longue date dans les anciens noyaux Unix affectant tous les programmes set-id. Nous irons ensuite discuter des situations de concurrence en gnral, comment elles se transforment en brches de scurit et les tapes que vous devez suivre pour viter de tomber dans ces trous.

Bogues de scurit du noyau Unix


Au-del des problmes vidents dcoulant du passage de privilges spciaux des interprteurs aussi souples et impntrables que les shells, les anciennes versions dUnix souffrent dun bogue du noyau qui rend tout script set-id non sr avant mme darriver jusqu linterprteur. Le problme ne rside pas dans le script lui-mme mais dans une situation de concurrence dans ce que fait le noyau lorsquil trouve un script set-id excutable. (Le bogue nexiste pas sur les machines qui ne reconnaissent pas #! dans le noyau.) Entre le moment o le noyau ouvre un tel fichier pour savoir quel interprteur lancer et celui o linterprteur (maintenant set-id) dmarre et ouvre nouveau le fichier, il existe une chance pour des entits malicieuses de changer le fichier en question, surtout si le systme implmente les liens symboliques. Heureusement, cette caractristique du noyau peut parfois tre dsactive. Malheureusement, il existe deux moyens pour ce faire. Le systme peut rendre hors-la-loi les scripts avec les bits set-id positionns, ce qui nest pas dune grande aide. Il peut galement ignorer les bits set-id sur les scripts. Dans ce dernier cas, Perl peut muler les mcanismes de setuid et de setgid quand il remarque les bits set_id (par ailleurs inutiles)

customer_8566

538

Chapitre 23 Scurit

sur les scripts Perl. Il effectue ceci grce un excutable spcial appel suidperl, qui est automatiquement appel pour vous si besoin.7 Cependant, si la fonctionnalit du noyau concernant les scripts set-id nest pas dsactive, Perl se plaint bruyamment de ce que le script nest pas sr. Vous devrez soit la dsactiver, soit enrober le script dans un programme C. Il sagit seulement dun programme compil qui ne fait rien dautre quappeler votre programme Perl. Les programmes compils ne sont pas sujets au bogue qui tourmente les scripts set-id. Voici un simple enrobage crit en C :
#define VRAI_FICHIER "/chemin/du/script" main(ac, av) char **av; { execv(VRAI_FICHIER, av); }

Compilez cet enrobage en un excutable binaire et rendez-le set-id au lieu de le faire sur votre script. Assurez-vous demployer un nom de chemin absolu, car le C nest pas assez malin pour vrifier le marquage sur votre PATH. (Une autre approche possible consiste employer le gnrateur exprimental de code C du compilateur Perl. Un image compile de votre script ne connatra pas la situation de concurrence. Voir au chapitre 18, Compiler.) Ces dernires annes, certains fournisseurs ont finalement sorti des systmes librs de ce bogue de set-id. Sur de tels systmes, lorsque le noyau passe le nom du script set-id linterprteur, il ne sagit plus dun nom de fichier sujet des interventions, mais dun fichier spcial reprsentant le descripteur de fichier, comme /dev/fd/3. Ce fichier spcial est dj ouvert sur le script de manire ce quil ne puisse plus avoir de situation de concurrence que des scripts diaboliques pourraient exploiter.8 La plupart des versions modernes dUnix emploient cette approche pour viter la situation de concurrence inhrente louverture dun mme fichier deux fois.

Gestion des situations de concurrence


Ce qui nous amne directement au thme des situations de concurrence. Que sont-elles rellement ? Les situations de concurrence se retrouvent frquemment dans les discussions propos de la scurit. (Bien quon les retrouvent moins que dans les programmes non srs. Malheureusement.) Cest parce quelles sont une source fertile derreurs subtiles de programmation et que de telles erreurs peuvent souvent se transformer en exploits (terme poli pour dsigner le fait de bousiller la scurit de quelquun) pour la

7. Si besoin et si cest permis si Perl dtecte que le systme de fichiers dans lequel rside le script a t mont avec loption nosuid, cette dernire sera toujours respecte. Vous ne pouvez pas utiliser Perl pour coutourner de cette faon la politique de scurit de votre administrateur systme. 8. Sur ces systmes, Perl doit tre compil avec -DSETUID_SCRIPTS_ARE_SECURE_NOW. Le programme Configure qui compile Perl essaie de deviner cette situation, ce qui fait que vous ne devriez jamais le spcifier explicitement.

customer_8566

Gestion des problmes de synchronisation

539

scurit. Une situation de concurrence arrive lorsque le rsultat de plusieurs vnements corrls dpend de lordre de ces vnements mais que cet ordre ne peut tre garanti cause des effets dune synchronisation non dterministe. Chaque vnement se prcipite pour tre le premier accompli et ltat final du systme est laiss limagination de chacun. Imaginez que vous ayez un processus crivant par dessus un fichier existant et un autre processus lisant le mme fichier. Vous ne pouvez prdire si vous lisez les anciennes donnes, les nouvelles ou un mlange alatoire des deux. Vous ne pouvez mme pas savoir si vous avez lu toutes les donnes. Le lecteur pourrait avoir gagn la course jusqu la fin du fichier avant de se terminer. En mme temps, si lcrivain a continu aprs que le lecteur a rencontr la fin de fichier, le fichier aura grossi plus loin que lendroit o le lecteur stait arrt et ce dernier ne laura jamais su. Ici, la solution est simple : il suffit que les deux parties verrouillent le fichier avec flock. Le lecteur demande gnralement un verrou partag et lcrivain un verrou exclusif. Tant que toutes les parties demandent et respectent ces verrous consultatifs, les lectures et critures ne peuvent pas senchevtrer et il ny aucun chance de trouver des donnes mutiles. Voir la section Verrouillage de fichier au chapitre 16. Vous risquez de rencontrer une forme bien moins vidente de situation de concurrence chaque fois que vous laissez des oprations sur des noms de fichier gouverner les oprations ultrieures sur ce fichier. Lorsquon les utilise sur des noms de fichier plutt que sur des descripteurs de fichier, les oprateurs de test de fichier reprsentent parfois un terrain fertile menant droit une situation de concurrence. Considrez ce code :
if (-e $fichier) { open(HF, "< $fichier") or die "impossible douvrir $fichier en lecture : $!"; } else { open(HF, "> $fichier") or die "impossible douvrir $fichier en criture : $!"; }

Le code parat aussi simple quil ne lest, mais il est toujours sujet des situations de concurrence. Il ny a aucune garantie que la rponse renvoye par le test -e soit toujours valide au moment o lun des open est appel. Dans le bloc if, un autre processus pourrait avoir supprim le fichier avant quil ne puisse tre ouvert et vous ne trouveriez pas le fichier dont vous pensiez quil allait se trouver l. Dans le bloc else, un autre processus pourrait avoir cr le fichier avant que le tour du second open narrive pour quil puisse le crer et le fichier que vous pensiez donc ne pas tre l, le serait. La simple fonction open cre de nouveaux fichiers mais crase ceux qui existaient. Vous pouvez penser que vous voulez craser tout fichier existant mais penser que le fichier existant pourrait trs bien tre un alias nouvellement cr ou un lien symbolique vers un fichier autre part sur le systme que vous ne voudriez vraiment pas craser. Vous pouvez penser que vous savez ce que signifie un nom de fichier nimporte quel instant mais vous ne pouvez jamais en tre vraiment sr, tant que dautres processus ayant accs au rpertoire du fichier tournent sur le mme systme. Pour rsoudre ce problme dcrasement, vous devrez employer sysopen, qui fournit des contrles individuels pour soit crer un nouveau fichier, soit pour en craser compltement un qui existe. Et nous abandonnerons ce test -e dexistence de fichier puis-

customer_8566

540

Chapitre 23 Scurit

quil nest plus utile ici et ne fait quaccrotre notre exposition aux situations de concurrence.
use Fcntl qw/O_WRONLY O_CREAT O_EXCL/; open (HF, "<", $fichier) or sysopen(HF, $fichier, O_WRONLY | O_CREAT | O_EXCL) or die "impossible de crer le nouveau fichier $fichier : $!";

Maintenant, mme si le fichier se met clore dune manire ou dune autre entre le moment o le open choue et celui o le sysopen essaie douvrir un nouveau fichier en criture, aucun mal ne peut tre fait car avec les f lags que nous lui avons fournis, sysopen refusera douvrir un fichier qui existe dj. Si quelquun essaie de persuader par la ruse votre programme de mal se conduire, il a une bonne chance de russir en faisant apparatre et disparatre les fichiers quand vous ne vous y attendez pas. Un moyen de rduire le risque de tromperie consiste vous promettre vous-mme que vous ne manipulerez jamais un nom de fichier plus dune fois. Ds que vous avez ouvert le fichier, oubliez son nom ( part peut-tre pour les messages derreur) et ne manipulez plus que le handle reprsentant le fichier. Cest beaucoup plus sr car, mme si quelquun pourrait samuser avec vos noms de fichier, il ne peut le faire avec les handles. (Ou sil le peut, cest parce que vous lavez laiss faire voir Passage de handles de fichiers au chapitre 16.) Plus haut dans ce chapitre, nous avons prsent une fonction handle_semble_sur qui appelait la fonction stat de Perl sur un handle de fichier (et non un nom de fichier) pour vrifier son appartenance et ses permissions. Lemploi du handle de fichier est critique pour lexactitude de la solution si nous avions pass le nom du fichier, il ny aurait eu aucune garantie que le fichier dont nous examinions les attributs ait t le mme que celui que nous venions douvrir (ou que nous tions sur le point douvrir). Un minable mcrant aurait pu supprimer notre fichier et le remplacer rapidement par un fichier subversif, un moment donn entre le stat et le open. Peut importe lequel aurait t appel en premier ; il y aurait toujours une opportunit pour un jeu dloyal entre les deux. Vous pouvez penser que le risque est trs rduit puisque la fentre lest aussi mais il existe de nombreux scripts pirates dans le monde qui seraient tout fait heureux de lancer votre programme des milliers de fois pour sen jouer la seule fois o il na pas t assez prudent. Un script pirate habile peut mme baisser la priorit de votre programme pour quil soit interrompu plus souvent que dordinaire, simplement pour acclrer un peu les choses. Les gens travaillent dur sur ces questions cest pourquoi on les appelle des exploits. En appelant stat sur un handle de fichier dj ouvert, nous naccdons au nom du fichier quune seule fois et vitons ainsi la situation de concurrence. Une bonne stratgie pour viter les situations de concurrence entre deux vnements consiste combiner les deux dune manire ou dune autre pour nen faire quun seul vnement, en rendant lopration atomique.9 Puisque nous naccdons au fichier quune seule fois par son
9. Oui, vous pouvez encore accomplir des oprations atomiques dans une zone dnuclarise. Lorsque Dmocrite a donn le nom atome aux parties indivisibles de la matire, il voulait littralement dire quelque chose qui ne peut tre divis : a-(non) + tomos (divisible). Une opration atomique est une action qui ne peut tre interrompue. (Essayez seulement dinterrompre un jour une bombe atomique.)

customer_8566

Gestion des problmes de synchronisation

541

nom, il ne peut y avoir de situation de concurrence entre plusieurs accs, ainsi a ne fait pas grand chose si le nom change. Mme si notre pirate supprime le fichier que nous avons ouvert (oui, cela peut arriver) et le remplace par un autre pour samuser avec nous, nous avons toujours un handle sur le fichier rel et original.

Fichiers temporaires
part autoriser les dpassements de tampons (ce contre quoi les scripts Perl sont virtuellement immuniss) et faire confiance des donnes en entre indignes de confiance (ce contre quoi le mode de marquage prserve), crer de manire incorrecte des fichiers temporaires est lun des trous de scurit les plus frquemment exploits. Heureusement, les attaques contre les fichiers temporaires exigent des pirates quils aient un compte dutilisateur valide sur le systme quils tentent de pirater, ce qui rduit drastiquement le nombre de mcrants potentiels. Les programmes imprudents ou dsinvoltes utilisent des fichiers temporaires avec toutes sortes de moyens non srs, comme en les plaant dans des rpertoires accessibles en criture par le monde entier, en utilisant des noms de fichier prvisibles et en ne sassurant pas que le fichier nexiste pas dj. Ds que vous trouvez un programme avec du code comme ceci :
open(TMP, ">/tmp/truc.$$") or die "impossible douvrir /tmp/truc.$$ : $!";

vous venez de trouver les trois erreurs dun coup. Ce programme est un accident en sursis. Le moyen mis en uvre par lexploit consiste pour le pirate tout dabord planter un fichier du mme nom que celui que vous utiliserez. Ajouter le PID la fin ne suffit pas garantir lunicit ; aussi surprenant que cela puisse paratre, ce nest vraiment pas difficile deviner des PID.10 Maintenant arrive le programme avec lappel imprudent open et au lieu de crer un nouveau fichier temporaire pour ses propres besoins, il crase celui du pirate la place. Quel mal cela peut-il donc faire ? Beaucoup ! Le fichier du pirate nest pas vraiment un fichier pur, voyez-vous. Cest un lien symbolique (ou parfois un lien en dur), pointant certainement vers un fichier critique dans lequel le pirate ne pourrait normalement pas crire tout seul, comme /etc/passwd. Le programme pensait avoir ouvert un fichier tout neuf dans /tmp mais la place, il a cras un fichier existant quelque part ailleurs. Perl offre deux fonctions abordant ce problme, si elles sont utilises correctement. La premire est POSIX::tmpnam, qui ne fait que renvoyer le nom de fichier que vous escomptiez ouvrir par vous-mme :
# Essaie des noms jusqu en obtenir un qui soit tout neuf use POSIX; do { $nom = tmpnam(); } until sysopen(TMP, $nom, O_RDWR | O_CREAT | O_EXCL, 0600); # Maintenant faites des E/S en utilisant le handle TMP.
10. Sauf si vous tes sur un systme comme OpenBSD, qui affecte de nouveaux PID de manire alatoire.

customer_8566

542

Chapitre 23 Scurit

La seconde est IO::FILE::new_tmpfile, qui vous redonne un handle dj ouvert :


# Ou sinon laissez le module le faire votre place. use IO::File; my $hf = IO::File::new_tmpfile(); # Il sagit de tmpfile(3) de POSIX # Maintenant faites des E/S en utilisant le handle $hf.

Aucune des deux approches nest parfaite, mais entre les deux, la premire est la meilleure. Le problme majeur avec la seconde est que Perl est tributaire des faiblesses de limplmentation de tmpfile(3) dans la bibliothque C de votre systme et que vous navez aucune garantie que cette fonction ne fasse pas quelque chose daussi dangereux que le open que nous essayons de corriger. (Et cest le cas, assez tristement, de certaines implmentations.) Un problme mineur est que cela ne vous donne pas du tout le nom du fichier. Bien que ce soit mieux si vous pouvez manipuler un fichier temporaire sans connatre son nom car de cette manire vous ne provoquerez jamais de situation de concurrence en essayant de louvrir nouveau bien souvent, vous ne pouvez pas. Le problme majeur avec la premire approche est que vous navez aucun contrle sur lendroit o se trouve le chemin du fichier, au contraire de la fonction mkstemp(3) de la bibliothque C. Une premire raison est quil faut viter de mettre le fichier sur un systme de fichiers mont en NFS. Il nest pas garanti que le f lag O_EXCL fonctionne correctement sous NFS, plusieurs processus demandant une cration exclusive pratiquement au mme moment peuvent donc tous russir. Une autre raison est que le chemin renvoy se situe probablement dans un rpertoire o les autres ont les droits en criture, quelquun pourrait avoir plant un lien symbolique pointant vers un fichier inexistant, vous forant crer votre fichier un endroit quil prfre.11 Si vous avez votre mot dire l-dessus, ne mettez pas vos fichiers temporaires dans un rpertoire o quelquun dautre peut crire. Si vous y tes oblig, assurez-vous dutiliser le f lag O_EXCL dans le sysopen et essayez demployer des rpertoires avec le f lag seul-le-propritairepeut-effacer (le sticky bit ) positionn. Depuis la version de Perl 5.6.1, il existe une troisime manire. Le module standard File::Temp prend en compte toutes les difficults que nous avons mentionnes. Vous pourriez utiliser les options par dfaut ainsi :
use File::Temp "tempfile"; $handle = tempfile();

Ou vous pourriez spcifier certaines options ainsi :


use File::Temp "tempfile"; ($handle, $nom_fichier) = tempfile("priseXXXXXX", DIR => "/var/spool/aventure", SUFFIX = .dat);

Le module File::Temp fournit galement des mulations se proccupant de la scurit pour les autres fonctions que nous avons mentionnes (bien que linterface native soit meilleure car elle vous donne un handle de fichier ouvert et pas seulement un nom de fichier, qui est sujet des situations de concurrence). Voir le chapitre 32, Modules stan11. Une solution ceci, qui ne fonctionne que sous certains systmes dexploitation, consiste appeler sysopen en utilisant un OU avec le f lag O_NOFOLLOW. Ceci fait chouer la fonction si le composant final du chemin est un lien symbolique.

customer_8566

Gestion du code non sr

543

dards, pour une plus longue description des options et de la smantique de ce module. Une fois que vous avez votre handle de fichier, vous pouvez en faire tout ce que vous voulez. Il est ouvert la fois en lecture et en criture, vous pouvez donc crire dans le handle, faire un seek pour revenir au dbut et ensuite, si vous le voulez, craser tout ce que vous veniez dy mettre ou le lire nouveau. La chose que vous voudrez vraiment, vraiment viter de faire est de jamais ouvrir ce fichier nouveau, car vous ne pouvez tre srs quil sagisse vraiment du mme fichier que vous aviez ouvert la premire fois.12 Lorsque vous lancez un autre programme depuis votre script, Perl ferme normalement pour vous tous les handles de fichiers pour viter une autre vulnrabilit. Si vous utilisez fcntl pour nettoyer votre f lag close-on-exec (comme dans la description dopen au chapitre 29, Fonctions), les autres programmes que vous appelez hriteront de ce nouveau descripteur de fichier ouvert. Sur les systmes qui implmentent le rpertoire /dev/fd, vous pourriez fournir un autre programme un nom de fichier qui soit vraiment le descripteur de fichier en le construisant de cette faon :
$nom_virtuel = "/dev/fd" . fileno(TMP);

Si vous naviez besoin que dappeler un sous-programme Perl ou un programme qui attend un nom de fichier comme argument et si vous saviez que ce sous-programme ou que ce programme lutilisait avec un open ordinaire, vous pourriez alors passer le handle de fichier en employant la notation de Perl pour indiquer un handle de fichier :
$nom_virtuel = "=&" . fileno(TMP);

Lorsque le nom de fichier est pass avec un open ordinaire en Perl un ou deux arguments (et non trois, ce qui enlverait toute cette magie bien utile), vous obtenez laccs au descripteur dupliqu. Dune certaine manire, ceci est plus portable que de passer un fichier depuis /dev/fd car cela fonctionne partout o Perl fonctionne ; tous les systmes nont pas de rpertoire /dev/fd. Dun autre ct, la syntaxe spciale dopen en Perl pour accder aux descripteurs de fichiers par des nombres ne fonctionne quavec des programmes Perl et non avec des programmes crits dans dautres langages.

Gestion du code non sr


La vrification de marquage nest quune sorte de couverture de survie dont vous avez besoin si vous voulez dbusquer des donnes fausses que vous auriez d dceler vousmme mais que vous navez pas pu dpister avant de les abandonner au systme. Cest un peu comme les avertissements optionnels que Perl peut vous donner ils peuvent ne pas indiquer de problme rel mais en moyenne le mal que lon se donne grer les fausses alertes est moindre que celui de ne pas dtecter les vrais problmes. Avec le marquage, ce dernier mal est encore plus insistant car lutilisation de donnes fausses ne donne pas seulement les mauvaises rponses ; cela peut saccager votre systme et vos deux dernires annes de travail avec. (Et peut-tre vos deux prochaines si vous navez pas fait de bonnes sauvegardes.) Le mode de marquage est utile lorsquil sagit davoir
12. Except aprs coup, en faisant un stat sur les deux handles de fichiers et en comparant le deux premires valeurs renvoyes pour chacun (la paire priphrique/inode). Mais cest trop tard car le mal est dj fait. Tout ce que vous pouvez faire est de constater les dgts et dabandonner (et peut-tre envoyer furtivement un email ladministrateur systme).

customer_8566

544

Chapitre 23 Scurit

confiance en vous-mme pour crire du code honnte mais ne que vous ne faites pas systmatiquement confiance quiconque vous passe des donnes pour ne pas essayer de vous pousser faire quelque chose de regrettable. Les donnes sont une chose. Mais cest tout fait une autre affaire lorsque vous ne pouvez mme pas faire confiance au code que vous tes en train dexcuter. Et si lapplet que vous avez rcupre sur le Net contenait un virus, une bombe retardement ou un cheval de Troie ? La vrification de marquage est ici inutile car, alors que les donnes qui sont fournies au programme peuvent tre trs bien, cest le code qui est indigne de confiance. Vous vous mettez dans la situation de quelquun qui reoit un appareil mystrieux de la part dun tranger, avec une note disant en substance : Placez ceci contre votre crne et appuyez sur la dtente. Vous pouvez penser que cela va scher vos cheveux, mais peut-tre plus pour trs longtemps. Dans ce domaine, la prudence est synonyme de paranoa. Il vous faut un systme qui vous permette de placer le code suspect en quarantaine. Il peut continuer exister et mme accomplir certaines fonctions mais vous ne le laissez pas se promener et faire tout ce dont il a envie. En Perl, vous pouvez imposer un genre de quarantaine en utilisant le module Safe.

Compartiments scuriss
Le module Safe vous laisse mettre en place un bac sable (sandbox), un compartiment spcial dans lequel toutes les oprations systme sont interceptes et o laccs lespace de noms est strictement contrl. Les dtails techniques de bas niveau de ce module sont changeants nous adopterons donc ici une approche plus philosophique.

Restriction de laccs lespace de noms


Au niveau le plus fondamental, un objet Safe ressemble un coffre-fort sauf que lide de base est de laisser les truands lintrieur et non lextrieur. Dans le monde Unix, il existe un appel systme connu sous le nom de chroot(2) qui peut consigner en permanence un processus dans un sous-rpertoire du systme de fichiers dans son enfer personnel si vous voulez. Une fois que le processus y est install, il ne peut absolument pas atteindre de fichiers lextrieur de ce rpertoire car il ne sait rien pas nommer de fichiers se trouvant lextrieur.13 Un objet Safe ressemble cela mais au lieu dtre restreint un sous-ensemble de la structure de rpertoires du systme de fichiers, il est restreint un sous-ensemble de la structure des paquetages de Perl, qui est tout aussi hirarchique que la structure du systme de fichiers. Une autre manire de voir un objet Safe est quelque peu similaire ces salles dobservations avec des miroirs sans tain dans lesquelles la police met ses suspects. Les gens lextrieur peuvent regarder ceux dans la salle mais non linverse. Lorsque vous crez un objet Safe, vous pouvez lui donner un nom de paquetage si vous le voulez. Sinon, un nouveau nom sera choisi pour vous :

13. Certains sites font cela pour excuter des scripts CGI, en utilisant des montages en boucle et en lecture seule. Cest quelque peu ennuyeux configurer mais si quelquun schappe un jour, il dcouvrira quil na nulle part o aller.

customer_8566

Gestion du code non sr


use Safe; my $salle = Safe->new("Donjon"); $Donjon::truc = 1; # Pourtant, laccs direct est dconseill.

545

Si vous qualifiez pleinement les variables et les fonctions utilisant le nom de paquetage donn la mthode new, vous pouvez y accder depuis lextrieur, du moins dans limplmentation actuelle. Cela peut toutefois changer, puisque le projet actuel est de cloner la table de symboles dans un nouvel interprteur. Une solution pouvant tre lgrement plus compatible consiste positionner les choses avant de crer lobjet Safe, comme montr ci-dessous. Ceci est susceptible de continuer fonctionner et cest une manire habile de configurer un objet Safe qui doit dmarrer avec beaucoup dtats . (Admettons-le, $Donjon::truc na pas beaucoup dtats.)
use Safe; $Donjon::truc = 1; # Laccs direct est toujours dconseill. my $salle = Safe->new("Donjon");

Mais Safe fournit galement un moyen daccs aux vnements globaux du compartiment si vous ne connaissez pas le nom de paquetage du compartiment. Ainsi, pour une compatibilit ascendante maximale (toutefois, la vitesse ne le sera pas, maximale), nous vous suggrons demployez la mthode reval :
use Safe; my $salle = Safe->new(); $salle->reval($truc = 1);

(En fait, il sagit de la mme mthode que vous utiliserez pour excuter du code suspect.) Lorsque vous passez du code dans le compartiment pour le compiler et lexcuter, ce code pense quil se trouve vraiment dans le paquetage main. Ce que le monde extrieur appelle $Donjon::truc, le code lintrieur pense quil sagit de $main::truc ou $::truc ou simplement $truc si use strict nest pas actif. Cela ne marchera pas si lon crit $Donjon::truc lintrieur du compartiment car ceci accderait en fait $Donjon::Donjon::truc. En donnant lobjet Safe sa propre notion de main, les variables et les sous-programmes dans le reste de votre programme sont protgs. Pour compiler et excuter du code dans le compartiment, utilisez la mthode reval ( eval restreint ) en passant une chane de code comme argument. Comme avec toute autre construction eval CHAINE, les erreurs la compilation et les exceptions lexcution pour reval ne tueront pas votre programme. Elles ne feront quabandonner le reval et laisser lexception dans $@, assurez-vous donc de la vrifier aprs chaque appel reval. En utilisant les initialisations donnes plus tt, ce code affichera que truc vaut maintenant 2 :
$salle->reval($truc++; print "truc vaut maintenant $main::truc\n"); if ($@) { die "Impossible de compiler le code dans le compartiment : $@"; }

Si vous ne voulez que compiler du code sans lexcuter, enrober votre chane dans une dclaration de sous-programme :
$salle->reval(q{ our $truc;

customer_8566

546
sub affiche_truc { print "truc vaut maintenant $main::truc\n"; } }, 1); die if $@; # vrification de la compilation

Chapitre 23 Scurit

Cette fois, nous avons pass reval un second argument qui, sil est vrai, indique reval de compiler le code avec le pragma strict actif. Depuis lintrieur de la chane de code, vous ne pouvez pas dsactiver strict car importer et ne pas importer sont justement deux des choses que vous ne pouvez pas faire normalement dans un compartiment Safe. Il existe encore beaucoup de choses que vous ne pouvez pas faire normalement dans un compartiment Safe voir le paragraphe suivant. Une fois que vous avez cr la fonction affiche_truc dans le compartiment, ces instructions sont peu prs quivalentes :
$salle->reval(affiche_truc()); die if $@; # Meilleure faon.

$salle->varglob(affiche_truc)->(); # Appel via un glob anonyme. Donjon::affiche_truc(); # Appel direct, fortement dconseill.

Restriction de laccs aux oprateurs


Lautre chose importante propos dun objet Safe est que Perl limite les oprations disponibles lintrieur du bac sable. (Vous pourriez trs bien laisser votre enfant prendre un seau et une pelle dans le bac sable mais vous refuseriez certainement de le laisser jouer avec un bazooka.) Il ne suffit pas de protger seulement le reste de votre programme ; vous devez aussi protger le reste de votre ordinateur. Lorsque vous compilez du code dans un objet Safe, avec reval ou rdo (la version restreinte de loprateur do FICHIER), le compilateur consulte une liste spciale, par compartiment, de contrle daccs pour dcider si chaque opration individuelle est considre ou non comme sre pour la compilation. De cette manire vous navez pas (trop) vous inquiter propos des squences dchappement imprvues du shell, de louverture de fichiers alors que vous ne le vouliez pas, des assertions de code tranges dans les expressions rgulires ou de la plupart des problmes daccs depuis lextrieur que la plupart des gens craignent habituellement. (Ou quils devraient craindre.) Linterface spcifiant quels oprateurs devraient tre permis ou restreints est actuellement en cours de rcriture, nous ne montrerons donc ici que la manire den utiliser un ensemble par dfaut. Pour plus de dtails, consultez la documentation en ligne du module Safe. Le module Safe noffre pas une protection complte contre les attaques par saturation des serveurs (denial-of-service attacks), particulirement lorsquon lutilise dans ses modes les plus permissifs. Les attaques par saturation des serveurs prennent toutes les ressources dun certain type disponibles sur le systme, empchant les autres processus daccder aux caractristiques essentielles du systme. Des exemples de telles attaques comprennent le bourrage de la table de processus du noyau, la main-mise sur la CPU en excutant dans une frntique boucle sans fin, lpuisement de toute la mmoire disponible et le remplissage dun systme de fichiers. Ces problmes sont trs difficiles

customer_8566

Gestion du code non sr

547

rsoudre, particulirement de manire portable. Voir la fin de la section Du code dguis en donnes pour une discussion plus approfondie sur les attaques par saturation des serveurs.

Exemples scuriss
Imaginez que vous ayez un programme CGI grant un formulaire dans lequel lutilisateur peut rentrer une expression Perl arbitraire et rcuprer le rsultat valu.14 Comme toutes les entres venant de lextrieur, la chane arrive marque, Perl ne vous laissera donc pas encore lui appliquer un eval vous devrez dabord la nettoyer grce une reconnaissance de motif. Le problme est que vous ne serez jamais capables de concevoir un motif qui puisse dtecter toutes les menaces possibles. Et vous noserez pas nettoyer ce que vous avez reu et lenvoyer leval interne. (Si vous osez, nous serons tents de pntrer dans votre systme pour supprimer le script.) Cest ici que reval entre en scne. Voici un script CGI qui traite un formulaire avec un simple champ, value (dans un contexte scalaire) la chane quil trouve et affiche le rsultat format :
#!/usr/bin/perl -lTw use strict; use CGI::Carp fatalsToBrowser; use CGI qw/:standard escapeHTML/; use Safe; print header(-type => "text/html;charset=UTF-8"), start_html("Rsultat de lexpression Perl"); my $expr = param("EXPR") =~ /^([^;]+)/ ? $1 # renvoie la portion maintenant nettoye : croak("aucun champ EXPR valide dans le formulaire"); my $reponse = Safe->new->reval($expr); die if $@; print p("Le rsultat de", tt(escapeHTML($expr)), "est", tt(escapeHTML($reponse)));

Imaginez quun utilisateur malveillant vous passe print cat /etc/passwd (ou pire) comme chane dentre. Grce lenvironnement restreint qui interdit les apostrophes inverses, Perl dclera le problme la compilation et quittera immdiatement. La chane dans $@ est quoted execution (, qx) trapped by operation mask (excution entre apostrophes inverses (, qx) capture par le masque des oprations), ainsi que les informations obligatoires la fin, identifiant o le problme a eu lieu. Puisque nous navons pas dit le contraire, les compartiments que nous avons crs utilisent tous lensemble par dfaut doprations permises. La manire dont vous vous y prenez pour dclarer des opration spcifiques comme permises ou interdites, importe peu ici. Et puisque vous pouvez crer plusieurs objets Safe dans votre programme, vous pouvez confrer diffrents degrs de confiance aux diffrents morceaux de code selon leur provenance.
14. Merci de ne pas rire. Nous avons vraiment vu des pages web faire cela. Sans Safe !

customer_8566

548

Chapitre 23 Scurit

Si vous dsirez vous amuser avec Safe, voici une petite calculatrice interactive en Perl. Vous pouvez lui passer des expressions numriques et voir immdiatement leur rsultats. Mais elle nest pas limite aux nombres. Elle ressemble plus lexemple de boucle pour eval au chapitre 29, o vous pouvez prendre tout ce quon vous donne, lvaluer et renvoyer le rsultat. La diffrence est que la version avec Safe nexcute pas aveuglment tout ce que vous souhaitez. Vous pouvez lancer cette calculatrice interactivement sur votre terminal, y taper quelques bouts de code en Perl et vrifier les rponses pour avoir un aperu des types de protection fournis par Safe.
#!/usr/bin/perl -w # calcscu - programme de dmonstration pour jouer avec Safe use strict; use Safe; my $salle = Safe->new(); while (1) { print "Entre : "; my $expr = <STDIN>; exit unless defined $expr; chomp($expr); print "$expr donne "; local $SIG{__WARN__} = sub { die @_ }; my $result = $salle->reval($expr, 1); if ($@ =~ s/at \(eval \d+\).*//) { printf "[%s]: %s", $@ =~ /trapped by operation mask/ ? "Violation de la scurit" : "Exception", $@; } else { print "[Rsultat normal] $result\n"; } }

Avertissement : le module Safe est actuellement en cours de re-spcification pour excuter chaque compartiment dans un interprteur Perl compltement indpendant dans le mme processus. (Cest la stratgie employe par le mod_perl dApache lorsquil excute des scripts Perl prcompils.) Les dtails sont encore vagues en ce moment mais notre boule de cristal suggre que dsigner des choses lintrieur du compartiment en utilisant un paquetage nomm ne vous conduira pas bien loin aprs la rcriture imminente. Si vous utilisez une version de Perl plus rcente que 5.6, vrifier les notes concernant la version dans perldata(1) pour voir ce qui a chang ou consultez la documentation du module Safe lui-mme. (Bien entendu, cest toujours ce que vous faites, nest-ce pas ?)

Du code dguis en donnes


Les compartiments Safe sont disponibles lorsque des choses vraiment effrayantes arrivent mais cela ne veux pas dire que vous devriez laisser tomber votre garde lorsque vous vous occupez chez vous de choses quotidiennes. Vous devez cultiver une vigilance sur ce qui vous entoure et regarder les choses du point de vue de quelquun voulant sintroduire. Vous devez prendre des mesures proactives comme garder les choses bien claires et tailler les buissons qui peuvent dissimuler divers problmes se tapissant dans lombre.

customer_8566

Gestion du code non sr

549

Perl essaie de vous aider dans ce domaine galement. Lanalyse conventionnelle et le schma dexcution de Perl vitent les piges dont les langages de programmation shell sont souvent la proie. Il existe beaucoup de fonctionnalits extrmement puissantes dans les langages, mais par de par leur conception, ils sont syntaxiquement et smantiquement limits de faon que le programmeur garde le contrle. quelques exceptions prs, Perl nvalue chaque token quune seule fois. Quelque chose semblant tre utilis comme une variable pour une simple donne ne senracinera pas soudainement quelque part dans votre systme de fichiers. Malheureusement, ce genre de chose peut arriver si vous appelez le shell pour lancer dautres programmes pour vous car vous tournez alors avec les rgles du shell la place de celles de Perl. Le shell est cependant facile viter vous navez qu utiliser les formes avec un argument de liste pour les fonctions system, exec ou open sur un pipe. Bien que les apostrophes inverses ne disposent pas dune forme avec un argument de liste qui soit scurise contre le shell, vous pouvez toujours les muler comme dcrit la section Accs aux commandes et aux fichiers avec des privilges restreints. (Alors quil ny a pas de moyen syntaxique pour donner aux apostrophes inverses un argument de liste, une forme plusieurs arguments de loprateur readpipe sous-jacent est en cours de dveloppement ; mais au moment o nous crivons ces lignes, elle nest pas encore prte pour le devant de la scne.) Lorsque vous utilisez une variable dans une expression (y compris lorsque vous linterpolez dans une chane entre guillemets), il ny a aucune chance pour que la variable contienne du code Perl qui fasse quelque chose auquel vous ne vous attendiez pas.15 Au contraire du shell, Perl na jamais besoin de guillemets ou dapostrophes protecteurs autour des variables, peu importe ce quelle peuvent contenir.
$nouveau = $ancien; print "$nouveau items\n"; # pas besoin de guillemets ou dapostrophes. # $nouveau ne peut pas vous faire de mal.

$phrase = "$nouveau items\n"; # ici non plus. print $phrase; # toujours parfaitement ok.

Perl adopte une approche WYSIWYG (what you see is what you get, ce que vous voyez est ce que vous obtenez). Si vous ne voyez pas de niveau supplmentaire dinterpolation, alors il ny en a pas. Il est possible dinterpoler arbitrairement des expressions Perl dans des chanes mais seulement si vous demandez spcifiquement Perl de le faire. (Et mme ainsi, le contenu est toujours sujet aux vrifications de marquage si vous tes en mode de marquage.)
$phrase = "Vous avez perdu @{[ 1 + int rand(6) ]} points\n";

Linterpolation nest cependant pas rcursive. Vous ne pouvez pas cacher une expression arbitraire dans une chane :
$compteur = 1 + int rand(6); $dire = "$compteur points"; $dire = "@{[$compteur]} points; # Du code alatoire. # Plutt un littral. # galement un littral.

15. Cela dit, si vous gnrez une page web, il est possible dmettre des balises HTML, comprenant du code JavaScript, qui pourrait faire quelque chose auquel le navigateur distant ne sattendait pas.

customer_8566

550

Chapitre 23 Scurit

Les deux affectations $dire produiraient 1 + rand(6) points , sans valuer le contenu interpol de $compteur en tant que code. Pour obliger Perl faire cela, vous devez appeler eval CHAINE explicitement :
$code = 1 + int rand(6); $lance_de_des = eval $code; die if $@;

Si $code tait marqu, cet eval CHAINE aurait lev sa propre exception. Bien entendu, il ne faut presque jamais valuer du code alatoire provenant de lutilisateur mais si vous le faites, vous devriez jetez un il au module Safe. Vous avez d en entendendre parler. Il existe un endroit o Perl peut parfois traiter des donnes comme du code ; savoir, lorsque le motif dans un oprateur qr//, m// ou s/// contient lune des nouvelles assertions des expressions rgulires, (?{ CODE }) ou (??{ CODE }). Celles-ci ne posent pas de problmes de scurit lorsquelles sont utilises comme des littraux dans des correspondances de motifs :
$cmpt = $n = 0; while ($donne =~ /( \d+ (?{ $n++ }) | \w+ )/gx) { $cmpt++; } print "$cmpt mots trouvs, dont $n nombres.\n";

Mais du code existant interpolant des variables dans des correspondances a t crit en prsupposant que les donnes taient des donnes, et non du code. Les nouvelles constructions pourraient avoir introduit un trou de scurit dans des programmes auparavant scuriss. Ainsi, Perl refuse dvaluer un motif si une chane interpole contient une assertion de code et lve la place une exception. Si vous avez vraiment besoin de cette fonctionnalit, vous pouvez toujours lactiver avec le pragma de porte lexicale use re eval. (Vous ne pouvez cependant toujours pas utiliser de donnes marques en tant quassertions de code interpol.) Un type compltement diffrent de soucis de scurit se produisant avec les expressions rgulires rside dans les problmes de saturation des serveurs (denial-of-service). Ceuxci peuvent faire sortir votre programme trop tt, ou tourner trop longtemps, ou encore puiser toute la mmoire disponible et mme parfois faire un core dump, selon lge du capitaine. Lorsque vous traitez des motifs fournis par lutilisateur, vous navez pas vous inquiter propos de linterprtation de code Perl quelconque. Cependant, le moteur dexpressions rgulires possde ses propres petits compilateur et interprteur et le motif fourni par lutilisateur est capable dinf liger un infarctus au compilateur dexpressions rgulires. Si un motif interpol nest pas valide, une exception est leve lexcution, ce qui est fatal moins de lintercepter. Si vous essayez effectivement de lintercepter, assurezvous dutiliser seulement eval BLOC, et non eval CHAINE, car le niveau dvaluation supplmentaire de cette dernire forme permettrait en fait lexcution de code Perl alatoire. la place, faites quelque chose comme ceci :
if (not eval { "" =~ /$corresp/; 1 }) { # (Maintenant faites ce que vous voulez avec un mauvais motif.) } else {

customer_8566

Gestion du code non sr

551

# Nous savons que le motif est au moins scuris pour la compilation. if ($donnee =~ /$corresp/) {...} }

Un problme plus troublant de saturation des serveurs est qutant donn la bonne donne et le bon motif de recherche, votre programme peut sembler se bloquer jamais. Car certaines correspondances de motifs exigent un temps de calcul exponentiel et cela peut facilement excder le taux de MTBF (Mean Time Between Failures, N.d.T. : temps moyen de fonctionnement entre deux incidents) de notre systme solaire. Si vous tes particulirement chanceux, ces motifs demandant des calcul intensifs exigeront galement un espace de stockage exponentiel. Si cest le cas, votre programme puisera toute la mmoire virtuelle disponible, croulera votre systme, embtera vos utilisateurs et soit dcdera par die avec une erreur ordinaire Out of memory! (dpassement de mmoire), soit laissera derrire lui un fichier core dump vraiment norme, peut-tre cependant pas aussi gros que le systme solaire. Comme la plupart des attaques par saturation des serveurs, celle-ci nest pas facile rsoudre. Si votre plate-forme implmente la fonction alarm, vous pouvez donner un dlai limite pour la correspondance de motifs. Malheureusement, Perl ne peut pas (actuellement) garantir que le simple acte de grer un signal ne va jamais lever un core dump. (Nous avons prvu de le rsoudre dans une prochaine version.) Vous pouvez cependant toujours lessayer et mme si le signal nest pas gr lgamment, au moins le programme ne bouclera pas jamais. Si votre systme implmente des limites de ressources par processus, vous pourriez configurer celles-ci dans votre shell avant dappeler le programme Perl ou utiliser le module BSD::Ressource de CPAN pour le faire directement en Perl. Le serveur web Apache vous permet de fixer des limites de temps, de mmoire et de taille de fichiers sur les scripts CGI quil lance. Finalement, nous esprons que nous vous avons laiss un sentiment non rsolu dinscurit. Souvenez-vous que si vous tes paranoaque, cela ne veut pas dire pour autant quil ny a personne vos trousses. Alors vous feriez mieux de vous en accommoder.

customer_8566

customer_8566

Techniques couramment employes


Adressez-vous nimporte quel programmeur Perl et il sera heureux de vous donner des pages et des pages de conseil sur la manire de programmer. Nous ne sommes pas diffrents (au cas o vous ne layez pas remarqu). Dans ce chapitre, plutt que dessayer de vous exposer les caractristiques spcifiques de Perl, nous prendrons la direction oppose en distillant quelques descriptions des techniques idiomatiques en Perl. Nous esprons quen rassemblant divers petits morceaux qui semblent sans rapport les uns avec les autres, vous parviendrez vous imbiber du sentiment de ce quest vraiment penser en Perl . Aprs tout, lorsque vous programmez, vous ncrivez pas un paquet dexpressions, puis un paquet de sous-programmes, puis un paquet dobjets. Vous devez tout apprhender dun seul coup, plus ou moins. Voil donc quoi ressemble ce chapitre. Il y a tout de mme une organisation rudimentaire dans ce chapitre, en ce que nous commencerons par les conseils ngatifs et tracerons le chemin jusquau conseils positifs. Nous ne savons pas si vous vous sentirez mieux grce cela mais cela nous aidera, nous, nous sentir mieux.

24

tourderies courantes des dbutants


La plus grande tourderie est doublier dutiliser use warnings, qui relve de nombreuses erreurs. La deuxime est de ne pas utiliser use strict quand il le faut. Ces deux pragmas peuvent vous conomiser des heures de casse-tte lorsque votre programme commence grossir. (Et ce sera le cas.) Un autre faux pas consiste oublier de consulter la FAQ en ligne. Imaginez que vous vouliez trouver si Perl dispose dune fonction round. Vous devriez essayer de chercher dabord dans la FAQ :
% perlfaq round

part ces mta-tourderies , il y a plusieurs types de piges de programmation. Certains piges dans lesquels presque tout le monde tombe et dautres dans lesquels vous ne tombez que si vous tes originaire dune culture particulire possdant des pratiques diffrentes. Nous les avons rpartis dans les sections suivantes.

customer_8566

554

Chapitre 24 Techniques couramment employes

Erreurs universelles
Mettre une virgule aprs le handle de fichier dans une instruction print. Bien quil paraisse tout fait rationnel et lgant dcrire :
print STDOUT, "adieu, monde ", $adj, " !\n"; # MAUVAIS

cest nanmoins incorrect, cause de la premire virgule. Ce quil faut la place est la syntaxe dobjet indirect :
print STDOUT "adieu, monde ", $adj, " !\n"; # ok

La syntaxe est ainsi faite que lon puisse crire :


print $handle_fichier "adieu, monde ", $adj, " !\n";

o $handle_fichier est un scalaire contenant le nom dun handle de fichier lexcution. Ce qui est diffrent de :
print $pas_un_handle_fichier, "adieu, monde ", $adj, " !\n";

o $pas_un_handle_fichier nest quune chane qui est ajoute la liste de ce qui doit tre imprim. Voir objet indirect dans le glossaire. Utiliser == au lieu de eq et != au lieu de ne. Les oprateurs == et != sont des tests numriques. Les deux autres sont des tests sur les chanes. Les chanes "123" et "123.00" sont gales en tant que nombres, mais pas en tant que chanes. De mme, les chanes non-numriques sont numriquement gales zro. moins que vous ne traitiez des nombres, vous utilisez presque toujours la place les oprateurs de comparaison de chanes. Oublier le point-virgule final. Chaque instruction Perl est termine par un pointvirgule ou la fin dun bloc. Les sauts de ligne ne sont pas des terminateurs dinstruction comme en awk, en Python ou en FORTRAN. Souvenez-vous que Perl est comme C. Une instruction contenant un document ici-mme (here document) est tout particulirement apte perdre son point-virgule. Cela devrait ressembler ceci :
print <<FINIS; Sans une grande roideur et une continuelle attention toutes ses paroles, on est expos dire en moins dune heure le oui et le non sur une mme chose ou sur une mme personne, dtermin seulement par un esprit de socit et de commerce qui entrane naturellement ne pas contredire celui-ci et celui-l qui en parlen diffremment. -- Jean de La Bruyre FINIS

Oublier quun BLOC exige des accolades. Les instructions seules ne forment pas de BLOC par elles-mmes. Si vous crez une structure de contrle comme un while ou un if qui demande un ou plusieurs BLOC s, vous devez utiliser des accolades autour de chaque BLOC. Souvenez-vous que Perl nest comme C. Ne pas sauver $1, $2, etc., dans les expressions rgulires. Souvenez-vous que chaque nouvelle correspondance (m//) ou substitution (s///) modifie (ou remet zro ou crase) vos variables $1, $2. . . , ainsi que $, $&, $ et consorts. Une manire de les sauvegarder consiste valuer la correspondance dans un contexte de liste,

customer_8566

Erreurs universelles
comme dans :
my ($un, $deux) = /(\w+) (\w+)/;

555

Ne pas se rendre compte quun local change aussi la valeur de la variable telle que la voient les autres sous-programmes appels depuis lintrieur de la porte du local. Il est facile doublier que local est une instruction dexcution qui travaille dans une porte dynamique, car il nen existe aucun quivalent dans des langages comme C. Voir la section Dclarations avec porte au chapitre 4, Instructions et dclarations. De toute faon, il est en gnral prfrable dutiliser un my. Perdre la trace des appariements daccolades. Un bon diteur vous aidera trouver les paires correspondantes. Prenez-en un. (Ou deux.) Employer des instructions de contrle de boucle dans un do {} while. Bien que les accolades dans cette structure de contrle ont lair de faire partie dun BLOC de boucle, ce nest en fait pas le cas. Utiliser $truc[1] alors que vous voulez dire $truc[0]. Les tableaux commence par dfaut zro en Perl. crire @truc[0] alors que vous vouliez dire $truc[0]. La rfrence @truc[0] est une tranche de tableau, reprsentant un tableau constitu du seul lment $truc[0]. Parfois, cela ne fait aucune diffrence, comme dans :
print "la rponse est @truc[0]\n";

Mais la diffrence est norme pour des choses comme :


@truc[0] = <STDIN>;

qui va absorber tout STDIN en affectant la premire ligne $truc[0] et en rejetant tout le reste, ce qui nest probablement pas ce que vous aviez prvu. Prenez lhabitude de considrer que $ reprsente une valeur unique, alors que @ reprsente une liste de valeurs, et tout ira bien. Oublier les parenthses avec un oprateur de liste comme my :
my $x, $y = (4, 8); # FAUX my ($x, $y) = (4, 8); # ok

Oublier de slectionner le bon handle de fichier avant de positionner $^, $~ ou $|. Ces variables dpendent du handle de fichier actuellement slectionn, comme le dtermine select (HANDLE_FICHIER). Le handle de fichier initialement slectionn est STDOUT. Vous devriez vraiment plutt utiliser les mthodes de handles de fichiers du module FileHandle. Voir le chapitre 28, Noms spciaux.

Conseils frquemment ignors


Les programmeurs Perl Pratiquants devraient prendre note de ce qui suit : Souvenez-vous que de nombreuses oprations se comportent diffremment dans un contexte de liste et dans un contexte scalaire. Par exemple :
($x) = (4, 5, 6); $x = (4, 5, 6); @a = (4, 5, 6); $x = @a; # Contexte de liste ; $x vaut 4 e scalaire ; $x vaut 6 # Co

# Contexte scalaire ; $x vaut 3 # (la longueur du tableau)

customer_8566

556

Chapitre 24 Techniques couramment employes

vitez si possible les mots simples, surtout sils sont entirement en minuscules. Il est impossible de savoir du premier coup dil si un mot est une fonction ou une chane brute. Vous supprimerez toute confusion en protgeant les chanes par des guillemets et des parenthses autour des arguments dappels de fonction. En fait, le pragma use strict au dbut de votre programme donne une erreur de compilation si lon utilise un mot simple ce qui est probablement une bonne chose. On ne peut pas distinguer au premier coup dil les fonctions internes qui sont des oprateurs unaires (comme chop et chdir), celles qui sont des oprateurs de liste (comme print et unlink) et celles qui nont pas dargument (comme time). Il vous faut les apprendre au chapitre 29. Comme toujours, utilisez des parenthses si vous ntes pas srs et mme si vous ntes pas srs dtre srs. Remarquez galement que les sous-programmes dfinis par lutilisateur sont par dfaut des oprateurs de liste mais peuvent tre dclars comme oprateurs unaires avec un prototype valant ($) ou sans arguments avec un prototype valant (). On a souvent du mal se souvenir que certaines fonctions emploient par dfaut $_, ou @ARGV ou autre chose, alors que dautres non. Prenez le temps dapprendre lesquelles, ou vitez les arguments par dfaut. <HF> nest pas le nom dun handle de fichier mais un oprateur dangle qui effectue une opration dentre par ligne sur le handle. Cette confusion se manifeste gnralement quand des gens essayent un print sur loprateur angle :
print <HF> "salut"; # MAUVAIS, omettre les angles

Souvenez-vous galement que les donnes lues par loprateur dangle ne sont affectes $_ que lorsque le fichier lu est la seule condition dune boucle while :
while (<HF>) { } <HF>; # Donnes affectes $_. # donnes lues et limines !

Nutilisez pas = lorsque vous avez besoin de =~ ; les deux constructions sont trs diffrentes :
$x = /truc/; $x =~ /truc/; # recherche "truc" dans $_, met le rsultat dans $x # recherche "truc" dans $x, limine le rsultat

Utilisez my pour les variables locales chaque fois que vous pouvez vous en accommoder. local donne en fait une valeur temporaire une variable globale, ce qui vous expose grandement aux effets secondaires dus la porte dynamique Nutilisez pas local sur les variables exportes par un module. La localisation dune variable exporte ne fait pas changer sa valeur. Le nom local devient lalias dune nouvelle valeur mais le nom externe reste lalias de loriginal.

Piges du C
Les programmeurs Crbraux du C devraient prendre note de ce qui suit : Les accolades sont obligatoires pour les blocs if et while. Vous devez utiliser elsif plutt que else if ou de elif . Une syntaxe comme :
if (expression) { bloc;

customer_8566

Erreurs universelles
} else if (autre_expression) { # MAUVAIS autre_bloc; }

557

est illgale. La partie else est toujours un bloc et un if tout nu nest pas un bloc. Ne vous attendez pas ce que Perl se comporte exactement comme le C. la place, il faut crire :
if (expression) { bloc; } elsif (autre_expression) { autre_bloc; }

Remarquez galement que elif est file crit lenvers. Seuls des fanatiques dAlgol pourraient tolrer un mot-clef identique un autre mot crit lenvers. Les mots-clefs break et continue de C deviennent respectivement last et next en Perl. En revanche, ces derniers ne fonctionnent pas dans une construction do {} while. Il nexiste pas dinstruction switch. (Mais il est facile den laborer une au vol ; voir les paragraphes Blocs simples et Structures de cas au chapitre 4. Les variables commencent par $, @ ou % en Perl. Les commentaires commencent par # et non par /*. Vous ne pouvez pas obtenir ladresse de nimporte quoi, bien quun oprateur similaire en Perl soit lantislash, qui cre une rfrence. ARGV doit tre en majuscules. $ARGV[0] est le argv[1] de C et le argv[0] de C devient $0. Les appels systme comme link, unlink et rename renvoient vrai en cas de succs et non 0. Les gestionnaires de signaux de %SIG traitent des noms de signaux et non des nombres.

Piges du shell
Les programmeurs Shrifs du Shell devraient prendre note de ce qui suit : Les variables sont prfixes par $ ou @ tant du ct gauche dune affectation que du ct droit. Une affectation la shell comme :
chameau=dromadaire; $chameau=dromadaire; # MAUVAIS # ok

ne sera pas analyse comme prvu. Vous devez mettre : La variable de boucle pour un foreach exige galement un $. Mme si csh prfre :
foreach bosse (une deux) remplir $bosse end

customer_8566

558
en Perl, ceci scrit plutt :

Chapitre 24 Techniques couramment employes

foreach $bosse ("une", "deux") { remplir($bosse); }

Loprateur apostrophe inverse interpole les variables sans se proccuper de la prsence dapostrophes dans la commande. Loprateur apostrophe inverse ne convertit pas la valeur de retour. En Perl, il faut explicitement liminer le saut de ligne, comme ceci :
chop($mon_hote = hostname);

Les shells (surtout csh) offrent plusieurs niveaux de substitution sur la ligne de commande. Perl neffectue de substitution que dans certaines constructions comme les guillemets, les apostrophes inverses, les signes infrieurs et suprieurs et les motifs de correspondance. Les shells ont tendance interprter les scripts petit petit. Perl compile le programme entier avant de lexcuter (hormis les blocs BEGIN, qui sexcutent avant que la compilation soit acheve). Les arguments sont accessibles via @ARGV et non $1, $2, etc. Lenvironnement nest pas automatiquement accessible sous forme de variables scalaires spares. Utilisez le module standard Env si vous voulez que ce soit le cas.

Piges des anciens Perl


Les programmeurs Pnitents de Perl 4 (et des Prcdents) devraient prendre note des modifications suivantes entre la version 4 et la version 5 qui pourraient affecter les anciens scripts : @ interpole maintenant systmatiquement un tableau dans des chanes protges par guillemets. Certains programmes doivent maintenant utiliser lantislash pour protger les @ qui ne devraient pas tre interpoles. Les mots simples qui ressemblaient des chanes Perl ont maintenant lair dappels un sous-programme si un sous-programme de ce nom est dfini avant que le compilateur ne les voie. Par exemple :
sub Ciao { die "Hasta la vista, baby !" } $SIG{QUIT} = Ciao;

Dans les prcdentes versions de Perl, ce code mettait en place le gestionnaire de signal. Il appelle maintenant la fonction ! Vous pouvez utiliser loption -w pour dtecter cette construction risque ou use strict pour la rendre illgale. Les identificateurs commenant par _ ne se trouvent plus forcment dans le paquetage main, sauf le symbole soulign brut lui-mme (comme dans $_, @_, etc). Le double deux-points est maintenant un sparateur de paquetage valide dans un identificateur. Ainsi, linstruction :
print "$a::$b::$c\n"

analyse maintenant $a:: comme la rfrence la variable, alors que dans les versions prcdentes, seul le $a tait considr comme la rfrence la variable. De

customer_8566

Erreurs universelles
mme :
print "$var::abc::xyz\n";

559

est maintenant interprt comme une variable unique $var::abc::xyz, alors que dans les versions prcdentes, la variable $var aurait t suivie par le texte constant ::abc::xyz. s$motifremplacement ninterpole plus $motif. (Le $ serait interprt comme une assertion de fin de ligne.) Ce comportement narrive que dans lutilisation dapostrophes en tant que sparateur de substitution ; dans les autres substitutions, $motif est toujours interpol. Le deuxime et le troisime argument de splice sont maintenant valus dans un contexte scalaire plutt que dans contexte de liste. Des erreurs smantiques apparaissent maintenant en raison de la prcdence :
shift @liste + 20; $n = keys %map + 20; # # # # maintenant analys comme shift(@liste + 20), illgal ! maintenant analys comme keys(%map + 20), illgal !

Parce que si ces derniers fonctionnaient, ceci ne le pourrait pas :


sleep $sieste + 20;

La prcdence des oprateurs daffectation est maintenant la mme que celle de laffectation. Les versions antrieures de Perl leur donnaient par erreur la prcdence de loprateur associ. Il faut donc maintenant les encadrer entre parenthses dans des expressions comme :
/truc/ ? ($a += 2) : ($a -= 2);

Sinon
/truc/ ? $a += 2 : $a -= 2;

serait analys par erreur en :


(/truc/ ? $a += 2 : $a) -= 2;

En revanche,
$a += /truc/ ? 1 : 2;

fonctionne maintenant comme sy attendrait un programmeur C. open TRUC || die est maintenant incorrect. Il faut des parenthses autour du handle de fichier, car open a la prcdence dun oprateur de liste. Les lments des listes darguments pour les formats sont maintenant valus dans un contexte de liste. Cela signifie que vous pouvez maintenant interpoler des valeurs de liste. Vous ne pouvez pas aller par un goto dans un bloc que loptimisation a supprim. Damnation. Il nest plus lgal demployer un espace comme nom de variable ou comme dlimiteur de construction protge. Enfer et damnation. La fonction caller renvoie maintenant une valeur fausse dans un contexte scalaire sil ny a pas dappelant. Cela permet aux modules de dterminer sils sont requis ou lancs directement.

customer_8566

560

Chapitre 24 Techniques couramment employes

m//g rattache maintenant son tat la chane recherche plutt qu lexpression rgulire. Voir le chapitre 5, Correspondance de motifs pour plus de dtails. reverse nest plus autoris en tant que nom de routine pour de tri pour sort. taintperl nest plus un excutable spar. Il existe maintenant une option -T qui active le marquage quand il ne lest pas automatiquement. Les chanes entre guillemets ne peuvent plus se terminer par un $ ou un @ non protg. La syntaxe archaque if BLOC BLOC nest plus supporte. Les indices de tableau ngatifs comptent maintenant depuis la fin du tableau. Il est maintenant garanti que loprateur virgule, dans un contexte scalaire, procure un contexte scalaire ses arguments. Loprateur ** lie maintenant plus troitement que le moins unaire. Diminuer $#tableau limine maintenant immdiatement des lments du tableau. Il nest pas garanti que delete renvoie la valeur dtruite des tableaux lis par tie car limplmentation de cette fonctionnalit serait onreuse pour certains modules. La construction "ceci est $$x", qui interpolait lID du processus cet endroit, essaie maintenant de drfrencer $x. Toutefois, $$ tout seul, fonctionne toujours trs bien. Le comportement de foreach a lgrement chang lorsquil parcours itrativement dans une liste qui nest pas un tableau. Il affectait la liste un tableau temporaire mais ne le fait plus pour des raisons defficacit. Cela signifie que lon parcourt maintenant les valeurs actuelles et non les copies des valeurs. Les modifications de la variable de boucle peuvent changer les valeurs originelles, mme aprs un grep ! Par exemple
% 1 % 2 perl4 -e @a = (1,2,3); for (grep(/./, @a)) { $_++ }; print "@a\n" 2 3 perl5 -e @a = (1,2,3); for (grep(/./, @a)) { $_++ }; print "@a\n" 3 4

Pour conserver lancien comportement de Perl, vous devrez affecter explicitement la liste un tableau temporaire et ensuite parcourir ce dernier. Par exemple, vous pourriez avoir besoin de changer :
foreach $var (grep /x/, @liste) { ... }

en
foreach $var (my @tmp = grep /x/, @list) { ... }

Autrement, la modification de $var crasera aussi les valeurs de @liste. (Cela se produit le plus souvent lorsque vous utilisez $_ comme variable de boucle et que vous appelez des sous-programmes dans la boucle qui ne mettent pas correctement $_ en local). Certains messages derreur sont diffrents. Certains bogues ont t limins par inadvertance.

customer_8566

Efficacit

561

Efficacit
Alors que lessentiel du travail de programmation peut se rsumer un fonctionnement correct, vous pouvez vous retrouver vouloir parfois un meilleur rapport qualit/prix pour votre programme Perl. Le vaste ensemble doprateurs, les types de donnes et les structures de contrle de Perl ne sont pas forcment intuitifs quant la rapidit dexcution et loptimisation de lespace mmoire. De nombreux compromis ont t ncessaires pendant la conception de Perl et ces dcisions sont profondment ancres dans les entrailles du code. En gnral, plus un programme est court et simple, plus il est rapide mais il existe des exceptions. Ce paragraphe tente de vous aider le faire fonctionner juste un petit peu mieux. Si vous voulez quil tourne beaucoup mieux, vous pouvez jouer avec la sortie (backend) du compilateur de Perl, dcrite au chapitre 18, Compiler ou rcrire votre boucle interne dans une extension C, comme lillustre le chapitre 21, Mcanismes internes et externes. Vous remarquerez que loptimisation de la vitesse dexcution est parfois coteuse en termes despace mmoire ou defficacit pour le programmeur (on sen rend compte en constatant que certaines des astuces ci-dessous sont incompatibles entre elles). Voil le hic. Si la programmation tait si simple, il ny aurait pas besoin de quelque chose daussi compliqu quun tre humain pour sen occuper, nest-ce pas?

Efficacit du temps dexcution


Utilisez des hachages au lieu de recherches linaires. Par exemple, au lieu de chercher dans @mots_cles pour voir si $_ est un mot-cl, construisez un hachage avec :
my %mots_cles; for (@mots_cles) { $mots_cles{$_}++; }

Vous pouvez alors savoir si $_ contient un mot-cl en testant si $mots_cles{$_} donne une valeur non nulle. vitez dindicer alors quun foreach ou un oprateur de liste fait laffaire. Non seulement lindiage est une opration supplmentaire, mais si votre variable dindiage se trouve tre un nombre virgule f lottante aprs avaoir fait de larithmtique, une conversion supplmentaire vers un entier est ncessaire. Il y a souvent mieux faire. Essayez dutiliser les oprations foreach, shift et splice. Pensez crire use integer. vitez goto. Il va chercher ltiquette correspondante hors de lendroit o vous vous trouvez. vitez printf lorsque print fait laffaire. vitez $& et ses deux copains, $ et $. La moindre occurrence dans votre programme fait que toutes les correspondances sauvegardent la chane recherche pour une rfrence ultrieure possible (cela dit, une fois que cest fait, vous pouvez en mettre autant que vous voulez). vitez dutiliser eval sur une chane. Un eval dune chane (mais pas dun bloc) force la recompilation chaque passage. Lanalyseur syntaxique de Perl est plutt

customer_8566

562

Chapitre 24 Techniques couramment employes

rapide pour un analyseur, ce qui ne veut pas dire grand-chose. De nos jours, il existe presque toujours un meilleur moyen darriver vos fins. En particulier, tout code utilisant eval pour construire des noms de variable est obsolte, puisque vous arrivez maintenant la mme chose en utilisant directement des rfrences symboliques :
no strict refs; $nom = "variable"; $$nom = 7;

# Positionne $variable 7

vitez eval CHAINE lintrieur dune boucle. Mettez plutt la boucle dans leval, pour viter des compilations redondantes du code. Voir loprateur study au chapitre 29 pour en trouver un exemple. vitez les motifs compils lexcution. Utilisez le modificateur de motif /motif/o (une seule fois) pour viter les recompilations du motif quand celui-ci ne change pas durant la vie du processus. Pour les motifs qui changent occasionnellement, vous pouvez utiliser le fait quun motif nul se rfre au motif prcdent, comme ceci :
"chaine_trouvee" =~ /$motif_courant/; # Correspondance bidon # (doit russir). while (<>) { print if //; }

Ou alors, vous pouvez prcompiler votre expression rgulire en utilisant la construction de protection qr. Vous pouvez galement utiliser eval pour recompiler un sous-programme ralisant la recherche de correspondance (si vous ne recompilez quoccasionnellement). Cela fonction encore mieux si vous compilez une f lope de recherches de correspondances dans un seul sous-programme, en amortissant ainsi la surcharge de lappel de sous-programme. Un court-circuit entre deux choix possibles est souvent plus rapide que lexpression rgulire correspondante. Ainsi :
print if /une-bosse/ || /deux/;

est susceptible dtre plus rapide que


print if /une-bosse|deux/;

du moins pour certaines valeurs de une-bosse et de deux. En effet, loptimiseur aime loger certaines oprations simples de recherche de correspondance dans des parties hautes de larbre syntaxique et effectue une recherche de correspondance trs rapide grce un algorithme de Boyer-Moore. Un motif compliqu en fait perdre le bnfice. Rejetez les cas frquents le plus tt possible avec next if. Tout comme pour les expressions rgulires simples, loptimiseur prfre cela. Et cela a toujours un sens dviter le travail superf lu. Vous pouvez typiquement liminer les lignes de commentaire et les lignes vides avant mme de faire un split ou un chop :
while (<>) { next if /^#/; next if /^$/; chop;

customer_8566

Efficacit
@gorets = split(/,/); ... }

563

vitez les expressions rgulires comportant de nombreux quantificateurs ou de grands nombres {MIN,MAX} pour des expressions entre parenthses. De tels motifs peuvent engendrer un comportement de retour arrire dune lenteur exponentielle moins que les sous-motifs quantifis ne correspondent la premire passe . Vous pouvez galement utiliser la construction (?>...) pour forcer un sous-motif correspondre compltement ou chouer sans retour arrire. Essayez de maximiser la longueur de toute chane non optionnelle dans les expressions rgulires. Ce principe nest pas intuitif mais les longs motifs trouvent souvent plus vite une correspondance que les courts. En effet, loptimiseur recherche les chanes constantes et les passe une recherche de Boyer-Moore, qui fonctionne mieux avec de longues chanes. Compilez votre motif avec loption de dbogage -Dr pour voir ce que Dr. Perl pense tre la chane constante la plus longue. vitez les appels de sous-programmes coteux dans les boucles courtes. Lappel de sous-programmes engendre une certaine surcharge, surtout quand vous leur passez de longues listes de paramtres ou que les valeurs renvoyes sont longues. Essayez, par ordre croissant de dsespoir, de passer les valeurs par rfrence, de passer les valeurs en tant que variables globales de porte dynamique, dinsrer le sous-programme littralement (inlining) ou de rcrire toute la boucle en C. (Si vous pouvez mettre le sous-programme hors dtat de nuire en utilisant un algorithme plus malin, cest encore mieux que toutes ces solutions.) Nemployez getc que pour les entres/sorties caractre par caractre sur le terminal. En fait, ne lutilisez pas du tout. Employez sysread. vitez les substr frquents sur les longues chanes, surtout si la chane contient de lUTF-8. Il ny a pas de problme pour utiliser substr au dbut dune chane et, pour certaines tches, vous pouvez garder le substr au dbut : utilisez la forme quatre arguments de substr et croquez la chane en remplaant la partie que vous avez happe par "" :
while ($tampon) { traiter(substr($tampon, 0, 10, "")); }

Utilisez pack et unpack au lieu de plusieurs substr. Utilisez substr en tant que lvalue au lieu de concatner des sous-chanes. Par exemple, pour remplacer les caractres allant du quatrime au septime de $truc avec le contenu de la variable $machin, ne faites pas :
$truc = substr($truc,0,3) . $machin . substr($truc,7);

Contentez-vous la place didentifier la partie de la chane remplacer et affectez-y une valeur, comme dans :
substr($truc, 3, 4) = $machin;

Mais faites attention que si $truc est une chane norme et que $machin nest pas exactement de mme longueur que le trou , cela entrane galement beaucoup de copies. Perl essaie de minimiser cela en copiant soit le dbut, soit la fin mais il y a trop de travail accomplir si le substr est au milieu.

customer_8566

564

Chapitre 24 Techniques couramment employes

Utilisez s/// au lieu dune concatnation de sous-chanes. Surtout si vous pouvez remplacer une constante par une autre de la mme taille. La substitution se fait alors sur place. Utilisez les modificateurs et les oprateurs quivalents and et or, au lieu des constructions conditionnelles compltes. Les modificateurs dinstructions (comme $alliance = 0 unless $fiance) et les oprateurs logiques vitent la surcharge de lentre et la sortie dun bloc. De plus, ils sont souvent plus lisibles. Utilisez $truc = $a || $b || $c. Cest beaucoup plus rapide (et plus court) que :
if ($a) { $truc = $a; } elsif ($b) { $truc = $b; } elsif ($c) { $truc = $c; }

De mme, mettez les valeurs par dfaut avec :


$pi ||= 3;

Regroupez tous les tests qui demandent la mme chane initiale. Au moment de tester une chane pour y chercher divers prfixes ressemblant un tant soit peu un branchement conditionnel multiple (N.d.T. : switch structure), rassemblez tous les motifs /^a/, tous les /^b/, et ainsi de suite. Ne testez pas de choses pour lesquelles vous savez quon ne peut pas trouver de correspondance. Utilisez last ou elsif pour viter que la recherche de correspondance choue pour le cas suivant dans votre instruction switch. Utilisez des oprateurs spciaux comme study, les oprations logiques sur les chanes, les formats pack u et unpack %. Attention ne pas utiliser un marteau-pilon pour craser une mouche. Des instructions mal conues comme (<STDIN>)[0] peuvent exiger de Perl un travail inutile. Cest en plein accord avec la philosophie UNIX que Perl vous donne la corde pour vous pendre. Factorisez les oprations hors des boucles. Loptimiseur de Perl nessaie pas denlever le code invariant des boucles. Il vous demande un certain bon sens. Les chanes peuvent tre plus rapides que les tableaux. Les tableaux peuvent tre plus rapides que les chanes. Tout dpend de la rutilisation ultrieure des chanes ou des tableaux et de quelles oprations il sagit. Des modifications importantes de chaque lment conviennent mieux aux tableaux, alors quune modification occasionnelle de quelques lments convient mieux aux chanes. Mais le plus souvent, vous devez essayer et aviser. Les variables my sont plus rapides que les variables local. Le tri selon une cl de tableau fabrique peut tre plus rapide quun joli sous-programme de tri. Une valeur de tableau donne sera gnralement compare plusieurs fois; donc si le sous-programme doit effectuer de nombreux recalculs, il vaut mieux factoriser ce calcul dans une passe spare avant le tri rel.

customer_8566

Efficacit
Si vous supprimez des caractres, tr/abc//d est plus rapide que s/[abc]//g.

565

print avec une virgule comme sparateur peut tre plus rapide que la concatnation de chanes. Par exemple :
print $nom_complet{$nom} . " a un nouveau rpertoire home " . $home{$nom} . "\n";

doit coller ensemble les deux hachages et les deux chanes constantes avant de les passer aux routines de bas niveau, ce qui nest pas le cas de :
print $nom_complet{$nom}, " a un nouveau rpertoire home ", $home{$nom}, "\n";

Cela dit, et selon les valeurs et larchitecture, la concatnation peut tre plus rapide. Essayez. Prfrez join("", ...) une srie de chanes concatnes. Des concatnations multiples peuvent effectuer des copies de chanes incessantes, ce quvite loprateur join. split sur une chane constante est plus rapide que split sur un motif. Cest--dire quil vaut mieux utiliser split(/ /, ...) plutt que split(/ +/, ...) si vous savez quil ny aura quun espace. Cependant, les motifs /\s+/, /^/ et / / sont particulirement optimiss, de mme que le split spcial sur du blanc. Il peut tre rentable de pr-tendre un tableau ou une chane. Au fur et mesure de laccroissement des chanes et des tableaux, Perl les tend en allouant une nouvelle copie avec de lespace pour la croissance et en y copiant lancienne valeur. La pr-extension dune chane avec loprateur x ou dun tableau en positionnant $#tableau peut prvenir cette surcharge occasionnelle, ainsi que minimiser la fragmentation mmoire. Ne undefinissez pas de longues chanes et de longs tableaux sils doivent tre rutiliss dans le mme but. Ceci afin de ne pas devoir rallouer quand la chane ou le tableau devra tre r-tendu. Prfrez "\0" x 8192 unpack("x8192",()). system("mkdir ...") peut tre plus rapide sur plusieurs rpertoires si lappel systme mkdir(2) nest pas disponible. vitez demployer eof() si les valeurs de retour lindiquent dj. Mettez dans un cache les entres des fichiers (comme les fichiers passwd et group) qui sont susceptibles dtre rutilises. Il est particulirement important de mettre dans un cache les entres provenant du rseau. Par exemple, pour mettre dans un cache la valeur de retour de gethostbyaddr lorsque vous convertissez des adresses numriques (comme 204.148.40.9) en noms (comme www.ora.com ), vous pouvez utiliser quelque chose comme :
sub numennom { local($_) = @_; unless (defined $num_en_nom{$_}) { my(@a) = gethostbyaddr(pack(C4, split(/\./)), 2); $num_en_nom{$_} = @a > 0 ? $a[0] : $_; } return $num_en_nom{$_}; }

customer_8566

566

Chapitre 24 Techniques couramment employes

vitez les appels systme inutiles. Les appels au systme dexploitation sont souvent coteux. Ainsi, par exemple, nappelez pas loprateur time lorsquune valeur, $maintenant, en cache fait laffaire. Utilisez le handle de fichier spcial _ pour viter des appels inutiles stat(2). Sur certains systmes, mme un appel systme minimal peut excuter un millier dinstructions. vitez les appels inutiles system. Loprateur system doit crer un sous-processus et excuter le programme spcifi ou pis encore, excuter un shell pour excuter le programme spcifi. On en arrive facilement un million dinstructions. Inquitez-vous de lancer des sous-processus, mais seulement sils sont frquents. Le lancement dun simple processus pwd, hostname ou find ne vous fera pas beaucoup de mal aprs tout, un shell narrte pas de lancer des sous-processus toute la journe. Il nous arrive dencourager lapproche bote outils. Mais si, mais si. Gardez la trace de votre rpertoire de travail courant au lieu dappeler sans arrt pwd. (Un module est fourni dans la bibliothque standard cet effet. Voyez le module Cwd au chapitre 30, Bibliothque standard.) vitez les mtacaractres du shell dans les commandes passez au besoin des listes system et exec. Mettez le sticky bit sur linterprteur Perl sur les machines ne disposant pas de pagination la demande :
chmod +t /usr/bin/perl

Pour mettre dans un cache les rsultats de fonction, utilisez le module Memoize de CPAN.

Efficacit de lespace mmoire


Vous pouvez utilisez vec pour un stockage compact des tableaux dentiers si les entiers sont de taille fixe. (Les entiers de taille variable peuvent tre stocks dans des chanes UTF8.) Prfrez les valeurs numriques aux valeurs de chanes quivalentes elles demandent moins de mmoire. Employez substr pour stocker des chanes de longueur constante dans une chane plus grande. Employez le module Tie::SubstrHash pour un stockage trs compact dun hachage, si les longueurs de clef et de valeur sont fixes. Utilisez __END__ et le handle de fichier DATA pour viter de stocker des donnes de programme la fois comme chane et comme tableau. Prfrez each keys lorsque lordre na pas dimportance. Supprimez ou undefinissez les variables globales qui ne sont plus utilises. Utilisez un type de DBM pour stocker les hachages. Utilisez des fichiers temporaires pour stocker les tableaux. Utilisez des pipes pour dcharger des traitements vers dautres outils. vitez les oprations de listes et les absorptions de fichiers.

customer_8566

Efficacit

567

vitez dutiliser tr///. Chaque expression tr/// doit stocker une table de traduction dune taille non ngligeable. Ne droulez pas vos boucles, ninsrez pas littralement (inline) vos sous-programmes.

Efficacit pour le programmeur


Utilisez des valeurs par dfaut. Utilisez les raccourcis gniaux donns par les options de ligne de commande comme -a, -n, -p, -s et -i. Utilisez for pour signifier foreach. Lancez des commandes systme avec des apostrophes inverses. Utilisez <*>, etc. Utilisez des motifs crs lexcution. Utilisez *, + et {} sans modration dans vos motifs. Traitez des tableaux complets tour de bras et avalez des fichiers entiers gogo. Utilisez getc. Utilisez $, $& et $. Ne vrifiez pas les valeurs de retour sur open, puisque <HANDLE> et print HANDLE ne feront rien lorsquils recevront un handle invalide. Ne fermez pas vos fichiers avec close ils le seront au prochain open. Ne passez darguments aux sous-programmes. Utilisez des variables globales. Ne nommez pas vos paramtres de sous-programmes. Vous pouvez y accder directement par $_[EXPR]. Utilisez ce quoi vous pensez en premier.

Efficacit pour le mainteneur


Nutilisez pas de valeurs par dfaut. Utilisez foreach pour signifier foreach. Utilisez des tiquettes de boucles significatives avec next et last. Utilisez des noms de variables significatifs. Utilisez des noms de sous-programmes significatifs. Mettez ce qui est important en premier sur la ligne en utilisant and, or et les modificateurs dinstruction (comme exit if $fini). Fermez vos fichiers ds que vous en avez fini avec eux. Utilisez des paquetages, des modules et des classes pour camouf ler les dtails dimplmentation. Passez des arguments en tant que paramtres de sous-programme.

customer_8566

568

Chapitre 24 Techniques couramment employes

Nommez vos paramtres de sous-programmes avec my. Mettez des parenthses dans un souci de clart. Mettez de nombreux commentaires (utiles). Incluez de la documentation pod dans votre code. Utilisez use warnings. Utilisez use strict.

Efficacit pour le porteur


Agitez sous son nez un gnreux pourboire sous son nez. vitez les fonctions qui ne sont pas implmentes partout. Vous pouvez utiliser des tests avec eval pour voir ce qui est disponible. Utilisez le module Config ou la variable $^O pour trouver sur quelle machine vous tes en train de tourner. Ne vous attendez pas ce que les f lottants et les doubles existent en natif pour pack et unpack sur des machines exotiques. Employez lordre des octets pour le rseau (les formats n et N de pack) pour envoyer des donnes binaires sur le rseau. Nenvoyez pas de donnes binaires sur le rseau. Envoyez de lASCII. Ou mieux, envoyez de lUTF8. Ou encore mieux, envoyez de largent. Vrifiez $] ou $^V pour savoir si la version courante implmente toutes les fonctionnalits que vous utilisez. Nemployez pas $] ni $^V Utilisez require ou use avec un numro de version. . Mettez une bidouille eval exec mme si vous nen avez pas lusage, votre programme pourra ainsi fonctionner sur le peu de systmes qui disposent de shells la Unix mais qui ne reconnaissent pas la notation #!. Mettez la ligne #!/usr/bin/perl mme si vous ne lutilisez pas. Testez les variantes de commandes Unix. Certains programmes find ne comprennent pas loption -xdev, par exemple. vitez les variantes des commandes Unix si lquivalent peut tre fait en interne. Les commandes Unix ne fonctionnent pas trs bien sous MS-DOS ou VMS. Mettez tous vos scripts et toutes vos pages de manuel sur un systme de fichiers rseau unique, mont sur toutes vos machines. Publiez votre module sur CPAN. Vous recevrez normment de commentaires sil nest pas portable.

Efficacit pour lutilisateur


Au lieu dimposer aux utilisateurs dentrer les donnes ligne par ligne, mettez-les dans leur diteur favori. Encore mieux, utilisez une interface graphique (GUI) comme Tk, o ils peuvent contrler lordre des vnements. (Perl/Tk est disponible sur CPAN.)

customer_8566

Programmation style

569

Donnez aux utilisateurs quelque chose lire pendant que vous continuez faire votre travail. Employez lautochargement afin que le programme paraisse tourner plus vite. Donnez la possibilit davoir des messages daide chaque invite. Donnez un conseil dutilisation utile si les utilisateurs ne donne pas dentres correctes. Affichez laction par dfaut chaque invite, et peut-tre quelques autres possibilits. Choisissez les valeurs par dfaut pour les dbutants. Permettez aux experts de les modifier. Utilisez une entre dun seul caractre l o cela a un sens. Modelez la dynamique dinteraction daprs dautres choses que lutilisateur connat bien. Rendez les messages derreurs explicites sur ce quil faut corriger. Fournissez toutes les informations pertinentes comme le nom de fichier et le code derreur, comme ceci :
open(FICHIER, $fichier) or die "$0: Ouverture de $fichier en lecture impossible : $!\n";

Utilisez fork && exit pour vous dtacher lorsque le reste du script fait du traitement en batch. Permettez aux arguments de provenir soit de la ligne de commande, soit de lentre standard. Ne mettez pas de restrictions arbitraires dans votre programme. Prfrez les champs de longueur variable aux champs de longueur fixe. Utilisez des protocoles rseau orients texte. Dites tout le monde dutiliser des protocoles rseau orients texte ! Dites tout le monde de dire tout le monde dutiliser des protocoles rseau orients texte ! Soyez paresseux par procuration. Soyez sympa.

Programmation style
Vous aurez certainement vos propres prfrences en matire de formatage, mais quelques lignes de conduite rendront vos programmes plus faciles lire, comprendre et maintenir. Le plus important est de toujours lancer vos programmes sous le pragma use warnings. (Vous pouvez dsactiver les avertissements dont vous ne voulez pas avec no warnings.) Vous devriez galement tourner sous le pragma use strict ou avoir une bonne excuse pour ne pas le faire. Le pragma use sigtrap et mme use diagnostics peuvent aussi tre bnfiques.

customer_8566

570

Chapitre 24 Techniques couramment employes

Quant lesthtique du code, la seule chose laquelle Larry prte une certaine importance est que laccolade fermante dun BLOC multiligne devrait se trouver sur la mme colonne que le mot-cl qui a commenc la construction. Par ailleurs, il a dautres prfrences qui ne sont pas si impratives. Les exemples de ce livre respectent ces conventions (ou du moins le devraient) : Indentation sur 4 colonnes. Une accolade ouvrante doit se trouver sur la mme ligne que le mot-cl qui la prcde, si possible ; sinon, il faut les aligner verticalement.
while ($condition) { # ici, court : sur la mme ligne # faire quelque chose } # si la condition dborde, aligner les accolades # lune au-dessus de lautre. while ($une_condition and $autre_condition and $encore_une_longue_condition) { # faire quelque chose }

Mettez un espace avant laccolade ouvrante dun BLOC multilignes. Un BLOC court peut tre mis sur une seule ligne, accolades comprises. Omettez le point-virgule dans un BLOC court dune seule ligne. Entourez la plupart des oprateurs avec des espaces. Entourez un indice complexe ( lintrieur de crochets) par des espaces. Mettez des lignes blanches entre les morceaux de code qui font des choses diffrentes. Mettez un saut de ligne entre une accolade fermante et else. Ne mettez pas despace entre un nom de fonction et sa parenthse ouvrante. Ne mettez pas despace avant un point-virgule. Mettez un espace aprs chaque virgule. Divisez les longues lignes aprs un oprateur (mais avant and et or, mme lorsquils scrivent && et ||). Alignez verticalement les items correspondants. Omettez les ponctuations redondantes tant que la clart nen souffre pas.

Larry a ses raisons concernant chacun de ces points mais il ne prtend pas que le cerveau de tout le monde fonctionne (ou ne fonctionne pas) comme le sien. Voici dautres questions de style plus substantielles, qui donnent matire rf lexion : Ce nest pas parce que vous pouvez faire quelque chose dune certaine manire que vous devez le faire ainsi. Perl est conu pour fournir plusieurs faons de faire tout ce que lon veut, il convient donc de choisir la plus lisible. Par exemple :
open(TRUC,$truc) or die "ouverture de $truc impossible : $!";

customer_8566

Programmation style
vaut mieux que
die "Ouverture de $truc impossible : $!" unless open(TRUC,$truc);

571

car la deuxime manire cache lessentiel de linstruction dans un modificateur. linverse,


print "Dbut de lanalyse\n" if $verbeux;

vaut mieux que


$verbeux and print "Dbut de lanalyse\n";

puisque lessentiel nest pas de savoir si lutilisateur a ou non tap -v. De mme, ce nest pas parce quun oprateur vous permet dutiliser des arguments par dfaut que vous devez en faire usage. Ils sont rservs aux programmeurs paresseux qui crivent des scripts vite fait, ne servant quune fois. Si vous voulez que vos programmes soient lisibles, pensez fournir les arguments. Dans la mme ligne, ce nest pas parce que vous pouvez omettre les parenthses dans de nombreux cas que vous devez le faire :
return print reverse sort num values %hachage; return print(reverse(sort num (values(%hachage))));

En cas de doute, mettez des parenthses. Au pire, cela permettra aux pauvres idiots de taper sur la touche % dans vi. Mme si vous navez aucun doute, imaginez ltat mental de la personne qui devra maintenir le code aprs vous et qui mettra probablement des parenthses au mauvais endroit. Ne vous livrez pas un exercice stupide de contorsionniste pour sortir en haut ou en bas dune boucle. Perl fournit loprateur last qui vous permet den sortir au milieu. Vous pouvez optionnellement l exdenter un peu pour le rendre plus visible :
LIGNE: for (;;) \{ instructions; last LIGNE if $machin; next LIGNE if /^#/; instructions; }

Nayez pas peur dutiliser des tiquettes de boucles elles sont l tant pour amliorer la lisibilit que pour permettre les ruptures de boucles sur plusieurs niveaux. Voir lexemple prcdent. vitez dutiliser grep, map ou les apostrophes inverses dans un contexte vide, cest-dire lorsque vous ne vous occupez pas des valeurs de retour. Ces fonctions ont toutes des valeurs de retour, qui ne demandent qu tre utilises. Sinon, employez une boucle foreach ou la fonction system. Dans un but de portabilit, quand vous employez des fonctionnalits qui peuvent ne pas tre implmentes sur toutes les machines, testez-les dans un eval pour savoir si elles chouent. Si vous connaissez la version ou le patch level (N.d.T. : niveau de correction) dune fonctionnalit particulire, vous pouvez tester $] ($PERL_VERSION avec le module English) pour savoir si telle fonctionnalit est pr-

customer_8566

572

Chapitre 24 Techniques couramment employes

sente. Le module Config permet galement de retrouver les valeurs dtermines par le programme Configure quand Perl a t install. Choisissez des identificateurs mnmoniques. Si vous ne vous souvenez pas de la signification du terme mnmonique, il y a un problme. Alors que des identificateurs courts comme $reussi conviennent souvent parfaitement, employez des souligns pour sparer les mots. Il est gnralement plus facile de lire un $nom_de_variable_comme_ceci quun $NomDeVariableCommeCeci, surtout pour des lecteurs dont la langue dorigine nest pas langlais. Mme chose pour $NOM_DE_VARIABLE_COMME_CECI. Les noms des paquetages reprsentent parfois une exception cette rgle. Perl rserve de faon informelle les noms en minuscule pour des modules de pragmas comme integer et strict. Les autres modules devraient commencer par une majuscule et mlanger les casses, mais de prfrence sans caractre soulign en raison des restrictions de nommage de certains systmes de fichiers primitifs. Il peut savrer utile dutiliser les casses de caractres pour indiquer la visibilit ou la nature dune variable. Par exemple :
$TOUT_EN_MAJUSCULES $Quelques_Majuscules $pas_de_majuscules # constantes uniquement (attention aux # conflits avec les vars de Perl!) # vars globales/statiques sur tout un paquetage # vars my() ou local(), dont la porte ne #dpasse pas une fonction

Pour diverses raisons plutt vagues, les noms de mthodes et de fonctions semblent plus lisibles lorsquils sont entirement en minuscules. Par exemple, $obj-> en_chaine(). Vous pouvez faire prcder le nom dun caractre soulign pour indiquer quune variable ou une fonction ne devrait pas tre utilise hors du paquetage qui la dfinie. (Perl ne force pas ceci ; ce nest quune forme de documentation.) Dans le cas dune expression rgulire rellement inextricable, utilisez le modificateur /x et insrez des espaces pour amliorer le rapport signal/bruit. Nemployez pas de slash comme dlimiteurs lorsque votre expression en comporte dj trop ou contient trop dantislashs. Nutilisez pas les apostrophes ou les guillemets comme dlimiteurs lorsque votre chane en contient dj. Utilisez plutt les pseudo-fonctions q//, qq// ou qx//. Utilisez les oprateurs and et or pour viter de mettre trop de parenthses autour des oprateurs de liste, et pour rduire lincidence des oprateurs de ponctuation comme && et ||. Appelez vos sous-programmes comme sil sagissait de fonctions ou doprateurs de liste afin dviter un excs desperluettes et de parenthses. Utilisez des documents ici-mme (here documents) au lieu dinstructions print rptes. Alignez verticalement les choses correspondantes, surtout si elles sont trop longues pour tenir sur une ligne :
$IDX = $ST_MTIME; $IDX = $ST_ATIME $IDX = $ST_CTIME if $opt_u; if $opt_c;

customer_8566

Perl avec aisance


$IDX = $ST_SIZE if $opt_s;

573

mkdir $rep_tmp, 0700 or die "mkdir $rep_tmp impossible : $!"; chdir($rep_tmp) or die "chdir $rep_tmp impossible : $!"; mkdir tmp, 0777 or die "mkdir $rep_tmp/tmp impossible : $!";

Ce que nous vous rptons trois fois est vrai : Vrifiez toujours les codes de retour des appels systme. Vrifiez toujours les codes de retour des appels systme . VRIFIEZ TOUJOURS LES CODES DE RETOUR DES APPELS SYSTME.

Les messages derreur devaient aller vers STDERR et devraient indiquer de quel programme provient lerreur, ainsi que lappel de fonction et les arguments. Le plus important est quils devraient contenir, lorsque les appels systme ont chou, le message derreur systme standard sur ce qui ne va pas. En voici un exemple simple mais suffisant :
opendir(R, $rep) or die "opendir $rep impossible : $!";

Alignez vos traductions si cela a un sens :


tr [abc] [xyz];

Pensez la rutilisabilit. Pourquoi gcher votre nergie crbrale sur des scripts jetables alors que vous tes susceptible de les rcrire plus tard? Vous pouvez rendre votre code gnrique. Vous pouvez crire un module ou une classe dobjets. Vous pouvez faire tourner proprement votre code en activant use strict et -w. Vous pouvez donner votre code aux autres. Vous pouvez changer votre vision globale du monde. Vous pouvez. . . oh et puis tant pis. Soyez cohrent. Soyez sympa.

Perl avec aisance


Nous avons abord quelques idiomes dans les paragraphes prcdents (pour ne pas citer les chapitres prcdents) mais il y en a beaucoup dautres que vous verrez couramment si vous lisez des programmes raliss par des programmeurs Perl accomplis. Lorsque nous parlons de Perl idiomatique dans ce contexte, nous ne parlons pas seulement dun ensemble arbitraire dexpressions Perl au sens fig. Nous parlons plutt de code Perl montrant une comprhension des mandres du langage, que vous pouvez avaler tel quel sans vous poser de question. Et quand lavaler. Nous nimaginons mme pas numrer tous les idiomes que vous pourriez rencontrer cela prendrait tout un livre, aussi pais que celui-ci. Et peut-tre mme deux. (Voir Perl en action, par exemple.) Mais voici quelques idiomes importants, o lon pourrait dfinir important comme ce qui incite les persif lages des gens qui pensent dj savoir comment les langages informatiques devraient fonctionner . Utilisez => en lieu et place dune virgule partout o vous pensez que cela amliore la lisibilit :
return bless $pagaille => $classe;

customer_8566

574

Chapitre 24 Techniques couramment employes

Vous devez lire cela comme Consacrer cette pagaille dans la classe spcifie. Faites juste attention ne pas lemployer aprs un mot dont vous ne voudriez pas quil soit automatiquement mis entre guillemets :
sub truc() { "TRUC" } sub machin() { "MACHIN"} print truc => machin; # affiche trucMACHIN et non TRUCMACHIN.

Un autre endroit appropri lemploi de => est proximit dune virgule littrale que lon pourrait confondre visuellement :
join(", " => @tableau);

Perl vous offre plus dune manire de le faire (N.d.T. : Theres More Than One Way To Do It, le slogan de Perl) vous pouvez donc faire preuve de crativit. Faites-en preuve ! Utilisez le pronom singulier pour amliorer la lisibilit :
for (@lignes) { $_ .= "\n"; }

La variable $_ est la version de Perl dun pronom et il signifie essentiellement il .1 Ainsi, le code ci-dessus signifie pour chaque ligne, ajoutez-lui un saut de ligne. De nos jours, vous pouvez mme crire cela comme :
$_ .= "\n" for @lignes;

Le pronom $_ est tellement important pour Perl quil est obligatoire de lutiliser dans grep et map. Voici un moyen de configurer un cache pour les rsultats communs dune fonction coteuse :
%cache = map { $_ => couteuse($_) } @args_communs; $xval = $cache{$x} || couteuse($x);

Omettez le pronom pour amliorer encore plus la lisibilit.2 Utilisez des contrles de boucles avec des modificateurs dinstructions.
while (<>) { next if /^=pour\s+(index|aprs)/; $cars += length; $mots += split; $lignes += y/\n//; }

Il sagit dun extrait de code que nous avons utilis pour compter les pages de ce livre. Lorsque vous vous apprtez travailler souvent avec la mme variable, il est souvent plus lisible de laisser compltement tomber les pronoms, contrairement la croyance populaire.
1. N.d.T. : et puisquen franais, nous avons la chance de faire la diffrence entre les genres, il signifie galement elle . De plus, comme la langue de Molire nous a galement fait cadeau dune diffrenciation des pronoms selon leur fonction grammaticale, $_ peut finalement vouloir dire il , elle , le , la ou lui . Pauvres anglo-saxons : ils nont pas plus dune manire de le dire ! 2. Dans ce paragraphe, plusieurs items numrs daffile se rfrent lexemple qui suit, puisque certains de nos exemples illustrent plus dun idiome.

customer_8566

Perl avec aisance

575

Cet extrait dmontre galement lutilisation idiomatique de next avec un modificateur dinstruction pour court-circuiter une boucle. La variable $_ est toujours la variable de contrle de boucle dans grep et map mais la rfrence du programme pointant dessus est souvent implicite :
$longueur_hachage = grep { length } @aleatoire;

Nous prenons ici une liste de scalaires alatoires et ne choisissons que ceux qui ont une longueur suprieure 0. Utilisez for pour positionner lantcdent dun pronom :
for ($episode) { s/fred/barney/g; s/wilma/betty/g; s/pebbles/bambam/g; }

Mais que se passe-t-il sil ny a quun seul lment dans la boucle ? Il sagit dun moyen pratique de positionner le , cest--dire $_. En linguistique, cela sappelle une topicalisation. Ce nest pas de la triche, cest de la communication. Rfrencez implicitement le pronom pluriel, @_. Utilisez les oprateurs de contrle de f lux pour fixer les valeurs par dfaut :
sub aboyer { my Chien $medor = shift; my $qualite = shift || "jappant"; my $quantite = shift || "sans_arrt"; ... }

Nous avons employ ici lautre pronom de perl, @_, qui signifie eux .3 Les arguments dune fonction arrivent toujours comme eux . Loprateur shift sait quil doit travailler sur @_ si vous lomettez, tout comme lemploy de Disneyland crierait Au suivant ! sans prciser quelle file dattente est suppose avancer. (Il ny a pas lieu de spcifier car il ny a quune seule queue qui importe.) Le || peut tre utilis pour fixer les valeurs par dfaut malgr ses origines doprateur boolen, puisque Perl renvoie la premire valeur qui soit vraie. Les programmeurs Perl font souvent preuve dune attitude assez cavalire avec la vrit ; la ligne ci-dessus ne fonctionnerait pas si, par exemple, vous essayiez de spcifier une quantit nulle. Mais tant que vous ne voulez jamais positionner $qualite ou $quantite une valeur fausse, lidiome marche parfaitement. Il ny a pas lieu de devenir superstitieux et de lancer partout des appels defined et exists. Tant que la valeur ne devient pas accidentellement fausse, tout ira bien. Utilisez les formes daffectation des oprateurs, y compris les oprateurs de contrle de f lux :
$xval = $cache{$x} ||= couteuse($x);

Ici nous ninitialisons pas du tout notre cache. Nous ne faisons que nous reposer sur loprateur ||= pour appeler couteuse($x) et ne laffecter $cache{$x} que si
3. ou elles , ou les , ou leur , ou eux .

customer_8566

576

Chapitre 24 Techniques couramment employes

$cache{$x} est faux. Le rsultat de ceci est la nouvelle valeur de $cache{$x} quelle quelle soit. Encore une fois, nous avons adopt une approche quelque peu cavalire de la vrit, en ce que si nous mettons en cache une valeur fausse, couteuse($x) sera nouveau appele. Le programmeur sait peut-tre que cela fonctionne car couteuse{$x} nest pas coteuse lorsquelle renvoie une valeur fausse. Ou peut-tre que le programmeur a simplement tendance bcler son travail. Ce qui peut tre analys comme une forme de crativit. Utilisez les contrles de boucles en tant quoprateurs, pas seulement en tant quinstructions. Et. . . Utilisez les virgules comme de petits points-virgules :
while (<>) { $commentaires++, next if /^#/; $blancs++, next if /^\s*$/; last if /^__END__/; $code++; } print "commentaires = $commentaires\nblancs = $blancs\ncode = $code\n";

Ceci montre que nous comprenons que les modificateurs dinstructions modifient les instructions, alors que next est un simple oprateur. Cela montre galement que la virgule, lorsquelle est utilise de faon idiomatique pour sparer les expressions, exactement comme vous le feriez avec un point-virgule. (La diffrence est que la virgule garde les deux expressions comme faisant partie de la mme instruction, sous le contrle de lunique modificateur dinstruction.) Utilisez le contrle de f lux votre avantage :
while (<>) { /^#/ and $commentaires++; /^s*$/ and $blancs++; /^__END__/ and last; $code++; } print "commentaires = $commentaires\nblancs = $blancs\ncode = $code\n";

Il sagit exactement de la mme boucle, seulement cette fois-ci, les motifs sont au dbut. Le programmeur Perl perspicace comprend que la compilation donne exactement le mme code interne que lexemple prcdent. Le modificateur if nest quune conjonction and (ou &&) inverse et le modificateur unless est une conjonction or (ou ||) inverse. Utilisez les boucles implicites fournies par les options -n et -p. Ne mettez pas de point-virgule la fin dun bloc dune seule ligne :
#!/usr/bin/perl -n $commentaires++, next LINE if /^#/; $blancs++, next LINE if /^\s*$/; last LINE if /^__END__/; $code++; END {print "commentaires = $commentaires\nblancs = $blancs\ncode = $code\n" }

customer_8566

Perl avec aisance

577

Il sagit essentiellement du mme programme que prcdemment. Nous avons mis une tiquette LINE (LIGNE en anglais) explicite dans les oprateurs de contrle de boucle parce que nous en avions envie mais nous ny tions pas obligs, puisque la boucle LINE implicite, fournie par -n est la boucle encadrante la plus intrieure. Nous avons employ END pour avoir linstruction print finale lextrieur de la boucle principale implicite, exactement comme dans awk. Utilisez des documents ici-mme (here documents) lorsque les affichages deviennent monstrueux. Utilisez un dlimiteur significatif dans les documents ici-mme :
END { print <<"COMPTEURS" } commentaires = $commentaires blancs = $blancs code = $code COMPTEURS

Au lieu dutiliser plusieurs print, le programmeur parlant Perl couramment emploie une chane multiligne avec interpolation. Bien que nous ayons appel ceci une tourderie courante auparavant, nous avons effrontment enlev le pointvirgule final car il nest pas ncessaire la fin du bloc END. (Si nous le changeons un jour en bloc multiligne, nous remettrons le point-virgule.) Faites des substitutions et des traductions en passant4 sur un scalaire :
($nouveau = $ancien) =~ s/mauvais/bon/g;

Puisque les lvalues sont lvaluables5, pour ainsi dire, vous verrez souvent les gens changer une valeur en passant alors quelle est en train dtre affecte. Ceci peut en fait viter une copie de chane en interne (si nous arrivons jamais implmenter loptimisation) :
chomp($reponse = <STDIN>);

Toute fonction qui modifie un argument sur place peut utiliser lastuce en passant. Mais attendez, il y a mieux ! Ne vous limitez pas modifier les scalaires en passant :
for (@nouveau = @ancien) { s/mauvais/bon/g }

Ici, nous copions @ancien dans @nouveau, en modifiant tout en passant (pas tout dun coup, bien entendu le bloc est excut de manire rptitive, un il (cest--dire $_) la fois). Passez les paramtres nomms en utilisant loprateur virgule de fantaisie, =>. Fiez-vous laffectation un hachage pour traiter un argument pair/impair :
sub aboyer { my Chien $medor = shift; my %param = @_

4. N.d.T. : en franais dans le texte. 5. N.d.T. : les lvalues sont des valeurs (values, en anglais) que lon peut mettre gauche (left, en anglais) dune affectation. Il y a donc ici un jeu de mots que lon peut traduire littralement par puisque les valeurs que lon peut mettre gauche dune affectation peuvent tre mises gauche dune affectation.

customer_8566

578

Chapitre 24 Techniques couramment employes


my $qualite = $param{QUALITE} || "jappant"; my $quantite = $param{QUANTITE} || "sans_arrt"; ... } $fido->aboyer( QUANTITE => "une_fois", QUALITE => "ouaf" );

Les paramtres nomms sont souvent un luxe abordable. Et avec Perl, vous les avez pour rien, si vous ne comptez pas le cot de laffectation de hachage. Rptez les expressions boolennes jusqu obtenir une valeur fausse. Utilisez les recherches de correspondances minimales lorsquelles sont appropries. Utilisez le modificateur /e pour valuer une expression de remplacement :
#!/usr/bin/perl -p 1 while s/^(.*)?(\t+)/$1 . x length($2) *4 - length($1) %4)/e;

Ce programme corrige tout fichier que vous recevez de la part de quelquun pensant par erreur quil peut redfinir les tabulations matrielles pour quelles occupent 4 espaces au lieu de 8. Il utilise plusieurs idiomes importants. Tout dabord, lidiome 1 while est commode lorsque tout le travail que vous voulez accomplir dans la boucle est en fait dj ralis par la condition. (Perl est assez malin pour ne pas vous avertir que vous tes en train dutiliser 1 dans un contexte vide.) Nous devons rpter cette substitution car chaque fois que nous remplaons un certain nombre despaces par des tabulations, nous devons recalculer depuis le dbut la colonne o doit se trouver la prochaine tabulation. Le (.*?) correspond la plus petite chane possible jusqu la premire tabulation, en utilisant le modificateur de correspondance minimal (le point dinterrogation). Dans ce cas, nous aurions pu utiliser un * gourmand comme dordinaire, ainsi : ([^\t]*). Mais cela ne marche que parce quune tabulation est un seul caractre, nous avons donc employ une classe de caractres avec une ngation pour viter de dpasser la premire tabulation. En gnral, la correspondance minimale est plus lgante et elle nchoue pas si la prochaine chose qui doit correspondre fait plus dun caractre. Le modificateur /e ralise une substitution en utilisant une expression plutt quune chane. Cela nous permet deffectuer les calculs dont nous avons besoin au moment exact o nous en avons besoin. Utilisez une mise en page et des commentaires cratifs pour les substitutions complexes :
#!/usr/bin/perl -p 1 while s{ ^ # attachement au dbut ( # commence le premier regroupement .*? # correspond au nombre de caractres minimal ) # termine le premier regroupement ( # commence le second regroupement \t+ # correspond une ou plusieurs tabulations ) # termine le second regroupement }

customer_8566

Perl avec aisance


{ my $lg_espaces = length($2) * 4; $lg_espaces -= length($1) % 4; $1 . x $lg_espaces; }ex; # # # # # #

579

comptage des tabulations compltes longueur de la tabulation incomplte calcule le nombre despaces correct

Nous en faisons probablement un peu trop mais certaines personnes trouvent cet exemple plus impressionnant que le prcdent qui tenait sur une seule ligne. vous de voir. Allez de lavant et utilisez $ si vous le sentez :
1 while s/(\t+)/ x (length($1) * 4 - length($) % 4)/e;

Il sagit ici dune version plus courte, qui utilise $, bien connu pour son impact sur les performances. Sauf que nous nutilisons que sa longueur, alors a ne compte pas vraiment. Utilisez les dcalages directement partir des tableaux @- (@LAST_MATCH_START) et @+ (@LAST_MATCH_END) :
1 while s/\t+/ x (($+[0] - $-[0]) * 4 - $-[0] % 4)/e;

Cet exemple-ci est encore plus court. (Si vous ne voyez pas de tableaux ici, essayez la place de rechercher des lments de tableaux.) Voir @- et @+ au chapitre 28. Utilisez eval avec une valeur de retour constante :
sub est_un_motif_valide { my $motif = shift; return eval { "" =~ /$motif/; 1 } || 0; }

Vous navez pas utiliser loprateur eval {} pour renvoyer un valeur relle. Ici, nous renvoyons toujours 1 si la correspondance parvient se terminer. Toutefois, si le motif contenu dans $motif explose, leval intercepte ceci et renvoie undef la condition boolenne de loprateur ||, qui transforme cela vers la valeur dfinie 0 (simplement pour tre poli, puisque undef est galement faux mais pourrait conduire quelquun penser que la routine est_un_motif_valide sest mal comporte et nous ne voudrions pas que cela se produise, nest-ce pas ?). Utilisez des modules pour faire le sale boulot. Utilisez des usines dobjets. Utilisez des fonctions de rappel (callbacks). Utilisez des piles pour garder une trace du contexte. Utilisez des indices ngatifs pour accder la fin dun tableau ou dune chane :
use XML::Parser; $p = new XML::Parser Style => subs; setHandlers $p Char => sub { $sorties[-1] .= $_[1] }; push @sorties, "";

customer_8566

580
sub literal { $sorties[-1] .= "C<"; push @sorties, ""; }

Chapitre 24 Techniques couramment employes

sub literal_ { my $texte = pop @sorties; $sorties[-1] .= $texte . ">"; } ...

Il sagit dun court extrait dun programme de 250 lignes que nous avons utilis pour retraduire la version XML de lancienne dition de ce livre6 en format pod afin que nous puissions louvrir pour la prsente dition dans un Vritable diteur de Texte. La premire chose que vous remarquerez est que nous nous appuyons sur le module XML::Parser (de CPAN) pour analyser notre XML correctement, nous navons donc pas comprendre comment le faire. Cela soulage dj notre programme de quelque milliers de lignes (en supposant que nous rimplmentions en Perl tout ce que XML::Parser accomplit pour nous,7 y compris la traduction de presque tous les ensembles de caractres vers de lUTF-8). XML::Parser utilise un idiome de haut niveau appel une usine dobjets. Dans ce cas, il sagit dune usine danalyseur. Lorsque nous crons un objet XML::Parser, nous lui disons quel style dinterface danalyseur nous voulons et il en cre un pour nous. Cest un excellent moyen de construire une plate-forme de test pour une application lorsque vous ntes pas sr de savoir quelle interface sera la meilleure long terme. Le style subs ne reprsente quune des interfaces de XML::Parser. En fait, il sagit de lune des plus anciennes interface et probablement pas la plus populaire de nos jours. La ligne setHandlers montre un appel de mthode sur lanalyseur, pas en notation f lche, mais dans la notation dobjet indirect , qui vous permet, entre autres, domettre les parenthses autour des arguments. La ligne utilise galement lidiome des paramtres nomms que nous avons vu plus tt. La ligne montre galement un autre concept trs puissant, la notion de fonction de rappel (callback). Plutt que dappeler lanalyseur pour obtenir llment suivant, nous lui demandons de nous appeler. Pour les balises XML nommes, comme <literal>, ce style dinterface appellera automatiquement un sous-programme de ce nom (ou le nom avec un soulign la fin pour la balise fermante correspondante). Mais les donnes entre les balises nont pas de nom, nous configurons donc
6. N.d.T. : le Camel book (littralement le livre au chameau) est le surnom couramment employ par les fans de Perl (les Perl Mongers) pour dsigner le livre que vous avez entre les mains ainsi que ses illustres anctres. Bien entendu, ceci est d au dessin de la couverture (heu... cest en fait un dromadaire, voir le Colophon). Selon les recherches approfondies des Perl Mongers, le chameau de cette troisime dition porte le doux nom dAmlia, alors que celui de la prcdente dition se prnommait Fido. 7. En fait, XML::Parser nest quun enrobage pratique autour de lanalyseur XML expat de James Clark.

customer_8566

Perl avec aisance

581

une fonction de rappel, Char, avec la mthode setHandlers. Ensuite, nous initialisons le tableau @sorties, qui est une pile des affichages. Nous y mettons une chane vide pour reprsenter le fait que nous navons collect aucun texte ce niveau dimbrication des balises (0, initialement). Cest maintenant que rapparat la fonction de rappel. Ds que nous voyons un texte, il est automatiquement ajout aprs llment final du tableau, via lidiome $sortie[-1] dans la fonction de rappel. Au niveau de balise le plus extrieur, $sorties[-1] est quivalent $sortie[0], $sorties[0] termine donc notre affichage complet. (ventuellement. Mais nous devons dabord traiter les balises.) Supposez que nous voyions une balise <literal>. Alors le sous-programme literal est appel, ajoute du texte laffichage courant, puis pousse un nouveau contexte dans la pile @sorties. Ds lors, tout texte rencontr jusqu la balise fermante se voit ajout cette nouvelle fin de la pile. Lorsque nous rencontrons la balise fermante, nous dpilons (avec pop) le $texte que nous avons collect hors de la pile @sorties et nous ajoutons le reste des donnes mtamorphoses la nouvelle (cest--dire, lancienne) fin de la pile, dont le rsultat est la traduction de la chane XML, <literal>texte</literal>, vers la chane pod correspondante, C<texte>. Les sous-programmes pour les autres programmes sont exactement les mmes, part quils sont diffrents. Utilisez my sans affectation pour crer un tableau ou un hachage vide. clatez la chane par dfaut selon les espaces quelle contient. Affectez aux listes de variables pour en collecter autant que vous voulez. Utilisez lautovivification des rfrences indfinies pour les crer. Autoincrmentez les lements indfinis de tableau ou de hachage pour les crer. Utilisez lautoincrmentation dun hachage %vus pour dterminer lunicit. Affectez une variable temporaire my bien pratique dans la condition. Utilisez le comportement de protection automatique des accolades. Utilisez un mcanisme de protection alternatif pour interpoler les guillemets. Utilisez loprateur ?: pour choisir entre deux arguments dun printf. Alignez verticalement les arguments de printf avec leur champ % :
my %vus; while (<>) { my ($a, $b, $c) = split; print unless $vus{$a}{$b}{$c}++; } if (my $tmp = $vus{nifnif}{nafnaf}{noufnouf}) { printf qq("nifnif nafnaf noufnouf" vu %d coup%s\n), $tmp, $tmp == 1 ? "" : "s"; }

Ces neuf lignes dbordent didiomes. La premire ligne donne un hachage vide car nous ny affectons rien. Nous parcourons itrativement les lignes entres en positionnant le , cest--dire $_, implicitement, puis nous utilisons un split sans arguments qui l clate selon les espaces qu il contient. Ensuite nous pre-

customer_8566

582

Chapitre 24 Techniques couramment employes

nons les trois premiers mots avec une affectation de liste, en rejetant les mots suivants. Puis nous mmorisons les trois premiers mots dans un hachage trois dimensions, qui cre automatiquement (si ncessaire) les deux premiers lments de rfrence et le dernier lment de comptage pour lautoincrmentation incrmenter. (Avec use warnings, lautoincrmentation ne vous avertira jamais que vous utilisez des valeurs indfinies car lautoincrmentation est un moyen accept pour dfinir des valeurs indfinies.) Nous imprimons alors la ligne si nous nen avons jamais vue avant commenant par ces trois mots, car lautoincrmentation est une postincrmentation, qui, en plus dincrmenter la valeur du hachage, renverra lancienne valeur vraie sil y en avait une. Aprs la boucle, nous testons %vus nouveau pour voir si une combinaison particulire de trois mots a t vue. Nous utilisons le fait que nous pouvons mettre un identificateur littral entre accolades pour quil soit automatiquement protg, comme avec des guillemets. Sinon, nous aurions d crire $vus{"nafnaf"} {"nifnif"}{"noufnouf"}, ce qui est une corve mme lorsque vous ntes pas poursuivi par un grand mchant loup. Nous affectons le rsultat de $vus{nifnif}{nafnaf}{noufnouf} une variable temporaire avant mme de la tester dans le contexte boolen fourni par le if. Comme laffectation renvoie sa valeur de gauche, nous pouvons toujours tester la valeur pour voir si elle tait vraie. Le my vous fait sauter aux yeux quil sagit dune nouvelle variable et que nous ne vrifions pas une galit mais ralisons une affectation. Cela aurait galement parfaitement march sans le my et un programmeur Perl expert aurait encore remarqu immdiatement que nous utilisions un = au lieu de deux ==. (Un programmeur Perl intermdiaire aurait cependant pu tre bluff. Le programmeur Pascal de nimporte quel niveau aura de lcume aux lvres.) Si lon passe linstruction printf, vous pouvez voir la forme qq() des guillemets que nous avons employe afin de pouvoir interpoler les guillemets ordinaires ainsi que le retour la ligne. Nous aurions aussi bien pu interpoler directement ici $tmp, puisquil sagit effectivement dune chane entre guillemets mais nous avons choisi de pousser plus loin linterpolation via printf. Notre variable temporaire $tmp est maintenant bien pratique, particulirement depuis que nous ne voulons plus seulement linterpoler mais galement la tester dans la condition dun oprateur ?: pour voir si nous devions mettre le mot coup au pluriel. Enfin, remarquez que nous avons align verticalement les deux champs avec leur marqueurs % correspondants dans le format de printf. Si un argument est trop long pour concider, vous pouvez toujours aller la ligne suivante pour largument suivant bien que nous nayons pas eu le faire dans ce cas. Wouah ! Vous en avez assez ? Il existe encore beaucoup dautres idiomes dont nous aurions pu dbattre mais ce livre est dj suffisamment lourd. Mais nous aimerions encore parler dun usage idiomatique de Perl, lcriture de gnrateurs de programmes.

Gnrer des programmes


Depuis le jour, ou presque, o les gens se sont aperus pour la premire fois quils pouvaient crire des programmes, ils ont commenc crire des programmes qui crivaient dautres programmes. Nous les appelons souvent des gnrateurs de programmes. (Les his-

customer_8566

Gnrer des programmes

583

toriens se souviennent que RPG signifiait Report Program Generator bien avant Role Playing Game.) De nos jours, on le appellerait probablement des usines programmes mais les gens des des gnrateurs sont arrivs les premiers, cest donc leur nom qui a prvalu. Quiconque a dj crit un gnrateur de programmes sait que cela peut vous donner un strabisme divergent quand bien mme vous portez des verres correcteurs. Le problme vient de ce quune grande partie des donnes du programme ressemble du code, a la couleur du code, mais nest pas du code (du moins pas encore). Le mme fichier texte contient la fois des choses qui font quelque chose et des choses qui y ressemblent mais qui ne font rien. Perl comporte de nombreuses fonctionnalits qui facilitent son intgration avec dautres langages, textuellement parlant. (Bien sr, ces fonctionnalits facilitent lcriture de Perl en Perl, mais cest le moins auquel on puisse sattendre ds prsent.)

Gnrer dautres langages en Perl


Perl est (entre autres) un langage de traitement de texte et la plupart des langages informatiques sont textuels. De plus, labsence de limites arbitraires et les divers mcanismes de protection et dinterpolation de Perl facilitent la sparation visuelle du code dun autre langage que lon gnre. Par exemple, voici un petit morceau de s2p, le traducteur sed-vers-perl :
print &q(< <"FIN"); : #!$bin/perl : eval exec $bin/perl -S \$0\${1+"\$@"} : if \$lance_sous_un_shell; : FIN

Il se trouve que le texte encadr est lgal en deux langages, Perl et sh. Nous avons utilis ds le dbut un idiome qui prservera votre sant mentale lors de lcriture dun gnrateur de programme : lastuce de mettre un caractre de bruit et une tabulation au dbut de chaque ligne protge, ce qui isole visuellement le code inclus, vous pouvez ainsi dire en un clin dil quil ne sagit pas du code qui est en train de sexcuter. Une variable, $bin, est interpole en deux endroits de la chane multiligne protge, puis la chane est passe travers une fonction qui limine le deux-points et la tabulation. Bien sr, il est inutile dutiliser des chanes protges multilignes. On voit souvent des scripts CGI contenant des millions dinstructions print, une par ligne. Cest un peu comme aller au supermarch en Mirage III, mais bon, tant que lon arrive destination... (Nous admettrons quune colonne dinstructions print possde ses propres proprits pour ressortir visuellement.) Lorsque vous encadrez une grosse chane protge multiligne contenant un autre langage (comme du HTML), il est parfois utile de faire comme si vous programmiez lenvers, en encadrant plutt du Perl dans lautre langage, exactement comme vous le feriez avec des langages ouvertement inverss comme PHP :
print <<"XML"; <truc> <insense>

customer_8566

584

Chapitre 24 Techniques couramment employes


bla bla bla @{[ scalar EXPR ]} bla bla bla bla bla bla @{[ LISTE ]} bla bla bla </insense> </truc>

XML

Vous pouvez utiliser lune de ces deux astuces pour interpoler des valeurs dexpressions arbitrairement complexes dans une grosse chane. Certains gnrateurs de programmes ne ressemblent pas beaucoup des gnrateurs de programmes, selon la quantit doprations quils vous cachent. Au chapitre 22, CPAN, nous avons vu comment un petit programme Makefile.PL pouvait tre utilis pour crire un Makefile. Makefile peut facilement tre 100 fois plus gros que le Makefile.PL qui la gnr. Pensez lusure que cela pargne vos doigts. Ou ny pensez plus aprs tout, cest le but.

Gnrer du Perl dans dautres langages


Il est facile de gnrer dautres langages en Perl, mais linverse est galement vrai. Perl peut facilement tre gnr par dautres langages parce quil est la fois concis et mallable. Vous pouvez choisir votre manire de protger les chanes entre guillemets afin de ne pas interfrer avec les mcanismes de protection des autres langages. Vous navez pas vous soucier de lindentation, ni o placer vos ruptures de lignes, ni si vous devez (encore) mettre un antislash avant vos antislashs. Vous navez pas besoin de dfinir un paquetage lavance par une seule chane de caractres, puisque vous pouvez glisser dans lespace de noms du paquetage de faon rpte chaque fois que vous voulez valuer plus de code dans ce paquetage. Une autre chose qui facilite lcriture de Perl dans dautres langages (y compris Perl) est la directive #line. Perl sait comment la traiter comme une directive spciale qui reconfigure lide quil se faisait du nom de fichier courant et du numro de ligne. Ceci peut savrer utile dans les messages derreur ou davertissement, en particulier pour les chanes traites avec eval (ce qui, lorsquon y pense, nest rien dautre que du Perl crivant du Perl). La syntaxe de ce mcanisme est celle utilise par le prprocesseur C : lorsque Perl rencontre un symbole # et le mot line, suivi par un numro et un nom de fichier, il positionne __LINE__ ce numro et __FILE__ ce nom de fichier.8 Voici quelques exemples que vous pouvez tester en tapant dans perl directement. Nous avons employ un Ctrl-D pour indiquer la fin de fichier, ce qui est typique dUnix. Les utilisateurs de DOS/Windows et de VMS peuvent taper Ctrl-Z. Si votre shell utilise autre chose, vous devrez lemployer pour dire perl que vous avez termin. Sinon, vous pouvez toujours taper __END__ pour dire au compilateur quil ny a plus rien analyser. Voici comment la fonction interne de Perl, warn, affiche le nouveau nom de fichier est le numro de ligne :

8. Techniquement parlant, Perl fait une correspondance avec le motif /^#\\s*line\\s+(\\d+)\\s*(?:\\s"([^"]+)")?\\s*$/, avec $1 fournissant le numro de ligne pour la ligne suivante et $2 le nom de fichier optionnel spcifi entre les guillemets. (Un nom de fichier vide laisse __FILE__ inchang.)

customer_8566

Gnrer des programmes

585

% perl # line 2000 "Odysse" # le "#" sur la ligne prcdente doit tre le premier caractre de la ligne warn "les portes du compartiment pod"; # or die ^D les portes du compartiment pod at Odysse line 2001.

Ici, lexception leve par le die lintrieur de leval retrouve ses petits dans la variable $@ ($EVAL__ERROR), accompagne du nouveau nom de fichier temporaire et du numro de ligne :
# line 1996 "Odysse" eval qq { #line 2025 "Hal" die "portes du compartiment pod"; }; print "Problmes avec $@"; warn "Jai peur de ne pouvoir faire cela", ^D Problme avec les portes du compartiment pod at Hal line 2025. Jai peur de ne pouvoir faire cela at Odysse line 2001.

Ceci montre comment une directive #line naffecte que lunit de compilation courante (le fichier ou leval CHAINE) et que, lorsque la compilation de cette unit est termine, la configuration prcdente est automatiquement restaure. De cette manire vous pouvez positionner vos propres messages lintrieur dun eval CHAINE ou dun do FICHIER sans affecter le reste de votre programme. Perl possde une option -P qui invoque le prprocesseur C, qui met les directives #line. Le prprocesseur C tait llan initial pour implmenter #line, mais il est rarement utilis de nos jours, depuis quil existe de meilleurs moyens pour faire ce pour quoi nous nous reposions sur lui. Perl possde toutefois de nombreux autre prprocesseurs, y compris le module AutoSplit. Le prprocesseur JPL (Java Perl Lingo) change les fichiers .jpl en fichiers .java, .pl, .h et .c. Il utilise #line pour conserver la prcision des messages derreurs. Un des tous premiers prprocesseurs de Perl tait le traducteur sed-vers-perl, s2p. En fait Larry a retard la premire version de Perl pour terminer s2p et awk-vers-perl (a2p) car il pensait quils amlioraient la manire dont Perl serait peru. Hum, peut-tre que cela a t le cas. Voir les documentations en ligne pour plus dinformation ce sujet, ainsi que sur le traducteur find2perl.

Filtres de code source


Si vous savez crire un programme pour traduire des choses quelconques en Perl, alors pourquoi ne pas disposer dun moyen pour invoquer ce traducteur depuis Perl ? La notion de filtre de code source est ne avec lide quun script ou un module devrait tre capable de se dcrypter lui-mme la vole, comme ceci :
#!/usr/bin/perl use MonFiltreDeDecryptage;

customer_8566

586

Chapitre 24 Techniques couramment employes

@*x$]0uN&k^Zx02jZ^X{.?s!(f;9Q/^A^@~~8H]|,%@^P:q-= ...

Mais lide a volu depuis et maintenant un filtre de code source peut tre dfini pour faire toutes les transformations que vous dsirez sur un texte en entre. Mettez ceci en rapport avec la notion doption -x mentionne au chapitre 19, Linterface de la ligne de commande, et vous obtiendrez un mcanisme gnral pour extraire dun message nimporte quel morceau de programme et pour lexcuter, indpendamment du fait quil soit crit ou non en Perl. En utilisant le module Filter de CPAN, on peut mme maintenant faire des choses comme programmer du Perl en awk :
#!/usr/bin/perl use Filter::exec "a2p"; 1,30 { print $1 } # le traducteur awk-vers-perl

Maintenant voila prcisment ce que vous pourriez qualifier didiomatique. Mais nous ne prtendons pas une seule seconde quil sagit dune technique couramment employe.

customer_8566

25

Portabilit

Un monde ne comportant quun seul systme dexploitation rendrait la portabilit facile et la vie ennuyeuse. Nous prfrons un large champ gntique de systmes dexploitations, tant que lcosystme ne se divise pas trop clairement en prdateurs et en proies. Perl tourne sur des douzaines de systmes dexploitation et puisque les programmes Perl ne sont pas dpendants de la plate-forme, le mme programme peut tourner sur tous ces systmes sans modification. Enfin, presque. Perl essaie doffrir au programmeur autant de fonctionnalits que possible mais si vous utilisez des fonctionnalits spcifiques un certain systme dexploitation, vous rduirez forcment la portabilit de votre programme sur dautres systmes. Dans ce paragraphe, nous donnerons quelques lignes de conduite pour crire du code Perl portable. Une fois que vous aurez pris votre dcision sur le degr de portabilit que vous souhaitez, vous saurez o tirer un trait et vous saurez quelle limites vous dcidez de ne pas franchir. Si lon regarde sous un autre angle, lcriture de code portable entrane une limitation volontaire des choix disponibles. Il nexiste aucune raison pour ne pas utiliser Perl pour lier ensemble des outils Unix, ou pour prototyper une application Macintosh, ou pour grer la base de registre de Windows. Si cela a un sens de sacrifier la portabilit, allez-y.1 En gnral, remarquez que les notions de UID, de rpertoire maison et mme ltat dtre logu nexisteront que sur des plates-formes multiutilisateur. La variable spciale $^O vous indique sur quel systme dexploitation Perl a t compil. Ceci permet dacclrer le code qui autrement aurait d faire use Config pour obtenir la mme information via $Config{osname}. (Mme si vous avez charg Config pour dautres raisons, cela vous conomise une recherche dans un hachage li.)

1. Toute conversation ne se doit pas dtre multiculturellement exacte. Perl essaie de vous donner au moins une manire de faire la Chose Faire mais nessaie pas de vous limposer strictement. cet gard, Perl se rapproche plus de votre langue maternelle que de la langue de votre nourrice.

customer_8566

588

Chapitre 25 Portabilit

Pour obtenir des informations plus dtailles sur la plate-forme, vous pouvez rechercher le reste de linformation dans le hachage %Config, qui est disponible grce au module standard Config. Par exemple, pour vrifier si la plate-forme dispose de lappel lstat, vous pouvez tester $Config{d_lstat}. Voir la documentation en ligne de Config pour une description complte des variables accessibles et la page de manuel perlport pour une liste des comportements des fonctions internes de Perl sur diffrentes platesformes. Voici les fonctions Perl dont le comportement varie le plus entre les plates-formes. -X (tests de fichiers), accept, alarm, bind, binmode, chmod, chown, chroot, connect, crypt, dbmclose, dbmopen, dump, endgrent, endhostent, endnetent, endprotoent, endpwent, endservent, exec, fcntl, fileno, flock, fork, getgrent, getgrgid, getgrnam, gethostbyaddr, gethostbyname, gethostent, getlogin, getnetbyaddr, getnetbyname, getnetent, getpeername, getpgrp, getppid, getpriority, getprotobyname, getprotobynumber, getprotoent, getpwent, getpwnam, getpwuid, getservbyport, getservent, getservbyname, getsockname, getsockopt, glob, ioctl, kill, link, listen, lstat, msgctl, msgget, msgrcv, msgsnd, open, pipe, qx, readlink, readpipe, recv, select, semctl, semget, semop, send, sethostent, setgrent, setnetent, setpgrp, setpriority, setprotoent, setpwent, setservent, setsockopt, shmctl, shmget, shmread, shmwrite, shutdown, socket, socketpair, stat, symlink, syscall, sysopen, system, times, truncate, umask, utime, wait, waitpid

Sauts de ligne
Sur la plupart des systmes dexploitations, les lignes dans les fichiers sont termines par un ou deux caractres qui signalent la fin de ligne. Les caractres varient dun systme lautre. Unix utilise traditionnellement \012 (cest--dire le caractre octal 12 en ASCII), un type dentres/sorties la DOS utilise \015\012 et les Mac utilisent \015. Perl emploie \n pour reprsenter un saut de ligne logique , indpendamment de la plate-forme. Sur MacPerl, \n signifie toujours \015. Sur les Perl la DOS, \n signifie gnralement \012, mais lorsquon accde un fichier en mode texte , il est traduit vers (ou depuis) \015\012, selon que vous lisez ou que vous crivez. Unix fait la mme chose sur les terminaux en mode canonique. On se rfre gnralement \015\012 en lappelant CRLF. Comme DOS fait une distinction entre les fichiers texte et les fichiers binaires, les Perl la DOS ont des restrictions sur lutilisation de seek et tell sur un fichier en mode texte . Pour obtenir les meilleurs rsultats possibles, ne faites seek que sur des emplacements obtenus depuis tell. Si toutefois vous utilisez la fonction interne de Perl binmode sur le handle de fichier,vous pouvez gnralement faire seek et tell en toute impunit. Un malentendu frquent dans la programmation de sockets est que \n vaudra \012 partout. Dans beaucoup de protocoles Internet habituels, \012 et \015 sont spcifis et les valeurs de \n et \r de Perl ne sont pas fiables puisquelles varient dun systme lautre :
print SOCKET "Salut, le client !\015\012"; print SOCKET "Salut le client !\r\n"; # correct # FAUX

Toutefois, lutilisation de \015\012 (ou \cM\cJ, ou encore \x0D\x0A, ou mme v13.10) peut devenir pnible et disgracieux, et semer la confusion chez ceux qui maintiennent

customer_8566

Boutisme et taille des nombres

589

le code. Le module Socket fournit quelques Choses Correctes pour ceux qui en veulent :
use Socket qw(:DEFAULT :crlf); print SOCKET "Salut le client !$CRLF" # correct

Lors dune lecture sur une socket, souvenez-vous que le sparateur denregistrement dentre par dfaut $/ est \n, ce qui signifie que vous avez encore du travail faire si vous ntes pas srs que de ce que vous verrez travers la socket. Un code de socket robuste devrait reconnatre soit \012 ou \015\012 comme tant la fin de ligne :
use Socket qw(:DEFAULT :crlf); local ($/) = LF # pas ncessaire si $/ vaut dj /012 while (<SOCKET>) { s/$CR?$LF/\n/; }

# remplace LF ou CRLF par un saut de ligne logique

De mme, un code renvoyant des donnes textuelles comme un sous-programmes qui va chercher une page web devrait souvent traduire les sauts de ligne. Souvent, une seule ligne de code suffit :
$donnees =~ s/\015?\012/\n/g; return $donnees;

Boutisme et taille des nombres


Les ordinateurs stockent les entiers et les nombres virgule f lottante dans des ordres diffrents (gros-boutiste, big-endian ou petit-boutiste, little-endian) et dans des tailles diffrentes (32 bits et 64 bits tant les tailles les plus courantes de nos jours). Normalement, vous naurez pas y penser. Mais si votre programme envoie des donnes binaires travers une connexion rseau ou sil crit sur le disque des donnes destines tre lues par un ordinateur diffrent, il se peut que vous deviez prendre des prcautions Des ordres rentrant en conf lit peuvent semer une pagaille absolue dans les nombres. Si un hte petit-boutiste (comme une CPU Intel) stocke 0x12345678 (305 419 896 en dcimal), un hte grand-boutiste (comme une CPU Motorola) le lira comme 0x78563412 (2 018 915 346 en dcimal). Pour viter ce problme dans les connexions rseau (sur une socket), utilisez pack et unpack avec les formats n et N, qui crivent des nombres entiers courts et longs dans lordre gros-boutiste (galement appel ordre rseau ) quelle que soit la plate-forme. Vous pouvez explorer le boutisme de votre plate-forme en dpaquetant une structure de donnes empaquete en format natif, comme ceci :
print unpack("h*", pack("s2", 1, 2)), "\n"; # 10002000 sur par ex. Intel x86 ou Alpha 21064 en mode petit-boutiste # 00100020 sur par ex. Motorola 68040

Pour dterminer votre boutisme, vous pourriez utiliser lune de ces deux instructions :
$est_gros_boutiste = unpack("h*", pack("s", 1)) =~ /01/; $est_petit_boutiste = unpack("h*", pack("s", 1)) =~ /^1/;

Mme si deux systmes ont le mme boutisme, il peut encore y avoir des problmes lors du transfert de donnes entre des plates-formes 32-bits et 64-bits. Il nexiste pas de bonne

customer_8566

590

Chapitre 25 Portabilit

solution autre que dviter de transfrer ou de stocker des nombres binaires bruts. Soit vous transfrez et vous stockez les nombres en texte plutt quen binaire, soit vous utilisez des modules comme Data::Dumper ou Storable pour le faire votre place. Vous avez tout intrt utiliser des protocoles orients texte en toutes circonstantes ils sont plus robustes, plus maintenables et encore plus extensibles que les protocoles binaires. Bien entendu, avec lavnement de XML et dUnicode, notre dfinition dun protocole orient texte devient encore plus souple. Par exemple, vous pouvez transfrer, entre deux systmes o Perl 5.6.0 (ou une version ultrieure) est install, une squence dentiers encods en tant que caractres en utf8 (la version UTF-8 de Perl). Si les deux extrmits tournent sur une architecture avec des entiers 64-bits, vous pouvez changer des entiers 64-bits. Sinon, vous tes limits des entiers 32-bits. Utilisez pack avec un canevas U* pour envoyer et unpack avec un canevas U* pour recevoir.

Fichiers et systmes de fichiers


Les composants des chemins de fichiers sont spars par / sur Unix, \ sur Windows et : sur Mac. Certains systmes nimplmentent ni les liens en dur (link), ni les liens symboliques (symlink, readlink, lstat). Certains systmes attachent une importance la casse (majuscules/minuscules) des noms de fichiers, dautres non et dautres encore ny font attention que lors de la cration de fichiers mais pas lors de leur lecture. Il existe des modules qui peuvent vous aider. Les modules standards File::Spec fournissent des fonctions qui Font La Bonne Chose :
use File::Spec::Functions; chdir( updir() ); # monter dans le rpertoire suprieur $fichier = catfile( curdir(), temp, fichier.txt);

La dernire ligne lit dans ./temp/fichier.txt sur Unix et Windows ou :temp:fichier.txt sur Mac ou [.temp]fichier.txt sur VMS et stocke le contenu du fichier dans $fichier. Le module File::Basename, un autre module livr avec Perl qui est galement indpendant de la plate-forme, clate un nom de chemin en ses composants : le nom de fichier de base, le chemin complet vers le rpertoire et le suffixe du fichier. Voici quelques astuces pour crire des programmes Perl manipulant des fichiers qui soient portables : Nutilisez pas deux fichiers du mme nom avec des casses diffrentes, comme test.pl et Test.pl, puisque certaines plates-formes ignorent la casse. Limitez vos noms de fichiers la convention 8.3 (noms de huit lettres et extensions de trois lettres) partout o cest possible. Vous pouvez souvent vous en sortir avec des noms de fichiers plus longs pour autant que vous soyez srs quils resteront uniques lorsquon les aura pousss travers un trou dans le mur de taille 8.3. (H, cela savre plus facile que de pousser un chameau travers le chas dune aiguille.) Rduire lemploi de caractres non alphanumriques dans les noms de fichiers. Lutilisation de souligns est souvent correcte mais elle gaspille un caractre qui pourrait tre mieux employ pour lunicit sur les systmes 8.3. (Souvenez-vous que cest la raison pour laquelle nous ne mettons habituellement pas de soulign dans les noms de modules.)

customer_8566

Interactions avec le systme

591

De mme, lorsque vous utiliser le module AutoSplit, essayez de limiter vos noms de sous-programmes huit caractres au plus et ne donnez pas le mme nom avec une casse diffrente deux sous-programmes. Si vous avez besoin de plus de huit caractres, arrangez-vous pour quil y ait unicit sur les huit premiers. Utilisez toujours < explicitement pour ouvrir un fichier en lecture ; sinon, sur les systmes qui autorisent la ponctuation dans les noms de fichiers, un fichier prfix par un caractre > pourrait tre effac et un fichier prfix par | pourrait engendrer une ouverture de pipe. Car la forme deux arguments dopen est magique et elle interprtera les caractres comme >, < et |, ce qui peut tre la mauvaise chose faire. (Sauf si cest la bonne).
open(FICHIER, $fichier_existant) or die $!; open(FICHIER, "<$fichier_existant) or die $!; open(FICHIER, "<", $fichier_existant) or die $!; # MAUVAIS # mieux # encore mieux

Ne prsupposez pas que les fichiers texte finiront par un saut de ligne. Ils le devraient, mais les gens oublient quelquefois, particulirement lorsque leur diteur de texte les y aide.

Interactions avec le systme


Les plates-formes reposant sur une interface graphique sont parfois dmunis de toute espce de ligne de commande, ainsi les programmes exigeant une interface en ligne de commande pourraient ne pas fonctionner partout. Vous ny pouvez pas grand chose, part mettre jour. Quelques autres astuces : Certaines plates-formes ne peuvent pas supprimer ou renommer des fichiers en train dtre utiliss, souvenez-vous donc de fermer avec close les fichiers lorsque vous en avez fini avec eux. Ne faites pas unlink ou rename sur un fichier ouvert. Ne faites pas tie ou open sur un fichier dj li avec tie ou dj ouvert ; faites dabord untie ou close sur ce fichier. Nouvrez pas le mme fichier plusieurs fois simultanment, car certains systmes posent doffice des verrous sur les fichiers ouverts. Ne dpendez pas dune variable denvironnement spcifique existant dans %ENV et ne prsupposez pas que quoi que ce soit dans %ENV soit insensible la casse ou prserve la casse. Ne prsumez pas de la smantique de lhritage dUnix pour les variables denvironnement ; sur certains systmes, elles peuvent tre visibles par tous les processus. Nutilisez pas les signaux, ni %SIG. Tchez dviter les globs de noms de fichiers. Utilisez opendir, readdir et closedir la place. (Depuis la version 5.6.0 de Perl, le glob basique de noms de fichiers est bien plus portable quil ne ltait mais certains systmes peuvent encore se frotter aux Unixismes de linterface par dfaut si vous essayez dtre original.) Ne prsumez pas des valeurs spcifiques pour les numros derreur ou les chanes stockes dans $!.

customer_8566

592

Chapitre 25 Portabilit

Communication interprocessus (IPC)


Pour maximiser la portabilit, nessayez pas de lancer de nouveaux processus. Cela signifie que vous devriez viter system, exec, fork, pipe, , qx// ou open avec un |. Le problme principal ne rside pas dans les oprateurs eux-mmes : les commandes lanant des processus externes sont gnralement implmentes sur la plupart des plates-formes (bien que certaines nimplmentent aucun type de fork). Les problmes sont davantage susceptibles de se produire lorsque vous invoquez des programmes externes qui ont des noms, des emplacements, des sorties ou des smantiques pour les arguments qui varient entre les plates-formes. Un morceau de code Perl particulirement populaire est louverture dun pipe vers sendmail pour que votre programme puisse envoyer un mail :
open(MAIL, |/usr/lib/sendmail -t) or die "fork sendmail impossible: $!";

Ceci ne marchera pas sur les plates-formes sans sendmail. Pour une solution portable, utilisez lun des modules de CPAN pour envoyer votre mail, comme Mail::Mailer et Mail::Send dans la distribution MailTools ou Mail::Sendmail. Les fonctions des IPC System V dUnix (msg*(), sem*(), shm*()) ne sont pas toujours disponibles, mme sur certaines plates-formes Unix.

Sous-programmes externes (XS)


Il est gnralement possible dlaborer un code XS pour quil fonctionne avec nimporte quelle plate-forme mais les bibliothques et les fichiers den-tte pourraient ne pas tre disponibles partout. Si les bibliothques et les fichiers den-tte sont portables, alors il y a une chance raisonnable pour que le code XS le soit galement. Un problme de portabilit diffrent se produit lors de lcriture de code XS : la disponibilit dun compilateur C sur la plate-forme de lutilisateur final. C apporte avec lui ses propres problmes de portabilit et lcriture de code XS vous exposera certains dentre eux. Lcriture en Perl pur est un moyen facile datteindre la portabilit car le processus de configuration de Perl traverse des supplices extrmes pour vous cacher les tares de portabilit du C.2

Modules standard
En gnral, les modules standard (ceux qui sont livrs avec Perl) fonctionnent sur toutes les plates-formes. Les exceptions notables sont le module CPAN.pm (qui ralise en fait des connexions vers des programmes externes qui peuvent ne pas tre disponibles), les modules spcifiques une plate-forme (comme ExtUtils::MM_VMS) et les modules DBM. Il nexiste pas un seul module DBM qui soit disponible sur toutes les plates-formes.
2. Certaines personnes en marge de la socit lancent le script Configure de Perl comme une forme damusement bon march. Certaines personnes sont mme connues pour organiser des courses de Configure entre des systmes concurrents et parient dessus de grandes sommes dargent. Cette pratique est dsormais hors-la-loi dans la majeure partie du monde civilis.

customer_8566

Dates et heures

593

SDBM_File et les autres sont gnralement disponibles sur tous les portages Unix et la DOS mais pas dans MacPerl, o seuls NBDM_File et DB_File sont disponibles. La bonne nouvelle est quau moins un module DBM devrait tre disponible et que AnyDBM_File utilisera nimporte quel module quil sera capable de trouver. Avec une telle incertitude, vous ne devriez utiliser que les fonctionnalits communes toutes les implmentations DBM. Par exemple, limitez vos enregistrements 1 K octet, pas plus. Voir la documentation du module AnyDBM_File pour plus de dtails.

Dates et heures
L o cest possible, utilisez le standard ISO-8601 ( AAAA-MM-JJ ) pour reprsenter les dates. Les chanes comme 1971-06-21 peuvent facilement tre converties vers une valeur spcifique au systme avec un module comme Date::Parse. Une liste de valeurs de date et dheure (comme celle renvoye par la fonction interne localtime) peut tre convertie vers une reprsentation spcifique au systme en utilisant Time::Local. La fonction interne time renverra toujours le nombre de secondes depuis le commencement de l epoch (lorigine, voir la fonction time au chapitre 29) mais les systmes dexploitation ont des opinions divergentes concernant la date laquelle cela sest produit. Sur la plupart des systmes, lorigine est fixe au 1er janvier 1970 00:00:00 UTC mais elle a commenc 66 ans plus tt sur Mac et sur VMS elle a dmarr le 17 novembre 1858 00:00:00. Ainsi, pour obtenir des dates portables, vous voudrez peut-tre calculer un dcalage pour lorigine :
require Time::Local; $decalage = Time::Local::timegm(0, 0, 0, 1, 0, 70);

La valeur de $decalage sur Unix et Windows vaudra toujours 0 mais sur Macs et VMS, elle pourra valoir un nombre plus grand. Il est alors possible dajouter $decalage une valeur de date et dheure Unix pour obtenir ce qui devrait tre la mme valeur sur tous les systmes. La reprsentation par le systme de lheure du jour et de la date calendaire peut tre contrle par des moyens largement diffrents. Ne prsupposez pas que le fuseau horaire soit stock dans $ENV{TZ}. Et mme sil lest, ne prsupposez pas que vous pouvez le contrler via cette variable.

Internationalisation
Utilisez de lUnicode dans vos programmes. Faites toutes les conversions depuis et vers dautres jeux de caractres dans vos interfaces vers le monde extrieur. Voir le chapitre 15, Unicode. En dehors du monde dUnicode, vous devriez prsumez de peu en ce qui concerne les jeux de caractres et de rien du tout propos des valeurs de ord pour les caractres. Ne prsupposez pas que les caractres alphabtiques aient des valeurs de ord squentielles. Les lettres minuscules peuvent venir avant ou aprs les majuscules ; les majuscules et les minuscules peuvent tre mles de manire ce qu la fois a et A viennent avant b ; les caractres accentus et les autres caractres internationaux peuvent tre mls pour que vienne avant b.

customer_8566

594

Chapitre 25 Portabilit

Si votre programme opre sur un systme POSIX (une hypothse plutt large), consultez la page de manuel de perllocale pour plus dinformations sur les locales de POSIX. Les locales affectent les jeux de caractres et les encodages ainsi que la date et lheure, entre autres choses. Une utilisation correcte des locales rendra votre programme un peu plus portable ou au moins, plus pratique et nativement amical pour les utilisateurs non anglo-saxons. Mais soyez conscients que les locales et Unicode ne se mlangent pas encore trs bien.

Style
Lorsquil est ncessaire davoir du code spcifique la plate-forme, pensez le garder un endroit qui facilite le portage vers dautres plates-formes. Utiliser le module Config et la variable spciale $^O pour marquer les diffrences entre les plates-formes. Faites attention aux tests que vous fournissez avec votre module ou vos programmes. Le code dun module peut tre totalement portable mais ses tests peuvent ne pas ltre tout fait. Ceci arrive souvent lorsque les tests engendrent dautres processus ou appellent des programmes externes pour faciliter les contrles ou lorsque (comme on la remarqu ci-dessus) les tests prsument de certaines choses concernant le systme de fichiers et les chemins. Prenez garde ne pas dpendre dun style daffichage spcifique pour les erreurs, mme en vrifiant $! pour les erreurs standards aprs un appel systme. Utilisez plutt le module Errno. Souvenez-vous quun bon style transcende la fois le temps et les cultures, ainsi, pour une portabilit maximale, vous devez chercher comprendre ce qui est universel parmis les exigences de votre existence. Les personnes les plus quilibres ne sont pas prisonnires et nont pas ltre car elles ne se soucient pas dtre la mode en gard leur propre culture, de programmation ou autre. La mode est variable mais le style est constant.

customer_8566

26
POD
Un des principes sous-jacents dans la conception de Perl est que les choses simples devraient rester simples et que les choses difficiles devraient tre possibles. La documentation devrait rester simple. Perl implmente un format de balises simple appel pod qui peut avoir son existence propre ou tre librement entreml avec votre code source pour crer une documentation insre. Pod peut tre converti vers diffrents formats pour limpression ou la consultation ou vous pouvez simplement le lire directement car il est plat (plain en anglais). Pod nest pas aussi expressif que des langages comme XML, LATEX, troff(1) ou mme HTML. Cest une volont de notre part : nous avons sacrifi lexpressivit au profit de la simplicit et de la commodit. Certains langages balises font crire aux auteurs plus de balises que de texte, ce qui rend lcriture plus difficile quelle ne ltait et la lecture proche de limpossible. Un bon format, comme une bonne musique de film, reste en arrire-plan sans distraire le spectateur. Amener les programmeurs crire de la documentation est presque aussi difficile que de les amener porter des cravates. Pod a t conu pour tre si simple crire que mme un programmeur puisse le faire et il devrait le faire. Nous ne prtendons pas que pod est suffisant pour crire un livre, bien quil ft suffisant pour crire celui-ci.

Pod en quelques mots


La plupart des formats de document exigent que le document entier soit dans ce format. Pod est plus indulgent : vous pouvez insrer du pod dans tout type de fichier, en vous reposant sur les traducteurs de pod pour lextraire. Certains fichiers sont entirement constitus de pod pur 100 %. Mais dautres, notamment les programmes Perl et les modules, peuvent contenir une belle quantit de pod disperse de-ci de-l au bon vouloir de lauteur. Il suffit Perl de sauter le texte en pod lorsquil analyse le fichier en vue de lexcuter. Lanalyseur lexical de Perl sait o commencer sauter le pod lorsqu un certain endroit

customer_8566

596

Chapitre 26 POD

o il trouverait dordinaire une instruction, il rencontre la place une ligne commenant par un signe gal et un identificateur, comme ceci :
=head1 Ici se trouvent les pods !

Ce texte, ainsi que tout ce qui se trouve jusqu et y compris une ligne commenant par =cut, sera ignor. Cela vous permet dentremler votre code source et votre documentation en toute libert, comme dans :
=item guinde La fonction guinde() se comportera de la faon la plus spectaculairement coince que vous puissiez imaginer, avec aussi peu de naturel quune pyrotechnie cyberntique. =cut sub guinde() { my $arg = shift; ... } =item guincher La fonction guincher() permet la gnration autodidact dpistmologie. =cut sub guincher { print "La gnration dpistmologie nest pas implmente sur cette plate-forme.\n"; }

Pour dautres exemples, regardez dans nimporte quel module standard ou venant de CPAN. Ils sont tous supposs venir avec du pod, et pratiquement tous le font, except ceux qui ne le font pas. Puisque le pod est reconnu par lanalyseur lexical de Perl et rejet, vous pouvez galement utiliser une directive pod approprie pour inhiber rapidement une section de code arbitrairement longue. Utilisez un bloc pod =for pour inhiber un paragraphe ou une paire =begin/=end pour un section plus grosse. Nous dtaillerons la syntaxe de ces directives pod plus tard. Souvenez-vous cependant que dans les deux cas, vous tes toujours dans le mode pod aprs ceci, vous avez donc besoin de faire un =cut pour revenir au compilateur.
print "reu 1\n"; =for comment Ce paragraphe seul est ignor par tout le monde sauf le mythique traducteur comment (N.d.t : commentaire). Lorsque cest fait, vous tes toujours en mode pod et non en mode programme.

customer_8566

Pod en quelques mots


print "reu 2\n"; =cut # ok, nouveau dans le programme rel print "reu 3\n"; =begin commentaire print "reu 4\n"; tout ce qui se trouve ici sera ignor par tout le monde print "reu 5\n"; =end commentaire =cut print "reu 6\n";

597

Ceci affichera quon a reu 1, 3 et 6. Souvenez-vous que ces directives pod ne peuvent pas aller partout. Vous devez les mettre seulement l o lanalyseur sattend trouver une nouvelle instruction, pas juste au milieu dune expression, ni dautres endroits arbitraires. Du point de vue de Perl, tout ce qui est balis par pod est rejet mais du point de vue des traducteurs de pod, cest le code qui est rejet. Les traducteurs de pod voient le texte qui reste comme une squence de paragraphes spars par des lignes blanches. Tous les traducteurs de pods modernes analysent le pod de la mme manire, en utilisant le module standard Pod::Parser. Ils ne se diffrencient que par leur sortie, puisque chaque traducteur se spcialise dans un format de sortie. Il existe trois sortes de paragraphes : les paragraphes tels quels (verbatim), les paragraphes de commandes et les paragraphes de prose.

Paragraphes tels quels


Les paragraphes tels quels sont utiliss pour du texte littral que vous voulez voir apparatre tel quil est, comme des extraits de code. Un paragraphe tel quel doit tre indent ; cest--dire quil doit commencer par un caractre espace ou de tabulation. Le traducteur devrait le reproduire exactement, gnralement avec une fonte de largeur fixe, et en alignant les tabulations sur des colonnes de huit caractres. Il ny a pas de formatage spcial des squences dchappement, vous ne pouvez donc pas jouer sur les fontes pour mettre en italique ou en relief. Un caractre < signifie un < littral et rien dautre.

customer_8566

598

Chapitre 26 POD

Directives pod
Toutes les directives pod commence par = suivi dun identificateur. Ce dernier peut tre suivi par autant de texte arbitraire que la directive peut utiliser de quelque manire qui lui plaise. La seule exigence syntaxique est que le texte doit tre tout entier dans un paragraphe. Les directives actuellement reconnues (appeles parfois commandes pod) sont : =head1 =head2 ... Les directives =head1, =head2,... produisent des en-ttes du niveau spcifi. Le reste du texte dans le paragraphe est trait comme tant la description de len-tte. Elle sont identiques aux en-ttes de section et de sous-section .SH et .SS dans man(7) ou aux balises <h1>. . .</h1> et <h2>. . .</h2> en HTML. En fait, ces traducteurs convertissent ces directives exactement comme cela. =cut La directive =cut indique la fin du mode pod. (Il peut y avoir encore du pod plus loin dans le document mais, si cest le cas, il sera introduit par une autre directive pod.) =pod La directive =pod ne fait rien dautre que dire au compilateur darrter danalyser le code jusquau prochain =cut. Elle est utile pour ajouter un autre paragraphe au document si vous mlangez beaucoup du code et du pod. =over NOMBRE =item SYMBOLE =back La directive =over commence un paragraphe spcifiquement pour la gnration dune liste utilisant la directive =item. la fin de votre liste, utilisez =back pour la terminer. Le NOMBRE, sil est fourni, indique au formateur de combien despaces indenter. Certains formateurs ne sont pas assez riches pour respecter lindication, alors que dautres le sont trop pour la respecter, tant il est difficile, lorsquon travaille avec des fontes proportionnelles, daligner le texte simplement en comptant les espaces. (Toutefois, on prsume en gnral quavec quatre espaces il y a assez de place pour une puce ou un numro.) Le vritable type de la liste est indiqu par le SYMBOLE sur chaque lment. Voici une liste puces :
=over 4 =item * Armure de mithril =item * Manteau elfique =back

customer_8566

Pod en quelques mots


Une liste numrote :
=over 4 =item 1. Premirement, dites "ami". =item 2. Deuximement, entrez dans la Moria. =back

599

Une liste de dfinitions :


=over 4 =item armure() Description de la fonction armure() =item chant() Description de la fonction chant()

Vous pouvez imbriquer des listes de types identiques ou diffrents mais il faut appliquer certaines rgles de base : nutilisez pas =item en dehors dun bloc =over/=back ; utilisez au moins un =item lintrieur dun bloc =over/=back ; et peut-tre le plus important, conservez une cohrence dans le type des items dans une liste donne. Utilisez soit =item * avec chaque lment pour produire une liste puces, soit =item 1., =item 2., et ainsi de suite pour produire une liste numrote, soit utilisez =item truc, =item machin, et ainsi de suite pour produire une liste de dfinitions. Si vous commencez avec des puces ou des numros, gardez-les, puisque les formateurs sont autoriss utiliser le type du premier =item pour dcider de comment formater la liste. Comme pour tout ce qui concerne pod, le rsultat nest pas meilleur que le traducteur. Certains traducteurs accordent de lattention aux nombres particuliers (ou aux lettres, ou aux chiffres romains) qui suivent l=item et dautres non. Le traducteur pod2html actuel, par exemple, est quelque peu cavalier : il vide entirement la squence dindicateurs sans les regarder pour en dduire quelle squence vous utilisez, puis il enveloppe la liste complte lintrieur de balises <ol> et </ol> pour que le navigateur puisse afficher une liste ordonne en HTML. Ce ne doit pas tre interprt comme une fonctionnalit, cela pourra ventuellement tre corrig. =for TRADUCTEUR =begin TRADUCTEUR =end TRADUCTEUR =for, =begin et =end vous permettent dinclure des paragraphes spciaux passer inchangs aux formateurs, mais seulement des formateurs particuliers. Les formateurs reconnaissant leur propre nom ou des alias pour leur nom, dans TRADUCTEUR font attention ces directives ; tous les autres les ignorent compltement. La direc-

customer_8566

600

Chapitre 26 POD

tive =for spcifie que le reste de ce paragraphe nest prvu que pour ( for, en anglais) un traducteur particulier.
=for html <p> Voici un paragraphe en <small>HTML</small> <flash>brut</flash> </p>

Les directives apparies =begin et =end fonctionnent de manire identique =for mais, au lieu de naccepter quun seul paragraphe, elles traitent tout le texte compris entre le =begin et le =end correspondant comme tant destin un traducteur particulier. Quelques exemples :
=begin html <br>Figure 1.<img src="figure.png"><br> =end html =begin text -----------------| truc | | machin | -----------------^^^^ Figure 1. ^^^^ =end text

Les valeurs de TRADUCTEUR couramment acceptes par les formateurs comprennent roff, man, troff, nroff, tbl, eqn, latex, tex, html et text. Certains formateurs accepteront certains dentre eux comme synonymes. Aucun traducteur naccepte comment il sagit juste du mot habituel pour quelque chose devant tre ignor par tout le monde. Nimporte quel mot non reconnu pourrait jouer le mme rle. En crivant ce livre, nous avons souvent laiss des remarques pour nous mmes sous la directive =for later (pour plus tard). Remarquez que =begin et =end sembotent mais seulement dans le sens o la paire la plus lextrieur fait que tout ce qui se trouve au milieu est trait comme ntant pas du pod, mme sil y a l-dedans dautres directives =mot. Cest- dire que ds quun traducteur voit =begin truc, soit il ignorera, soit il traitera tout jusquau =end truc correspondant.

Squences pod
Le troisime type de paragraphe est simplement du texte au kilomtre. Cest dire que si un paragraphe ne commence ni par un espace, ni par un signe gal, il est pris comme un paragraphe plat : du texte ordinaire tap avec aussi peu de dcorations que possible. Les sauts de ligne sont traits comme des espaces. Cest en grande partie au traducteur de le rendre agrable car les programmeurs ont des choses plus importantes faire. On prsume que les traducteurs appliqueront certaines heuristiques courantes voir la section Traducteurs et modules pod plus loin dans ce chapitre. Vous pouvez toutefois faire certaines choses explicitement. lintrieur des paragraphes ordinaires ou des directives den-ttes ou ditems (mais pas dans les paragraphes

customer_8566

Pod en quelques mots

601

tels quels ), vous pouvez utiliser des squences spciales pour ajuster le formatage. Ces squences commencent toujours par une seule lettre majuscule suivie par un signe infrieur et elles se prolongent jusquau signe suprieur correspondant (qui nest pas forcment le suivant). Les squences peuvent contenir dautres squences. Voici les squences dfinies par pod : I<texte> Texte en italique, utilis pour mettre en relief, pour les titres de livres, les noms de bateaux et les rfrences de pages de manuel comme perlpod(1) . B<texte> Texte en gras, utilis presquexclusivement pour les options de la ligne de commande et parfois pour les noms de programmes. C<texte> Code littral, probablement dans une fonte de largeur fixe, comme du Courrier. Ce nest pas ncessaire pour les items dont le traducteur devrait tre capable den dduire quil sagit de code mais vous devriez mettre cette squence de toute faon. S<texte> Texte avec des espaces inscables. Entoure souvent dautres squences. L<nom> Une rfrence croise (un lien) vers un nom : L<nom> Page de manuel. L<nom/ident> Article dans une page de manuel. L<nom /"sec"> Section dans une autre page de manuel. L<"sec"> Section dans cette page de manuel (les guillemets sont optionnels). L</"sec"> Idem. Les cinq squences suivantes sont les mmes que celles ci-dessus, mais la sortie sera seulement texte, en cachant linformation sur le lien, comme en HTML : L<texte L<texte L<texte L<texte L<texte |nom> |nom/ident> |nom/"sec"> |"sec"> |/"sec">

Le texte ne peut pas contenir les caractres / et | et il ne devrait contenir < ou > que sil sagit dune paire.

customer_8566

602
F<chemin>

Chapitre 26 POD

Utilis pour les noms de fichiers. Ceci donne traditionnellement la mme prsentation que I. X<entre> Une entre dindex quelconque. Comme toujours, cest au traducteur de dcider quoi faire. La spcification de pod nimpose rien ce sujet. E<seq_chappement> Un caractre nomm, comme les squences dchappement en HTML : E<lt> Un < littral (optionnel, sauf lintrieur dautres squences et lorsquil est prcd dune lettre en majuscule). E<gt> Un > littral (optionnel, sauf lintrieur dautres squences). E<sol> Un / littral (ncessaire seulement dans L<>). E<verbar> Un | littral (ncessaire seulement dans L<>). E<NNN> Le caractre numro NNN, probablement en ISO-8859-1, mais peut-tre en Unicode. Cela ne devrait rien changer, dans labstrait... E<entit> Une entit HTML non numrique, comme E<Agrave>. Z<> Un caractre de taille nulle. Cest sympathique pour prfixer des squences qui pourrait rendre quelque chose confus. Par exemple, si vous aviez une ligne en prose ordinaire que devait commenc par un signe gal, vous devriez lcrire ainsi :
Z<>=vous voyez ?

ou pour quelque chose contenant un From , pour que le logiciel de mail ne mette pas un > devant :
Z<>From veut dire "de la part de" en anglais...

La plupart du temps, vous naurez besoin que dun seul ensemble de signes suprieur/infrieur pour dlimiter lune de ces squence pod. Cependant, vous voudrez parfois mettre un < ou un > lintrieur dune squence. (Cest particulirement courant lorsquon utilise une squence C<> pour donner une fonte de largeur fixe un extrait de code.) Comme toujours en Perl, il y a plus dune manire de faire. Une mthode est de simplement reprsenter les signes infrieur/suprieur avec une squence E :
C<$a E<lt>=E<gt> $b>

Ce qui donne $a <=> $b . Une mthode plus lisible et peut-tre plus plat , est dutiliser un autre ensem-

customer_8566

Traducteurs et modules pod

603

ble de dlimiteurs qui ne ncessite pas que les signes infrieur/suprieur soient protgs. Des doubles chevrons (C<< truc >>) peuvent tre employs, pourvu quil y ait un espace suivant immdiatement le dlimiteur ouvrant et prcdent immdiatement le dlimiteur fermant. Par exemple, ce qui suit fonctionnera :
C<< $a <=> $b >>

Vous pouvez utiliser autant de chevrons que vous dsirez pour autant que vous en avez le mme nombre des deux cts et que vous vous tes assur quun espace suive immdiatement le dernier < du ct gauche et quun espace prcde immdiatement le premier > du ct droit. Ainsi, ce qui suit fonctionnera galement :
C<<< $a <=> $b >>> C<<<< $a <=> $b >>>>

Tous ces exemples finissent par donner $a <=> $b dans une fonte de largeur fixe. Lespace supplmentaire lintrieur de chaque extrmit disparat, vous devriez donc laisser un espace lextrieur si vous en voulez un. De mme, les deux caractres espaces supplmentaires lintrieur ne se chevauchent pas, donc, si la premire chose cite est >>, ce nest pas pris en tant que dlimiteur fermant :
Loprateur C<< >> >> de dcalage vers la droite.

Ce qui donne Loprateur >> de dcalage vers la droite . Remarquez que les squences pod simbriquent bien. Cela signifie que vous pouvez crire La I<Santa MarE<iacute>a> a pris le large depuis longtemps pour produire La Santa Mara a pris le large depuis longtemps ou B<touch> S<B<t> I<time> > I<fichier> pour produire touch -t time fichier , et vous attendre ce que a marche correctement.

Traducteurs et modules pod


Perl est livr avec plusieurs traducteurs de pod qui convertissent les documents en pod (ou le pod inclus dans dautres types de documents) vers divers formats. Tous devraient travailler purement sur 8 bits. pod2text Convertit du pod en texte. Normalement, ce texte sera en ASCII sur 7 bits mais il sera sur 8 bits sil a reu une entre sur 8 bits, ou spcifiquement de lISO-8859-1 (ou de lUnicode) si vous utilisez des squence telles que LE<uacute>thien pour Lthien ou EE<auml>rendil pour Erendil. Si vous avez un fichier contenant du pod, la manire la plus facile (mais peut-tre pas la plus jolie) de ne visualiser que le pod format serait :
% pod2text Fichier.pm | more

Mais, encore une fois, le pod est suppos tre lisible par un humain sans formatage. pod2man Convertit du pod vers le format des pages de manuel dUnix, qui convient pour tre visualis via nroff (1) ou pour crer des copies composes via troff (1). Par exemple :
% pod2man Fichier.pm | nroff -man | more

ou

customer_8566

604

Chapitre 26 POD
% pod2man Fichier.pm | troff -man -Tps -t > page_temp.ps % ghostview page_temp.ps

et pour imprimer :
% lpr -Ppostscript page_temp.ps

pod2html Convertit le pod en HTML pour aller avec votre navigateur prfr :
% pod2html Fichier.pm > page_temp.html % lynx page_temp.html % netscape -remote "openURL(file:pwd/page_temp.html)"

Le dernier exemple est une astuce de Netscape qui ne fonctionne que si vous avez dj un navigateur de lanc quelque part pour dire cette incarnation de charger la page. Sinon, appelez-le exactement comme vous lavez fait pour lynx. pod2latex Convertit du pod en LATEX. Des traducteurs supplmentaires pour dautres formats sont disponibles sur CPAN. Les traducteurs font preuve de comportements par dfaut diffrents selon le format de sortie. Par exemple, si votre pod contient un paragraphe en prose disant :
Il sagit ici dune $variable

alors pod2html changera a en :


Il sagit ici dune <STRONG>$variable</STRONG>

alors que pod2text le laissera sans dcoration, puisque le dollar devrait suffire pour que cela soit lisible. Vous devriez crire votre pod en restant le plus proche possible du texte plat , en vous passant le plus possible de balises explicites. Cest chaque traducteur de dcider comment crer des signes de protection apparis, comment remplir et ajuster le texte, comment trouver une fonte plus petite pour les mots entirement en majuscules, etc. Puisquils ont t crits pour traiter la documentation en Perl, la plupart des traducteurs1 devraient galement reconnatre des lments sans dcoration comme ceux-ci et les prsenter de manire approprie : HANDLE_FICHIER $scalaire @tableau fonction() page_man(3r) quelquun@quelquepart.com http://truc.com/

Perl apporte galement plusieurs modules standard pour analyser et convertir du pod,

1. Si vous concevez un traducteur de pod gnrique, et non pour du code Perl, vos critres peuvent diffrer.

customer_8566

crire vos propres outils pod

605

comprenant Pod::Checker (et lutilitaire associ podchecker) pour vrifier la syntaxe des documents pod, Pod::Find pour trouver des documents pod dans les arborescences de rpertoires et Pod::Parser pour crer vos propres utilitaires pod. Remarquez que les traducteurs de pod devraient seulement regarder les paragraphes commenant par une directive pod (cela facilite lanalyse), puisquen fait le compilateur sait rechercher les squences dchappement pod mme au milieu dun paragraphe. Cela signifie que le secret suivant sera ignor la fois par le compilateur et par les traducteurs.
$a=3; =secret warn "Ni du POD, ni du CODE !?" =cut back print "reu $a\n";

Vous ne devriez probablement pas vous reposer sur le fait que le warn restera jamais sorti du pod. Les traducteurs de pod ne sont pas tous sages cet gard et le compilateur pourrait devenir moins slectif un jour ou lautre.

crire vos propres outils pod


Pod a t conu tout dabord et surtout pour tre facile crire. Un corollaire de la simplicit de pod est quelle permet dcrire soi-mme des outils simples pour traiter du pod. Si vous recherchez des directives pod, vous navez qu positionner le sparateur denregistrements en entre en mode paragraphe (peut-tre avec loption -00) et naccorder de lattention qu ce qui ressemble du pod. Voici par exemple un simple programme afficheur de plan en pod :
#!/usr/bin/perl -l00n # planpod - affiche le plan en pod next unless /^=head/; s/^=head(\d)\s+/ x ($1 * 4 - 4)/e; print $_, "\n";

Si vous le lancez sur le prsent chapitre de ce livre, vous obtiendrez quelque chose comme cela :
Plain Old Documentation Pod en quelques mots Paragraphes tels quels Directives pod Squences pod Traducteurs et modules pod crire vos propres outils pod Piges du pod Documenter vos programmes perl

Cet afficheur de plan en pod na pas vraiment fait attention au fait que le bloc pod tait valide ou non. Puisque ce qui est en pod et ce qui ne lest pas peuvent sentremler dans le mme fichier, cela na pas toujours de sens de lancer des outils gnriques pour rechercher et analyser le fichier complet. Mais ce nest pas un problme, tant donn quil est si facile dcrire des outils pour le pod. Voici un outil qui est attentif aux diffrences

customer_8566

606
entre le pod et ce qui nest pas du pod, puis naffiche que le pod :
#!/usr/bin/perl -00 # catpod - naffiche que ce qui est en pod while (<>) { if (!$enpod) { $enpod = /^=/; } if ($enpod) { $enpod = !/=cut/; print; } } continue { if (eof) { close ARGV; $enpod = ; } }

Chapitre 26 POD

Vous pourriez utiliser ce programme sur un autre programme ou un module en Perl, puis mettre un pipe sur la sortie vers un autre outil. Par exemple, si vous possder le programme wc(1)2 pour compter le nombre de lignes, de mots et de caractres, vous pourriez lapprovisionner avec la sortie de catpod pour quil ne considre dans son comptage que le pod :
% catpod MonModule.pm | wc

Il existe beaucoup dendroits o le pod vous permet dcrire des outils rudimentaires de faon simplissime en utilisant directement du Perl brut. Maintenant que vous avez catpod utiliser comme composant, voici un autre outil pour ne montrer que le code indent :
#!/usr/bin/perl -n00 # podlit - affiche les blocs littraux indents # partir de pod en entre print if /^\s/;

Que pourriez-vous faire avec a ? Et bien, vous pourriez premirement vouloir vrifier le code dans le document avec perl -wc. Ou peut-tre voudriez-vous une fonctionnalit de grep(1)3 qui ne regarde que les exemples de code :
% catpod MonModule.pm | podlit | grep nom_fonc

Cette philosophie, selon laquelle les outils et les filtres sont des parties interchangeables (et testables unitairement), est une approche tout bonnement simple et puissante pour concevoir des composants logiciels rutilisables. Cest une forme de paresse de ne construire quune solution minimale pour accomplir le travail aujourdhui du moins, pour certains types de travaux. Cependant, pour dautres tches, ceci peut mme savrer contre-productif. Parfois, il y a plus de travail crire un outil partir de rien et parfois moins. Pour ceux que nous vous avons montrs prcdemment, les prouesses naturelles de Perl en ce qui concerne le traitement du texte sont tout indiques pour appliquer la force brute . Mais tout ne fonctionne pas de cette faon. En jouant avec le pod, vous pourriez remarquer que bien que ses directives soient simples analyser, ces squences peuvent savrer plus risques. Bien que des traducteurs, hum, pas trs corrects, ne sadaptent pas ceci, les squences peuvent simbriquer dans dautres squences et peuvent avoir des dlimiteurs de taille variable.
2. Et si ce nest pas le cas, allez cherchez la version des Perl Power Tools dans le rpertoire scripts de CPAN. 3. Et si vous ne possdez pas grep, voir la prcdente note de bas de page.

customer_8566

crire vos propres outils pod

607

Au lieu de vous mettre coder vous-mme ce code danalyse, les paresseux chercheront une autre solution. Le module standard Pod::Parser remplit ce contrat. Il est tout particulirement utile pour les tches difficiles, comme celles qui ncessitent une relle analyse des morceaux internes des paragraphes, une conversion vers dautres formats de sortie, et ainsi de suite. Il est plus facile dutiliser le module pour les cas compliqus car la quantit de code laquelle vous aboutirez est plus petite. Cest galement mieux car lanalyse pineuse est dj ralise pour vous. Il sagit tout fait du mme principe que lemploi de catpod dans une chane de pipes. Le module Pod::Parser adopte une approche intressante dans son travail. Cest un module orient objet dune facture diffrente de la plupart de ceux que vous avez vus dans ce livre. Son objectif premier nest pas tant de fournir des objets manipuler directement que dapporter une classe de base partir de laquelle dautres classes peuvent tre construites. Vous crez votre propre classe et hritez de Pod::Parser. Puis vous dclarez des sousprogrammes servant de mthodes de rappel (callbacks) que lanalyseur de votre classe parente invoquera. Il sagit dune faon de programmer diffrente des programmes procduraux donns prcdemment. Dans un sens, il sagit plus dun style de programmation dclaratif car, pour accomplir le travail, vous enregistrez simplement des fonctions et laissez dautres entits les invoquer pour vous. La logique ennuyeuse du programme est gre ailleurs. Vous ne faites que donner des morceaux plug-and-play . Voici une rcriture du programme original catpod donn auparavant mais, cette fois-ci, elle utilise le module Pod::Parser pour crer votre propre sous-classe :
#!/usr/bin/perl # catpod2, classe et programme package catpod_analyseur; use Pod::Parser; @ISA = qw(Pod::Parser); sub command { my ($analyseur, $commande, $paragraphe, $num_ligne) = @_; my $hf_sortie = $analyseur->output_handle(); $paragraphe .= "\n" unless substr($paragraphe, -1) eq "\n"; $paragraphe .= "\n" unless substr($paragraphe, -2) eq "\n\n"; print $hf_sortie "=$commande $paragraphe"; } sub verbatim { my ($analyseur, $paragraphe, $num_ligne) = @_; my $hf_sortie = $analyseur->output_handle(); print $hf_sortie $paragraphe; } sub textblock { my ($analyseur, $paragraphe, $num_ligne) = @_; my $hf_sortie = $analyseur->output_handle(); print $hf_sortie $paragraphe; }

customer_8566

608
sub interior_sequence { my ($analyseur, $commande_seq, $argument_seq) = @_; return "$commande_seq<$argument_seq>"; } if (!caller) { package main; my $analyseur = catpod_analyseur->new(); unshift @ARGV, - unless @ARGV; for (@ARGV) { $analyseur->parse_from_file($_); } } 1; __END__ =head1 NAME documentation dcrivant le nouveau programme catpod, ici

Chapitre 26 POD

Comme vous le voyez, cest un peu plus long et plus compliqu. Cest galement plus volutif car tout ce que vous avez faire est de brancher vos propres mthodes lorsque vous voulez que votre sous-classe agisse diffremment que sa classe de base. Le dernier morceau la fin, o il est crit !caller, vrifie si le fichier est utilis en tant que module ou en tant que programme. Sil est employ comme programme, il ny aura alors pas dappelant (caller en anglais). Il lancera donc son propre analyseur (en utilisant la mthode new dont il a hrit) sur les arguments de la ligne de commande. Si aucun nom de fichier na t pass, il prend lentre standard, tout comme le faisait la version prcdente. la suite du code du module, il y a un marqueur __END__, une ligne vide sans espace, puis la propre documentation en pod du programme/module. Il sagit dun exemple dun fichier qui est la fois un programme et un module et sa propre documentation. Il est probablement plusieurs autres choses galement.

Piges du pod
Pod est assez direct apprendre et crire mais il est toujours possible de rater quelques petites choses : Il est vraiment facile doublier le signe suprieur final. Il est vraiment facile doublier la directive =back finale. Il est facile de mettre accidentellement une ligne vide au milieux dune longue directive =for comment. Songez utiliser =begin/=end la place. Si vous faites une faute de frappe sur lune des deux balises dune paire =begin/=end, cela avalera tout le reste de votre fichier (en ce qui concerne le pod). Songez utiliser =for la place. Les traducteurs de pod exigent que les paragraphes soient spars par des lignes compltement vides ; cest--dire, par au moins deux caractres de saut de ligne conscutifs (\n). Si vous avez une ligne avec des espaces ou des tabulations, elle ne sera pas prise comme une ligne blanche. Ceci peut causer le traitement de deux paragraphes ou plus comme sil ny en avait quun seul.

customer_8566

Documenter vos programmes Perl

609

La signification dun lien nest pas dfinie par pod et cest chaque traducteur de dcider quoi en faire. (Si vous commencez penser que la plupart des dcisions ont t reportes sur les traducteurs et pas dans pod, vous avez raison.) Les traducteurs ajouteront souvent des mots autour dun lien L<>, ainsi, L<truc(1)> deviendra la page de manuel truc(1) , par exemple. Vous ne devriez donc pas crire des choses comme la page de manuel L<truc> si vous voulez que le document traduit soit raisonnablement lisible : cela aboutirait la page de manuel la page de manuel truc(1) . Si vous avez besoin dun contrle total sur le texte utilis dans un lien, utilisez plutt la forme L<montre ce texte|truc>.

Le programme standard podchecker vrifie la syntaxe pod pour trouver les erreurs et les avertissements. Par exemple, il recherche les squences pod inconnues et les lignes blanches trompeuses contenant des espaces. Il est toujours recommand de passer votre document travers diffrents traducteurs de pod et de corriger les rsultats. Certains des problmes que vous trouverez peuvent tre des idiosyncrasies des traducteurs particuliers, ce sur quoi vous voudrez ou non travailler. Et, comme toujours, tout est sujet modification selon les caprices dun hacker quelconque.

Documenter vos programmes Perl


Nous esprons que vous documentez votre code, que vous soyez ou non un hacker quelconque. Si cest le cas, vous pouvez souhaiter inclure les sections suivantes dans votre pod : =head1 NOM Le nom de votre programme ou de votre module. =head1 SYNOPSIS Une description dune ligne sur ce que fait (soi-disant) votre programme ou votre module. =head1 DESCRIPTION La masse de votre documentation. (Masse est le terme appropri dans ce contexte.) =head1 AUTEUR Qui vous tes. (Ou un pseudonyme, si vous avez honte de votre programme.) =head1 BOGUES Ce que vous avez mal fait (et pourquoi ce ntait pas vraiment votre faute). =head1 VOIR AUSSI O les gens peuvent trouver des informations en rapport (pour quils puissent travailler sur vos bogues). =head1 COPYRIGHT Les instructions lgales. Si vous voulez revendiquer un copyright explicite, vous devriez dire quelque chose comme :
Copyright 2013, Randy Waterhouse. Tous droits rservs?

customer_8566

610
Beaucoup de modules ajoutent galement :

Chapitre 26 POD

Ce programme est un logiciel libre. Vous pouvez le copier ou le redistribuer sous les mmes termes que Perl lui-mme.

Un avertissement : si vous tes sur le point de mettre votre pod la fin du fichier et que vous utilisez les tokens __END__ ou __DATA__, assurez-vous de mettre une ligne vide avant la premire directive pod :
__END__ =head1 NOM Moderne - Je suis vraiment un modle dun module essentiel moderne

Sans la ligne vide avant le =head1, les traducteurs de pod ignoreront le dbut de votre documentation (vaste, prcise, cultive).

customer_8566

Culture Perl

27

Ce livre fait partie de la culture Perl, nous ne pouvons donc pas esprer mettre ici tout ce que nous connaissons propos de la culture Perl. Nous pouvons seulement attiser votre apptit avec un peu dhistoire et un peu dart certains diraient de lart mineur . Pour une dose beaucoup plus grosse de culture Perl, voir www.perl.org et www.perl.com. (Larry garde des copies de tous ses dlires (officiels) www.wall.org/~larry.) Ou acoquinez-vous dautres programmeurs Perl. Nous ne pouvons pas vous dire quel genre de personnes ils seront le seul trait de caractre que les programmeurs Perl ont en commun est quils sont pathologiquement serviables.

Lhistoire en pratique
Pour comprendre pourquoi Perl est ainsi dfini (ou indfini), il faut dabord comprendre la raison mme pour laquelle Perl existe. Sortons donc le grimoire poussireux... En 1986, Larry tait un programmeur systme sur un projet de rseaux grande chelle et multiples niveaux de scurit. Il soccupait dune installation compose de trois Vax et de trois Sun sur la Cte Ouest, connects par une ligne srie chiffre 1200 bauds une configuration similaire sur la Cte Est. Comme son travail consistait surtout en du support (il ntait pas programmeur sur le projet, seulement le gourou systme), il put exploiter ses trois vertus (paresse, impatience et orgueil) pour dvelopper et amliorer toutes sortes doutils intressants comme rn, patch et warp.1
1. Cest peu prs ce moment que Larry revendiqua lexpression feeping creaturism (N.d.T. : jeu de mot dlibr avec creeping featurism , ajouter des fonctionnalits rampantes, signifiant que le systme ou le programme en question est devenu une crature difforme cause des bidouilles quon lui a successivement ajoutes). Ceci dans une tentative dsespre de justifier, sur la base dune ncessit biologique, lhabitude dajouter rien quune dernire fonctionnalit . Aprs tout, si la vie est simplement trop complique, pourquoi pas les programmes ? Surtout les programmes comme rn qui devraient vraiment tre traits comme des projets avancs dIntelligence Artificielle afin quils puissent lire les news pour vous. videmment, certains trouvent le programme patch dj trop intelligent.

customer_8566

612

Chapitre 27 Culture Perl

Un jour, alors que Larry finissait de dcouper rn en petits morceaux, le laissant parpill sur le sol de son rpertoire, le Grand Patron vint lui et dit : Larry, il nous faut un systme de gestion de configurations et de contrle pour les six Vax et les six Sun. Dans un mois. Excution ! Larry, qui na jamais t un fainant, se demanda quel tait le meilleur moyen dobtenir un systme de gestion de configurations transcontinental, sans devoir partir de zro, qui permettrait de visualiser les rapports dincidents sur les deux ctes, avec validation et contrle. La rponse tenait en un mot : B-news.2 Larry commena par installer les news sur ces machines et ajouta deux commandes de contrle : une commande append pour enrichir un article existant et une commande synchronize pour que les numros darticles restent les mmes sur les deux ctes. La gestion du contrle passerait par RCS (Revision Control System) et les validations et les soumissions se feraient par les news et rn. Jusquici, tout allait bien. Puis, le Grand Patron lui demanda de fournir des rapports. Les news taient maintenues dans des fichiers spars sur une machine matre, avec un grand nombre de rfrences croises entre les fichiers. La premire pense de Larry fut : Utilisons awk. Malheureusement, le awk dalors ne savait pas grer louverture et la fermeture de plusieurs fichiers en fonction des informations de ces fichiers. Larry ne voulait pas programmer un outil spcifique. Cest ainsi quun nouveau langage naquit. lorigine, il ne sappelait pas Perl. Larry envisagea un certain nombre de noms avec ses collgues et son entourage (Dan Faigin, qui crivit cette histoire et Mark Biggar, son beau-frre, qui lassista normment lors de la conception initiale). Larry considra et rejeta en fait tous les mots de 3 ou 4 lettres du dictionnaire. Lun des premiers avait t Gloria , inspir de sa chre et tendre (et pouse). Il se dit rapidement que cela provoquerait trop de confusions dordre domestique. Le nom devint alors Pearl , qui muta en notre Perl actuel, en partie parce que Larry trouva une rfrence un autre langage nomm PEARL mais surtout parce quil est trop paresseux pour taper cinq lettres daffile chaque fois. videmment, afin que Perl puisse tre utilis comme lun de ces mots de quatre lettres chers aux anglophones. (Notez cependant les vestiges du nom initial dans le dveloppement de lacronyme : Practical Extraction And Report Language ). Le Perl des origines avait beaucoup moins de fonctionnalits que celui daujourdhui. La recherche de correspondances et les handles de fichiers taient l, les scalaires aussi, de mme que les formats, mais il ne comportait que trs peu de fonctions, pas de tableaux associatifs et juste une implmentation restreinte des expressions rgulires, emprunte rn. Le manuel ne contenait que 15 pages. Mais Perl tait plus rapide que sed et awk et commena tre utilis pour dautres applications du projet. Mais Larry tait demand par ailleurs. Un autre Grand Patron arriva un jour et dit : Larry, il faut assister la R&D . Et Larry fut daccord. Il prit Perl avec lui et dcouvrit quil se transformait en un bon outil dadministration systme. Il emprunta Henry Spencer son superbe paquetage dexpressions rgulires et le charcuta en quelque chose auquel Henry prfrerait ne pas penser table. Puis Larry ajouta la plupart des fonctionnalits qui lui semblaient bonnes et quelques autres que dautres personnes dsi2. Cest--dire la seconde implmentation du logiciel de transport de Usenet.

customer_8566

Posie en Perl
raient. Il le diffusa sur le rseau.3 Le reste, comme on dit, appartient lhistoire.4

613

Lhistoire sest droule comme ceci : Perl 1.0 sort le 18 dcembre 1987 ; certains prennent toujours au srieux lanniversaire de Perl. Perl 2.0 suit en juin 1988 et Randal Schwartz cre la signature lgendaire Just Another Perl Hacker (juste un autre bidouilleur Perl). En 1989, Tom Christiansen prsente le premier tutoriel public au Usenix de Baltimore. Avec Perl 3.0 en octobre 1989, le langage sort et distribu pour la premire fois dans les termes de la Licence Publique Gnrale de GNU. En mars 1990, Larry crit le premier pome en Perl (voir la section suivante). Puis lui et Randal crivent la premire dition de ce livre, le Pink Camel (le chameau rose ou fushia) ; il est publi en dbut danne 1991. Perl 4.0 sort en mme temps ; il comprend la Licence Artistique ainsi que la LPG. Linauguration du trs attendu Perl 5 se droule en octobre 1994. Cest une rcriture complte de Perl, comprenant des objets et des modules. Lavnement de Perl 5 fait mme la couverture du journal The Economist. En 1995, CPAN est officiellement prsent la communaut Perl. Jon Orwant commence publier The Perl Journal en 1996. Aprs une longue gestation, la seconde dition de ce livre, le Blue Camel (le chameau bleu) parat cet automne. La premire confrence Perl dOReilly (TPC) se droule San Jos, en Californie, durant lt 1997. Des vnements marquants arrivent maintenant presque quotidiennement, donc, pour la suite de lhistoire, regardez la Perl Timeline sur CPAST, le Comprehensive Perl Arcana Society Tapestry (N.d.T. : la ligne du temps sur la tapisserie de la socit des arcanes dtailles de Perl) sur history.perl.org.

Posie en Perl
La contrefaon ci-contre apparut sur Usenet le 1er avril 1990. Elle est prsente sans commentaires, essentiellement afin de montrer quel degr dabjection peuvent atteindre les mtaphores dun langage de programmation typique. Larry est particulirement soulag que Black Perl , crit lorigine pour Perl 3, ne compile plus sous Perl 5. Le, euh, corpus de Larry a t heureusement supplant par la Potesse Perl rgnante, Sharon Hopkins. Elle a crit un certain nombre de pomes Perl, ainsi quun article sur la posie en Perl, quelle a prsent la Confrence Technique Usenix de lhiver 1992, intitul Camel and Needles: Computer Poetry Meets the Perl Programming Language (Le chameau et les aiguilles : quand la posie informatique rencontre le langage de programmation Perl). (Larticle est disponible sous misc/poetry.ps sur CPAN.) Non contente dtre la plus prolifique des potesses Perl, Sharon est galement la plus largement publie, le pome suivant tant sorti dans lEconomist et le Guardian :

3. Ce qui est encore plus extraordinaire, cest quil continua le diffuser alors quil tait embauch chez Jet Propulsion Lab, puis NetLabs, puis Seagate. Maintenant, dautres personnes font la plupart du vrai boulot et Larry prtend travailler pour OReilly & Associates (une petite socit qui publie des opuscules sur les ordinateurs et autres balivernes). 4. Et voici, pour ainsi dire, un addendum lhistoire. Aux dbuts de Perl, rn venait dtre mis en pices avant une rcriture complte. Depuis quil a commenc travailler sur Perl, Larry na plus touch rn. Il reste en pices dtaches. Parfois, Larry menace de rcrire rn en Perl mais jamais srieusement.

customer_8566

614
#!/usr/bin/perl APPEAL: listen (please, please); open yourself, wide; join (you, me), connect (us,together), tell me. do something if distressed; @dawn, dance; @evening, sing; read (books,$poems,stories) until peaceful; study if able; write me if-you-please;

Chapitre 27 Culture Perl

sort your feelings, reset goals, seek (friends, family, anyone); do*not*die (like this) if sin abounds; keys (hidden), open (locks, doors), tell secrets; do not, I-beg-you, close them, yet. accept (yourself, changes), bind (grief, despair); require truth, goodness if-you-will, each moment; select (always), length(of-days) # listen (a perl poem) # Sharon Hopkins # rev. June 19, 1995

customer_8566

Posie en Perl

615

Posie en Perl
Article 970 of comp.lang.perl: Path: jpl-devvax!jpl-dexxav!lwall From: lwall@jpl-dexxav.JPL.NASA.GOV (Larry Wall) Newsgroups: news.groups,rec.arts.poems,comp.lang.perl Subject: CALL FOR DISCUSSION: comp.lang.perl.poems Message-ID: <0401@jpl-devvax.JPL.NASA.GOV> Date: 1 Apr 90 00:00:00 GMT Reply-To: lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) Organization: Jet Prepulsion Laboratory, Pasadena, CA Lines: 61 Mon attention a t attire par lurgente ncessit quprouvent les gens exprimer simultanment leurs natures motionnelle et technique. Plusieurs personnes mont envoy des messages qui ne correspondent aucun groupe de news. Cest peut-tre parce que jai rcemment post simultanment dans comp.lang.perl et dans rec.arts.poems que des gens crivent des pomes en Perl, et quils me demandent o les poster. En voici un chantillon : Dun tudiant en facult (dans ses dernires semaines), le haiku suivant :
study, write, study, do review (each word) if time. close book. sleep? whats that?

Et quelquun de Fort Lauerdale crit :


sleep, close together, sort of sin each spring & wait; 50% die

Une personne dsirant rester anonyme a crit lexemple suivant de Black Perl (le pote de Pearl en aurait t choqu, sans aucun doute.)
BEFOREHAND: close door, each window & exit; wait until time. open spellbook, study, read (scan, select, tell us); write it, print the hex while each watches, reverse its length, write again; kill spiders, pop them, chop, split, kill them. unlink arms, shift, wait & listen (listening, wait), sort the flock (then, warn the "goats" & kill the "sheep"); kill them, dump qualms, shift moralities, values aside, each one; die sheep! die to reverse the system you accept (reject, respect); next step, kill the next sacrifice, each sacrifice, wait, redo ritual until "all the spirits are pleased"; do it ("as they say"). do it(*everyone***must***participate***in***forbidden**s*e*x*). return last victim; package body; exit crypt (time, times & "half a time") & close it, select (quickly) & warn your next victim; AFTERWORDS: tell nobody. wait, wait until time; wait until next year, next decade; sleep, sleep, die yourself, die at last

Je lai essay et il compile effectivement en Perl. Il ne semble cependant pas faire grand chose. Ce qui mon avis est probablement heureux... Je propose donc la cration de comp.lang.perl.poems pour servir de lieu daccueil pour ces articles, afin que nous ne polluions pas les groupes de news sur perl ou les pomes avec des choses qui ne seraient dintrt aucun dentre eux. Ou bien, nous pouvons crer rec.arts.poems.perl pour ceux qui se contentent de compiler, sans rien faire dutile (il existe des prcdents dans rec.arts.poems, aprs tout). Ensuite, crons galement comp.lang.perl.poems pour ceux qui font rellement quelque chose, comme ce haiku personnel :
print STDOUT q Just another Perl hacker, unless $spring

Larry Wall

lwall@jpl-devvax.jpl.nasa.gov

customer_8566

customer_8566

Rfrences

customer_8566

customer_8566

Noms spciaux

28

Ce chapitre traite des variables qui ont une signification spciale pour Perl. La plupart des noms ponctuation ont des mnmoniques raisonnables ou des homologues dans les shells (ou les deux). Nanmoins, sil faut utiliser les noms longs de variables, il suffit dcrire :
use English;

au dbut du programme. Ceci cre des alias longs pour les noms courts dans le paquetage courant. Certain dentre eux ont mme des noms moyens, gnralement emprunts awk. La plupart des gens continuent dutiliser les noms courts, du moins pour les variables les plus courantes. Au long de cet ouvrage, nous employons uniformment les noms courts, mais nous mentionnerons aussi les noms longs (entre parenthses) pour que vous puissiez facilement les retrouver dans ce chapitre. La smantique de ces variables est quelque peu magique (pour crer vos propres sorts, voir le chapitre 24, Variables lies). Certaines de ces variables sont en lecture seule. Si lon essaie dy assigner une valeur, une exception sera lance. Dans ce qui suit, nous donnerons tout dabord une liste des variables et fonctions auxquelles Perl attribue une signification spciale, classes par type ; ainsi vous pourrez retrouver les variables dont vous ntes plus tout fait srs du nom exact. Ensuite nous dtaillerons toutes les variables par ordre alphabtique, avec leur nom appropri (ou leur nom le moins inappropri).

Noms spciaux classs par type


Nous utilisons improprement le mot type , les sections suivantes regroupent davantage les variables selon leur contexte, cest--dire depuis lendroit o elles sont visibles.

Variables spciales des expressions rgulires


Les variables spciales suivantes sont associes la recherche de motifs. Elles sont visibles tout au long du contexte dans lequel la recherche a lieu (hormis $*, qui est dpr-

customer_8566

620

Chapitre 28 Noms spciaux

cie). Autrement dit, elles se comportent comme si elles taient dclares avec local, vous navez donc pas besoin de les dclarer ainsi vous-mme. Voir le chapitre 5, Reconnaissance de motifs.
$* $chiffres @+ (@LAST_MATCH_END) @- (@LAST_MATCH_START) $+ ($LAST_PAREN_MATCH) $^R ($LAST_REGEXP_CODE_RESULT) $& ($MATCH) $ ($POSTMATCH) $ ($PREMATCH)

Variables spciales des handles de fichiers


Ces variables spciales nont jamais besoin dtre mentionnes dans un local car elles se rfrent toujours des valeurs appartenant au handle de sortie actuellement slectionn chaque handle de fichier garde son propre jeu de valeurs. Quand on slectionne un autre handle de fichier, lancien garde ses valeurs et les variables ref ltent alors les valeurs du nouveau handle de fichier. Voir aussi le module FileHandle dans le chapitre 32, Modules standards.
$| $$= $~ $% $^ ($AUTOFLUSH, $OUTPUT_AUTOFLUSH) ($FORMAT_LINES_LEFT) ($FORMAT_LINES_PER_PAGE) ($FORMAT_NAME) ($FORMAT_PAGE_NUMBER) ($FORMAT_TO_NAME)

Variables spciales par paquetage


Ces variables spciales existent sparment dans chaque paquetage. Il nest pas besoin de les localiser, puisque sort le fait automatiquement pour $a et $b, et quil est probablement prfrable de laisser les autres se dbrouiller toutes seules (cependant si vous employez use strict, vous devrez les dclarer avec our).
$a $b @EXPORT @EXPORT_OK %EXPORT_TAGS %FIELDS @ISA %OVERLOAD $VERSION

Variables spciales pour le programme entier


Ces variables sont vraiment globales au sens exact du terme elles signifient la mme chose dans chaque paquetage, car elles sont toutes localises de force dans le paquetage

customer_8566

Noms spciaux classs par type

621

main lorsquelles sont non qualifies (sauf pour @F, qui est spciale dans main, mais pas force). Si vous voulez une copie temporaire de lune dentre elles, vous devez la localiser dans le contexte dynamique courant.
%ENV %INC %SIG %! %^H @_ @ARGV @F @INC $_ ($ARG) $0 ($PROGRAM_NAME) $ARGV $! ($ERRNO, $OS_ERROR) $" ($LIST_SEPARATOR) $# $$ ($PID, $PROCESS_ID) $( ($GID, $REAL_GROUP_ID) $) ($EGID, $EFFECTIVE_GROUP_ID) $, ($OFS, $OUTPUT_FIELD_SEPARATOR) $. ($NR, $INPUT_LINE_NUMBER) $/ ($RS, $INPUT_RECORD_SEPARATOR) $: ($FORMAT_LINE_BREAK_CHARACTERS) $; ($SUBSEP, $SUBSCRIPT_SEPARATOR) $< (UID, $REAL_USER_ID) $> (EUID, $EFFECTIVE_USER_ID) $? ($CHILD_ERROR) $@ ($EVAL_ERROR) $[ $\ ($ORS, $OUTPUT_RECORD_SEPARATOR) $] ($OLD_PERL_VERSION) $^A ($ACCUMULATOR) $^C ($COMPILING) $^D ($DEBUGGING) $^E ($EXTENDED_OS_ERROR) $^F ($SYSTEM_FD_MAX) $^H $^I ($INPLACE_EDIT) $^L ($FORMA_FORMFEED) $^M $^O ($OSNAME) $^P ($PERLDB) $^R ($LAST_REGEXP_DOC_RESULT) $^S ($EXCEPTION_BEING_CAUGHT) $^T ($BASETIME) $^V ($PERL_VERSION) $^W ($WARNING) ${^WARNING_BITS} ${^WIDE_SYSTEM_CALLS} $^X ($EXECUTABLE_NAME)

Handles de fichiers spciaux par paquetage


Sauf pour DATA, qui est toujours particulier un paquetage, les handles de fichiers suivants sont toujours considrs comme tant dans main lorsquils ne sont pas pleinement qualifis dans un autre paquetage.
_ (soulign) ARGV ARGVOUT DATA STDIN STDOUT STDERR

customer_8566

622

Chapitre 28 Noms spciaux

Fonctions spciales par paquetage


Les noms des routines suivantes ont une signification spciale pour Perl. Elles sont toujours appeles implicitement suite un vnement, comme laccs une variable lie ou lappel une fonction indfinie. Nous ne les dcrirons pas dans ce chapitre puisquelles sont largement couvertes par ailleurs dans cet ouvrage. Fonction indfinie appelant une interception (voir le chapitre 10, Paquetages) :
AUTOLOAD

Achvement des objets moribonds (voir le chapitre 12, Objets) :


DESTROY

Objets dexception (voir die dans le chapitre suivant) :


PROPAGATE

Fonctions dauto-initialisation et dautonettoyage (voir le chapitre 18, Compilation) :


BEGIN, CHECK, INIT, END

Mthodes de liaison (voir le chapitre 14) :


BINMODE, CLEAR, CLOSE, DELETE, EOF, EXISTS, EXTEND, FETCH, FETCHIZE, FILENO, FIRSTKEY, GETC, NEXTKEY, OPEN, POP, PRINT, PRINTF, PUSH, READ, READLINE, SEEK, SHIFT, SPLICE, STORE, STORESIZE, TELL, TIEARRAY, TIEHANDLE, TIEHASH, TIESCALAR, UNSHIFT, WRITE

Variables spciales dans lordre alphabtique


Nous avons class alphabtiquement ces entres selon le nom long des variables. Si vous ne connaissez pas le nom long dune variable, vous pouvez le trouver dans la section prcdente. (Les variables sans nom alphabtique sont classes au dbut.) Pour viter les rptitions, chaque description de variable dbute avec une, ou plusieurs, des annotations suivantes.
Annotation XXX NON GLO PKG AHF DYN LEX LEC Signification Dprcie, ne pas utiliser pour quelque chose de nouveau. Non Officiellement Nomme (pour usage interne seulement). Rellement globale, partage par tous les paquetages. Globale au paquetage ; chaque paquetage peut redfinir sa propre variable. Attribut de handle de fichier ; un attribut par objet dentre/sortie. Automatiquement dans un contexte dynamique (entrane GLO). Dans un contexte lexicographique la compilation. En lecture seule ; lve une exception si vous tentez de modifier.

Quand plus dun symbole ou plus dun nom de variable est mentionn, seul le nom court est disponible par dfaut. En utilisant le module English, les synonymes plus longs sont disponibles dans le paquetage courant et uniquement dans le paquetage cou-

customer_8566

Variables spciales dans lordre alphabtique


rant, mme si la variable est marque avec [GLO].

623

Les entres de la forme mthode HANDLE EXPR montrent linterface oriente objet des variables pourvues par FileHandle et les diffrents module IO::. (Si vous prfrez vous pouvez aussi utiliser la notation HANDLE->mthode(EXPR)). Ceci vous permet dviter dappeler select pour changer le handle de sortie par dfaut avant dexaminer ou de modifier la variable en question. Chacune de ces mthodes renvoie lancienne valeur de lattribut du FileHandle ; lattribut prend une nouvelle valeur si lon positionne largument EXPR. Si cet argument nest pas fourni, la plupart des mthodes ne modifient pas la valeur courante, except pour autoflush, qui suppose que largument vaut 1, uniquement pour se distinguer. _ (soulign) [GLO] Il sagit du handle de fichier spcial utilis pour garder en cache les informations obtenues lors du dernier stat, lstat ou du dernier oprateur de test de fichier (comme -w $file ou -d $file) ayant russi. $chiffres [DYN, LEC] Les variables numrotes $1, $2, etc. (aussi lev que vous le dsirez)1 contiennent le texte trouv par le jeu de parenthses correspondant dans la dernire recherche de motifs du contexte dynamique actif cet instant. (Mnmonique : comme \chiffres). $[ [XXX, LEX] Lindex du premier lment dun tableau et du premier caractre dune sous-chane. 0 par dfaut, mais nous utilisons cette variable positionne 1 pour que Perl se comporte mieux comme awk (ou FORTRAN) au moment dindicer et dvaluer les fonctions index et substr. Parce quon a trouv cette variable dangereuse, laffectation de $[ est maintenant trait comme une directive de compilation dans un contexte lexical et ne peut pas inf luencer le comportement de tout autre fichier. (Mnmonique : [ prcde les indices). $# [XXX, GLO] Nutilisez pas cette variable ; prfrez printf. $# contient le format de sortie des nombres imprims, dans une tentative peu convaincante dmulation de la variable OFMT de awk. (Mnmonique : # en anglais signifie numro, mais si vous tes pointilleux, mieux vaut oublier tout ceci afin de ne pas trop parasiter votre programme et viter ainsi un sermon). $* [XXX, GLO] Et bien, trois variables dprcies la suite ! Celle-ci peut (mais ne doit pas) tre positionne vrai pour que Perl assume un /m sur chaque recherche de motif qui na pas explicitement de /s. (Mnmonique : * correspond de multiples quantits).

1. Bien que beaucoup de moteur dexpressions rgulires ne supportent que jusqu neuf rfrences arrires, Perl ne possde pas de telle limite ; ainsi si vous crivez $768, Perl nen aura cure, bien que ceux qui maintiennent votre code puissent tiquer si vous employez autant de parenthses dans vos expressions rgulires.

customer_8566

624
$a

Chapitre 28 Noms spciaux

[PKG] Cette variable est utilise par la fonction sort pour contenir le premier lment de chaque paire de valeurs comparer ($b est le second lment de chaque paire). Le paquetage pour $a est le mme que celui o loprateur sort a t compil, qui nest pas ncessairement celui dans lequel la fonction de comparaison a t compile. Cette variable est implicitement localise dans le bloc de comparaison de sort. Comme elle est globale, elle est exempte des messages de protestation de use strict. Puisque cest un alias pour la valeur du tableau concern, on pourrait penser quon peut la modifier, nen faites rien. Voir la fonction sort. $ACCUMULATOR $^A [GLO] La valeur courante de laccumulateur de write pour les lignes de format. Un format contient contient des commandes formline qui mettent leur rsultat dans $^A. Aprs avoir appel son format, write affiche le contenu de $^A et le vide. On ne voit donc jamais le contenu de $^A moins dappeler formline soi-mme pour lexaminer. Voir la fonction formline. $ARG $_ [GLO] Lespace dentre et de recherche de motifs par dfaut. Ces paires sont quivalentes :
while (<>) {...} # nest quivalent quavec un while sans dcorations while (defined($_ = <>)) {...} chomp chomp($_) /^Objet:/ $_ =~ /^Objet:/ tr/a-z/A-Z/ $_ = ~ tr/a-z/A-Z/

Voici les endroits o Perl prend $_ si lon ne spcifie pas doprande aux fonctions et oprateurs : Des fonctions de listes comme print et unlink et des fonctions unaires comme ord, pos et int, ainsi que tous les tests de fichier (sauf pour -t, qui prend STDIN par dfaut). Toutes les fonctions qui prennent par dfaut $_ sont repres en tant que telles dans le chapitre 29, Fonctions. Les oprations de recherche de motifs m// et s/// et les oprations de transformation y/// et tr///, lorsquon les utilise sans loprateur =~. La variable ditration dans une boucle foreach (mme si on lple for ou lorsquon lutilise avec un modificateur dinstruction) si aucune autre variable nest fournie. La variable ditration implicite dans les fonctions grep et map. (Il ny a aucun moyen de spcifier une variable diffrente pour ces fonctions.)

customer_8566

Variables spciales dans lordre alphabtique

625

Lendroit par dfaut o est plac un enregistrement en entre quand le rsultat dune opration <HF>, readline ou glob est test en tant quunique critre dun while. Cette affectation ne se produit pas en dehors dun while ou si un quelconque lment additionnel est inclus dans lexpression while.

(Mnmonique : le soulign est loprande sous-jacente de certaines oprations). @ARG @_ [GLO] Dans un sous-programme, ce tableau contient la liste darguments passe ce sous-programme. Voir le chapitre 6, Sous-programmes. Un split dans un contexte scalaire sapplique sur ce tableau, mais cet usage est dprci. ARGV [GLO] Le handle de fichier spcial qui parcourt les noms de fichiers de la ligne de commande et contenus dans @ARGV Habituellement, on lcrit comme le handle de . fichier nul dans loprateur dangle <>. $ARGV [GLO] Contient le nom du fichier courant lorsquon lit depuis le handle de fichier ARGV en utilisant les oprateurs <> ou readline. @ARGV [GLO] Le tableau contenant les arguments de la ligne de commande prvus pour le script. Remarquez que $#ARGV est gnralement le nombre darguments moins un, puisque $ARGV[0] est le premier argument et non le nom de la commande ; utilisez scalar @ARGV pour le nombre darguments du programme. Voir $0 pour le nom du programme. ARGVOUT [GLO] Ce handle de fichier spcial est utilis lorsquon traite le handle de fichier ARGV avec loption -i ou la variable $^I. Voir loption -i dans le chapitre 19, Linterface de ligne de commande. $b [PKG] Cette variable, sur de $a, est utilise dans les comparaisons avec sort. Voir $a et la fonction sort pour les dtails. $BASETIME $^T [GLO] Le moment o le script a commenc tourner, en secondes depuis lorigine (le dbut de 1970, pour les systmes Unix). Les valeurs renvoyes par les tests de fichier -M, -A et -C sont bases sur ce moment. $CHILD_ERROR $? [GLO] Le statut renvoy par la dernire fermeture de tube, la dernire commande en apostrophe inverse () ou les fonctions wait, waitpid ou system. Remarquez quil ne sagit pas simplement du code retour, mais le mot entier de 16-bits du statut renvoy par les appels systme sous-jacents wait(2) ou waitpid(2) (ou leurs quivalents). Ainsi, la valeur de retour du sous-programme se trouve dans loctet de

customer_8566

626

Chapitre 28 Noms spciaux

poids fort, cest--dire, $? >> 8 ; dans loctet de poids faible, $? & 127 donne quel signal (sil y en a un) a tu le processus, alors que $? & 128 rapporte si sa disparition a produit un core dump. (Mnmonique : similaire $? dans sh et sa progniture). lintrieur dun bloc END, $? contient la valeur qui va tre donne exit. Vous pouvez modifier $? dans un END pour changer le statut retour du script. Sous VMS, le pragma use vmsish status fait que $? ref lte le vritable statut de retour de VMS, au lieu de lmulation par dfaut du statut POSIX. Si la variable h_errno est supporte en C, sa valeur numrique est retourne via $? si lune des fonctions gethost*() choue. $COMPILING $^C [GLO] La valeur courante de largument interne associ loption -c, principalement utilis avec -MO et loutil perlcc(1) pour laisser le code modifier son comportement lorsquil est compil pour la gnration de code. Par exemple, vous pouvez avoir envie dexcuter AUTOLOAD pendant la phase de compilation, au lieu dutiliser le chargement diffr habituel, de sorte que le code sera gnr immdiatement. Voir le chapitre 18. DATA [PKG] Ce handle de fichier spcial se rfre tout ce qui suit soit le token __END__ ou le token __DATA__ dans le fichier courant. Le token __END__ ouvre toujours le handle de fichier main::DATA, ainsi il est utilis dans le programme principal. Le token __DATA__ ouvre le handle de fichier DATA dans nimporte quel paquetage effectif ce moment. Ainsi diffrents modules peuvent possder leur propre handle de fichier DATA, puisquils ont (on le prsume) des noms de paquetage diffrents. $DEBUGGING $^D [GLO] La valeur courante des arguments internes, positionns par loption -D de la ligne de commande ; voir le chapitre 19 pour les valeurs de bit. (Mnmonique : valeur de loption -D). $EFFECTIVE_GROUP_ID $EGID $) [GLO] Le gid (group ID) effectif de ce processus. Si vous vous trouvez sur une machine qui accepte que lon soit membre de plusieurs groupes simultanment, $) donne une liste des groupes concerns, spars par des espaces. Le premier nombre est celui qui est renvoy par getgid(2), et les suivants par getgroups(2), lun dentre eux pouvant tre identique au premier nombre. De mme, une valeur assigne $) doit galement tre une liste de nombres spars par des espaces. Le premier nombre est utilis pour positionner le GID effectif, et les autres (sil y en a) sont passs lappel systme setgroups(2). Pour obtenir leffet dune liste vide pour setgroups, il suffit de rpter le nouveau GID effectif ; par exemple, pour forcer un GID effectif de 5 et une liste vide effective pour

customer_8566

Variables spciales dans lordre alphabtique


setgroups :
$) = "5 5";

627

(Mnmonique : les parenthses sont employes pour regrouper les choses. Le GID effectif est le groupe qui est fermement le bon, si votre script est lanc avec setgid. Il faut donc une parenthse fermante). Remarque : $<, $>, $( et $) ne peuvent tre modifis que sur des machines qui supportent la routine systme set-id correspondante. $( et $) ne peuvent tre changs que sur des machines supportant setregid(2). $EFFECTIVE_USER_ID $EUID $> [GLO] LUID effectif de ce processus tel que renvoy par lappel systme geteuid(2). Exemple :
$< = $>; ($<, $>) = ($>, $<); # mettre luid rel luid effectif # changer luid rel et luid effectif

(Mnmonique : il sagit de lUID vers lequel vous tes parvenus si votre script est lanc avec setuid). Remarque : $< et $> ne peuvent tre changs que sur des machines qui supportent setreuid(2). Parfois mme, cela ne suffit pas. %ENV [GLO] Le hachage contenant les variables de lenvironnement courant. Modifier une valeur dans %ENV change lenvironnement la fois pour votre processus et pour les processus fils lancs aprs laffectation. (On ne peut modifier lenvironnement dun processus parent sur aucun systme ressemblant Unix).
$ENV{PATH} $ENV{PAGER} $ENV{LESS} system "man = "/bin:/usr/bin;" = "less"; = "MQeicsnf"; # nos options favorites pour less(1) perl"; # rcupre les nouveaux paramtres

Pour supprimer quelque chose dans votre environnement, soyez sr dutiliser la fonction delete au lieu dun undef sur la valeur du hachage. Remarquez que les processus qui sont lancs par une entre de crontab(5) hritent dun jeu de variables denvironnement particulirement appauvri. (Si votre programme fonctionne parfaitement depuis la ligne de commande mais pas avec cron, cest probablement la cause). Remarquez galement que vous devez modifier $ENV{PATH}, $ENV{SHELL}, $ENV{BASH_ENV}, et $ENV{IFS} si votre script est lanc avec setuid. Voir le chapitre 23, Scurit. $EVAL_ERROR $@ [GLO] Lexception courante leve ou le message derreur de syntaxe Perl de la dernire opration eval. (Mnmonique : quelle est ladresse de la dernire erreur de syntaxe ?) Contrairement $! ($OS_ERROR), qui est positionn sur un chec mais pas nettoy lors dun succs, on a la garantie que $@ est bien positionn ( une valeur vraie) si le dernier eval a engendr une erreur de compilation ou une exception lexcution, mais aussi la garantie que $@ est nettoy ( une valeur fausse) si aucun de ces problmes ne survient.

customer_8566

628

Chapitre 28 Noms spciaux

Les messages davertissement ne sont pas collects dans cette variable. Cependant, vous pouvez installer une routine destine traiter les avertissements en positionnant $SIG{__WARN__} comme dcrit plus loin dans cette section. Remarquez que la valeur de $@ peut tre un objet exception plutt quune chane. Dans ce cas, vous pouvez toujours le traiter comme une chane pourvu que lobjet exception ait dfini une surcharge de la transformation en chane (N.d.T. : stringification overload) pour sa classe. Si vous propagez une exception en crivant :
die if $@;

alors un objet exception appellera $@->PROPAGATE pour savoir que faire. (Une chane exception ajoutera une ligne propage la chane.) $EXCEPTIONS_BEING_CAUGHT $^S [GLO] Cette variable ref lte la situation courante de linterprteur, en retournant vrai lintrieur dun eval, faux sinon. Elle est indfinie si lanalyse de lunit courante de compilation nest pas encore finie, ce qui peut tre le cas dans les gestionnaires de signaux $SIG{__DIE__} et $SIG{__WARN__}. (Mnmonique : situation de eval.) $EXECUTABLE_NAME $^X [GLO] Le nom avec lequel le binaire perl lui-mme a t excut, provient de argv[0] en C. @EXPORT [PKG] Ce tableau est consult par la mthode import du module Exporter pour trouver la liste des variables et sous-programmes dautres paquetages qui doivent tre exports par dfaut quand le module est utilis (avec use) ou lorsquon emploie loption dimportation :DEFAULT. Il nest pas exempt des complaintes de use strict, ainsi il doit tre dclar avec our ou pleinement qualifi avec le nom du paquetage si vous avez activ ce pragma. De toute faon, toutes les variables qui commencent par EXPORT sont exemptes des avertissements comme quoi elles ne sont utilises quune seule fois. Voir le chapitre 11, Modules. @EXPORT_OK [PKG] Ce tableau est consult par la mthode import du module Exporter pour dterminer si une requte dimportation est lgale. Il nest pas exempt des complaintes de use strict. Voir le chapitre 11. %EXPORT_TAGS [PKG] Ce hachage est consult par la mthode import du module Exporter lorsquon requiert un symbole dimportation dbutant par deux points, comme dans use POSIX ":queue". Les cls sont les tags commenant par deux points mais sans les deux points (comme sys_wait_h). Les valeurs doivent tre des rfrences des tableaux contenant les symboles importer lorsquon requiert ce tag ; toutes les valeurs du hachage doivent galement apparatre soit dans @EXPORT, soit dans @EXPORT_OK. Ce hachage nest pas exempt des complaintes de use strict. Voir le chapitre 11.

customer_8566

Variables spciales dans lordre alphabtique


$EXTENDED_OS_ERROR $^E

629

[GLO] Information derreur spcifique au systme dexploitation courant. Sous Unix, $^E est identique $! ($OS_ERROR), mais elle diffre sous OS/2, VMS, les systmes Microsoft et MacPerl. Consultez les informations sur votre portage pour les spcificits. Les mises en garde mentionnes dans la description de $! sappliquent aussi $^E en gnral . (Mnmonique : explication tendue derreur.) @F [PKG] Le tableau dans lequel les lignes dentre sont clates quand la ligne de commande comporte loption -a est donne. Si loption -a nest pas utilise, ce tableau na aucune signification particulire (ce tableau nest en fait que @main::F et non dans tous les paquetages la fois). %FIELDS [NON, PKG] Ce hachage est utilis en interne par le pragma use fields pour dterminer les champs lgaux courants dans un objet hachage. Voir use fields, use base et Dclarations de champ avec use fields au chapitre 12. format_formfeed HANDLE EXPR $FORMAT_FORMFEED $^L [GLO] Ce quune fonction write gnre implicitement pour effectuer un saut de page avant dmettre un en-tte de page. "\f" par dfaut. format_lines_left HANDLE EXPR $FORMAT_LINES_LEFT $[AHF] Le nombre de lignes restantes dans la page du canal de sortie actuellement slectionn, pour une utilisation avec la dclaration format et la fonction write. (Mnmonique : lines_on_pages lines_printed.) format_lines_per_page HANDLE EXPR $FORMAT_LINES_PER_PAGE $= [AHF] La longueur de la page courante (lignes imprimables) du canal de sortie actuellement slectionn, pour une utilisation avec format et write. 60 par dfaut. (Mnmonique : est compos des lignes horizontales.) format_line_break_characters HANDLE EXPR $FORMAT_LINE_BREAK_CHARACTERS $: [GLO] Le jeu de caractres courant daprs lequel une chane peut tre scinde pour remplir les champs de continuation (commenant par ^) dans un format. " \n-" par dfaut, pour couper sur lespace ou le tiret. (Mnmonique : un deux-points en posie fait partie dune ligne. Maintenant il ne vous reste plus qu vous rappeler du procd mnmonique. . . )

customer_8566

630
format_name HANDLE EXPR $FORMAT_NAME $~

Chapitre 28 Noms spciaux

[AHF] Le nom du format de rapport courant pour le canal de sortie actuellement slectionn. Le nom du handle du fichier par dfaut. (Mnmonique : cette variable tourne aprs $^.) format_page_number HANDLE EXPR $FORMAT_PAGE_NUMBER $% [AHF] Le numro de page courant du canal de sortie actuellement slectionn, pour une utilisation avec format et write. (Mnmonique : % est le registre de numro de page dans troff(1). Quoi, vous ne savez pas ce quest troff ?) format_top_name HANDLE EXPR $FORMAT_TOP_NAME $^ [AHF] Le nom du format den-tte de page courant pour le canal de sortie actuellement slectionn. Le nom du handle de fichier auquel est ajout _TOP par dfaut. (Mnmonique : pointe vers le haut de la page.) $^H [NON, LEX] Cette variable contient les bits de statut du contexte lexical (autrement dit, des indications) pour le parseur Perl. Cette variable est strictement rserve une utilisation interne. Sa disponibilit, son comportement et son contenu sont sujets modifications sans pravis. Si vous y touchez, vous prirez indubitablement dune mort horrible cause par une dtestable maladie tropicale inconnue de la science. (Mnmonique : nous ne vous donnerons aucune indication.) %^H [NON, LEX] Le hachage %^H fournit la mme smantique de contexte lexical que $^H, le rendant utile pour limplmentation des pragmas de contexte lexical. Lisez les affreuses mises en garde nonces pour $^H, et ajoutez-y le fait que cette variable est encore exprimentale. %INC [GLO] Le hachage contenant les entres de noms de fichiers pour chaque fichier Perl charg via do FICHIER, require ou use. La cl est le nom du fichier spcifi, et la valeur est lendroit o le fichier a t vritablement trouv. Loprateur require utilise ce tableau pour dterminer si un fichier donn a dj t charg. Par exemple :
% perl -MLWP::Simple -le print $INC{LWP/Simple.pm} /usr/local/lib/perl/5.6.0/lib/site_perl/LWP/Simple.pm

@INC [GLO] Le tableau contenant la liste des rpertoires o les modules Perl peuvent tre trouvs par do FICHIER, require ou use. Initialement, il se compose des arguments de nimporte quelle option -I de la ligne de commande et des rpertoires de la variable denvironnement PERL5LIB, suivis par les bibliothques par dfaut de

customer_8566

Variables spciales dans lordre alphabtique


Perl, comme :
/usr/local/lib/perl5/5.6.0/i386-linux /usr/local/lib/perl5/5.6.0 /usr/local/lib/perl5/site_perl/5.6.0/i386-linux /usr/local/lib/perl5/site_perl/5.6.0 /usr/local/lib/perl5/site_perl/5.00552/i386-linux /usr/local/lib/perl5/site_perl/5.00552 /usr/local/lib/perl5/site_perl/5.005/i386-linux /usr/local/lib/perl5/site_perl/5.005 /usr/local/lib/perl5/site_perl

631

suivies par . , qui reprsente le rpertoire courant. Si vous avez besoin de modifier cette liste depuis votre programme, essayer le pragma use lib, qui non seulement modifie la variable durant la compilation, mais qui fait galement des ajouts dans tous les rpertoires dpendant de larchitecture (comme ceux qui contiennent les bibliothques partages utilises par les modules XS) :
use lib "/monchemin/lib/"; use UnModule;

$INPLACE_EDIT $^I [GLO] La valeur courante de lextension ddition sur place. Employez undef pour dsactiver ldition sur place. Vous pouvez utilisez ceci lintrieur de votre programme pour obtenir le mme comportement quavec loption -i. Par exemple, pour produire lquivalent de cette commande :
% perl -i.orig -pe s/machin/truc/g *.c

vous pouvez utiliser le code suivant dans votre programme :


local $^I = .orig; local @ARGV = glob("*.c"); while (<>) { s/machin/truc/g; print; }

(Mnmonique : la valeur de loption -i.) $INPUT_LINE_NUMBER $NR $. [GLO] Le numro de lenregistrement courant (gnralement le numro de ligne) pour le dernier handle de fichier dans lequel vous avez lu (ou sur lequel vous avez appel seek ou tell). La valeur peut tre diffrente de la ligne physique actuelle, selon la dfinition ce moment de ce quest une ligne voir $/ ($INPUT_RECORD_NUMBER) pour la manire de choisir cette dfinition). Un close explicite sur un handle de fichier rinitialise zro le numro de ligne. Comme <> neffectue jamais de close explicite, les numros de ligne augmentent en parcourant les fichiers ARGV (mais voyez les exemples de eof). La mise en local de $. a galement pour effet de mettre en local la notion que Perl a du dernier handle de fichier lu . (Mnmonique : de nombreux programmes utilise . pour le numro de ligne courant.)

customer_8566

632
$INPUT_RECORD_SEPARATOR $RS $/

Chapitre 28 Noms spciaux

[GLO] Le sparateur denregistrement en entre, le caractre saut de ligne par dfaut, celui qui est consult par la fonction readline, loprateur <HF>, et la fonction chomp. Il se comporte comme la variable RS de awk, et, sil contient la chane nulle, traite une ou plusieurs lignes blanches comme des dlimiteurs denregistrements. (Mais une ligne vide ne doit contenir aucun espace cach ou aucune tabulation). Vous pouvez affecter cette variable une chane de plusieurs caractres pour correspondre un sparateur sur plusieurs caractres, mais vous ne pouvez pas lui affecter un motif il faut bien que awk soit meilleur dans un domaine. Remarquez que le fait daffecter "\n\n" $/ signifie quelque chose de sensiblement diffrent que de lui affecter "", si le fichier contient des lignes blanches conscutives. "" traitera deux lignes blanches conscutives ou plus comme une seule ligne blanche. "\n\n" signifie que Perl suppose aveuglment quune troisime ligne appartient au paragraphe suivant. Si lon rend carrment $/ indfini, la prochaine opration de lecture de ligne avalera le reste du fichier dans une seule valeur scalaire :
undef $/; $_ = <HF>; s/\n[ \t]+/ /g; # enclenche le mode "cul-sec" # maintenant le fichier entier est ici # aplatit les lignes indentes

Si vous utilisez la construction while (<>) pour accder au handle de fichier ARGV alors que $/ vaut undef, chaque lecture prend le fichier suivant :
undef $/; while (<>) { ... } # $_ contient le prochain fichier dans sa totalit

Bien que nous ayons employ undef ci-dessus, il est plus sr de rendre $/ indfini en utilisant local :
{ local $/; $_ = <HF>; }

Affecter $/ une rfrence soit un entier, soit un scalaire contenant un entier, soit un scalaire convertible en entier, fera que les oprations readline et <HF> liront des enregistrements de taille fixe (avec la taille maximale denregistrement valant lentier rfrenc) au lieu dun enregistrement de taille variable termin par une chane particulire. Ainsi, ceci :
$/ = 32768; # ou \"32768" ou \$var_scalaire_contenant_32768 open(FICHIER, $monfichier); $enregistrement = <FICHIER>;

lira un enregistrement dau plus 32768 octets depuis le handle de FICHIER. Si vous ne lisez pas un fichier structur par enregistrement (N.d.T. : record-oriented file) (ou si votre systme dexploitation ne connat pas les fichiers structurs par enregistrement), alors vous aurez vraisemblablement un morceau de donnes chaque lecture. Si un enregistrement est plus volumineux que la taille que vous avez fixe,

customer_8566

Variables spciales dans lordre alphabtique

633

vous recevrez lenregistrement dcoup en plusieurs tranches. Le mode par enregistrement ne se marie bien avec le mode par ligne que sur les systmes o les entres/sorties standards fournissent une fonction read(3) ; VMS est une exception notoire. Un appel chomp lorsque $/ est positionne sur le mode par enregistrement ou lorsquelle nest pas dfinie na aucun effet. Voir aussi les options de la ligne de commande -0 (le chiffre) et -l (la lettre) dans le chapitre 19. (Mnmonique : / est utilis pour sparer les lignes lorsque lon cite de la posie.) @ISA [PKG] Ce tableau contient les noms des autres paquetages dans lesquels il faut rechercher une mthode qui na pu tre trouve dans le paquetage courant. Autrement dit, il contient les classes de base du paquetage. Le pragma use base positionne ceci implicitement. Il nest pas exempt des complaintes de use strict. Voir le chapitre 12. @LAST_MATCH_END @+ [DYN,LEC] Ce tableau contient les positions des fins des sous-lments de la dernire recherche de correspondance ayant russi dans le contexte dynamique actuellement actif. $-[0] est la position la fin de la correspondance entire. Il sagit de la mme valeur que celle retourne par la fonction pos lorsquon lappelle avec comme paramtre la variable sur laquelle sest faite la recherche de correspondance. Lorsque nous parlons de la position de la fin , nous voulons rellement dire la position du premier caractre qui suit la fin de ce qui a correspondu, ainsi nous pouvons soustraire les positions de dbut aux positions de fin pour obtenir la longueur. Le nime lment de ce tableau contient la position du nime lment de la correspondance, ainsi $+[1] est la position o finit $1, $+[2] la position o $2 finit, etc. Vous pouvez utiliser $#+ pour dterminer combien dlments ont russi correspondre dans la dernire recherche. Voir aussi @- (@LAST_MATCH_START). Aprs une recherche de correspondance russi sur une variable $var : $ est identique substr($var, 0, $-[0]) $& est identique substr($var, $-[0], $+[0] - $-[0]) $ est identique substr($var, $+[0]) $1 est identique substr($var, $-[1], $+[1] - $-[1]) $2 est identique substr($var, $-[2], $+[2] - $-[2]) $3 est identique substr($var, $-[3], $+[3] - $-[3]), etc.

@LAST_MATCH_START @[DYN,LEC] Ce tableau contient les positions des dbuts des sous-lments de la dernire recherche de correspondance ayant russi dans le contexte dynamique actif. $-[0] est la position au dbut de la correspondance entire. Le nime lment de ce tableau contient la position du nime lment de la correspondance, ainsi $[1] est la position o dbute $1, $-[2] la position o $2 dbute, etc. Vous pouvez utiliser $#- pour dterminer combien dlments ont russi correspondre dans la dernire recherche. Voir aussi @+ (@LAST_MATCH_END).

customer_8566

634
$LAST_PAREN_MATCH $+

Chapitre 28 Noms spciaux

[DYN, LEC] Cette variable renvoie ce qua trouv la dernire recherche de parenthse dans le contexte dynamique actuellement actif. Cest utile si lon ne sait pas (ou si lon ne sen proccupe pas) lequel des motifs parmi une alternative a t trouve. (Mnmonique : Soyez positifs et regardez droit devant.) Exemple :
$rev = $+ if /Version: (.*)|Revision: (.*)/;

$LAST_REGEXP_CODE_RESULT $^R [DYN] Cette variable contient le rsultat du dernier morceau de code excut au sein dune recherche de motifs russie construite avec (?{ CODE }). $^R vous donne un moyen dexcuter du code et den retenir le rsultat pour lutiliser plus tard dans le motif, ou mme encore aprs. Comme le moteur dexpressions rgulires de Perl se dplace tout au long du motif, il peut rencontrer de multiples expressions (?{ CODE }). Lorsque cela arrive, il retient chaque valeur de $^R de manire ce quil puisse restaurer lancienne valeur de $^R si plus tard il doit reculer avant lexpression. En dautres termes, $^R possde un contexte dynamique au sein du motif, un peu comme $1 et ses amis. Ainsi, $^R nest pas juste le rsultat du dernier morceau de code excut au sein dun motif. Cest le rsultat du dernier morceau de code qui a conduit au succs de la correspondance. Un corollaire est que si la correspondance a chou, $^R reprendra la valeur quelle avait avant la correspondance. Si le motif (?{ CODE }) est employ directement comme la condition dun sousmotif (?(CONDITION)SI_VRAI|SI_FAUX), $^R nest pas valorise. $LIST_SEPARATOR $" [GLO] Lorsquun tableau ou une tranche est interpol dans une chane entre guillemets (ou un quivalent), cette variable indique la chane mettre entre les lments individuels. Un espace par dfaut. (Mnmonique : on peut esprer que cest vident.) $^M [GLO] Par dfaut, on ne peut pas intercepter un dpassement de mmoire. Toutefois, si votre perl a t compil pour bnficier de $^M, vous pouvez lutiliser comme un espace mmoire en cas durgence. Si votre Perl est compil avec DPERL_EMERGENCY_SBRK et utilise le malloc de Perl, alors :
$^M = a x (1 < < 16);

allouera un tampon de 64K en cas durgence. Voir le fichier INSTALL dans le rpertoire du code source de la distribution Perl pour les informations sur la manire dactiver cette option. En guise deffet dissuasif pour lemploi de cette fonctionnalit avance, il ny a pas de nom long avec use English pour cette variable (et nous ne vous dirons pas quel est le procd mnmonique).

customer_8566

Variables spciales dans lordre alphabtique


$MATCH $&

635

[DYN, LEC] La chane trouve par la dernire recherche de motif dans le contexte dynamique actuellement actif. (Mnmonique : comme & dans certains diteurs.) $OLD_PERL_VERSION $] [GLO] Renvoie la version + niveau_de_patch/1000. On peut lutiliser pour dterminer au dbut du script si linterprteur Perl qui excute le script est dans une plage de versions correcte. (Mnmonique : cette version de Perl est-elle dans le bon intervalle ? Lintervalle mathmatique tant reprsent par un crochet). Exemple :
warn "Pas de somme de contrle !\n" if $] < 3.019; die "Exige la disponibilit du prototypage\n" if $] < 5.003;

Voir aussi la documentation de use VERSION et require VERSION pour un moyen convenable dchouer si linterprteur Perl est trop ancien. Voir $^V pour une reprsentation UTF-8 plus f lexible de la version de Perl. $OSNAME $^O [GLO] Cette variable contient le nom de la plate-forme (gnralement du systme dexploitation) pour laquelle le binaire Perl courant a t compil. Elle sert surtout ne pas appeler le module Config. $OS_ERROR $ERRNO $! [GLO] Dans un contexte numrique, donne la valeur courante de la dernire erreur dappel systme, avec toutes les restrictions dusage. (Ce qui signifie quil vaut mieux ne pas attendre grand chose de la valeur de $! moins quune erreur renvoye nindique spcifiquement une erreur systme). Dans un contexte de chane, $! donne la chane du message derreur correspondant. Vous pouvez assigner un numro derreur $! si, par exemple, vous voulez que $! renvoie la chane correspondant cette erreur particulire, ou si vous voulez positionner la valeur de sortie de die. Voir aussi le module Errno au chapitre 32. (Mnmonique : jai entendu quon venait de sexclamer ?) %OS_ERROR %ERRNO %! [GLO] Ce hachage nest dfini que si vous avez charg le module standard Errno dcrit au chapitre 32. Une fois ceci fait, vous pouvez accder %! en utilisant une chane derreur particulire, et sa valeur nest vraie que sil sagit de lerreur courante. Par exemple, $!{ENOENT} nest vraie que si la variable C errno vaut ce moment la valeur de ENOENT dans le #define en C. Cest un moyen pratique daccder aux symboles spcifiques dun fabriquant.

customer_8566

636
autoflush HANDLE EXPR $OUTPUT_AUTOFLUSH $AUTOFLUSH $|

Chapitre 28 Noms spciaux

[AHF] Si elle est positionne vrai, cette variable force un tampon tre vid aprs chaque print, printf et write sur le handle de sortie actuellement slectionn. (Cest ce que nous appelons vidage du tampon de commande. Contrairement la croyance populaire, positionner cette variable ne dsactive pas le vidage du tampon.) Elle vaut faux, par dfaut, ce qui signifie sur de nombreux systmes que STDOUT est vid ligne par ligne si la sortie seffectue sur terminal, et vid bloc par bloc si ce nest pas le cas, mme dans les tubes et les sockets. Positionner cette variable est utile lorsque vous envoyez la sortie vers un tube, comme lorsque vous lancez un script Perl sous rsh(1) et que vous voulez en voir la sortie en temps rel. Si vous avez des donnes en attente dtre vides dans le tampon du handle de fichier actuellement slectionn lorsque cette variable est positionne vrai, ce tampon sera immdiatement vid par effet de bord de laffectation. Voir la forme un seul argument de select pour des exemples de contrle du tampon sur les handles de fichier autres que STDOUT. (Mnmonique : quand vous voulez que vos tubes soient fumants.) Cette variable na aucun effet sur le vidage du tampon dentre ; pour ceci, voir getc dans le chapitre 29 ou lexemple dans le module POSIX au chapitre 32. $OUTPUT_FIELD_SEPARATOR $OFS $, [GLO] Le sparateur de champs en sortie (le limitateur, en fait) pour print. Normalement, print affiche simplement la liste dlments que vous spcifiez sans rien entre eux. Affecter cette variable fera spcifier la variable OFS de awk ce qui doit tre affich entre les champs. (Mnmonique : ce qui est affich quand il y a une , dans linstruction print.) $OUTPUT_RECORD_SEPARATOR $ORS $\ [GLO] Le sparateur denregistrement en sortie (le dlimiteur, en fait) pour print. Normalement, print affiche simplement les champs spars par des virgules que vous avez spcifi, sans saut de ligne final, ni sparateur denregistrements. Affectez cette variable, comme vous auriez affect la variable ORS de awk, pour spcifier ce qui est affich la fin du print. (Mnmonique : vous assignez $\ au lieu dajouter "\n" la fin du print. De mme, cette variable ressemble /, mais pour ce que Perl retourne .) Voir aussi loption de la ligne de commande -l (pour ligne ) dans le chapitre 19 %OVERLOAD [NON, PKG] Ces entres de hachage sont positionnes en interne grce au pragma use overload pour implmenter la surcharge doprateur pour les objets de la classe du paquetage courant. Voir le chapitre 13, Surcharge.

customer_8566

Variables spciales dans lordre alphabtique


$PERLDB $^P [NON, GLO] La variable interne pour activer le dbogueur Perl (perl -d). $PERL_VERSION $^V

637

[GLO] La rvision, la version, et la sous-version de linterprteur Perl, reprsents comme une chane de version binaire. Les v-chanes nont gnralement pas de valeur numrique, mais cette variable est doublement value, et elle a une valeur numrique quivalente lancienne variable $] ; cest--dire un nombre virgule valant rvision + version/1000 + sous-version/1000000. La valeur de la chane est compose des caractres UTF8 : chr($revision) . chr($version) . chr($sous_version). Cela signifie que $^V nest pas affichable. Pour lafficher, vous devez crire :
printf "%vd", $^V;

Dans les bons cts, cela veut galement dire que la comparaison normale de chanes peut tre utilise pour dterminer si linterprteur Perl qui excute votre script est dans une plage de versions correcte. (Ceci sapplique nimporte quelle version numrique reprsente avec des v-chanes, pas seulement celles de Perl). Exemple :
warn "Pas de dclarations avec our\n" if $^V lt v5.6;

Voir la documentation de use VERSION et require VERSION pour un moyen convenable dchouer si linterprteur Perl est plus ancien que ce que vous espriez. Voir aussi $] pour la reprsentation originelle de la version de Perl. $POSTMATCH $ [DYN, LEC] La chane qui suit tout ce qui a t trouv par la dernire recherche de motif russie dans le contexte dynamique actuellement actif. (Mnmonique : suit souvent une chane protge.) Exemple :
$_ = abcdefghi; /def/; print "$:$&:$\n";

# affiche abc:def:ghi

cause du contexte dynamique, Perl ne peut pas savoir quel motif aura besoin de sauvegarder ses rsultats dans ces variables, ainsi mentionner $ ou $ nimporte o dans le programme entrane une pnalisation dans les performances pour toutes les recherches de motif tout au long du programme. Ce nest pas un gros problme dans les programmes courts, mais vous voudrez probablement viter cette paire de variables si vous crivez le code dun module rutilisable. Lexemple ci-dessus peut tre rcrit de manire quivalente, mais sans le problme de performances globales, ainsi :
$_ = abcdefghi; /(.*?)(def)(.*)/s # /s au cas o $1 contiendrait des sauts de ligne print "$1:$2:$3\n"; # affiche abc:def:ghi

$PREMATCH $ [DYN, LEC] La chane qui prcde tout ce qui a t trouv par la dernire recherche de motif russie dans le contexte dynamique actuellement actif.

customer_8566

638

Chapitre 28 Noms spciaux

(Mnmonique : prcde souvent une chane protge.) Voir la remarque sur les performances de $ ci-dessus. $PROCESS_ID $PID $$ [GLO] Le numro de processus (PID) du Perl en train dexcuter ce script. Cette variable est automatiquement mise jour dans un fork. En fait, vous pouvez mme modifier $$ vous-mme ; ceci ne changera pas votre PID de toute faon. Ce serait un joli coup. (Mnmonique : comme pour les shells divers et varis). Vous devez faire attention de ne pas utiliser la variable $$ nimporte o elle pourrait tre malencontreusement interprte comme une drfrence : $$alphanum. Dans ce cas, crivez ${$}alphanum pour distinguer de ${$alphanum}. $PROGRAM_NAME $0 [GLO] Contient le nom du fichier contenant le script Perl en train dtre excut. Laffectation dune valeur $0 est magique : elle tente de modifier la zone darguments que voit le programme ps(1). Ceci est plus utile pour indiquer ltat courant du programme que pour cacher le programme en train de tourner. Mais cela ne fonctionne pas sur tous les systmes. (Mnmonique : pareil que dans sh, ksh, bash, etc.) $REAL_GROUP_ID $GID $( [GLO] Le GID (groupe ID) rel de ce processus. Si vous vous trouvez sur une machine qui accepte que lon soit membre de plusieurs groupes simultanment, $( donne une liste des groupes concerns, spars par des espaces. Le premier nombre est celui qui est renvoy par getgid(2), et les suivants par getgroups(2), lun dentre eux pouvant tre identique au premier nombre. De toute faon, une valeur assigne $( doit tre un seul et unique nombre utilis pour positionner le GID. Ainsi la valeur donne par $( ne doit pas tre raffecte $( sans la forcer tre numrique, comme en lui ajoutant zro. Ceci parce que vous ne pouvez avoir quun seul groupe rel. Voir plutt $) ($EFFECTIVE_GROUP_ID), qui vous permet daffecter plusieurs groupes effectifs. (Mnmonique : les parenthses sont employes pour regrouper les choses. Le GID rel est le groupe que vous laissez ouvert derrire vous, si votre script est lanc avec setgid. Il faut donc une parenthse ouvrante.) $REAL_USER_ID $UID $< [GLO] LUID rel de ce processus tel que renvoy par lappel systme geteuid(2). Savoir si vous pouvez le changer et comment le faire est dpendant de la bonne volont de limplmentation sur votre systme voir les exemples dans $> ($EFFECTIVE_USER_ID). (Mnmonique : il sagit de lUID do vous provenez si votre script est lanc avec setuid.)

customer_8566

Variables spciales dans lordre alphabtique


%SIG

639

[GLO] Le hachage utilis pour installer les gestionnaires de divers signaux. (Voir la section Signaux dans le chapitre 16, Communication inter-processus). Par exemple :
sub gestionnaire { my $sig = shift; # le 1er argument est le nom du signal syswrite STDERR, "SIG$sig dtect--on quitte\n"; # vitez les entres/sorties standards dans les # gestionnaires asynchrones pour supprimer le # core dump). (Mme cette concatnation de chane # est risque). close LOG; # Ceci appelle une entre/sortie standard, ainsi # il peut y avoir quand mme un core dump ! exit 1; # Mais puisque lon quitte le programme, # il ny a pas de mal essayer. } $SIG{INT} = \&gestionnaire; $SIG{QUIT) = \&gestionnaire; ... $SIG{INT} = DEFAULT; # rtablir laction par dfaut $SIG{QUIT} = IGNORE; # ignorer SIGQUIT

Le hachage %SIG contient des valeurs indfinies correspondant aux signaux pour lesquels aucun gestionnaire na t affect. Un gestionnaire peut tre spcifi comme une rfrence de sous-programme ou comme une chane. Une chane dont la valeur nest pas lune des deux actions spciales DEFAULT ou IGNORE est le nom dune fonction, qui, si elle nest pas qualifie par un paquetage, est interprte comme faisant partie du paquetage main. Voici quelques exemples :
$SIG{PIPE} = "Plombier"; $SIG{PIPE} = \&Plombier; # # # # OK, on suppose quil sagit de main::plombier bien, on utilise Plombier dans le paquetage courant

Certaines routines internes peuvent galement tre installes avec le hachage %SIG. La routine indique par $SIG{__WARN__} est appele quand un message davertissement va tre affich. Le message est pass en premier argument. La prsence dune routine __WARN__ provoque la suppression de laffichage normal des messages davertissements vers STDERR. Vous pouvez vous en servir pour sauvegarder ces messages dans une variable ou pour transformer les avertissements en erreurs fatales, comme ceci :
local $SIG{__WARN__} = sub { die $_[0] }; eval $programmette;

Cest quivalent :
use warnings qw/FATAL all/; eval $programmette

except le fait que le premier code a un contexte dynamique alors que le second a un contexte lexical. La routine indique par $SIG{__DIE__} offre un moyen de changer une exception batracienne en exception princire avec un baiser magique, ce qui souvent ne fonc-

customer_8566

640

Chapitre 28 Noms spciaux

tionne pas. La meilleure utilisation est lexcution de choses de dernire minute lorsquun programme est sur le point de mourir suite une exception non intercepte. Vous ne sauverez pas votre peau ainsi, mais vous aurez le droit de formuler une dernire volont. Le message dexception est pass en premier argument. Quand une routine __DIE__ revient, le traitement de lexception continue comme il laurait fait en labsence de linterception, moins que la routine dinterception ne quitte elle-mme par un goto, une sortie de boucle ou un die. Le gestionnaire de __DIE__ est explicitement dsactiv pendant lappel, afin que vous puissiez vous-mme appeler alors le vritable die depuis un gestionnaire de __DIE__. (Si ce ntait pas le cas, le gestionnaire sappellerait lui-mme indfiniment.) Le gestionnaire pour $SIG{__WARN__} procde de la mme faon. Seul le programme principal doit positionner $SIG{__DIE__}, pas le module. Ceci car actuellement, mme les exceptions qui sont interceptes continuent de dclencher un gestionnaire de $SIG{__DIE__}. Ceci est fortement dconseill car vous pourriez briser dinnocents modules qui ne sattendaient pas ce que les exceptions quils prvoyaient soient altres. Utilisez cette fonctionnalit uniquement en dernier ressort, et si vous le devez, mettez toujours devant un local pour limiter la dure du danger. Nessayez pas de construire un mcanisme de gestion de signal partir de cette fonctionnalit. Utilisez plutt eval {} pour intercepter les exceptions. STDERR [GLO] Le handle de fichier spcial pour la sortie derreur standard dans nimporte quel paquetage. STDIN [GLO] Le handle de fichier spcial pour lentre standard dans nimporte quel paquetage. STDOUT [GLO] Le handle de fichier spcial pour la sortie standard dans nimporte quel paquetage. $SUBSCRIPT_SEPARATOR $SUBSEP $; [GLO] Le sparateur dindices pour lmulation de hachage multidimensionnels. Si vous vous rfrez un lment de hachage comme :
$machin{$a,$b,$c}

cela veut vraiment dire :


$machin{join($;, $a, $b, $c)}

Mais ne mettez pas :


@machin{$a,$b,$c} # une tranche de tableau - remarquez le @

qui signifie :
($m{$a},$machin{$b},$machin{$c})

La valeur par dfaut est "\034", la mme que SUBSEP dans awk. Remarquez que si vos cls contiennent des donnes binaires, il ne peut exister de valeur sre pour $;.

customer_8566

Variables spciales dans lordre alphabtique

641

(Mnmonique : virgule le sparateur dindices syntaxique est un point-virgule. Oui, je sais, cest un peu faible, mais $, est dj prise pour quelque chose de plus important.) Bien que nous nayons pas dcourag cette fonctionnalit, vous devez plutt envisager dutiliser maintenant de vritables hachages multidimensionnels, comme $machin{$a}{$b}{$c} au lieu de $machin{$a,$b,$c}. Les simulations de hachages multidimensionnels peuvent cependant tre plus faciles trier et sont plus mme dutiliser les fichiers DBM. $SYSTEM_FD_MAX $^F [GLO] Le descripteur de fichier systme maximum, gnralement 2. Les descripteurs de fichiers systmes sont passs aux nouveaux programmes durant un exec, alors que les descripteurs suprieurs ne le sont pas. De plus, pendant un open, les descripteurs de fichiers systmes sont prservs mme si le open choue. (Les descripteurs de fichiers ordinaires sont ferms avant que louverture ne soit tente et le restent si elle choue.) Remarquez que le statut de close-on-exec dun descripteur de fichier se dcide daprs la valeur de $^F au moment du open, et non au moment du exec. vitez ceci en affectant $^F une valeur qui explose les compteurs :
{ local $^F = 10_000; pipe(SALUT, CAVA) or die "pipe a chou : $!"; }

$VERSION [PKG] Cette variable est accessible tout moment o une version minimale acceptable dun module est spcifie, comme dans use UnModule 2.5. Si $UNMODULE::VERSION est infrieure, une exception est leve. Techniquement, cest la mthode UNIVERSAL->VERSION qui inspecte cette variable, vous pouvez donc dfinir votre propre fonction VERSION dans le paquetage courant si vous voulez autre chose que le comportement par dfaut. Voir le chapitre 12. $WARNING $^W [GLO] La valeur boolenne courante de loption globale davertissement ( ne pas confondre avec loption globale dasservissement, propos de laquelle nous avons entendus de nombreux avertissements globaux). Voir aussi le pragma use warnings au chapitre 31, Modules de pragma, et les options de la ligne de commande -W et -X pour les avertissements dans un contexte lexical, qui ne sont pas affects par cette variable. (Mnmonique : la valeur est lie loption -w.) ${^WARNING_BITS} [NON, GLO] Lensemble courant des tests davertissement activs par le pragma use warnings. Voir use warnings au chapitre 31 pour de plus amples dtails. ${^WIDE_SYSTEM_CALLS} [GLO} Largument global qui permet tous les appels systmes effectus par Perl dutiliser les API wide-characters natives du systme, si elles sont disponibles. Il peut

customer_8566

642

Chapitre 28 Noms spciaux

galement tre activ depuis la ligne de commande en utilisant loption -C. La valeur initiale est gnrallement 0 pour assurer la compatibilit avec les versions de Perl antrieures la 5.6, mais il peut tre automatiquement mis 1 par Perl si le systme fournit une valeur par dfaut modifiable par lutilisateur (comme via $ENV{LC_TYPE}). Le pragma use bytes annule les effets de cet argument dans le contexte lexical courant. Et maintenant attachez vos ceintures pour un grand chapitre. . .

customer_8566

29

Fonctions

Ce chapitre dcrit les fonctions intrinsques de Perl par ordre alphabtique1 par souci pratique de rfrence. Chaque description de fonction commence par un bref rsum de la syntaxe pour cette fonction. Les noms de paramtre en CAPITALES OBLIQUES indiquent en fait les emplacements pour des expressions ; le texte qui suit le rsum de la syntaxe dcrit ensuite la smantique de ces arguments lorsquon les fournit (ou quon les omet). Vous pouvez considrer que les fonctions sont des termes dans une expression au mme titre que les littraux et les variables. Ou bien, vous pouvez considrer quil sagit doprateurs prfixes, qui traitent les arguments qui les suivent. Dailleurs, nous utilisons le mot oprateur la plupart du temps. Certains de ces oprateurs, euh, fonctions, prennent comme argument une LISTE. Les lments de la LISTE doivent tre spars par des virgules (ou par =>, qui est juste une drle de varit de virgule). Les lments de la LISTE sont valus dans un contexte de liste, ainsi chaque lment renvoie, soit un scalaire, soit une valeur de liste, selon sa sensibilit au contexte de liste. Chaque valeur renvoye, que ce soit un scalaire ou une liste, sera interpole comme tant un composant de la squence entire de valeurs scalaires. Cest--dire que les listes sont mises plat dans une seule liste. Du point de vue de la fonction qui reoit les arguments, largument global LISTE est toujours une valeur de liste une dimension. (Pour interpoler un tableau comme un lment unique, vous devez explicitement crer et interpoler la place une rfrence ce tableau.) Les fonction prdfinies de Perl peuvent tre utilises avec ou sans parenthses encadrant les arguments ; dans ce chapitre les rsums de syntaxe omettent les parenthses. Si vous utilisez des parenthses, la rgle simple mais parfois surprenante est la suivante : si a ressemble une fonction, alors cest une fonction, ainsi la prcdence na pas dimportance. Sinon, il sagit dun oprateur de liste ou dun oprateur unaire, et la prc1. Parfois, les fonctions troitement lies sont regroupes ensemble dans les pages man du systme, nous respectons donc ici cette organisation. Pour trouver par exemple la description de endpwent, vous devrez cherchez sous getpwent.

customer_8566

644

Chapitre 29 Fonctions

dence devient importante. Soyez vigilants, car mme si vous mettez un espace entre le mot-cl et sa parenthse ouvrante, cela ne lempche pas dtre une fonction :
print 1+2*4; print(1+2) * 4; print (1+2)*4; print +(1+2)*4; print ((1+2)*4); # # # # # Affiche Affiche Affiche Affiche Affiche 9. 3 ! aussi 3 ! 12. 12.

Perl peut vous avertir de cette situation, si vous le lancez avec loption -w. Par exemple, la deuxime et la troisime ligne ci-dessus donneront ce type de messages :
print () interpreted as function at - line 2. Useless use of integer multiplication (*) in void context at - line 2.

Avec la simple dfinition de certaines fonctions, vous avez une latitude considrable dans la manire de passer des arguments. Par exemple, la faon la plus habituelle dutiliser chmod est de passer les permissions du fichier (le mode) comme argument initial :
chmod 0644, @tableau;

mais la dfinition de chmod indique juste :


chmod LISTE

ainsi vous pouvez tout aussi bien crire :


unshift @tableau, 0644; chmod @tableau;

Si le premier argument de la liste nest pas un mode valide, chmod chouera, mais cest un problme smantique lexcution sans rapport avec la syntaxe de lappel. Si la smantique rclame des arguments spciaux donner en premier, le texte dcrira ces restrictions. Au contraire des simples fonctions de LISTE, dautres fonctions imposent des contraintes syntaxiques supplmentaires. Par exemple, push a un rsum de syntaxe comme ceci :
push TABLEAU, LISTE

Cela veut dire que push demande un tableau correct comme premier argument, mais ne tient pas compte des arguments suivants. Cest ce que signifie le LISTE la fin. (Les LISTE viennent toujours la fin, puisquelles englobent toutes les valeurs qui restent). Si le rsum de syntaxe contient des arguments avant la LISTE, ces arguments sont distingus syntaxiquement par le compilateur, et non seulement distingus smantiquement par linterprteur lorsquon le lancera plus tard. De tels arguments ne sont jamais valus dans un contexte de liste. Ils peuvent tre valus soit dans un contexte scalaire, soit ce sont des rfrences spciales comme le tableau dans push. (La description vous dira qui est qui.) Pour les oprations qui sont directement bases sur les fonctions de la bibliothque C, nous nessayerons pas de dupliquer la documentation de votre systme. Lorsque la description dune fonction demande de voir fonction(2), cela signifie que vous devez vous rfrer la version correspondante en C de cette fonction pour en savoir plus sur sa smantique. Le nombre entre parenthses indique la section du manuel de programmation systme dans laquelle vous trouverez la page man, si vous avez installez les pages man. (Et dans laquelle vous ne trouverez rien, si vous navez rien install.)

customer_8566

Fonctions

645

Ces pages de manuel peuvent documenter des comportements spcifiques de votre systme, comme les mots de passe shadow, les listes de contrle daccs et ainsi de suite. De nombreuses fonctions Perl drivent de la bibliothque C sous Unix mais sont mules mme sur les autres plates-formes. Par exemple, mme si votre systme dexploitation ne connat pas les appels systme flock(2) et fork(2), Perl fait de son mieux pour les muler avec les ressources natives de votre plate-forme. Parfois, vous constaterez que, dans la documentation, la fonction C reoit plus darguments que la fonction Perl correspondante. En gnral, les arguments supplmentaires sont dj connus par Perl, comme la longueur dun autre argument. Les autres diffrences viennent de la faon dont Perl et C spcifient les handles de fichiers, ainsi que les valeurs de succs et dchec. En gnral, les fonctions en Perl qui servent de sur-couches aux appels systme du mme nom (comme chown(2), fork(2), closedir(2), etc.) renvoient toutes une valeur vraie lorsquelle russissent, sinon undef comme indiqu dans les descriptions qui suivent. Ceci est diffrent des interfaces C ces oprations, lesquelles retournent toutes -1 en cas dchec. Les exceptions cette rgle sont wait, waitpid et syscall. Les appels systme positionnent aussi la variable spciale $! ($OS_ERROR). Les autres fonctions ne le font pas, except accidentellement. Pour les fonctions qui peuvent tre utilises aussi bien dans un contexte scalaire que dans un contexte de liste, un chec est gnralement indiqu dans un contexte scalaire en retournant une valeur fausse (en gnral undef) et dans un contexte de liste en retournant une liste vide. La russite de lopration est gnralement indique en renvoyant une valeur qui sera value comme vraie (dans le contexte). Retenez la rgle suivante : il ny a pas de rgle qui relie le comportement dune fonction dans un contexte de liste son comportement dans un contexte scalaire, ou vice versa. Il peut sagir de deux choses totalement diffrentes. Chaque fonction connat le contexte dans lequel elle a t appele. La mme fonction, qui renvoie une liste lorsquon lappelle dans un contexte de liste, retournera, lorsquon lappelle dans un contexte scalaire, la valeur qui lui semble la plus approprie. Certaines fonctions renvoient la longueur de la liste qui aurait t retourne dans un contexte de liste. Dautres fonctions retourne lautre valeur, lorsque quelque chose peut tre manipul, soit par un nombre, soit par son nom. Dautres encore renvoient un compteur des oprations qui ont russi. En gnral, les fonctions de Perl font exactement ce que vous voulez faire, moins que vous ne vouliez de la cohrence. Une dernire remarque : nous avons essay dtre trs cohrents dans notre emploi des termes octets et caractres. Historiquement, ces termes ont t confondus lun avec lautre (et avec eux-mmes). Mais lorsque nous disons octet, nous dsignons toujours un octet de 8 bits. Lorsque nous disons caractre, nous voulons dire un caractre dans son abstraction, gnralement un caractre Unicode, lequel peut tre reprsent dans vos chanes par un ou plusieurs octets. Mais notez que nous avons dit gnralement . Perl confond dessein les octets avec les caractres dans le contexte dune dclaration use bytes, ainsi chaque fois que nous parlons de caractre, vous devez comprendre un octet dans un contexte use bytes, sinon un caractre Unicode. En dautres termes, use bytes reprend la dfinition dun caractre telle quon la concevait dans les prcdentes versions de Perl. Ainsi, par exemple,

customer_8566

646

Chapitre 29 Fonctions

si nous disons quun reverse scalaire, inverse une chane caractre par caractre, ne nous demandez pas si cela veut vraiment dire caractres ou alors octets, car la rponse est : Oui .

Fonctions Perl par catgorie


Voici les fonctions de Perl et les mots-cls assimils, classs par catgorie. Certaines fonctions apparaissent sous plusieurs en-ttes. Manipulation de scalaires chomp, chop, chr, crypt, hex, index, lc, lcfirst, length, oct, ord, pack, q//, qq//, reverse, rindex, sprintf, substr, tr///, uc, ucfirst, y/// Expressions rationnelles et recherche de motifs m//, pos, qr//, quotemeta, s///, split, study Fonctions numriques abs, atan2, cos, exp, hex, int, log, oct, rand, sin, sqrt, srand Traitement des tableaux pop, push, shift, splice, unshift Traitement des listes grep, join, map, qw//, reverse, sort, unpack Traitement des hachages delete, each, exists, keys, values Entres et sorties binmode, close, closedir, dbmclose, dbmopen, die, eof, fileno, flock, format, getc, print, printf, read, readdir, readpipe, rewinddir, seek, seekdir, select (descripteurs de fichiers prts), syscall, sysread, sysseek, syswrite, tell, telldir, truncate, warn, write Donnes et enregistrements de longueur fixe pack, read, syscall, sysread, sysseek, syswrite, unpack, vec Handles de fichiers, fichiers et rpertoires chdir, chmod, chown, chroot, fcntl, glob, ioctl, link, lstat, mkdir, open, opendir, readlink, rename, rmdir, select (descripteurs de fichiers prts), select (handle du fichier de sortie), stat, symlink, sysopen, umask, unlink, utime Contrle de f lux des programmes caller, continue, die, do, dump, eval, exit, goto, last, next, redo, return, sub, wantarray Porte caller, import, local, my, no, our, package, use Divers defined, dump, eval, formline, lock, prototype, reset, scalar, undef, wantarray

customer_8566

Fonctions Perl par ordre alphabtique


Processus et groupes de processus

647

alarm, exec, fork, getpgrp, getppid, getpriority, kill, pipe,qx//, setpgrp, setpriority, sleep, system, times, wait, waitpid Modules de bibliothques do, import, no, package, require, use Classes et objets bless, dbmclose, dbmopen, package, ref, tie, tied, untie, use Accs aux sockets de bas niveau accept, bind, connect, getpeername, getsockname, getsockopt, listen, recv, send, setsockopt, shutdown, socket, socketpair Communications inter-processus System V msgctl, msgget, msgrcv, msgsnd, semctl, semget, semop, shmctl, shmget, shmread, shmwrite Recherches dinformations sur les groupes et les utilisateurs endgrent, endhostent, endnetent, endpwent, getgrent, getgrgid, getgrnam, getlogin, getpwent, getpwnam, getpwuid, setgrent, setpwent Recherches dinformations rseaux endprotoent, endservent, gethostbyaddr, gethostbyname, gethostent, getnetbyaddr, getnetbyname, getnetent, getprotobyname, getprotobynumber, getprotoent, getservbyname, getservbyport, getservent, sethostent, setnetent, setprotoent, setservent Date et heure gmtime, localtime, time, times

Fonctions Perl par ordre alphabtique


La plupart des fonctions suivantes sont annotes avec, euh, des annotations. Voici leur signification :

_ ! @ ? T t G O

Utilise $_ ($ARG) comme variable par dfaut. Modifie $! ($OS_ERROR) pour les erreurs dans les appels systme. Lve des exceptions ; utilisez eval pour intercepter $@ ($EVAL_ERROR). Modifie $? ($CHILD_ERROR) lorsque le processus fils se termine. Marque la donne retourne. Marque la donne retourne dans certains systmes, localement, ou configure manuellement. Lve une exception si un argument dun type inappropri est donn. Lve une exception si on modifie une cible en lecture seule.

customer_8566

648

Chapitre 29 Fonctions

X U

Lve une exception si on lalimente avec une donne marque. Lve une exception sil nexiste pas dimplmentation sur la plate-forme courante.

Les fonctions qui retournent une donne marque lorsquelles sont alimentes avec une donne marque ne sont elles-mmes pas marques, puisque cest le cas de la plupart des fonctions. En particulier, si vous utilisez nimporte quelle fonction avec %ENV ou @ARGV vous obtiendrez une donne marque. , Les fonctions annotes avec G lvent une exception lorsquelles attendent, mais ne reoivent pas, un argument dun type prcis (comme des handles de fichiers pour les oprations dentre/sortie, des rfrences pour bless, etc.). Les fonctions annotes avec O ont parfois besoin de modifier leurs arguments. Si elles ne peuvent pas modifier largument car il est marqu en lecture seule, elles lvent une exception. Des exemples de variables en lecture seule sont les variables spciales contenant une donne capture durant une recherche de motif et les variables qui sont en fait des alias de constantes. Les fonctions annotes avec U peuvent ne pas tre implmentes sur toutes les platesformes. Bien que la plupart dentre elles soient nommes daprs les fonctions de la bibliothque C sous Unix, ne croyez pas que vous ne pouvez en appeler aucune, seulement parce que vous ntes pas sous Unix. Beaucoup sont mules, mme celles que vous nespriez jamais voir comme fork sur les systmes Win32, qui est en place depuis la version 5.6 de Perl. Pour plus dinformations sur la portabilit et le comportement de fonctions spcifiques un systme, voir la page de man perlport, plus quelques documentations spcifiques la plate-forme fournie par votre portage de Perl. Les fonctions qui lvent dautres exceptions diverses et varies sont annotes avec @, y compris les fonctions mathmatiques qui mettent des erreurs dintervalle, comme sqrt(-1).

abs
abs VALEUR abs

Cette fonction renvoie la valeur absolue de son argument.


$diff = abs($premier - $second);

Remarque : ici et dans les exemples suivants, un bon style (et le pragma use strict) exigerait que vous ajoutiez un modificateur my pour dclarer une nouvelle variable de porte lexicale, comme ceci :
my $diff = abs($premier - $second);

Toutefois, nous avons omis my de la plupart de nos exemples pour plus de clart. Vous navez qu supposer quune telle variable a t dclare plus tt, si cela vous dmange.

accept
accept SOCKET, SOCKET_PROTO

!GU

Cette fonction est utilise par les processus serveurs qui dsirent se mettre en attente de

customer_8566

Fonctions Perl par ordre alphabtique

649

connexion de clients sur une socket. SOCKET_PROTO doit tre un handle de fichier dj ouvert via loprateur socket et attach lune des adresses rseau du serveur ou INADDR_ANY. Lexcution est suspendue jusqu ce quune connexion soit tablie, un handle de fichier SOCKET tant alors ouvert et attach la nouvelle connexion. Le handle original SOCKET_PROTO reste inchang ; son seul but est dtre cln dans une vritable socket. La fonction renvoie ladresse de la connexion si lappel russit, une valeur fausse sinon. Par exemple :
unless ($interlocuteur = accept(SOCK, SOCK_PROTO)) { die "Ne peut accepter la connexion : $!\n"; }

Sur les systmes qui lacceptent, le f lag close-on-exec sera positionn pour le nouveau descripteur de fichier ouvert, comme le veut la valeur de $^F ($SYSTEM_FD_MAX). Voir accept(2). Voir aussi lexemple dans la section Sockets au chapitre 16, Communication interprocessus.

alarm
alarm EXPR alarm

_U

Cette fonction envoie un signal SIGALRM au processus courant aprs EXPR secondes. Un seul minuteur (timer) peut tre actif un moment donn. Chaque appel dsactive le prcdent minuteur et un argument EXPR valant 0 peut tre fourni pour annuler le minuteur prcdent sans en lancer un de nouveau.
print "Rpondez en une minute ou allez en enfer : "; alarm(60); # tue le programme dans une minute $reponse = <STDIN>; $temps_restant = alarm(0) # efface lalarme print "Il vous reste $temps_restant secondes\n";

Une erreur courante est de mlanger les appels alarm et sleep, car nombre de systmes utilisent le mcanisme de lappel systme alarm(2) pour implmenter sleep(3). Sur des machines plus anciennes, le temps coul peut tre jusqu une seconde infrieur celui que vous avez spcifi, selon la manire dont sont comptes les secondes. De plus, un systme surcharg peut ne pas tre prt lancer votre processus immdiatement. Voir le chapitre 16 pour plus dinformations sur linterception de signaux. Pour des alarmes dune granularit plus fine que la seconde, vous pouvez utiliser la fonction syscall pour accder setitimer(2) si votre systme le supporte. Le module CPAN, Timer::HiRes offre aussi des fonctions dans cet objectif.

atan2
atan2 Y, X

Cette fonction renvoie la valeur principale de larctangente de Y/X dans lintervalle de -! !. Une moyen rapide dobtenir une valeur approche de ! est dcrire :
$pi = atan2(1, 1) * 4;

customer_8566

650

Chapitre 29 Fonctions

Pour la tangente, vous pouvez utiliser la fonction tan provenant soit du module Math::Trig, soit du module POSIX, ou employer la relation bien connue :
sub tan { sin($_[0] / cos($_[0]) }

bind
bind SOCKET, NOM

!GUX

Cette fonction attache une adresse (un nom) une socket dj ouverte, spcifie par le handle de fichier SOCKET. La fonction renvoie vrai si elle a russi, sinon faux. NOM doit tre une adresse empaquete de la socket avec le type appropri.
use Socket; $numero_port = 80; # prtend que nous voulons tre un serveur web $adresse_socket = sockaddr_in($numero_port, INADDR_ANY); bind SOCK, $adresse_socket or die "Impossible dattacher $numero_port : $!\n";

Voir bind(2). Voir aussi les exemples de la section Sockets au chapitre 16.

binmode
binmode HANDLE_FICHIER, DISCIPLINES binmode HANDLE_FICHIER

Cette fonction sarrange pour que le HANDLE_FICHIER ait la smantique spcifie par largument DISCIPLINES. Si lon omet DISCIPLINES, des smantiques binaires (ou raw ) sont appliques au handle de fichier. Si HANDLE_FICHIER est une expression, la valeur est prise de manire approprie, comme le nom du handle de fichier ou comme une rfrence un handle de fichier. La fonction binmode doit tre appele aprs lopen mais avant quune quelconque opration dentre/sortie sur le handle de fichier nait t effectue. Le seul moyen de rinitialiser le mode dun handle de fichier est de rouvrir le fichier, puisque les diverses disciplines ont pu conserver divers bits et segments de donnes dans diverses mmoires tampons. Cette restriction est susceptible dtre leve lavenir. Autrefois, binmode tait principalement utilis sur les systmes dexploitation dont les bibliothques dexcution distinguaient les fichiers textes des fichiers binaires. Sur ces systmes, lobjectif de binmode tait de dsactiver la smantique de texte par dfaut. De toute faon, depuis lavnement dUnicode, tous les programmes sur tous les systmes doivent connatre la distinction, mme sur les systmes Unix ou Mac. De nos jours, il nexiste quun type de fichiers binaire (du moins pour Perl), mais une multitude de types de fichiers texte. Ainsi, Perl ne connat quun seul format interne pour les textes Unicode, UTF-8. Puisquil existe une varit de fichiers texte, ceux-ci doivent souvent tre convertis en entre vers UTF-8 et en sortie vers le jeu de caractre dorigine ou vers une autre reprsentation dUnicode. Vous pouvez utiliser les disciplines pour indiquer Perl comment raliser exactement (ou inexactement) ces conversions.2
2. Plus prcisment, vous serez capable demployer les disciplines pour ceci, mais nous navons pas achev leur implmentation au moment o ces lignes sont crites.

customer_8566

Fonctions Perl par ordre alphabtique

651

Par exemple, une discipline de ":text" dira Perl de traiter les textes de faon gnrique sans prciser quel type de texte traiter. Mais des disciplines comme ":utf8" ou ":latin1" disent Perl quel format de texte lire et crire. Dun autre ct, la discipline ":raw" prvient Perl de garder ses sales mains en dehors des donnes. Pour en savoir plus sur le fonctionnement (ventuellement futur) des disciplines, voir la fonction open. La suite de cette discussion dcrit ce que binmode fait sans largument DISCIPLINES, cest-dire la signification historique de binmode, qui est quivalente :
binmode HANDLE_FICHIER, ":raw";

Sauf indication contraire, Perl suppose que votre fichier frachement ouvert doit tre lu ou crit en mode texte. Le mode texte signifie que \n (newline) est votre caractre fin de ligne interne. Tous les systmes utilisent \n comme leur caractre de fin de ligne interne mais ce quil reprsente rellement varie dun systme lautre, dun priphrique un autre et mme dun fichier un autre, selon la faon dont vous accder au fichier. Sur de tels systmes (comprenant MS-DOS et VMS), ce que votre programme voit comme un \n peut ne pas tre ce qui est stock physiquement sur le disque. Le systme dexploitation peut, par exemple, stocker des fichiers textes avec les squences \cM\cJ qui sont converties en entre pour apparatre comme \n dans votre programme et inversement convertir \n depuis votre programme vers \cM\cJ en sortie dans un fichier. La fonction binmode dsactive cette conversion automatique sur de tels systmes. En labsence dun argument DISCIPLINES, binmode na aucun effet sous Unix ou MAC OS, tous deux utilisant \n pour terminer chaque fin de ligne et reprsentant ceci avec un seul caractre. (Il peut sagir toutefois dune autre caractre : Unix utilise \cJ et les anciens Macs \cM. Mais cela ne porte pas consquence.) Les exemples suivants montrent comment un script Perl doit lire une image GIF depuis un fichier et lafficher sur la sortie standard. Sur les systmes qui autrement altreraient les donnes littrales en quelque chose dautre que leur exacte reprsentation physique, vous devez prparer les deux handles de fichiers. Alors que vous pourriez directement utiliser une discipline ":raw" pour ouvrir le fichier GIF, vous ne pouvez pas si facilement faire de mme avec les handles de fichiers dj ouverts, tels que STDOUT :
binmode STDOUT; open(GIF, "vim-power.gif") or die "Impossible douvrir vim-power.gif : $!\n"; binmode GIF; while (read(GIF, $buf, 1024)) { print STDOUT $buf; }

bless
bless REF, NOM_DE_CLASSE bless REF

Cette fonction indique lobjet sur lequel pointe REF quil est maintenant un objet du paquetage NOM_DE_CLASSE ou du paquetage courant si aucun NOM_DE_CLASSE nest spcifi. Si REF nest pas une rfrence valide, une exception est leve. Pour des raisons pratiques, bless retourne la rfrence, puisque cest souvent la dernire fonction dun constructeur. Par exemple :

customer_8566

652

Chapitre 29 Fonctions

$dromadaire = Animal->nouveau(TYPE => "Chameau", NOM => "amelia"); # puis dans Amimal.pm : sub nouveau { my $classe = shift; my %attrs = @_; my $obj = { %attrs }; return bless($obj, $classe); }

Vous devez gnralement consacrer les objets avec bless dans des NOMS_DE_CLASSE en majuscules et minuscules mlanges. Les espaces de noms tout entiers en minuscules sont rserv pour des besoins internes, comme les pragmas (directives de compilation) de Perl. Les types prdfinis (tels que SCALAR , ARRAY , HASH , etc., pour ne pas mentionner la classe de base de toutes les classes, UNIVERSAL ) sont tous en majuscules, alors peut-tre vaut-il mieux que vous vitiez des noms de paquetages crits ainsi. Assurez-vous que NOM_DE_CLASSE ne soit pas une valeur fausse, la conscration dans des paquetages faux nest pas supporte et peut conduire des rsultats imprvisibles. Ce nest pas un bug quil ny ait pas doprateur curse correspondant. (Mais il existe un oprateur sin, jeu de mot intraduisible, loprateur sin soccupant de la fonction sinus et non dun quelconque blasphme.) Voir aussi le chapitre 12, Objet, pour en savoir plus sur la bndiction (et les conscrations) des objets.

caller
caller EXPR caller

Cette fonction renvoie des informations concernant la pile dappels en cours de sousprogrammes et assimils. Sans argument, elle renvoie le nom du paquetage, le nom du fichier et le numro de ligne do la routine en cours dexcution a t appele :
($paquetage, $fichier, $ligne) = caller;

Voici un exemple dune fonction extrmement fastidieuse, qui utilise les tokens spciaux __PACKAGE__ et __FILE__ dcrit au chapitre 2, Composants de Perl :
sub attention { my ($paquetage, $fichier) = caller; unless ($paquetage eq __PACKAGE__ && $file eq __FILE__) { die "Vous ntes pas suppos mappeller, $paquetage !\n"; } print "Appelez-moi en toute tranquillit\n"; } sub appel_tranquille { attention(); }

Appele avec un argument, caller interprte EXPR comme tant le nombre de groupes dlments dans la pile (stack frames) remonter avant la routine courante. Par exemple,

customer_8566

Fonctions Perl par ordre alphabtique

653

un argument de 0 signifie llment courant dans la pile ; 1, la routine appelante ; 2, la routine appelante de la routine appelante ; et ainsi de suite. La fonction renvoie galement des informations supplmentaires, comme le montre lexemple suivant :
$i = 0; while (($paquetage, $fichier, $ligne, $routine, $args_presents, $tableau_demande, $texte_eval, $est_requis, $indications, $masque_de_bits) = caller($i++)) { ... }

Si llment est un appel de sous-programme, $args_presents est vrai sil possde son propre tableau @_ (et non un qui soit emprunt la routine qui la appel). Sinon, $routine peut valoir "(eval)" si llment nest pas un appel de sous-programme mais un eval. Si cest le cas, les informations supplmentaires $texte_eval et $est_requis sont positionnes : $est_requis est vrai si llment est cr par une instruction require ou un use, et $texte_eval contient le texte de linstruction eval EXPR. Plus particulirement, pour une instruction eval BLOCK, $fichier vaut "(eval)", mais $texte_eval est indfini. (Remarquez galement que chaque instruction use cre un lment require dans un lment eval EXPR.) $indications et $masque_de_bits sont des valeurs internes ; vous tes pris de les ignorer moins que vous ne soyez membre de la thaumatocratie. Dans un esprit de magie encore plus pousse, caller positionne galement le tableau @DB::args avec les arguments pass llment donn de la pile mais seulement lorsquon lappelle depuis le paquetage DB. Voir le chapitre 20, Le dbogueur Perl.

chdir
chdir EXPR chdir

!X

Cette fonction change le rpertoire de travail du processus courant en EXPR, si cela est possible. Si EXPR est omise, on utilise le rpertoire de base de lutilisateur. La fonction renvoie vraie si elle russit, sinon faux.
chdir "$prefixe/lib" or die "Impossible de faire un cd dans $prefixe/lib\n";

Voir aussi le module Cwd, dcrit au chapitre 32, Modules standard, qui vous permet de garder automatiquement une trace de votre rpertoire courant.

chmod
chmod LISTE

!X

Cette fonction modifie les permissions dune liste de fichiers. Le premier lment de la liste doit tre le mode numrique, comme dans lappel systme chmod(2). La fonction renvoie le nombre de fichiers modifis avec succs. Par exemple :
$compt = chmod 0755, fichier1, fichier2;

affectera 0, 1 ou 2 $compt, selon le nombre de fichiers modifis. Lopration est juge russie par labsence derreur et non par un vritable changement, car un fichier peut

customer_8566

654

Chapitre 29 Fonctions

avoir le mme mode quavant lopration. Une erreur signifie vraisemblablement que vous manquez de privilges suffisants pour changer le mode du fichier car vous ntes ni son propritaire, ni le super-utilisateur. Vrifiez $! pour dcouvrir la cause relle de lchec. Voici une utilisation plus typique :
chmod(0755, @executables) == @executables or die "Modification impossible de certains lments de @executables : $!";

Si vous devez connatre quels fichiers nont pas pu tre changs, crivez quelque chose comme ceci :
@immuables = grep {not chmod 0755, $_} fichier1, fichier2, fichier3; die "$0 : impossible dexcuter chmod @immuables\n" if @immuables;

Cet idiome utilise la fonction grep pour ne slectionner que les lments de la liste pour lesquels la fonction chmod a chou. Lorsque des donnes non littrales sont utilises pour le mode, vous pouvez avoir besoin de convertir une chane octale en un nombre dcimal en utilisant la fonction oct. Ceci car Perl ne devine pas automatiquement quune chane contient un nombre octal seulement parce quelle commence par un 0 .
$MODE_DEFAUT = 0644; # On ne peut pas utiliser de guillemets ici ! PROMPT: { print "Nouveau mode ? "; $chaine_mode = <STDIN>; exit unless defined $chaine_mode; # test de fin de fichier if ($chaine_mode =~ /^\s*$/ { # test de ligne blanc $mode = $MODE_DEFAUT; } elsif ($chaine_mode !~ /^\d+$/) { print "Demande un mode numrique, $chaine_mode invalide\n"; redo PROMPT; } else { $mode = oct($chaine_mode); # convertit "755" en 0755 } chmod $mode, @fichiers; }

Cette fonction marche avec des modes numriques comme dans lappel systme Unix chmod(2). Si vous voulez une interface symbolique comme celle fournie par la commande chmod(1), voir le module File::chmod de CPAN. Vous pouvez aussi importer les constantes symboliques S_I* du module Fcntl :
use Fcntl :mode; chmod S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH, @executables;

Certains considrent que ceci est plus lisible quavec 0755. Maintenant, cest vous de voir.

customer_8566

Fonctions Perl par ordre alphabtique

655

chomp
chomp VARIABLE chomp LISTE chomp

_O

Cette fonction supprime (normalement) un saut de ligne la fin dune chane contenue dans une variable. Il sagit dune fonction lgrement plus sre que chop (dcrite ci-dessous) en ce quelle na pas deffet sur une chane ne se terminant pas par un saut de ligne. Plus prcisment, elle supprime la fin dune chane correspondant la valeur courante de $/, et non nimporte quel caractre de fin. linverse de chop, chomp renvoie le nombre de caractres supprims. Si $/ vaut "" (en mode paragraphe), chomp enlve tous les caractres de fin de ligne la fin de la chane slectionne (ou des chanes si lon chompe une LISTE). Vous ne pouvez pas chomper un littral, seulement une variable. Par exemple :
while (<PASSWD>) { chomp; # vite davoir \n dans le dernier champ @tableau = split /:/; ... }

Avec la version 5.6, la signification de chomp change lgrement en ce que les disciplines en entre peuvent prendre le dessus sur la valeur de la variable $/ et affecter la manire dont les chanes doivent tre chompes . Ceci a lavantage quune discipline en entre peut reconnatre plus dune varit de dlimiteur de ligne (comme un paragraphe Unicode et les sparateurs de ligne), mais chompe encore en toute scurit tout ce qui termine la ligne courante.

chop
chop VARIABLE chop LISTE chop

_O

Cette fonction coupe le dernier caractre dune chane et renvoie le caractre coup. Loprateur chop est utilis en premier lieu pour couper le caractre fin de ligne la fin dun enregistrement en entre, mais est plus efficace quune substitution. Si cest tout ce que vous en faites, alors il est plus sr dutiliser chomp, puisque chop tronque toujours la chane dun caractre quel quil soit, alors que chomp est plus slectif. Vous ne pouvez pas choper un littral, seulement une variable. Si vous chopez une LISTE de variables, chacune des chanes de la liste est coupe :
@lignes = cat mon_fichier; chop @lignes;

Vous pouvez choper tout ce qui est une lvalue, y compris une affectation :
chop($rep_courant = pwd); chop($reponse = <STDIN>);

customer_8566

656
Ce qui est diffrent de :
$reponse = chop($tmp = <STDIN>); # MAUVAIS

Chapitre 29 Fonctions

qui met un caractre fin de ligne dans $reponse puisque chop renvoie le caractre limin et non la chane rsultante (qui se trouve dans $tmp). Une manire dobtenir le rsultat voulu est dutiliser substr :
$reponse = substr <STDIN>, 0, -1;

Mais on lcrit plus frquemment :


chop($reponse = <STDIN>);

La plupart du temps, on peut exprimer chop en termes de substr :


$dernier_caractere = chop($var); $dernier_caractere = substr($var, -1, 1, ""); # la mme chose

Une fois que vous aurez compris cette quivalence, vous pourrez lutiliser pour faire des coupes plus volues. Pour couper plus dun caractre, utilisez substr comme une lvalue, en assignant une chane vide. Ce qui suit enlve les cinq derniers caractres de $caravane :
substr($caravane, -5) = "";

Le paramtre ngatif fait partir substr de la fin de la chane au lieu du dbut. Si vous voulez rcuprer les caractres ainsi enlevs, vous pouvez employer la forme quatre arguments de substr, crant ainsi quelque chose comme un quintuple chop :
$queue = substr($caravane, -5, 5, "");

chown
chown LISTE

!UX

Cette fonction change le propritaire et le groupe dune liste de fichiers. Les deux premiers lements de la liste doivent tre les UID et GID numriques, dans cet ordre. Une valeur de -1, dans lune ou lautre position, est interprte par la plupart des systmes en conservant la valeur inchange. La fonction renvoie le nombre de fichiers modifis avec succs. Par exemple :
($compt = chown($uidnum, $gidnum, fichier1, fichier2)) == 2 or die "chown impossible pour fichier1 ou fichier2 : $!";

mettra $compt 0, 1 ou 2, selon le nombre de fichiers modifis (dans le sens o lopration sest droule avec succs, et non selon que le propritaire est diffrent aprs coup). Voici une utilisation plus typique :
chown($uidnum, $gidnum, @fichiers) == @fichiers or die "Modification impossible de @fichiers avec chown : $!";

Voil un sous-programme qui accepte un nom dutilisateur, vrifie les UID et GID pour vous, puis effectue le chown :
sub chown_avec_le_nom { my ($utilisateur, @fichiers) = @_; chown((getpwnam($utilisateur))[2,3], @fichiers) == @fichiers or die "chown impossible pour @fichiers : $!";

customer_8566

Fonctions Perl par ordre alphabtique


} chown_avec_le_nom("larry", glob("*.c"));

657

Cependant, il se peut que vous ne vouliez pas modifier le groupe ainsi que le fait la fonction prcdente, car le fichier /etc/passwd associe chaque utilisateur, un groupe unique mme si cet utilisateur peut tre membre de plusieurs groupes secondaires dans /etc/groups. Dans ce cas, vous pouvez passer -1 pour le GID, ce qui laisse inchang le groupe du fichier. Si vous passez -1 comme UID et un GID valide, vous pouvez affecter le groupe sans changer lutilisateur. Sur la plupart des systmes, vous navez la permission de changer le propritaire du fichier que si vous tes le super-utilisateur, bien que vous puissiez changer le groupe en nimporte lequel de vos groupes secondaires. Sur des systmes peu srs, ces restrictions peuvent tre assouplies, mais cette supposition nest pas gnralisable. Sur les systmes POSIX, vous pouvez dtecter quelle rgle sapplique ainsi :
use POSIX qw(sysconf _PC_CHOWN_RESTRICTED); # essayez seulement si vous tes le super-utilisateur # ou sur un systme permissif if ($> == 0 || !sysconf(_PC_CHOWN_RESTRICTED)) { chown($uidnum, -1, $fichier) or die "chown de $fichier $uidnum impossible : $!";

chr
chr NOMBRE chr

Cette fonction renvoie le caractre reprsent par ce NOMBRE dans le jeu de caractres. Par exemple, chr(65) vaut A en ASCII comme en Unicode, et chr(0x263a) est un smiley Unicode. Pour obtenir linverse de chr, utilisez ord. Si vous prfrez spcifier votre caractre par son nom plutt que par un nombre (par exemple, "\N{WHITE SMILING FACE}" pour un smiley Unicode), voir charname au chapitre 31, Modules de pragmas.

chroot
chroot FICHIER chroot

_!UX

En cas de succs, FICHIER devient le nouveau rpertoire racine pour le processus courant, le point de dpart des noms de chemin commenant par / . Ce rpertoire est hrit par appels exec et par tous les sous-processus forks aprs lappel chroot. Il ny a aucun moyen de revenir ltat prcdent un chroot. Pour des raisons de scurit, seul le super-utilisateur peut utiliser cette fonction. Voici un morceau de code ressemblant approximativement ce que font de nombreux serveurs FTP :
chroot((getpwnam(ftp))[7] or die "Ftp anonyme impossible : $!\n";

Il est improbable que cette fonction marche sur des systmes non-Unix. Voir chroot(2).

customer_8566

658

Chapitre 29 Fonctions

close
close HANDLE close

!?G

Cette fonction ferme le fichier, la socket ou le pipe associ au HANDLE. (Elle ferme le handle de fichier actuellement slectionn si largument est omis.) Elle renvoie vrai si la fermeture se droule avec succs, sinon faux. Vous navez pas besoin de fermer HANDLE si vous le rouvrez immdiatement, puisque le open suivant le ferme automatiquement pour vous. (Voir open.) Cependant, un close explicite sur un fichier en entre remet zro le compteur de lignes ($.), ce qui nest pas le cas de la fermeture implicite effectue par open. HANDLE peut tre une expression dont la valeur peut tre employe en tant que handle de fichier indirect (soit le non rel du handle de fichier, soit une rfrence tout ce qui peut tre interprt comme un objet handle de fichier.) Si le handle de fichier vient dune ouverture de pipe, close renverra faux si un appel systme sous-jacent choue ou si le programme lautre extrmit du pipe se termine avec un statut non nul. Dans ce dernier cas, le close force la variable $! ($OS_ERROR) zro. Donc, si un close sur un pipe renvoie un statut non nul, vrifiez $! pour dterminer si le problme vient du pipe lui-mme (valeur non nulle) ou du programme lautre bout du pipe (valeur nulle). Dans tous les cas, $? ($CHILD_ERROR) contient la valeur de statut dattente (N.d.T. : wait status ; voir son interprtation la fonction system) de la commande associe lautre extrmit du pipe. Par exemple :
open(SORTIE, | sort -rn | lpr -p) # or die "Impossible de dmarrer le print SORTIE @lignes; # close SORTIE # or warn $! ? "Erreur systme lors : "Statut dattente du pipe pour sort et lpr pipe sortlpr : $!"; imprime des choses sur la sortie attend que le sort finisse de la fermeture du pipe sortlpr : $!" pipe sortlpr $?";

Un handle de fichier produit, en dup(2)liquant un pipe, est trait comme un handle de fichier ordinaire, ainsi close nattendra pas le fils pour ce handle de fichier. Vous devez attendre le fils en fermant le handle de fichier dorigine. Par exemple :
open(NESTSTAT, "netstat -rn |") or die "Impossible de lancer netstat : $!"; open (STDIN, "<&NETSTAT") or die "Impossible de dupliquer vers stdin : $!";

Si vous fermez le STDIN ci-dessus, il ny aura pas dattente ; par contre, il y en aura si vous fermez NETSTAT. Si vous vous dbrouillez dune manire ou dune autre pour rcolter vous-mme un pipe fils qui sest termin, le close chouera. Ceci peut arriver si vous avez votre propre gestionnaire pour $SIG{CHLD} qui se dclenche lorsque le pipe fils se termine, ou si vous appelez intentionnellement waitpid avec lidentifiant de processus renvoy par lappel de open.

customer_8566

Fonctions Perl par ordre alphabtique

659

closedir
closedir HANDLE_REP

!GU

Cette fonction ferme un rpertoire ouvert par opendir et renvoie la russite de lopration. Voir les exemples de readdir. HANDLE_REP peut tre une expression dont la valeur peut tre employe en tant que handle de rpertoire indirect, gnralement le non rel du handle du rpertoire.

connect
connect SOCKET, NOM

!GXU

Cette fonction dmarre une connexion avec un autre processus qui attend par un accept. La fonction renvoie vrai si elle russit, faux sinon. NOM doit tre une adresse rseau binaire du type correspondant celui de la socket. Par exemple, en supposant que SOCK soit une socket cre pralablement :
use Socket; my ($distant, $port) = ("www.perl.com", 80); my $adr_dest = sockaddr_in($port, inet_aton($distant)); connect SOCK, $adr_dest or die "Connexion impossible vers $distant sur le port $port : $!";

Pour dconnecter une socket, utilisez soit close, soit shutdown. Voir aussi les exemples de la section Sockets au chapitre 16. Voir connect(2).

cos
cos EXPR cos

Cette fonction renvoie le cosinus de EXPR (exprime en radians). Par exemple, le script suivant affiche une table des cosinus dangles mesurs en degrs :
# Voici la manire de ne pas se fatiguer pour convertir de degrs en radians $pi = atan2(1,1) * 4; $pi_apres_180 = $pi/180; # Affiche la table for ($deg = 0; $deg <= 90; $deg++) { printf "%3d %7.5f\n", $deg, cos($deg * $pi_apres_180); }

Pour lopration cosinus inverse, vous pouvez utilisez la fonction acos() des modules Math::Trig ou POSIX, ou encore utiliser cette relation :
sub acos { atan2( sqrt(1 - $_[0] * $_[0]), $_[0] ) }

customer_8566

660

Chapitre 29 Fonctions

crypt
crypt TEXTE_EN_CLAIR, PERTURBATION

Cette fonction calcule le hachage non bijectif dune chane exactement comme le fait crypt(3). Ceci savre trs utile pur vrifier que le fichier de mots de passe nen contient pas qui soient trop faibles3, bien que ce que vous vouliez rellement faire est dempcher les gens de commencer en ajouter de mauvais. crypt se veut une fonction non bijective, un peu comme casser des ufs pour faire une omelette. Il nexiste aucun moyen (connu) de dcrypter un mot de passe chiffr, moins dessayer de deviner toutes les combinaisons de manire exhaustive. Lorsque vous vrifiez une chane crypte existante, vous devez utiliser le texte chiffr en tant que PERTURBATION (comme crypt($texte_en_clair, $crypte) eq $crypte). Ceci permet votre code de fonctionner avec le crypt standard ainsi quavec dautres implmentations plus exotiques. Lorsque vous choisissez une nouvelle PERTURBATION, vous avez au moins besoin de crer une chane de deux caractres alatoires appartenant lensemble [./0-9A-Za-z] (comme join , (., /, 0..9, A..Z, a..z)[rand 64, rand 64]). Les anciennes implmentations de crypt avaient seulement besoin des deux premiers caractres de PERTURBATION, mais le code qui donnait seulement les deux premiers caractres est maintenant considr comme non portable. Voir votre page de manuel locale de crypt(3) pour des dtails intressants. Voici un exemple qui sassure que quiconque lanant ce programme connat son propre mot de passe :
$mot_de_passe = (getpwuid ($<))[1] system "stty -echo"; print "Mot de passe : "; chomp($mot = <STDIN>); print "\n"; system "stty echo"; # Suppose que lon soit sur Unix. # ou regarder Term::Readkey dans CPAN

if (crypt($mot, $mot_de_passe) ne $mot_de_passe) { print "Dsol\n"; } else { print "ok\n"; }

Il est bien sr dconseill de donner votre mot de passe quiconque le demande car cest imprudent. Les mots de passes cachs sont lgrement plus srs que les fichiers de mots de passe traditionnels et vous devez tre le super-utilisateur pour y accder. Comme peu de programmes doivent tourner avec des privilges si puissants, il se peut que le programme maintienne son propre systme dautentification indpendant en stockant les chanes cryptes dans un fichier autre que /etc/passwd ou /etc/shadow.
3. Seules les personnes qui ont des intentions louables sont autorises faire ceci.

customer_8566

Fonctions Perl par ordre alphabtique

661

La fonction crypt nest pas adapte au chiffrement de grandes quantits de donnes, au moins parce que vous ne pouvez pas retrouver en sens inverse linformation en clair. Regardez dans les rpertoires by-module/Crypt et by-module/PGP de votre miroir favori de CPAN pour trouver un grand nombre de modules potentiellement utiles.

dbmclose
dbmclose HACHAGE

!U

Cette fonction brise le lien entre un fichier DBM (DataBase Management, gestion de base de donnes) et un hachage. dbmclose nest en fait quun appel untie avec les bons arguments, mais est fournie pour des raisons de compatibilit avec les anciennes versions de Perl.

dbmopen
dbmopen HACHAGE, NOMDB, MODE

!U

Relie un fichier DBM un hachage. (DBM signifie DataBase Management, gestion de base de donnes, et consiste en un ensemble de routines de bibliothque C qui permettent un accs direct des enregistrements via un algorithme de hachage.) HACHAGE est le nom de la base de donnes (sans lextension .dir ou .pg). Si la base de donnes nexiste pas et quun MODE valide est spcifi, la base de donnes est cre avec les protections spcifies par MODE, modifi par le umask. Pour empcher la cration de la base donnes au cas o elle nexiste pas, il est possible de spcifier un mode valant undef, et la fonction renverra faux si elle ne peut trouver de base existante. Les valeurs associes au hachage avant le dbmopen ne sont plus accessibles. La fonction dbmopen nest en fait quun appel tie avec les arguments appropris, mais elle est fournie pour des raisons de compatibilit avec les anciennes versions de Perl. Vous pouvez contrler quelle est bibliothque DBM utiliser en employant directement linterface tie ou en chargeant le module appropri avant dappeler open. Voici un exemple qui fonctionne sur certains systmes pour les versions de DB_file similaires celle de votre navigateur Netscape :
use Db_file; dbmopen(%NS_hist, "$ENV{HOME}/.netscape/history.dat", undef) or die "Impossible douvrir le fichier dhistorique de netscape : $!"; while (($url, $quand) = each %NS_hist) { next unless defined($quand); chop ($url, $quand); # supprime les octets nuls fin printf "Dernire visite de %s le %s.\n", $url, scalar(localtime(unpack("V", $quand))); }

Si vous navez pas daccs au fichier DBM en criture, vous pourrez seulement lire les variables du hachage sans les modifier. Pour tester si vous pouvez crire, utilisez soit un test de fichier comme -w, soit essayez de modifier une entre dans un hachage bidon lintrieur dun eval {}, ce qui interceptera lexception. Les fonctions comme keys et values peuvent renvoyer une importante liste de valeurs

customer_8566

662

Chapitre 29 Fonctions

lorsquon les utilise avec de grands fichiers DBM. Vous prfrerez sans dote utiliser la fonction each pour les parcourir itrativement et ne pas tout charger dun bloc en mmoire. Les hachages lis des fichiers DBM ont les mmes limitations que le type de paquetage DBM que vous utilisez, notamment pour ce qui concerne la dimension de ce quon peut mettre dans une cellule (bucket). Si vous vous restreignez des clefs et des valeurs courtes, cela ne constitue que rarement un problme. Voir aussi le module DB_file au chapitre 32. Une autre chose dont il faut tenir compte est que de nombreuses bases de donnes DBM existantes contiennent des clefs et des valeurs termines par un caractre nul car elles ont t conues pour tre exploites par des programmes C. Le fichier dhistorique de Netscape et le fichier dalias des anciens sendmail en sont des exemples. Il vous suffit dutiliser "$key\0" lorsque vous extrayez une valeur, puis de supprimer le caractre nul dans cette dernire.
$alias = $les_alias{"postmaster\0"}; chop $alias; # supprime le caractre nul

Il nexiste lheure actuelle aucun moyen intgr de verrouiller un fichier DBM gnrique. Certains pourraient considrer quil sagit dun bogue. Le module GDBM_file permet lui de verrouiller lensemble du fichier. En cas de doute, il vaut mieux utiliser un fichier verrou spar.

defined
defined EXPR defined

Cette fonction renvoie une valeur boolenne selon que EXPR contient une valeur dfinie ou non. La plupart des donnes que vous manipulez sont dfinies, mais un scalaire qui ne contient ni de chane valide, ni valeur numrique, ni de rfrence est considr contenir la valeur indfinie, ou pour abrger undef. Initialiser une variable scalaire une valeur particulire la rendra dfinie et elle restera dfinie jusqu ce que vous lui assigniez une valeur indfinie ou que vous appeliez explicitement undef avec cette variable comme paramtre. De nombreuses oprations renvoient undef dans des conditions exceptionnelles, comme une fin de fichier, une variable non initialise, une erreur systme, etc. Puisque undef nest quun type de valeur fausse, un simple test boolen ne fait pas de distinction entre undef, le chiffre zro, la chane vide et la chane dun seul caractre, 0 toutes ces valeurs sont fausses de la mme manire. La fonction defined vous permet de distinguer entre une chane vide indfinie et une chane vide dfinie lorsque vous employez des oprateurs susceptibles de renvoyer une vritable chane vide. Voici un morceau de code qui teste une valeur scalaire dun hachage :
print if defined $option{D};

Lorsquon lutilise sur un lment de hachage comme ceci, defined ne fait quindiquer si la valeur est dfinie, et non si la clef possde une entre dans le hachage. Il est possible davoir une clef dont la valeur est indfinie ; cependant la clef elle-mme existe. Utilisez exist pour dterminer si une clef de hachage existe.

customer_8566

Fonctions Perl par ordre alphabtique

663

Dans lexemple suivant, nous exploitons la convention qui fait que certaines oprations renvoient une valeur indfinie lorsquil ny a plus de donnes.
print "$val\n" while defined($val = pop(@tableau));

Et dans celui-ci, nous faisons la mme chose avec la fonction getpwent pour obtenir des informations propos des utilisateurs du systme :
setpwent(); while (defined($nom = getpwent())) { print "< <$nom> >\n"; } endpwent();

Il en va de mme pour les erreurs renvoyes par les appels systme qui peuvent lgitimement renvoyer une valeur fausse :
die "readlink $sym impossible : $!" unless defined($valeur = readlink $sym);

Vous pouvez galement utiliser defined pour dterminer si un sous-programme a dores et dj t dfini. Ceci vite de se surcharger avec des sous-programmes inexistants (ou des sous-programmes qui on t dclars mais jamais dfinis) :
indirect("nom_fonction", @liste_args); sub indirect { my $nom_routine = shift; no strict refs; # ainsi nous pouvons utiliser # nom_routine indirectement if (defined &$nom_routine) { &$nom_routine(@_); # ou $nom_routine->(@_); } else { warn "Appel ignor une fonction invalide $nom_routine"; } }

Lutilisation de defined sur les agrgats (hachages et tableaux) est dprcie. (On lutilisait pour savoir si la mmoire pour cet agrgat avait jamais t alloue.) la place, employez un simple test boolen pour voir si si le tableau ou le hachage possde des lments :
if (@un_tableau) { print "tableau possdant des lments\n"; if (%un_hachage) { print "hachage possdant des lments\n";

Voir aussi undef et exists.

delete
delete EXPR

Cette fonction supprime un lment (ou une tranche dlments) dans le hachage ou le tableau spcifi. (Voir unlink si vous voulez supprimer un fichier.) Les lments supprims sont renvoys dans lordre spcifi, bien que ce comportement ne soit pas garanti dans le cas de variables lies comme les fichiers DBM. Aprs la suppression, la fonction exists renverra faux pour toute clef ou indice supprim. ( loppos, aprs la fonction undef, la fonction exists continue de renvoyer vrai, car la fonction undef ne fait que rendre indfinie la valeur dun lment, mais ne supprime pas llment lui-mme.)

customer_8566

664

Chapitre 29 Fonctions

Supprimer dans le hachage %ENV modifie lenvironnement. Les supprimer dans un hachage qui est li un fichier DBM (dans lequel on a les droits en criture) supprime lentre dans ce fichier DBM. Historiquement, vous pouviez seulement supprimer dans un hachage, mais avec Perl version 5.6 vous pouvez galement supprimer dans un tableau. Une suppression dans un tableau a pour consquence que llment la position spcifie retourne dans un tat non initialis, mais sans combler le vide, puisque ceci modifierait les positions de toutes les entres suivantes. Utilisez un splice pour cela. (Toutefois, si vous supprimez le dernier lment dun tableau, la taille de celui-ci diminuera de un ou plus, selon la position de llment existant prcdent sil y en a.) EXPR peut tre arbitrairement complexe, pourvu que lopration ultime soit une consultation de hachage ou de tableau :
# installation dun tableau de tableau de hachage $donjon[$x][$y] = \%proprietes; # supprimer une proprit dans le hachage delete $donjon[$x][$y]{OCCUPE} # supprimer trois proprits dans le hachage dun seul coup delete @{ $donjon[$x][$y] }{ "OCCUPE", "HUMIDE", "ECLAIRE" }; # supprimer la rfrence %proprietes dans le tableau delete $donjon[$x][$y];

Lexemple naf qui suit supprime toutes les valeurs dun %hachage de manire inefficace :
foreach $clef (keys %hachage) { delete $hachage{$clef}; }

De mme que celui-ci :


delete @hachage{keys %hachage};

Mais ces deux exemples sont plus lents que si lon assigne simplement au hachage la liste vide ou quon le rende indfini :
%hachage = (); undef %hachage; # vide entirement %hachage # oublie que %hachage a jamais exist

Il en va de mme pour les tableaux :


foreach $indice (0.. $#tableau) { delete $tableau[$indice]; }

et :
delete @tableau[0 .. $#tableau];

sont moins efficaces que :


@tableau = (); undef @tableau; # vide entirement @tableau # oublie que @tableau a jamais exist

customer_8566

Fonctions Perl par ordre alphabtique

665

die
die LISTE die

Hors dun eval, cette fonction affiche la valeur concatne de LISTE sur STDERR et sort avec la valeur courante de $! (la variable errno de la bibliothque C). Si $! vaut 0, elle sort avec la valeur de $? >> 8 (qui est le statut du dernier fils rcolt depuis un system, un wait, un close sur un pipe, ou une commande). Si $? >> 8 vaut 0, elle sort avec 255. lintrieur dun eval, la fonction met le message derreur qui aurait autrement t produit dans la variable $@, puis elle interrompt le eval, qui renvoie undef. La fonction die peut ainsi tre utilise pour lever des exceptions nommes susceptibles dtre exploites un plus haut niveau dans le programme. Voir eval plus loin dans ce chapitre. Si LISTE est une rfrence vers un objet unique, cet objet est suppos tre un objet exception et il est renvoy sans modification comme lexception dans $@. Si LISTE est vide et que $@ contient dj une chane (provenant gnralement dun prcdent eval), cette chane est rutilise en lui ajoutant "\t...propagated". Ceci est utile pour propager (lever nouveau) des exceptions :
eval { ... }; die unless $@ =~ /Exception attendue/;

Si LISTE est vide et que $@ contient dj un objet exception, la mthode $@->PROPAGATE est appele pour dterminer comment lexception doit tre propage. Si LISTE est vide ainsi que $@, la chane "Died" est utilise. Si la valeur finale de LISTE ne se termine pas par un saut de ligne (et que vous ne passez pas dobjet exception), le nom du script courant, le numro de ligne et le numro de ligne du fichier dentre (sil existe) sont ajouts au message, ainsi quun saut de ligne. Astuce : quelque fois, le fait dajouter ", stopped" votre message le rendra plus explicite quand la chane "at nom_de_script line 123" lui sera ajoute. Supposons que vous lanciez le script canasta ; considrez la diffrence entre les deux manires suivantes de mourir :
die "/usr/games ne vaut rien"; die "/usr/games ne vaut rien, stopped";

qui produisent respectivement :


/usr/games ne vaut rien at canasta line 123. /usr/games ne vaut rien, stopped at canasta line 123.

Si vous dsirez que vos propres messages donnent le nom de fichier et le numro de ligne, employez les tokens spciaux __FILE__ et __LINE__ :
die ", __FILE__, ", ligne , __LINE__, ", hou la honte !\n";

La sortie ressemblera alors :


"canasta", ligne 38, hou la honte !

Une autre question de style considrez les exemples quivalents suivants :


die "Impossible de faire un cd vers le spool : $!\n" unless chdir /usr/spool/news;

customer_8566

666

Chapitre 29 Fonctions

chdir /usr/spool/news or die "Impossible de faire un cd vers le spool : $!\n";

Comme la partie importante est le chdir, on prfre gnralement la seconde forme. Voir galement exit, warm, %SIG et le module Carp.

do (bloc)
do BLOC

La forme do BLOC excute la squence de commandes indique par BLOC et renvoie la valeur de la dernire expression value dans le bloc. Lorsquelle est modifie par une instruction while ou until, Perl excute le BLOC une fois avant de tester la condition de sortie. (Pour dautres instructions, les modificateurs de boucle testent la condition en premier.) Le do BLOC lui-mme ne compte pas comme une boucle, ainsi les instructions de contrle de boucle next, last ou redo ne peuvent pas tre utilises pour quitter ou recommencer le bloc. Voir la section Blocs simples au chapitre 4, Instruction et dclaration, pour contourner ce problme.

do ( fichier)
do FICHIER

La forme do FICHIER utilise la valeur de FICHIER comme nom de fichier et excute son contenu comme un script Perl. Son usage premier est (ou plutt tait) dinclure des sous-programmes depuis une bibliothque Perl, de sorte que :
do stat.pl;

est identique :
scalar eval cat stat.pl; #type stat.pl sur Windows

sauf que la premire forme est plus efficace, plus concise, elle garde la trace du nom de fichier courant pour les messages derreur, cherche dans tous les rpertoires du tableau @INC et met jour %INC si le fichier est trouv. (Voir au chapitre 28, Noms spciaux.) Elle diffre galement dans le fait que le code valu avec do FICHIER ne peut pas voir les variables lexicales dans la porte qui lenglobe, linverse du code dans eval FICHIER. Mais elle est pourtant similaire la seconde en ce quelle rescrute le fichier chaque appel, et il vaut mieux ne pas lemployer dans une boucle moins que le nom du fichier lui-mme change chaque itration. Si do ne peut pas lire le fichier, elle renvoie undef et met lerreur dans $!. Si do peut lire le fichier mais pas le compiler, elle retourne undef et met un message derreur dans $@. Si le fichier est compil avec succs, do renvoie la valeur de la dernire expression value. Linclusion de modules de bibliothques (qui ont obligatoirement un suffixe .pm) est mieux gre par les oprateurs use et require, qui contrlent les erreurs et lvent une exception sil y a un problme. Ils ont galement dautres avantages : ils vitent de dupliquer le chargement, facilitent la programmation oriente objet et fournissent des indications au compilateur sur les prototypes de fonctions. Mais do FICHIER est toujours utile pour des choses comme la lecture de fichiers de con-

customer_8566

Fonctions Perl par ordre alphabtique


figuration. On peut faire un contrle derreur manuel comme ceci :

667

# lit dans les fichiers de configuration : systme dabord, # ensuite utilisateur for $fichier ("/usr/share/projet/defaut.rc", "$ENV{HOME}/.programmerc") { unless ($retour = do $fichier) { warn "Impossible de scruter $fichier : $@" if $@; warn "Impossible de faire do $fichier : $!" unless defined $retour; warn "Impossible de lancer $fichier" unless $retour; } }

Un dmon qui doit tourner longtemps peut priodiquement examiner la date de son fichier de configuration, et si le fichier a t modifi depuis sa dernire lecture, le dmon peut utiliser do pour recharger le fichier. Il est plus propre de le faire avec do quavec require ou use.

do (sous-programme)
do SOUS-PROGRAMME(LISTE)

La forme do SOUS-PROGRAMME(LISTE) est une forme dprcie dappel dun sous-programme. Une exception est leve si le SOUS-PROGRAMME nest pas dfini. Voir le chapitre 6, Sous-programmes.

dump
dump LABEL dump

Cette fonction provoque un core dump immdiat. En premier lieu, ceci vous permet dutiliser le programme undump(1) (non fourni) pour transformer le fichier de copie rsultant en un binaire excutable aprs avoir initialis toutes les variables au dbut du programme. Quand le nouveau binaire sera excut, il commencera par un goto LABEL (avec toutes les restrictions inhrentes goto). On peut voir le processus complet comme un saut inconditionnel avec un core dump, suivi dune rincarnation. Si LABEL est omis, le programme repart du dbut. Attention : tout fichier ouvert au moment de la copie avec dump, ne le sera plus au moment de la rincarnation du programme, do une possible confusion de la part de Perl. Voyez galement loption de ligne de commande -u au chapitre 19, Interface de la ligne de commande. Cette fonction est maintenant tout fait obsolte, en partie parce quil est extrmement difficile de convertir un core dump en un binaire dans le cas gnral, et parce que les divers compilateurs gnrant du bytecode portable ou du C compilable lont surpass. Si vous dsirez utiliser dump pour acclrer vos programmes, allez voir la discussion concernant les questions defficacit au chapitre 24, Usage courant, ainsi que le compilateur en code natif au chapitre 18, Compilation. Lautochargement peut galement prsenter un certain intrt, en ce quil semble acclrer lexcution.

customer_8566

668

Chapitre 29 Fonctions

each
each HACHAGE

Cette fonction parcours pas pas un hachage raison dune paire clef/valeur la fois. Appele dans un contexte de liste, each renvoie une liste deux lments compose de la clef et de la valeur de lentre suivante dun hachage, il vous est ainsi possible de circuler dans la liste toute entire. Appele dans un contexte scalaire, each renvoie seulement la clef de lentre suivante du hachage. Quand le hachage est entirement lu, elle renvoie la liste vide, qui produit une valeur fausse lorsquelle est assigne dans un contexte scalaire, comme un test de boucle. Lappel suivant each redmarrera une nouvelle itration. On lutilise gnralement comme dans lexemple suivant qui utilise le hachage prdfini %ENV :
while (($clef, $valeur) = each %ENV) { print "$clef=$valeur\n"; }

En interne, un hachage conserve ses entres dans un ordre apparemment alatoire. La fonction each boucle le long de cette squence car chaque hachage se souvient de lentre renvoye en dernier. Lordre rel de cette squence est susceptible de changer dans les prochaines versions de Perl, mais il est garanti quil sera identique celui que renverrait la fonction keys (ou values) avec le mme hachage (sans modification). Il existe un itrateur unique pour chaque hachage, partag par tous les appels aux fonctions each, keys et values du programme ; on peut le remettre zro en lisant tous les lments du hachage, ou en valuant keys %hachage ou values %hachage. Si vous ajoutez ou supprimez des lements dun hachage pendant quil y a une itration sur celuici, les consquences ne sont pas bien dfinies : des entres peuvent tre passes ou dupliques. Voir aussi keys, values et sort.

eof
eof HANDLE_FICHIER eof() eof

Cette fonction renvoie vrai si la lecture suivante sur HANDLE_FICHIER renverra une fin de fichier, ou si HANDLE_FICHIER nest pas ouvert. HANDLE_FICHIER peut tre une expression dont la valeur donne le vrai nom du handle de fichier. Un eof sans argument renvoie le statut de fin de fichier pour le dernier fichier lu. Un eof() avec des parenthses vides teste le handle de fichier ARGV (plus gnralement rencontr en tant que handle de fichier nul dans <>). Ainsi, lintrieur dune boucle while (<>), un eof() avec parenthses ne dtectera la fin que du dernier dun groupe de fichiers. Utilisez eof (sans parenthses) pour tester chacun des fichiers dans une boucle while (<>). Par exemple le code suivant insre des tirets juste avant la dernire ligne du dernier fichier :
while (<>) { if (eof()) { print "-" x 30, "\n"; }

customer_8566

Fonctions Perl par ordre alphabtique


print; }

669

Pour sa part, ce script remet zro la numrotation des lignes pour chaque fichier dentre :
# remet zro la numrotation des lignes pour chaque fichier dentre while (<>) { next if /^\s*#/; # passe les commentaires print "$.\t$_"; } continue { close ARGV if eof; # Et non eof() ! }

De mme que $ dans un programme sed, eof brille particulirement dans les numrotations de lignes par zones. Voici un script qui affiche les lignes de /motif/ la fin de chaque fichier dentre :
while (<>) { print if /motif/ .. eof; }

Ici, loprateur de bascule (..) value la correspondance du motif chaque ligne. Jusqu ce que le motif corresponde, loprateur renvoie faux. Quand la correspondance est enfin trouve, loprateur commence par renvoyer vrai, provoquant ainsi laffichage des lignes. Quand loprateur eof renvoie finalement vrai ( la fin du fichier examin), loprateur de bascule se remet zro et renvoie de nouveau faux pour le prochain fichier dans @ARGV. Attention : la fonction eof lisant un octet puis le remettant dans le f lux dentre avec ungetc(3), elle nest pas trs utile dans un contexte interactif. En fait, les programmeurs Perl expriments utilisent rarement eof, puisque les divers oprateurs dentre se comportent plutt bien dans les expressions conditionnelles des boucles while. Reportezvous lexemple de la description de foreach au chapitre 4.

eval
eval BLOC eval EXPR eval

_X

Le mot-cl eval dessert en Perl deux buts diffrents mais nanmoins lis. Ces buts sont reprsents par deux formes de syntaxe, eval BLOC et eval EXPR. La premire forme intercepte les exceptions lexcution (erreurs) qui auraient sinon provoqu une erreur fatale, de la mme manire quun bloc try en C++ ou en Java. La seconde forme compile et excute de petits morceaux de code la vole et intercepte galement (et cest bien commode) les exceptions exactement comme la premire forme. Mais la seconde forme sexcute beaucoup plus lentement que la premire, puisquelle doit analyser la chane chaque fois. Dun autre ct, elle est aussi plus gnrique. Quelle que soit la forme que vous utilisez, eval est la manire standard dintercepter les exceptions en Perl. Pour chacune des formes, la valeur renvoye par eval est celle de la dernire expression

customer_8566

670

Chapitre 29 Fonctions

value, tout comme dans un sous-programme. Vous pouvez de mme utiliser loprateur return pour renvoyer une valeur au beau milieu de leval. Lexpression gnrant la valeur de retour est value dans un contexte vide, scalaire ou de liste, selon le contexte de leval lui-mme. Voir wantarray pour plus dinformations sur la manire de dterminer un contexte. Sil se produit une erreur interceptable (y compris une erreur engendre par loprateur die), eval renvoie undef et met le message derreur (ou lobjet) dans $@. Sil ny a pas derreur, $@ est garantie contenir la chane vide, vous pouvez ainsi dtecter les erreurs aprs coup de manire fiable. Un simple test boolen suffit.
eval { ... }; if ($@) { ... } # intercepte les erreurs lexcution # gre les erreurs

La forme eval BLOC est vrifie syntaxiquement durant la compilation, ce qui la rend assez performante. (Cela trouble de temps autre les personnes habitues la forme lente eval EXPR.) Puisque le code du BLOC est valu la compilation en mme temps que le code qui lentoure, cette forme deval ne peut pas intercepter les erreurs de syntaxe. La forme eval EXPR peut quant elle intercepter les erreurs syntaxiques car elle analyse le code durant lexcution. (Si lanalyse choue, elle met lerreur analyse dans $@, comme dhabitude.) Sinon, elle excute la valeur de EXPR comme si ctait un petit programme Perl. Le code est excut dans le contexte courant du programme Perl, ce qui signifie quil peut voir toutes les variables lexicales de la porte qui lenglobe, tout comme les dfinitions de sous-programmes ou de formats. Le code de leval est trait en tant que bloc, toute variable de porte locale dclare lintrieur de leval nexiste donc que le temps de leval. (Voir my et local.) Comme dans tout code lintrieur dun bloc, il ny a pas besoin de point-virgule la fin. Voici un simple script Perl. Il demande lutilisateur dentrer une chane arbitraire de code Perl, la compile, lexcute et affiche les ventuelles erreurs qui se sont produites :
print "\nEntrer du code Perl : "; while (<STDIN>) { eval; print $@; print "\nEntrer nouveau du code Perl : "; }

Voici un programme rename pour changer le nom dune quantit de fichiers en utilisant une expression Perl :
#!/usr/bin/perl # rename - change les noms des fichiers $op = shift; for (@ARGV) { $ancien = $_; eval $op; die if $@; # la prochaine ligne appelle la fonction interne Perl, # non le script du mme nom rename($ancien, $_) unless $ancien eq $_; }

customer_8566

Fonctions Perl par ordre alphabtique


Vous pouvez utiliser ce programme comme ceci :
$ rename s/\.orig$// *.orig $ rename y/A-Z/a-z/ unless /^Make/ * $ rename $_ .= ".bad" *.f

671

Puisqueval intercepte des erreurs qui sinon seraient fatales, il est trs utile pour dterminer si une fonctionnalit donne (comme fork ou symlink) est implmente. Comme un eval BLOC est vrifi syntaxiquement la compilation, toute erreur de syntaxe est reporte en amont. Ainsi, si votre code est invariant et qu la fois un eval EXPR et un eval BLOC vous conviennent, la dernire forme est la meilleure. Par exemple :
# rend la division par zro non fatale eval { $reponse = $a / $b; }; warn $@ if $@; # idem, mais moins performant si on lexcute plusieurs fois eval $reponse = $a / $b; warn $@ if $@; # une erreur de syntaxe la compilation (non intercepte) eval { $reponse = }; # MAUVAIS # une erreur de syntaxe lexcution eval $reponse =; # positionne $@

Ici, le code du BLOC doit tre un code Perl valide pour passer la phase de compilation. Le code de lEXPR nest pas examin avant lexcution, il ne produit donc pas derreur avant dtre excut. Le bloc dun eval BLOCK ne compte pas comme une boucle, ainsi les instructions de contrle de boucle next, last et redo ne peuvent pas tre employes pour sortir ou recommencer le bloc.

exec
exec CHEMIN LISTE exec LISTE

!X

La fonction exec termine le programme courant, excute une commande externe et nen revient jamais !!! Utilisez system au lieu de exec si vous voulez reprendre le contrle aprs la la fin de la commande. La fonction exec choue et renvoie faux seulement si la commande nexiste pas et si elle est excute directement et non par lintermdiaire dune commande shell de votre systme (nous en discuterons plus loin). Sil ny a quun seul argument scalaire, celui-ci est inspect pour y chercher des mtacaractres du shell. Sil y en a, largument est tout entier pass linterprteur de commandes standard du shell (/bin/sh sous Unix). Sinon, largument est dcompos en mots et excut directement dans un souci defficacit, puisquon conomise ainsi la surcharge due au traitement du shell. Cela vous donne galement plus de contrle sur la reprise derreur si jamais le programme nexistait pas. Sil y a plus dun argument dans la LISTE, ou si LISTE est un tableau avec plus dune valeur, le shell du systme ne sera jamais utilis. Ceci vite galement tout traitement de la commande par le shell. La prsence ou labsence de mtacaractres dans les argu-

customer_8566

672

Chapitre 29 Fonctions

ments naffecte pas ce comportement dclench par la liste, ce qui en fait la forme idale pour des programmes soucieux de la scurit, ne voulant pas sexposer des fuites potentielles dans le shell. Cet exemple entrane le remplacement du programme Perl en train de tourner par le programme echo, qui affiche la liste darguments courante :
exec echo, Vos arguments sont :, @ARGV;

Cet autre exemple montre que vous pouvez executer un pipeline et non uniquement un seul programme :
exec "sort $fichier_sortie | uniq" or die "Impossible de faire un sort/uniq : $!\n";

exec ne revient gnralement jamais si cest le cas, il retourne toujours faux et vous devez vrifier $! pour savoir ce qui sest mal pass. Remarquez que dans les anciennes versions de Perl, exec (et system) ne vidaient pas votre tampon de sortie, vous deviez donc activer le vidage du tampon de commande en positionnant $| sur un ou plusieurs handles de fichier pour viter la perte de la sortie dans le cas dexec, ou une sortie dsordonne dans le cas de system. La version 5.6 de Perl remdie largement cette situation. Lorsque vous demandez au systme dexploitation dexcuter un nouveau programme lintrieur dun processus existant (comme le fait la fonction exec de Perl), vous indiquez au systme o se trouve le nouveau programme excuter, mais vous donnez aussi au nouveau programme ( travers son premier argument) le nom sous lequel il a t invoqu. Habituellement, le nom que vous donnez est juste une copie de lendroit o se trouve le programme, mais vous ny tes pas ncessairement obligs, puisquil y a deux arguments distincts au niveau du langage C. Lorsquil ne sagit pas dune copie, vous obtenez comme curieux rsultat que le nouveau programme croit quil est lanc sous un nom qui peut tre compltement diffrent du vritable chemin dans lequel il rside. Cela na souvent pas de consquences pour le programme en question, mais certains programmes y font attention et adoptent une personnalit diffrente selon ce quils pensent tre leur nom. Par exemple, lditeur vi regarde sil a t appel avec vi ou avec view . Sil a t invoqu avec view , il se met automatiquement en mode lecture seule, exactement comme sil avait t appel avec loption de la ligne de commande -R. Voil o le paramtre optionnel CHEMIN de exec entre en jeu. Syntaxiquement, il vient se brancher sur la position dun objet indirect comme le handle de fichier pour print ou printf. Ainsi, il ny a pas de virgule aprs lui car il ne fait pas exactement partie de la liste darguments. (En un sens, Perl adopte lapproche oppose du systme dexploitation en ce quil suppose que le premier argument est le plus important et quil vous laisse modifier le chemin sil diffre.) Par exemple :
$editeur = "/usr/bin/vi"; exec $editeur "view", @fichiers # active le mode lecture seule or die "Impossible dexcuter $editeur : $!\n";

Comme avec tout objet indirect, vous pouvez galement remplacer le simple scalaire contenant le nom du programme avec un bloc contenant du code arbitraire, ce qui simplifie lexemple prcdent en donnant :
exec { "/usr/bin/vi" } "view" @fichiers # active le mode lecture seule or die "Impossible dexcuter /usr/bin/vi : $!\n";

customer_8566

Fonctions Perl par ordre alphabtique

673

Comme nous lavons dj voqu, exec traite une liste discrte darguments comme une indication quil doit viter le traitement du shell. Toutefois, il y a un endroit o vous pourriez tre drouts. Lappel exec (et galement system) ne distingue pas un unique argument scalaire dun tableau ne contenant quun seul lment.
@args = ("echo surprise"); # une liste un seul lment exec @args # toujours sujet aux fuites du shell or die "exec : $!\n"; # car @args == 1

Pour viter ceci, vous pouvez utiliser la syntaxe avec CHEMIN, en dupliquant exactement le premier argument dans le chemin, ce qui force linterprtation du reste des arguments tre une liste, mme sil ny en a quun seul :
exec { args[0] } @args # scuris mme si la liste na quun argument or die "exec @args impossible : $!";

La premire version, celle avec les parenthses, lance le programme echo en lui passant surprise comme argument. La seconde version ne fait pas la mme chose elle tente de lancer un programme appel littralement echo surprise, ne le trouve pas (du moins on lespre) et positionne $! une valeur non nulle indiquant lchec. Comme la fonction exec est le plus souvent utilise peu aprs un fork, on suppose que lon doit passer outre tout ce qui survient normalement lorsquun processus Perl se termine. Sous un exec, Perl nappellera pas les blocs END, ni les mthodes DESTROY associes aux objets. Sinon, vos processus fils se termineraient en faisant le nettoyage alors que vous vous attendiez ce que ce soit le processus parent qui le fasse. (Nous aimerions que ce soit le cas dans la vie relle.) Comme cest une erreur courante dutiliser exec au lieu de system, Perl vous en avertit si la prochaine instruction nest pas die, warn ou exit, lorsquil est lanc avec loption populaire de la ligne de commande -w, ou si vous employez le pragma use warnings qw(exec syntax). Si vous voulez vraiment faire suivre un exec dune autre instruction, vous pouvez utiliser lun ou lautre de ces styles pour viter lavertissement :
exec (machin) or print STDERR exec machin impossible : $!"; { exec (machin) }; print STDERR exec machin impossible : $!";

Comme dans la seconde ligne ci-dessus, un appel exec qui est la dernire instruction dans un bloc est exempt de cet avertissement. Voir aussi system.

exists
exists EXPR

Cette fonction renvoie vrai si la clef de hachage ou lindice de tableau spcifi existe dans le hachage ou le tableau. Peu importe que la valeur correspondante soit vraie ou fausse, ou mme quelle soit dfinie.
print print print print print print "Vraie\n" "Dfinie\n" "Existe\n" "Vrai\n" "Dfini\n" "Existe\n" if if if if if if $hachage{$clef}; defined $hachage{$clef}; exists $hachage{$clef}; $tableau[$indice]; defined $tableau[$indice]; exists $tableau[$indice];

customer_8566

674

Chapitre 29 Fonctions

Un lment ne peut tre vrai que sil est dfini, et ne peut tre dfini que sil existe, mais linverse nest pas forcment valable. EXPR peut tre arbitrairement complexe, tant que lopration finale est une consultation de clef de hachage ou dindice de tableau.
if (exists $hachage{A}{B}{$clef}) { ... }

Bien que le dernier lment ne vienne pas exister spontanment seulement parce quon a test son existence, cest le cas de ceux que lon fait intervenir. Ainsi, $$hachage{"A"} et $hachage{"A"}->{"B"} se mettent tous deux exister. Ce nest pas une fonctionnalit de exists en soi ; cela se produit partout o loprateur f lche est utilis (explicitement ou implicitement) :
undef $ref if (exists $ref->"Une clef"}) { } print $ref; # affiche HASH(0x80d3d5c)

Mme si llment "Une clef" ne se met pas exister, la variable $ref, indfinie auparavant, vient tout coup contenir un hachage anonyme. Cest une instance surprise dautovivification de ce qui napparaissait pas au premier ou mme au second coup dil comme un contexte lvalue. Ce comportement sera agrablement corrig dans une prochaine version. Autrement, vous pouvez emboter vos appels :
if ($ref and exists $ref->[$x] and exists $ref->[$x][$y] and exists $ref->[$x][$y]{$clef} and exists $ref->[$X][$y]{$clef}[2] ) { }

Si EXPR est le nom dun sous-programme, la fonction exists renverra vrai si celui-ci est a t dclar, mme sil na pas encore t dfini. Lexemple suivant affiche seulement Existe :
sub couic; print "Existe\n" if exists &couic; print "Dfini\n" if defined &couic;

Lutilisation dexists avec le nom dun sous-programme peut tre utile pour un sousprogramme AUTOLOAD qui a besoin de savoir si un paquetage particulier veut quun sousprogramme particulier soit dfini. Le paquetage peut indiquer ceci en dclarant un entte de sub comme couic.

exit
exit EXPR exit

Cette fonction value EXPR comme un entier et sort immdiatement avec cette valeur comme statut derreur final du programme. Si EXPR est omise, la fonction sort avec le statut 0 (signifiant aucune erreur ). Voici un fragment qui permet un utilisateur de sortir du programme en entrant x ou X.
$rep = <STDIN>; exit if $rep =~ /^[Xx]/;

Vous ne devriez pas utiliser exit pour quitter un sous-programme sil y a la moindre chance que quelquun veuille intercepter lerreur qui sest produite. Utilisez plutt die,

customer_8566

Fonctions Perl par ordre alphabtique

675

qui peut tre intercept par un eval. Ou alors, utilisez lune des sur-couches de die du module Carp, comme croak ou confess. Nous avons dit que la fonction exit sortait immdiatement, mais ctait un mensonge darracheur de dents. Elle sort aussitt que possible, mais elle appelle tout dabord les routines END dfinies afin les grer les vnements de fin (N.d.T. : at-exit). Ces routines ne peuvent pas annuler la terminaison, bien quelles puissent changer la valeur de retour ventuelle en positionnant la variable $?. De la mme manire, toute classe qui dfinit une mthode DESTROY peut invoquer cette mthode au nom de tous ses objets avant que le programme rel ne finisse. Si vous avez vraiment besoin doutrepasser le traitement avant la terminaison, vous pouvez appeler les fonctions _exit du module POSIX pour viter toutes les oprations de END et des destructeurs. Et si POSIX nest pas disponible, vous pouvez faire un exec "/bin/false" ou quelque chose de ce genre.

exp
exp EXPR exp

Cette fonction renvoie e la puissance EXPR. Pour obtenir la valeur de e, utilisez juste exp(1). Pour effectuer une exponentiation gnrale de diffrentes bases, utilisez loprateur ** que nous avons emprunt au FORTRAN :
use Math::Complex; print -exp(1) ** (i * pi); # affiche 1

fcntl
fcntl HANDLE_FICHIER, FONCTION, SCALAIRE

!GOXU

Cette fonction appelle les fonctions de contrle de fichier de votre systme dexploitation, documentes dans la page de man de fnctl(2). Avant dappeler fcntl, vous devrez probablement tout dabord crire :
use Fcntl;

pour charger les dfinitions correctes des constantes. SCALAIRE sera lu ou crit (ou les deux) selon la FONCTION. Un pointeur sur la valeur de chane de SCALAIRE sera pass comme troisime argument de lappel vritable fcntl. (Si SCALAIRE na pas de valeur chane mais une valeur numrique, celle-ci sera passe directement au lieu dun pointeur sur la valeur chane.) Voir le module Fcntl pour une description des valeurs les plus communes quil est possible demployer pour FONCTION. La fonction fcntl lvera une exception si elle est utilise sur un systme qui nimplmente pas fcntl(2). Sur les systmes qui au contraire limplmentent, vous pouvez faire des choses comme modifier les f lags close-on-exec (si vous ne dsirez pas jouer avec la variable $^F ($SYSTEM_FD_MAX)), modifier les f lags dentres/sorties non bloquantes, muler la fonction lockf (3) ou sarranger pour recevoir un signal SIGIO lorsquil y a des entres/sorties en attente. Voici un exemple o lon rend non bloquant au niveau du systme, un handle de fichier nomm DISTANT. Ceci fait que toute opration dentre revient immdiatement si rien nest disponible lors dune lecture dans un pipe, une socket ou une ligne srie qui autre-

customer_8566

676

Chapitre 29 Fonctions

ment aurait bloqu. De mme, les oprations de sortie qui bloqueraient normalement, renvoient un statut dchec la place. (Pour celles-ci, vous feriez mieux de ngocier galement $|.)
use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK); $flags = fcntl(DISTANT, F_GETFL, 0) or die "Impossible de lire les flags pour la socket : $!\n"; $flags = fcntl(DISTANT, F_SETFL, $flags | O_NONBLOCK) or die "Impossible de modifier les flags de la sockets : $!\n";

La valeur de retour de fcntl (et de ioctl) se comporte comme ceci :


Lappel systme renvoie -1 0 autre chose Perl renvoie undef. La chane 0 but true . Le mme nombre.

Perl rend donc vrai pour un succs et faux pour un chec, tout en vous laissant facilement dterminer la vritable valeur renvoye par le systme dexploitation :
$valret = fcntl() || -1; printf "fcntl a vraiment renvoy %d\n", $valret;

Ici, mme la chane 0 but true affiche 0, grce au format %d. Cette chane est vraie dans un contexte boolen et 0 dans un contexte numrique. (Par bonheur, elle est galement exempte des avertissements habituels pour les conversions numriques inadaptes.)

fileno
fileno HANDLE_FICHIER

Cette fonction renvoie le descripteur de fichier sous-jacent dun handle de fichier. Si ce handle de fichier nest pas ouvert, fileno renvoie undef. Un descripteur de fichier est un petit entier positif comme 0 ou 1, alors que les handles de fichiers comme STDIN ou STDOUT sont des symboles. Malheureusement, le systme dexploitation ne connat pas vos sympathiques symboles. Il ne pense aux fichiers ouverts quen terme de ces petits numros de fichiers et bien que Perl fasse automatiquement la traduction pour vous, vous devrez parfois connatre le vritable descripteur de fichier. Ainsi, par exemple, la fonction fileno est utile pour construire des masques de bits pour select et pour passer certains appels systme obscurs si syscall(2) est implment. Elle sert galement vrifier que la fonction open vous a donn le descripteur de fichier que vous vouliez et galement dterminer si deux handles de fichiers utilisent le mme descripteur de fichier systme.
if (fileno(CECI) == fileno(CELA)) { print "CECI et CELA sont des duplicata\n"; }

Si HANDLE_FICHIER est une expression, sa valeur est prise comme un handle de fichier

customer_8566

Fonctions Perl par ordre alphabtique

677

indirect, gnralement son nom ou une rfrence quelque chose qui ressemble un objet handle de fichier. Attention : ne comptez pas sur une association entre un handle de fichier Perl et un descripteur de fichier numrique qui soit permanente tout au long de la vie du programme. Si un fichier a t ferm et rouvert, le descripteur de fichier peut changer. Perl sefforce dassurer que certains descripteurs de fichiers ne sont pas perdus si un open sur eux choue, mais il ne fait cela que pour les descripteurs de fichiers qui ne dpassent pas la valeur courante de la variable spciale $^F ($SYSTEM_MAX_FD) (par dfaut, 2). Bien que les handles de fichiers STDIN, STDOUT et STDERR dmarrent avec les descripteurs de fichiers 0, 1 et 2 (la convention standard Unix), mme ceux-ci peuvent changer si vous commencez les fermer et les ouvrir sans prendre garde. Ceci dit, vous ne pouvez pas avoir dennuis avec 0, 1 et 2 aussi longtemps que vous les rouvrez toujours immdiatement aprs les avoir ferms. La rgle de base sur les systmes Unix est de prendre le descripteur disponible le plus bas possible, et ce sera celui que vous venez juste de fermer.

f lock
flock HANDLE_FICHIER, OPRATION

!GU

La fonction flock est linterface portable de Perl pour le verrouillage de fichiers, bien quelle ne verrouille un fichier que dans son intgralit et non des enregistrements. La fonction gre les verrous sur le fichier associ HANDLE_FICHIER, en renvoyant vrai pour un succs et faux sinon. Pour viter la possibilit de perdre des donnes, Perl vide le tampon de votre HANDLE_FICHIER avant de le verrouiller ou de le dverrouiller. Perl peut implmenter son flock avec flock(2), fcntl(2), lockf (3) ou des mcanismes de verrouillage spcifiques dautres plate-formes, mais si aucun dentre eux nest disponible, appeler flock lve une exception. Voir la section Verrouillage de fichier au chapitre 16. OPRATION peut valoir LOCK_SH, LOCK_EX ou LOCK_UN, combins ventuellement par un OU avec LOCK_NB. Ces constantes valent gnralement 1, 2, 8 et 4, mais vous pouvez employer les noms symboliques si vous les importez depuis le module Fcntl, soit individuellement, soit par groupe en utilisant le tag :flock. LOCK_SH demande un verrou partag, il est donc gnralement utilis pour les lectures. LOCK_EX demande un verrou exclusif, il est donc gnralement utilis pour les critures. LOCK_UN relche un verrou demand auparavant ; fermer le fichier relche galement ses verrous. Si le bit LOCK_NB est employ avec LOCK_SH ou LOCK_EX, flock rend la main immdiatement au lieu dattendre un verrou indisponible. Vrifiez le statut de retour pour voir si vous avez obtenu le verrou que vous avez demand. SI vous nutilisez pas LOCK_NB, vous pouvez attendre indfiniment laccs au verrou. Un autre aspect difficile, mais gnral, de flock est que ses verrous sont simplement consultatifs. Les verrous discrets sont plus f lexibles mais offrent moins de garanties que les verrous obligatoires. Cela signifie que les fichiers verrouills avec flock peuvent tre modifis par les programmes qui nutilisent pas flock. Les voitures qui sarrtent aux feux rouges sentendent bien entre elles, mais pas avec celles qui ne sarrtent pas aux feux rouges. Conduisez sur la dfensive. Certaines implmentations de flock ne peuvent pas verrouiller quoique ce soit travers un rseau. Bien quen thorie vous puissiez utiliser fcntl, plus spcifique au systme, pour cela, le jury (ayant dlibr sur le cas pendant peu prs une dcennie) est tou-

customer_8566

678

Chapitre 29 Fonctions

jours indcis pour dterminer si cest une chose digne de confiance ou non. Voici un exemple qui ajoute un message la fin dune bote aux lettres sur les systmes Unix qui utilisent flock(2) pour verrouiller les botes aux lettres :
use Fcntl qw/:flock/ # importer les constantes FLOCK_* sub mon_verrou { flock(MBOX, LOCK_EX) or die "Impossible de verrouiller la bote aux lettres : $!"; # dans le cas ou quelquun ajoutait quelque chose alors que #nous tions en train dattendre et que notre tampon stdio ne # soit pas synchronis seek(MBOX, 0, 2) or die "Impossible de se positionner la fin de la bote aux lettres : $!"; } open(MBOX, "> >/usr/spool/mail/$ENV{USER}") or die "Impossible douvrir la bote aux lettres : $!"; mon_verrou(); print MBOX $msg, "\n\n"; close MBOX or die "Impossible de fermer la bote aux lettres : $!";

Sur les systmes qui supportent un appel systme flock(2) rel, les verrous sont hrits travers les appels fork. Les autres implmentations ne sont pas aussi chanceuses et sont susceptibles de perdre les verrous travers les forks. Voir galement le module DB_File au chapitre 32 pour dautres exemples de flock.

fork
fork

!U

Cette fonction cre deux processus partir dun seul en invoquant lappel systme fork(2). En cas de russite, la fonction renvoie lID du nouveau processus fils au processus parent et 0 au processus fils. Si le systme ne dispose pas des ressources suffisantes pour allouer un nouveau processus, lappel choue et retourne undef. Les descripteurs de fichiers (et parfois les verrous sur ces descripteurs) sont partags, alors que tout le reste est copi ou moins parat ltre. Dans les versions de Perl antrieures 5.6, les tampons non vids le restent dans les deux processus, ce qui veut dire quil vous faut parfois positionner $| sur un ou plusieurs handles de fichiers lavance pour viter des sorties dupliques. Voici une faon de blinder presque totalement le lancement dun processus fils tout en testant les erreurs de type fork impossible :
use Errno qw(EAGAIN); FORK: { if ($pid = fork) { # on est ici dans le pre # le pid du processus fils est accessible par $pid }

customer_8566

Fonctions Perl par ordre alphabtique


elsif (defined $pid) { # $pid vaut ici 0 sil dfini # on est ici dans le fils # le pid du processus pre est accessible par getppid } elsif ($! == EAGAIN) { # EAGAIN est lerreur de fork susceptible dtre corrige sleep 5; redo FORK; } else { # erreur de fork trange die "fork impossible :$!\n"; } }

679

Ces prcautions ne sont pas ncessaires pour des oprations qui font un fork(2) implicite, comme system, les apostrophes inverses ou louverture dun processus comme un handle de fichier, car Perl ressaye automatiquement un fork en cas dchec dans ces cas. Faites trs attention terminer le code du fils par un exit, faute de quoi le fils pourrait quitter par inadvertance le bloc conditionnel et commencer excuter du code prvu pour le seul processus pre. Si vous forkez sans mme attendre vos enfants, vous accumulerez les zombies (les processus termins qui nont toujours pas de parents qui les attendent). Sur certains systmes, vous pouvez viter ceci en positionnant $SIG{CHLD} "IGNORE" ; sur la plupart, vous devrez attendre avec wait vos enfants moribonds. Vous en trouverez des exemples dans la description de la fonction wait, ou dans la section Signaux du chapitre 16. Si un fils fork hrite des descripteurs fichiers systmes comme STDIN ou STDOUT qui sont connects un pipe distant ou une socket, il se peut que vous deviez les redirigez vers /dev/null dans le fils. Ceci car mme lorsque le processus pre se termine, le fils vivra avec ses copies de ces handles de fichiers. Le serveur distant (mettons comme un script CGI ou une tche lance en arrire plan par un shell distant) semblera bloquer car il attendra que toutes les copies soient fermes. Rouvrir les handles de fichiers systmes en les dirigeant vers autre chose corrige ceci. Sur la plupart des systmes supportant fork(2), on a port une attention toute particulire ce que la fonction soit performante (par exemple, utilisant une technologie de copie en criture sur les pages de donnes), ce qui en fait le paradigme dominant de ces dernires dcennies pour le multitche. La fonction fork est susceptible de ne pas tre implmente efficacement, voire de ne pas tre implmente du tout, sur les systmes qui ne ressemblent pas Unix. Par exemple, Perl 5.6 mule un fork appropri sur les systmes de Microsoft, mais sans assurance sur les performances ce jour. Vous pouvez avoir plus de chances ici avec le module Win32::Process.

format
format NOM = ligne dimage liste de valeurs ... .

customer_8566

680

Chapitre 29 Fonctions

Cette fonction dclare une squence nomme de lignes dimages (avec les valeurs associes) lusage de la fonction write. Si NOM est omis, le nom par dfaut est STDOUT, qui est celui du format par dfaut pour le handle de fichier STDOUT. Puisque, comme pour une dclaration de sub, il sagit dune dclaration globale au paquetage se produisant la compilation, toutes les variables utilises dans la liste de valeurs doivent tre visibles au point de la dclaration du format. Cest--dire que les variables porte lexicale doivent tre auparavant dclares dans le fichier, alors que les variables porte dynamique peuvent ntre initialises quau moment o lon appelle write. En voici un exemple (qui suppose que nous avons dj calcul $cout et $quantite :
my $chn = "widget"; # Une variable de porte lexicale.

format Jolie_Sortie = Test: @<<<<<<<< @||||| @>>>>> $chn, $%, $ . int($num) . local $~ = "Jolie_Sortie"; local $num = $cout * $quantite; write; # Slection du format. # Variable de porte dynamique.

Tout comme les handles de fichier, les noms de format sont de simples identificateurs qui existent dans une table de symboles (paquetage) et peuvent tre pleinement qualifis par le nom du paquetage. Dans les typeglobs des entres dune table de symboles, les formats rsident dans leur propre espace de noms, qui est distinct des handles de fichiers et de rpertoires, des scalaires, des tableaux, des hachages ou des sous-programmes. Cependant, comme pour ces six autres types, un format nomm Nimportequoi serait aussi affect par un local sur le typeglob *Nimportequoi. En dautres termes, un format nest quun machin de plus, contenu dans un typeglob, indpendant des autres machins. La section Variables de format du chapitre 7, Formats contient de nombreux dtails et des exemples dutilisation. Le chapitre 28 dcrit les variables internes spcifiques aux formats, et les modules English et FileHandle y fournissent un accs ais.

formline
formline IMAGE, LISTE

Il sagit dune fonction interne utilise par les formats, bien que vous puissiez galement lappeler vous-mme. Elle formate une liste de valeurs daprs le contenu dIMAGE, en plaant la sortie dans laccumulateur de sortie, $^A (ou $ACCUMULATOR si vous utilisez le module English). Finalement, au moment dun write, le contenu de $^A est crit vers un handle de fichier, mais vous pouvez aussi bien lire $^A par vous-mme pour ensuite le remettre "". Typiquement, un format lance un formline par ligne de format, mais la fonction formline elle-mme ne fait pas attention au nombre de sauts de ligne inclus dans lIMAGE. Cela veut dire que les tokens ~ et ~~ traitent IMAGE comme une seule ligne. Il peut donc tre ncessaire demployer plusieurs formlines pour implmenter un unique format denregistrement, comme le compilateur de format le fait en interne. Attention si vous mettez des doubles apostrophes autour de limage, car un caractre @

customer_8566

Fonctions Perl par ordre alphabtique

681

peut tre confondu avec le dbut dun nom de tableau. Voir le chapitre 7, Formats, pour des exemples dutilisation.

getc
getc HANDLE_FICHIER getc

tG

Cette fonction renvoie le caractre suivant depuis le fichier dentre attach HANDLE_FICHIER. Elle renvoie undef la fin du fichier ou si une erreur dentre/sortie se produit. Si HANDLE_FICHIER est omis, la fonction lit depuis STDIN. Cette fonction est quelque peu lente, mais se rvle parfois utile pour les entres dun seul caractre (octet, rellement) au clavier pourvu que vous vous arrangiez pour que les entres depuis le clavier ne passent pas par un tampon. Cette fonction demande une entre non tamponne depuis la bibliothque standard dentre/sortie. Malheureusement, la bibliothque standard dentre/sortie nest pas assez standard pour fournir une manire portable de dire au systme dexploitation sous-jacent de donner au systme dentre/sortie des entres non tamponnes depuis le clavier. Pour accomplir ceci, vous devez tre un peu plus habile et utiliser un style dpendant du systme dexploitation. Sous Unix, vous pourriez dire ceci :
if ($BSD_STYLE) { system "stty cbreak </dev/tty >/dev/tty 2>&1"; } else { system "stty", "-icanon", "eol", "\001"; } $clef = getc; if ($BSD_STYLE) { system "stty -cbreak </dev/tty >/dev/tty 2&1"; } else { system "stty", "icanon", "eol", "^@"; # ASCII NUL } print "\n";

Ce code met le prochain caractre (octet) frapp sur le terminal dans la chane $clef. Si votre programme stty possde des options comme cbreak, vous devrez utiliser le code o $BSD_STYLE est vrai. Sinon, vous devrez utiliser le code o il est faux. Dterminer les options de stty(1) est laiss comme exercice au lecteur. Le module POSIX en fournit une version plus portable grce la fonction POSIX::getattr. Voir aussi le module Term::ReadKey dans votre site CPAN le plus proche pour une approche plus portable et plus f lexible.

getgrent
getgrent setgrent endgrent

Ces routines parcourent votre fichier /etc/group (ou peut-tre le fichier /etc/group de quel-

customer_8566

682

Chapitre 29 Fonctions

quun dautre, sil provient dun serveur quelque part). La valeur renvoye par getgrent dans un contexte de liste est :
($nom, $mot_de_passe, $gid, $membres)

o $membres contient une liste des noms de login des membres du groupe spars par des espaces. Pour mettre en uvre un hachage traduisant les noms de groupes en GID, crivez ceci :
while (($nom, $mot_de_passe, $gid) = getgrent) { $gid{$nom} = $gid; }

Dans un contexte scalaire, getgrent renvoie seulement le nom du groupe. Le module standard User::grent supporte une interface oriente par nom pour cette fonction. Voir getgrent(3).

getgrid
getgrid GID

Cette fonction recherche une entre de fichier de groupe par le numro du groupe. La valeur renvoye dans un contexte de liste est :
($nom, $mot_de_passe, $gid, $membres)

o $membres contient une liste des noms de login des membres du groupe spars par des espaces. Si vous voulez faire cela de faon rptitive, il vaut mieux utiliser un hachage comme cache en utilisant getgrent. Dans un contexte scalaire, getgrid renvoie seulement le nom du groupe. Le module standard User::grent supporte une interface oriente par nom pour cette fonction. Voir getgrid(3).

getgrnam
getgrid NOM

Cette fonction recherche une entre de fichier de groupe par le nom du groupe. La valeur renvoye dans un contexte de liste est :
($nom, $mot_de_passe, $gid, $membres)

o $membres contient une liste des noms de login des membres du groupe spars par des espaces. Si vous voulez faire cela de faon rptitive, il vaut mieux utiliser un hachage comme cache en utilisant getgrent. Dans un contexte scalaire, getgrnam renvoie seulement le nom du groupe. Le module standard User::grent supporte une interface oriente par nom pour cette fonction. Voir getgrnam(3).

gethostbyaddr
gethostbyaddr ADR, TYPE_ADR

Cette fonction convertit des adresses en noms (et en adresses alternatives). ADR doit tre une adresse rseau binaire empaquete et TYPE_ADR en pratique doit tre normalement

customer_8566

Fonctions Perl par ordre alphabtique


AF_INET (du module Socket). La valeur de retour dans un contexte de liste est :
($nom, $alias, $type_adr, $longueur, @adrs) = gethostbyaddr($adresse_binaire_empaquete, $type_adr);

683

o @adrs est une liste dadresses brutes. Dans le domaine de lInternet, chaque adresse est (historiquement) longue de 4 octets et peut tre dcoupe en crivant quelque chose comme ceci :
($a, $b, $c, $d) = unpack(C4, $adrs[0]);

Ou alors, vous pouvez directement la convertir dans la notation de vecteur point avec le modificateur v de sprintf :
$points = sprintf "%vd", $adrs[0];

La fonction inet_ntoa du module Socket est trs utile pour produire une version affichable. Cette approche deviendra importante si et quand nous parviendrons passer IPv6.
use Socket; $adresse_affichable = inet_ntoa($addrs[0]);

Dans un contexte scalaire, gethostbyaddr renvoie seulement le nom de lhte. Pour obtenir une ADR partir dun vecteur point, crivez ceci :
use Socket; $adr_ip = inet_aton("127.0.0.1"); # localhost $nom_officiel = gethostbyaddr($adr_ip, AF_INET);

De manire intressante, vous pouvez avec la version 5.6 de Perl vous passer de inet_aton et employer la nouvelle notation v-chane, qui a t invente pour les numros de versions, mais il est apparu quelle fonctionnait aussi bien pour les adresses IP :
$adr_ip = v127.0.0.1;

Voir la section Sockets au chapitre 16 pour plus dexemples. Le module Net::hostent supporte une interface oriente par nom pour cette fonction. Voir gethostbyaddr(3).

gethostbyname
gethostbyname NOM

Cette fonction convertit un nom dhte rseau en son adresse correspondante (et en dautres noms). La valeur de retour dans un contexte de liste est :
($nom, $alias, $type_adr, $longueur, @adrs) = gethostbyname($nom_hote_distant);

o @adrs est une liste dadresses brutes. Dans le domaine de lInternet, chaque adresse est (historiquement) longue de 4 octets et peut tre dcoupe en crivant quelque chose comme ceci :
($a, $b, $c, $d) = unpack(C4, $adrs[0]);

Vous pouvez directement la convertir dans la notation de vecteur avec le modificateur v de sprintf :
$points = sprintf "%vd", $adrs[0];

customer_8566

684

Chapitre 29 Fonctions

Dans un contexte scalaire, gethostbyname renvoie uniquement ladresse de lhte :


use Socket; $adr_ip = gethostbyname($hote_distant); printf "%s a comme adresse %s\n", $hote_distant, inet_ntoa($adr_ip);

Voir la section Sockets au chapitre 16 pour une autre approche. Le module Net::hostent supporte une interface oriente par nom pour cette fonction. Voir galement gethostbyname(3).

gethostent
gethostent sethostent RESTE_OUVERT endhostent

Ces fonctions parcourent votre fichier /etc/hosts et renvoient chaque entre une par une. La valeur de retour de gethostent dans un contexte de liste est :
($nom, $alias, $longueur, @adrs)

o @adrs est une liste dadresses brutes. Dans le domaine Internet, chaque adresse est longue de 4 octets et peut tre dcoupe en crivant quelque chose comme ceci :
($a, $b, $c, $d) = unpack(C4, $adrs[0]);

Les scripts qui utilisent gethostent ne doivent pas tre considrs comme portables. Si une machine utilise un serveur de noms, elle interrogera la quasi-totalit de lInternet pour tenter de satisfaire une requte portant sur toutes les adresses de toutes les machines de la plante. Voir gethostent(3) pour dautres dtails. Le module Net::hostent supporte une interface oriente par nom pour cette fonction.

getlogin
getlogin

Cette fonction renvoie le nom de login courant sil est trouv. Sur les systmes Unix, il est lu partir du fichier utmp(5). Si la fonction renvoie faux, utilisez getpwuid la place. Par exemple :
$login = getlogin() || (getpwuid($<))[0]) || "Intrus !!";

getnetbyaddr
getnetbyaddr ADR, TYPE_ADR

Cette fonction convertit une adresse rseau vers le nom ou les noms de rseau correspondants. La valeur renvoye dans un contexte de liste est :
use Socket; ($nom, $alias, $type_adr, $reseau) = getnetbyaddr(127, AF_INET);

Dans un contexte scalaire, getnetbyaddr renvoie seulement le nom du rseau. Le module Net::netent supporte une interface oriente par nom pour cette fonction. Voir getnetbyaddr(3).

customer_8566

Fonctions Perl par ordre alphabtique

685

getnetbyname
getnetbyname NOM

Cette fonction convertit un nom de rseau vers son adresse rseau correspondante. La valeur de retour dans un contexte de liste est :
($nom, $alias, $type_adr, $reseau) = getnetbyname("loopback");

Dans un contexte scalaire, getnetbyname renvoie seulement ladresse du rseau. Le module Net::netent supporte une interface oriente par nom pour cette fonction. Voir getnetbyname(3).

getnetent
getnetent setnetent RESTE_OUVERT endnetent

Ces fonctions parcourent votre fichier /etc/networks. La valeur renvoye dans un contexte de liste est :
($nom, $alias, $type_adr, $reseau) = getnetent();

Dans un contexte scalaire, getnetent renvoie seulement le nom du rseau. Le module Net::netent supporte une interface oriente par nom pour cette fonction. Voir getnetent(3). Le concept de nom de rseau semble un peu dsuet de nos jours ; la plupart des adresses IP tant sur des sous-rseaux innomms (et innommables).

getpeername
getpeername SOCKET

!GU

Cette fonction ladresse socket empaquete de lautre extrmit de la connexion SOCKET. Par exemple :
use Socket; $son_adr_sock ($port, $son_adr) $son_nom_hote $son_adr_chaine = = = = getpeername SOCK; sockaddr_in($son_adr_sock); gethostbyaddr($son_adr, AF_INET); inet_ntoa($son_adr);

getpgrp
getpgrp PID

Cette fonction renvoie lidentifiant du groupe de processus courant pour le PID spcifi (employez un PID gal 0 pour le processus courant). Linvocation de getpgrp lvera une exception sur une machine nimplmentant pas getpgrp(2). Si PID est omis, la fonction renvoie le groupe de processus du processus courant (ce qui est identique un PID de 0). Sur les systmes qui implmentent cet oprateur avec lappel systme POSIX getpgrp(2), PID doit tre omis ou, sil est fourni, doit tre gal 0.

customer_8566

686

Chapitre 29 Fonctions

getppid
getppid

Cette fonction renvoie lidentifiant du processus parent. Sur un systme UNIX typique, si lID du processus pre se change en 1, cest que ce dernier est mort et que le processus courant a t adopt par le programme init(8).

getpriority
getpriority QUOI, QUI

!U

Cette fonction renvoie la priorit courante dun processus, dun groupe de processus ou dun utilisateur. Voir getpriority(2). Son invocation lvera une exception sur une machine o getpriority(2) nest pas implmente. Le module BSD::Resource de CPAN fournit une interface plus pratique, comprenant les constantes symboliques PRIO_PROCESS, PRIO_PGRP et PRIO_USER quil faut fournir pour largument QUOI. Bien quelles soient gnralement gales 0, 1 et 2 respectivement, vous ne savez vraiment pas ce qui peut se passer aux sombres confins des fichiers #include du C. Une valeur de 0 pour QUI signifie le processus, le groupe de processus ou lutilisateur courant, ainsi pour obtenir la priorit du processus en cours, utilisez :
$prio_cour = getpriority(0, 0);

getprotobyname
getprotobyname NOM

Cette fonction convertit un nom de protocole vers son numro correspondant. La valeur renvoye dans un contexte de liste est :
($nom, $alias, $numero_protocole) = getprotobyname("tcp");

Lorsquon lappelle dans un contexte scalaire, getprotobyname renvoie seulement le numro de protocole. Le module Net::proto supporte une interface oriente par nom pour cette fonction. Voir getprotobyname(3).

getprotobynumber
getprotobynumber NUMERO

Cette fonction convertit un numro de protocole vers son nom correspondant. La valeur renvoye dans un contexte de liste est :
($nom, $alias, $numero_protocole) = getprotobynumber(6);

Lorsquon lappelle dans un contexte scalaire, getprotobynumber renvoie seulement le nom de protocole. Le module Net::proto supporte une interface oriente par nom pour cette fonction. Voir getprotobynumber(3).

customer_8566

Fonctions Perl par ordre alphabtique

687

getprotoent
getprotoent setprotoent RESTE_OUVERT endprotoent

Ces fonctions parcourent votre fichier /etc/protocols. Dans un contexte de liste, la valeur renvoye par getprotoent est :
($nom, $alias, $numero_protocole) = getprotoent();

Lorsquon lappelle dans un contexte scalaire, getprotoent renvoie seulement le numro du protocole. Le module Net::protoent supporte une interface oriente par nom pour cette fonction. Voir getprotent(3).

getpwent
getpwent setpwent endpwent

tU

Ces fonctions parcourent conceptuellement votre fichier /etc/passwd, bien que ceci puisse impliquer le fichier /etc/shadow si vous tes le super-utilisateur et que vous utilisez les mots de passe shadow , NIS (ex-Pages Jaunes, Yellow Pages, YP) ou NIS+. La valeur renvoye dans un contexte de liste est :
($nom,$mot_de_passe,$uid,$gid,$quota,$commentaire,$nom_reel,$rep,$shell)= getpwent();

Certaines machines peuvent utiliser les champs quota et commentaire dautres fins que leurs noms ne le laissent supposer, mais les champs restants seront toujours les mmes. Pour mettre en uvre un hachage de traduction des noms de login en UID, crivez ceci :
while (($nom, $mot_de_passe, $uid) = getpwent()) { $uid{$nom} = $uid; }

Dans un contexte scalaire, getpwent renvoie seulement le nom dutilisateur. Le module User::pwent supporte une interface oriente par nom pour cette fonction. Voir getpwent(3).

getpwnam
getpwnam NOM

tU

Cette fonction convertit un nom dutilisateur vers lentre correspondante du fichier /etc/passwd. La valeur renvoye dans un contexte de liste :
($nom,$mot_de_passe,$uid,$gid,$quota,$commentaire,$nom_reel,$rep,$shell)= getpwnam("daemon");

Sur les systmes qui supportent les mots de passe shadow , vous devrez tre le superutilisateur pour rcuprer le vritable mot de passe. Votre bibliothque C doit remarquer que vous avez les permissions suffisantes et ouvre votre fichier /etc/shadow (ou

customer_8566

688

Chapitre 29 Fonctions

nimporte quel endroit o le fichier shadow est conserv). Du moins, cest cens fonctionner ainsi. Perl essayera de faire ceci si votre bibliothque C est trop stupide pour le remarquer. Pour faire des recherches rptitives, mieux vaut utiliser un hachage comme cache avec getpwent. Dans un contexte scalaire, getpwnam renvoie seulement lUID numrique. Le module User::pwent supporte une interface oriente par nom pour cette fonction. Voir getpwnam(3) et passwd(5).

getpwuid
getpwuid UID

tU

Cette fonction convertit un UID numrique vers lentre correspondante du fichier /etc/passwd. La valeur renvoye dans un contexte de liste :
($nom,$mot_de_passe,$uid,$gid,$quota,$commentaire,$nom_reel,$rep,$shell)= getpwuid(2);

Pour faire des recherches rptitives, mieux vaut utiliser un hachage comme cache avec getpwent. Dans un contexte scalaire, getpwuid renvoie seulement le nom de lutilisateur. Le module User::pwent supporte une interface oriente par nom pour cette fonction. Voir getpwnam(3) et passwd(5).

getservbyname
getservbyname NOM, PROTO

Cette fonction convertit un nom de service (port) vers son numro de port correspondant. PROTO est un nom de protocole comme "tcp". La valeur renvoye dans un contexte de liste est :
($nom, $alias, $numero_port, $nom_protocole) = getservbyname("www", "tcp");

Dans un contexte scalaire, getservbyname renvoie seulement le numro du port de service. Le module Net::servent supporte une interface oriente par nom pour cette fonction. Voir getservbyname(3).

getservbyport
getservbyport PORT, PROTO

Cette fonction convertit un numro de service (port) vers les noms correspondants. PROTO est un nom de protocole comme "tcp". La valeur renvoye dans un contexte de liste est :
($nom, $alias, $numero_port, $nom_protocole) = getservbyport(80, "tcp");

Dans un contexte scalaire, getservbyport renvoie seulement le nom du service. Le module Net::servent supporte une interface oriente par nom pour cette fonction. Voir getservbyport(3).

customer_8566

Fonctions Perl par ordre alphabtique

689

getservent
getservent setservent RESTE_OUVERT endservent

Cette fonction parcourt votre fichier /etc/services ou son quivalent. La valeur renvoye dans un contexte de liste est :
($nom, $alias, $numero_port, $nom_protocole) = getservent();

Dans un contexte scalaire, getservent renvoie seulement le nom du port de service. Le module Net::servent supporte une interface oriente par nom pour cette fonction. Voir getservent(3).

getsockname
getsockname SOCKET

!GU

Cette fonction renvoie ladresse socket empaquete de cette extrmit de la connexion SOCKET. (Et pourquoi ne connatriez vous plus votre propre adresse ? Peut-tre parce que vous avez attach une adresse contenant des jokers (wildcards) la socket serveur avant de faire un accept et que maintenant vous avez besoin de savoir travers quelle interface quelquun est connect avec vous. Ou la socket vous a t passe par votre processus pre inetd, par exemple.)
use Socket; $mon_adr_sock = getsockname SOCK; ($port, $mon_adr) = sockaddr_in($mon_adr_sock); $mon_nom = gethostbyaddr($mon_adr, AF_INET); printf "Je suis %s [%vd]\n", $mon_nom, $mon_adr;

getsockopt
getsockopt SOCKET, NIVEAU, NOM_OPTION

!GU

Cette fonction renvoie loption de socket requise ou undef en cas derreur. Voir setsockopt pour plus dinformations.

glob
glob EXPR glob

_@TX

Cette fonction renvoie la valeur de EXPR avec expansion des noms de fichiers, exactement comme un shell le ferait. Il sagit de la fonction interne implmentant loprateur <*>. Pour des raisons historiques, lalgorithme correspond au style dexpansion de csh(1) et pas celui du Bourne Shell. Les versions de Perl antrieures 5.6 utilisaient un processus externe, mais la 5.6 et les suivantes excutent les globs en interne. Les fichiers dont le premier caractre est un point ( . ) sont ignors sauf si ce caractre correspond explicitement. Un astrisque ( * ) correspond nimporte quelle squence de nimporte quels caractres (y compris aucun). Un point dinterrogation ( ? ) correspond un

customer_8566

690

Chapitre 29 Fonctions

unique caractre quel quil soit. Une squence entre crochets ( [. . . ] ) spcifie une simple classe de caractres, comme [chy0-9] . Les classes de caractres peuvent tre nies avec un accent circonf lexe, comme dans *.[^oa] , qui correspond tous les fichiers ne commenant pas par un point et dont les noms contiennent un point suivi par un seul caractre qui ne soit ni un a , ni un o la fin du nom. Un tilde ( ~ ) se dveloppe en un rpertoire maison, comme dans ~/.*rc pour les fichiers rc de lutilisateur courant, ou ~caro/Mail/* pour tous les fichiers mails de Caro. On peut employer des accolades pour les alternatives, comme dans ~/.{mail,ex,csh,twm,}rc pour obtenir ces fichiers rc particuliers. Si vous voulez glober sur des noms de fichiers qui peuvent contenir des espaces, vous devrez utilisez le module File::Glob directement, puisque les grands-pres de glob utilisaient les espaces pour sparer plusieurs motifs comme <*.c *.h>. Pour plus de dtail, voir File::Glob au chapitre 32. Lappel de glob (ou de loprateur <*>) fait automatiquement un use sur ce module, donc si se module svapore mystrieusement de votre bibliothque, une exception est leve. Lorsque vous appelez open, Perl ne dveloppe pas les jokers, y compris les tildes. Vous devez dabord glober les rsultats.
open(MAILRC, "~/.mailrc") # FAUX : le tilde est un truc du shell or die "Impossible douvrir ~/.mailrc : $!"; open(MAILRC, (glob("~/.mailrc"))[0]) # dveloppe dabord le tilde or die "Impossible douvrir ~/.mailrc : $!";

La fonction glob na aucun rapport avec la notion Perl de typeglobs, sinon quelles utilisent toutes deux un * pour reprsenter plusieurs lments. Voir aussi la section Oprateur de globalisation des noms de fichier au chapitre 2.

gmtime
gmtime EXPR gmtime

Cette fonction convertit une heure renvoye par la fonction time en un tableau de neuf lments dont lheure est en phase avec le mridien de Greenwich (alias GMT ou UTC, ou mme Zoulou dans certaines cultures, dont ne fait bizarrement pas partie la culture Zoulou). Elle est gnralement employe comme suit :
# 0 1 2 3 4 5 6 7 8 ($sec,$min,$heure,$mjour,$mois,$annee,$sjour,$ajour,$est_dst) = gmtime();

Si, comme dans ce cas, EXPR est omise, la fonction effectue gmtime(time()). Le module Time::Local de la bibliothque Perl contient un sous-programme, timegm, qui peut linverse convertir la liste vers une valeur de time. Tous les lments sont numriques et proviennent directement dune struct tm (une structure de programmation C ; pas daffolement). Cela signifie en particulier que $mois se situe dans lintervalle 0..11 avec janvier comme le mois 0 et que $sjour est dans 0..6 avec dimanche comme jour 0. Vous pouvez vous rappeler de ceux qui commencent par zro car ce sont ceux que vous utilisez toujours comme indices dans les tableaux dbutant par zro contenant les noms des mois et des jours. Par exemple, pour afficher le mois courant Londres, vous pouvez crire :

customer_8566

Fonctions Perl par ordre alphabtique


$mois_londres = (qw((Jan Fev Mar Avr Mai Jun Jui Aou Sep Oct Nov Dec))[(gmtime)[4]];

691

$annee est le nombre dannes depuis 1900 ; cest--dire quen 2023, $annee vaudra 123, et pas simplement 23. Pour obtenir lanne sur 4 chiffres, il suffit dcrire $annee+1900. Pour lavoir sur 2 chiffres (par exemple 01 en 2001), utilisez sprintf("%02d", $annee % 100). Dans un contexte scalaire, gmtime renvoie une chane ressemblant ctime(3) base sur la valeur de lheure GMT. Le module Time::gmtime supporte une interface oriente par nom pour cette fonction. Voir aussi POSIX::strftime pour une approche permettant de formater des dates avec une granularit plus fine. Cette valeur scalaire nest pas dpendante des locales mais plutt interne Perl. Voir aussi le module Time::Local et les fonctions strftime(3) et mktime(3) disponibles via le module POSIX. Pour obtenir des chanes pour la date qui soient similaires mais locales, positionnez vos variables denvironnement locales de manire approprie (merci de voir la page de man pour perllocale) et essayez :
use POSIX qw(strftime); $chaine_maintenant = strftime "%a %b %e %H:%M:%S %Y", gmtime;

Les caractres dchappement %a et %b, qui reprsentent la forme abrge pour le jour de la semaine et le mois de lanne, peuvent ne pas tre ncessairement de trois caractres dans toutes les locales .

goto
goto ETIQUETTE goto EXPR goto &NOM

goto ETIQUETTE trouve linstruction tiquete par ETIQUETTE et continue lexcution partir de l. Si lETIQUETTE est impossible trouver, une exception est leve. Elle ne peut pas tre utilise pour aller dans une construction demandant une initialisation, comme un sous-programme ou une boucle foreach. De mme, elle ne peut tre employe pour rentrer dans une construction optimise. Elle peut tre utilise pour aller quasiment partout ailleurs dans lespace de porte dadressage dynamique,4 y compris pour sortir des sous-programmes, mais il vaut alors mieux employer une autre instruction comme last ou die. Lauteur de Perl na jamais ressenti le besoin dutiliser cette forme de goto (en Perl en C, cest une autre histoire). Pour aller plus loin dans lorthogonalit (et plus profond dans la stupidit), Perl autorise goto EXPR qui sattend ce que EXPR donne un nom dtiquette, dont lemplacement ne peut jamais tre rsolu avant lexcution puisque ltiquette est inconnue lorsquon compile linstruction. Cela permet des gotos calculs comme en FORTRAN mais ce nest pas vraiment recommand5 lorsquon cherche optimiser la maintenabilit :

4. Cela veut dire que si elle ne trouve pas ltiquette dans la routine courante, elle cherche dans celles qui lont appele, rendant ainsi la maintenance du programme quasiment impossible. 5. Les euphmismes sont rputs tre amusants, alors nous avons pens en essayer un ici.

customer_8566

692
goto +("TRUC", "MACHIN", "CHOUETTE")[$i];

Chapitre 29 Fonctions

Sans aucun rapport, le goto &NOM fait de la grande magie en substituant un appel au sous-programme nomm en lieu et place du sous-programme actuellement en cours. Cette construction est utilise sans scrupule par les sous-programmes AUTOLOAD qui veulent en charger un autre pour ensuite prtendre que celui-ci et non loriginal a t appel en premier lieu (sauf que toute modification de @_ dans le sous-programme dorigine est propage dans le sous-programme de remplacement). Aprs le goto, mme caller ne pourra pas dire que la routine AUTOLOAD originelle avait t appele en premier lieu.

grep
grep EXPR, LISTE grep BLOC LISTE

Cette fonction value EXPR ou BLOC dans un contexte boolen pour chaque lment de LISTE, en positionnant temporairement $_ avec chaque lment tout tour, un peu comme la construction foreach. Dans un contexte de liste, elle renvoie la liste des lments pour lesquels lexpression est vraie. (Loprateur a t nomm daprs le bienaim programme UNIX qui extrait les lignes dun fichier qui correspondent un motif particulier. En Perl, lexpression est souvent un motif, mais ce nest pas obligatoire.) Dans un contexte scalaire, grep renvoie le nombre doccurrences o lexpression est vraie. supposer que @toutes_les_lignes contienne des lignes de code, cet exemple limine les lignes de commentaires :
@lignes_de_code = grep !/^\s*#/, @toutes_les_lignes;

$_ tant un alias implicite chaque valeur de la liste, laltration de $_ modifiera les lments de la liste originelle. Bien que ceci soit utile et support, les rsultats peuvent devenir bizarres si lon ne sy attend pas. Par exemple,
@liste = qw(barney fred dino wilma); @liste_grep = grep { s/^[bfd]// } @liste;

@liste_grep contient maintenant arney , red , ino , mais @liste est devenu arney , red , ino , wilma ! Danger de bourde de programmeur. Voir galement map. Les deux instructions suivantes sont fonctionnellement quivalentes :
@sortie = grep { EXPR } @entree; @sortie = map { EXPR ? $_ : () } @entree

hex
hex EXPR hex

Cette fonction interprte EXPR comme une chane hexadcimale et renvoie la valeur dcimale quivalente. Sil y un 0x au dbut, il est ignor. Pour interprter des chanes commenant soit par 0, soit par 0b, ou par 0x, voir oct. Le code suivant met $nombre

customer_8566

Fonctions Perl par ordre alphabtique


4 294 906 560 :
$nombre = hex("ffff12c0");

693

Pour la fonction inverse, employez sprintf :


sprintf "%lx", $nombre; # (la lettre L en minuscule, pas le chiffre un.)

Les chanes hexadcimales ne peuvent reprsenter que des entiers. Les chanes qui causeraient un dbordement de la limite pour les entiers dclenchent un avertissement.

import
import NOM_CLASSE LISTE import NOM_CLASSE

Il nexiste pas de fonction import intgre. Il sagit essentiellement dune mthode de classe ordinaire dfinie (ou hrite) par les modules qui dsirent exporter des noms vers un autre module par lintermdiaire de loprateur use. Voir use pour plus de dtails.

index
index CHAINE, SOUS_CHAINE, DECALAGE index CHAINE, SOUS_CHAINE

Cette fonction recherche une chane lintrieur dune autre. Elle renvoie la position de la premire occurrence de SOUS_CHAINE dans CHAINE. Le DECALAGE, sil est spcifi, indique partir de combien de caractre dbute la recherche. Les positions partent de 0 (ou de l o vous avez positionn la variable de base des indices $[, mais ne faites pas a). Si la sous-chane nest pas trouve, la fonction renvoie un de moins que la base, gnralement -1. Pour balayer une chane, on peut crire :
$pos = -1; while (($pos = index($chaine, $chaine_recherchee, $pos)) > -1) { print "Trouv en $pos\n"; $pos++; }

int
int EXPR int

Cette fonction renvoie la partie entire de EXPR. Si vous tes un programmeur C, vous tes susceptible doublier frquemment dutiliser int en conjonction avec la division, qui est une opration en virgule f lottante en Perl :
$age_moyen = 939/16; # donne 58.6875 (58 en C) $age_moyen = int 939/16; # donne 58

Vous ne devez pas employer cette fonction pour arrondir dans tous les cas, car elle tronque vers 0 et parce que la reprsentation pour la machine des nombres en virgule f lottante peut quelque fois produire des rsultats qui ne sont pas intuitifs. Par exemple, int(-6.725/0.025) donnera -268 au lieu de la valeur correcte -269 ; ceci car la valeur est plus proche de -268.99999999999994315658. Gnralement, les fonctions sprintf,

customer_8566

694

Chapitre 29 Fonctions

printf ou POSIX::floor ou encore POSIX::ceil vous serviront plus que ne le ferait int.
$n = sprintf("%.0f", $f); # arrondit (et ne tronque pas) # vers lentier le plus proche

ioctl
ioctl HANDLE_FICHIER, FONCTION, SCALAIRE

!GOXU

Cette fonction implmente lappel systme ioctl(2) qui contrle les entres/sorties. Il vous faudra peut-tre dabord crire pour obtenir les dfinitions de fonctions correctes :
require "sys/ioctl.ph"; # probablement /usr/local/lib/perl/sys/ioctl.ph

Si sys/ioctl.ph nexiste pas ou ne comporte pas les dfinitions correctes, vous devrez crire les vtres, en vous basant sur vos en-ttes de fichiers C comme sys/ioctl.h. (La distribution Perl contient un script appel h2ph pour vous y aider, mais cela reste complexe.) SCALAIRE sera lu ou crit (ou les deux) selon la FONCTION un pointeur sur la valeur chane de SCALAIRE sera pass comme troisime argument de lappel rel ioctl(2). (Si SCALAIRE na pas de valeur chane, mais une valeur numrique, cest cette dernire qui sera passe directement au lieu dun pointeur sur la valeur chane.) Les fonctions pack et unpack servent notamment manipuler les valeurs des structures utilises par ioctl. Lexemple suivant dtermine combien doctets sont disponibles pour tre lus en utilisant un FIONREAD :
require sys/ioctl.ph; $taille = pack("L", 0); ioctl(HF, FIONREAD(), $taille) or die "Impossible dappeler ioctl : $!\n"; $taille = unpack("L", $taille);

Si h2ph na pas t install ou ne fonctionne pas dans votre cas, vous pouvez faire un grep la main sur les fichiers den-ttes ou crire un petit programme C pour afficher la valeur. La valeur de retour dioctl (et de fcntl) est comme suit :
Lappel systme renvoie -1 0 autre chose Perl renvoie undef. La chane 0 but true . Le mme nombre.

Perl renvoie donc vrai pour un succs et faux pour un chec, tout en vous laissant facilement dterminer la valeur renvoye par le systme dexploitation :
$val_ret = ioctl(...) || -1; printf "ioctl a en fait renvoy %d\n", $val_ret;

La chane spciale 0 but true (N.d.T. : 0 mais vrai) est exempte des avertissements de -w propos des conversions numriques inadaptes. Les appels ioctl ne doivent pas tre considrs comme portables. Si, par exemple,

customer_8566

Fonctions Perl par ordre alphabtique

695

vous voulez simplement dsactiver lcho une seule fois pour le script tout entier, il est beaucoup plus portable dcrire :
system "stty -echo"; # Fonctionne sur la plupart des Unix

Ce nest pas parce quil est possible de faire quelque chose en Perl quil faille le faire. Pour citer laptre Saint Paul : Tout est acceptable mais tout nest pas bnfique. Pour une meilleur portabilit, vous devriez regarder le module de CPAN Term::ReadKey.

join
join EXPR, LISTE

Cette fonction joint les chanes spares de LISTE en une chane unique dont les champs sont spars par la valeur de EXPR, et renvoie la chane rsultante. Par exemple :
$enreg = join :, $login,$mot_de_passe,$uid,$gid,$nom_reel,$rep,$shell;

Pour faire linverse, voir split. Pour joindre des lments dans des champs position fixe, voir pack. La manire la plus efficace de concatner des chanes consiste les joindre avec la chane vide :
$chaine = join "", @tableau;

Au contraire de split, join ne prend pas un motif comme premier argument, et elle produit un avertissement si vous tentez de le faire.

keys
keys HACHAGE

Cette fonction renvoie une liste constitue de toutes les clefs du HACHAGE indiqu. Les clefs sont renvoyes dans un ordre apparemment alatoire, mais cest le mme que celui produit par les fonctions values ou each ( supposer que le hachage na pas t modifi entre les appels). Comme effet de bord, elle rinitialise litrateur de HACHAGE. Voici une manire (un peu tordue) dafficher votre environnement :
@clefs = keys %ENV; # les clefs sont dans le mme ordre que @valeurs = values %ENV; # les valeurs, comme ceci le dmontre while (@clefs) { print pop(@clefs), =, pop(@valeurs), "\n"; }

Vous prfrez peut-tre plus voir votre environnement affich dans lordre des clefs :
foreach $clef (sort keys %ENV) { print $clef, =, $ENV{$clef}, "\n"; }

Vous pouvez trier les valeurs dun hachage directement, mais cest plutt inutile en labsence dune solution pour retrouver les clefs partir des valeurs. Pour trier un hachage par ses valeurs, vous avez gnralement besoin de trier le rsultat de keys en fournissant une fonction de comparaison qui accde aux valeurs en fonction des clefs. Voici un tri numrique dcroissant dun hachage par ses valeurs :

customer_8566

696

Chapitre 29 Fonctions

foreach $clef (sort { $hachage{$b} <=> $hachage{$a} } keys %hachage) { printf "%4d %s\n", $hachage{$clef}, $clef; }

Lutilisation de keys sur un hachage li un gros fichier DBM produirait une liste volumineuse, et donc un processus volumineux. Il vaut mieux que vous utilisiez dans ce cas la fonction each, qui parcourt les entres du hachage une une sans les absorber toutes dans une seule liste gargantuesque. Dans un contexte scalaire, keys renvoie le nombre dlments du hachage (et rinitialise litrateur de each). Cependant, pour obtenir cette information partir dun hachage li, y compris un fichier DBM, Perl doit le parcourir en entier, ce qui nest pas trs efficace dans ce cas. Lappel de keys dans un contexte vide facilite ceci. Utilise en tant que lvalue, keys augmente le nombre de cellules de hachage (N.d.T. : hash buckets) alloues pour le hachage donn. (Cest la mme chose que dtendre a priori un tableau en assignant un nombre lev pour $#tableau.) tendre a priori un hachage peut se traduire par un gain de performance, sil vous arrive de savoir si le hachage va tre gros, et quelle grosseur il atteindra. Si vous crivez :
keys %hachage = 1000;

le %hachage aura alors au moins 1000 cellules alloues pour lui (vous aurez en fait 1024 cellules, puisquon arrondit la prochaine puissance de deux). Vous pouvez diminuer le nombre de cellules alloues pour un hachage en utilisant keys de cette manire (mais vous naurez pas vous inquiter de faire cela par accident, puisquessayer est sans effet). Les cellules seront conserves mme si vous faites %hachage = (). Utilisez undef %hachage si vous voulez librer de la place en mmoire alors que %hachage est toujours dans la porte courante. Voir galement each, value et sort.

kill
kill SIGNAL, LISTE

!GUX

Cette fonction envoie un signal une liste de processus. Pour le SIGNAL, vous pouvez utiliser soit un entier, soit le nom dun signal entre apostrophes (sans le SIG au dbut). Une tentative demployer un SIGNAL non-reconnu lve une exception. La fonction renvoie le nombre de processus qui ont russi recevoir le signal. Si SIGNAL est ngatif, la fonction touchera des groupes de processus au lieu des processus. (Sur System V un , numro de processus ngatif touchera galement des groupes de processus, mais ce nest pas portable.) Un PID gal zro enverra le signal tous les processus du mme groupe que celui de lmetteur. Par exemple :
$compt = kill 1, $fils1, $fils2; kill 9, @mourants; kill STOP, getppid # Peut suspendre *ainsi* le shell de login unless getppid == -1; # (Mais ne titillez pas init(8).)

Un SIGNAL valant 0 teste si un processus est toujours en vie et que vous avez toujours les permissions pour lui envoyer un signal. Aucun signal nest envoy. Vous pouvez de cette manire dtecter si un processus est toujours en vie et sil na pas chang dUID.
use Errno qw(ESRCH EPERM);

customer_8566

Fonctions Perl par ordre alphabtique


if (kill 0 => $larbin) { print "$larbin est en vie !\n"; } elsif ($! == EPERM) { # UID chang print "$larbin a chapp mon contrle !\n"; } elsif ($! == ESRCH) { # ou zombie print "$larbin est dcd.\n"; } else { warn "Bizarre : je nai pas pu vrifier ltat de $larbin : $!\n"; }

697

Voir la section Signaux au chapitre 16.

last
last ETIQUETTE last

Loprateur last sort immdiatement de la boucle en question, exactement comme linstruction break en C ou en Java (lorsquelle est utilise dans les boucles). Si lETIQUETTE est omise, loprateur se rfre la boucle la plus intrieure qui lencadre. Le bloc continue, sil existe, nest pas excut.
LIGNE: while (<MSG_MAIL>) { last LIGNE if /^$/; # sort lorsquon en a fini avec les en-ttes # suite de la boucle ici }

last ne peut pas tre employ pour sortir dun bloc qui renvoie une valeur, comme eval {}, sub {} ou do {}, et ne doit pas tre utilis pour sortir dune opration grep ou map. Si les avertissements sont actifs, Perl vous prviendra si vous faites un last pour sortir dune boucle qui est hors de votre porte lexicale, comme une boucle dans une sous-routine appelante. Un bloc en soi-mme est smantiquement identique une boucle qui ne sexcute quune seule fois. Ainsi last peut tre employ pour effectuer une sortie anticipe dun tel bloc. Voir aussi le chapitre 4 pour des illustrations du fonctionnement de last, next, redo et continue.

lc
lc EXPR lc

_t

Cette fonction renvoie une version en minuscules de EXPR. Il sagit de la fonction interne implmentant lchappement \L dans les chanes entre guillemets. La valeur de votre locale LC_CTYPE est respecte si use locale est actif, bien que la manire dont les locales interagissent avec Unicode est toujours un sujet ltude, comme ils disent. Voir la page de man perllocale pour les rsultats les plus jour.

customer_8566

698

Chapitre 29 Fonctions

lcfirst
lcfirst EXPR lcfirst

_t

Cette fonction renvoie une version de EXPR avec le premier caractre en minuscule. Il sagit de la fonction interne implmentant lchappement \l dans les chanes entre guillemets. La valeur de votre locale LC_CTYPE est respecte si vous employez use locale et nous tchons de comprendre le rapport avec Unicode.

length
length EXPR length

Cette fonction renvoie la longueur en caractres de la valeur scalaire de EXPR. Si EXPR est omise, la fonction renvoie la longueur de $_ (mais prenez garde que ce qui suit ne ressemble pas au dbut dune EXPR ression, faute de quoi le moteur lexical de Perl sera perturb. Par exemple, length < 10 ne compilera pas. En cas de doute, mettez des parenthses.) Nessayez pas dutiliser length pour trouver la taille dun tableau ou dun liste. scalar @tableau donne la taille dun tableau et scalar keys %hachage celle des couples clef/valeur dun hachage. (Le scalar est habituellement omis lorsquil est redondant.) Pour trouver la taille dune chane en octets plutt quen caractres, crivez :
$oct_long = do { use bytes; length $chaine; };

ou
$oct_long = bytes::length $chaine; # doit dabord faire un use bytes

link
link ANCIEN_FICHIER, NOUVEAU_FICHIER

!UX

Cette fonction cre un nouveau nom de fichier li lancien. La fonction renvoie vrai en cas de succs, faux sinon. Voir galement symlink plus loin dans ce chapitre. Il est peu probable que cette fonction soit implmente sur les systmes de fichiers non-Unix.

listen
listen SOCKET, TAILLE_FILE

!GU

Cette fonction informe le systme que vous allez accepter des connexions sur cette SOCKET et que le systme peut mettre en file dattente le nombre de connexions spcifies par TAILLE_FILE. Imaginez un signal dappel sur votre tlphone, avec la possibilit de mettre 17 appels en file dattente. (Encore faut-il le vouloir !) La fonction renvoie vrai si elle a russi, sinon faux.
use Socket; listen(SOCK_PROTO, SOMAXCONN) or die "Impossible de mettre une file dattente avec listen sur SOCK_PROTO : $!";

customer_8566

Fonctions Perl par ordre alphabtique


Voir accept. Voir galement la section Sockets au chapitre 16. Voir listen(2).

699

local
local EXPR

Cet oprateur ne cre pas de variable locale ; utilisez my pour le faire. la place, il rend locales des variables existantes ; cest--dire quil donne une ou plusieurs variables globales une porte locale lintrieur du bloc, de leval ou du fichier le plus intrieur les encadrant. Si plus dune valeur est liste, la liste doit tre place entre parenthses car la priorit de loprateur est plus leve que celle des virgules. Tous les lments lists doivent tre des lvalues lgales, cest--dire quelque chose auquel vous pouvez assigner une valeur ; ceci peut comprendre les lments individuels de tableaux ou de hachages. Cet oprateur fonctionne en sauvegardant les valeurs courantes des variables spcifies dans une pile cache et en les restaurant au moment de sortir du bloc, du sous-programme, de leval ou du fichier. Aprs que le local a t excut, mais avant de sortir de sa porte, tout sous-programme ou tout format excut verra les valeurs locales internes et non les valeurs externes prcdentes car la variable reste globale, bien que sa valeur soit localise. Le terme technique est porte dynamique . Voir la section Dclarations avec porte au chapitre 4. On peut assigner une valeur EXPR si besoin, ce qui permet dinitialiser vos variables au moment o vous les rendez locales. Si aucune initialisation explicite nest effectue, tous les scalaires sont initialiss undef et tous les tableaux et hachages (). Comme pour les affectations ordinaires, si lon utilise des parenthses autour des variables gauche (ou si la variable est un tableau ou un hachage), lexpression de droite est value dans un contexte de liste. Sinon, lexpression de droite est value dans un contexte scalaire. Dans tous les cas, lexpression de droite est value avant de rendre les variables locales, mais linitialisation est effectue aprs, vous permettant ainsi dinitialiser une variable rendue locale avec la valeur quelle contenait avant de ltre. Par exemple, ce code dmontre comment modifier temporairement un tableau global :
if ($op eq -v) { # initialiser le tableau local avec le tableau global local @ARGV = @ARGV; unshift @ARGV, echo; system @ARGV; } # @ARGV restaur

Vous pouvez aussi modifier temporairement des hachages globaux :


# ajoute temporairement quelques entres au hachage %chiffres if ($base12) \{ # (NB : ce nest pas forcment efficace !) local(%chiffres) = (%chiffres, T => 10, E => 11); &parcours_nombres(); }

Vous pouvez utiliser local pour donner des valeurs temporaires aux lments individuels de tableaux ou de hachages, mme sils ont une porte lexicale :

customer_8566

700

Chapitre 29 Fonctions

if ($protege) { local $SIG{INT} = IGNORE; precieux(); # pas dinterruption durant cette fonction } # le gestionnaire prcdent (sil y en a) est restaur

Vous pouvez utiliser local avec les typeglobs pour crer des handles de fichiers locaux sans charger des modules objets encombrants :
local *MOTD; my $hf = do { local *HF }; # protge tout handle MOTD global # cre un nouveau handle de fichier indirect

(Depuis la version 5.6 de Perl, un my $hf; ordinaire suffit car il vous donne une variable indfinie l o un handle de fichier est attendu, comme le premier argument de open ou socket, Perl donne maintenant la vie un tout nouveau handle de fichier pour vous.) Mais en gnral, prfrez my au lieu de local, car local nest pas vraiment ce que la plupart des gens dfinit comme local , ni mme lo-cal . Voir my.

localtime
localtime EXPR localtime

Cette fonction convertit une heure renvoye par la fonction time en un tableau de neuf lments dont lheure est en phase avec le mridien local. Elle est gnralement employe comme suit :
# 0 1 2 3 4 5 6 7 8 ($sec,$min,$heure,$mjour,$mois,$annee,$sjour,$ajour,$est_dst) = localtime;

Si, comme dans ce cas, EXPR est omise, la fonction effectue localtime(time()). Tous les lments sont numriques et proviennent directement dune struct tm (un jargon de programmation C pas daffolement). Cela signifie en particulier que $mois se situe dans lintervalle 0..11 avec janvier comme le mois 0 et que $sjour est dans 0..6 avec dimanche comme jour 0. Vous pouvez vous rappeler de ceux qui commencent par zro car ce sont ceux que vous utilisez toujours comme indices dans les tableaux dbutant par zro contenant les noms des mois et des jours. Par exemple, pour obtenir le jour actuel de la semaine :
$ce_jour = (qw((Dim Lun Mar Mer Jeu Ven Sam))[(localtime)[6]];

$annee est le nombre dannes depuis 1900 ; cest--dire quen 2023, $annee vaudra 123, et pas simplement 23. Pour obtenir lanne sur 4 chiffres, il suffit dcrire $annee+1900. Pour lavoir sur 2 chiffres (par exemple 01 en 2001), utilisez sprintf("%02d", $annee % 100). Le module Time::Local de la bibliothque Perl contient un sous-programme, timelocal, qui peut faire la conversion dans le sens linverse. Dans un contexte scalaire, localtime renvoie une chane ressemblant ctime(3). Par exemple, la commande date(1) peut (presque6) tre mule par :
6. date(1) affiche le fuseau horaire, alors que scalar localtime ne le fait pas.

customer_8566

Fonctions Perl par ordre alphabtique


perl -le print scalar localtime;

701

Voir aussi la fonction strftime du le module standard POSIX pour une approche permettant de formater des dates avec une granularit plus fine. Le module Time::localtime supporte une interface oriente par nom pour cette fonction.

lock
lock CHOSE

La fonction lock place un verrou sur une variable, un sous-programme ou un objet rfrenc par CHOSE jusqu ce que le verrou sorte de la porte courante. Pour assurer une compatibilit antrieure, cette fonction nest interne que si Perl a t compil en autorisant les threads et si vous avez crit use Threads. Sinon, Perl supposera quil sagit dune fonction dfinie par lutilisateur. Voir le chapitre 17, Threads.

log
log EXPR log

_@

Cette fonction renvoie le logarithme naturel (cest--dire en base e) de EXPR. Si EXPR est ngative, un exception est leve. Pour obtenir le log dans une autre base, utilisez lalgbre de base : le log en base-N dun nombre est gal au log de ce nombre divis par le log naturel de N. Par exemple :
sub log10 { my $n = shift; return log($n)/log(10); }

Pour linverse du log, voir exp.

lstat
lstat EXPR lstat

_!U

Cette fonction est similaire la fonction stat de Perl (y compris en positionnant le handle de fichier spcial _), mais si le dernier composant du nom de fichier est un lien symbolique, elle agit sur le lien symbolique lui-mme au lieu du fichier sur lequel pointe le lien en question. (Si les liens symboliques ne sont pas implments, cest un stat normal qui est lanc en lieu et place.)

m//
/MOTIF/ m/MOTIF/

tX

Il sagit de loprateur de correspondance, qui interprte MOTIF comme une expression rgulire. Loprateur est valu comme une chane entre guillemets plutt que comme une fonction. Voir le chapitre 5, Recherche de motif.

customer_8566

702

Chapitre 29 Fonctions

map
map BLOC LISTE map EXPR, LISTE

Cette fonction value le BLOC ou lEXPR pour chaque lment de LISTE (en affectant localement $_ chaque lment) et renvoie la liste compose des rsultats de chacune de ces valuations. Elle value BLOC ou EXPR dans un contexte de liste, ce qui fait que chaque lment de LISTE peut produire zro, un ou plusieurs lments dans la valeur renvoye. Ces lments sont tous rassembls en une seule liste plate. Par exemple :
@mots = map { split } @lignes;

clate une ligne en une liste de mots. Mais on observe souvent une correspondance bijective entre les valeurs de sortie et dentre :
@caracteres = map chr, @nombres;

convertit une liste de nombres vers leurs caractres correspondants. Voici un exemple de correspondance un-vers-deux :
%hachage = map { gen_clef($_) => $_ } @tableau;

qui nest quune faon amusante et fonctionnelle dcrire ceci :


%hachage = (); foreach $_ (@tableau) { $hachage{gen_clef($_)} = $_; }

Comme $_ est un alias (une rfrence implicite) pour les valeurs de la liste, on peut utiliser cette variable pour modifier les lments dans le tableau. Cest utile et support bien que cela puisse gnrer dtranges rsultats si la LISTE nest pas un tableau nomm. Lutilisation dune boucle foreach habituelle dans cet objectif peut paratre plus clair. Voir galement grep ; map diffre de grep en ce que map renvoie une liste compose des rsultats de chaque valuation successive de EXPR, alors que grep renvoie une liste compose de chaque valeur de LISTE pour laquelle EXPR est value vrai.

mkdir
mkdir REPERTOIRE, MASQUE mkdir REPERTOIRE

!X

Cette fonction cre le rpertoire spcifi par REPERTOIRE en lui donnant les permissions spcifies par le MASQUE numrique, modifi par le umask courant. Si lopration russie, elle renvoie vrai, sinon faux. Si MASQUE est omis, on suppose un masque de 0777, qui de toute faon est ce que vous voulez dans la plupart des cas. En gnral, crer des rpertoires avec un MASQUE permissif (comme 0777) et laisser lutilisateur modifier cela avec son umask est une meilleure habitude plutt que de fournir un MASQUE restrictif sans donner lutilisateur un moyen dtre plus permissif. Lexception cette rgle est le cas o le fichier ou le rpertoire doit rester priv (les fichiers mail, par exemple). Voir umask. Si lappel systme mkdir(2) nest pas intgr votre bibliothque C, Perl lmule en appelant le programme mkdir(1). Pour crer une longue liste de rpertoires sur ce genre

customer_8566

Fonctions Perl par ordre alphabtique

703

de systme, il sera plus efficace dappeler vous-mmes le programme mkdir avec la liste des rpertoires pour viter de crer des palanques de sous-processus.

msgctl
msgctl ID, CMD, ARG

!U

Cette fonction invoque lappel system msgctl(2) des IPC System V ; voir msgctl(2) pour plus de dtails. Il se peut que vous deviez faire un use IPC::SysV pour obtenir les dfinitions de constante correctes. Si CMD vaut IPC_STAT, ARG doit alors tre une variable qui contiendra la structure C msqid_ds renvoye. Les valeurs de retour fonctionnent comme celles de ioctl et fcntl : undef pour une erreur, 0 but true (N.d.T. : 0 mais vrai) pour zro ou la valeur relle dans les autres cas. Cette fonction nest disponible que sur les machines qui supportent les IPC System V ce , qui savre bien plus rare que celles qui supportent les sockets.

msgget
msgget CLEF, FLAGS

!U

Cette fonction invoque lappel systme msgget(2) des IPC System V Voir msgget(2) pour . plus de dtails. La fonction renvoie lID de file de messages ou undef sil y a une erreur. Avant dappeler, vous devez crire use IPC::Sys V. Cette fonction nest disponible que sur les machines qui supportent les IPC System V .

msgrcv
msgrcv ID, VAR, TAILLE, TYPE, FLAGS

!U

Cette fonction invoque lappel systme msgrcv(2) des IPC System V pour recevoir un message depuis la file de messages ID dans la variable VAR avec une taille maximum TAILLE. Voir msgrcv(2) pour plus de dtails. Lorsquun message est reu, le type de message sera la premire chose dans VAR et la longueur maximale de VAR sera TAILLE plus la taille du type de message. La fonction renvoie vrai si elle russit ou undef sil y a une erreur. Avant dappeler, vous devez crire use IPC::Sys V. Cette fonction nest disponible que sur les machines qui supportent les IPC System V .

msgsnd
msgsnd ID, MSG, FLAGS

!U

Cette fonction invoque lappel systme msgsnd(2) des IPC System V pour envoyer le message MSG dans la file de messages ID. Voir msgsnd(2) pour plus de dtails. MSG doit commencer par lentier long reprsentant le type de message. Vous pouvez crer un message comme ceci :
$msg = pack "L a*", $type, $texte_du_message;

La fonction renvoie vrai si elle russit ou undef sil y a une erreur. Avant dappeler, vous devez crire use IPC::Sys V. Cette fonction nest disponible que sur les machines qui supportent les IPC System V .

customer_8566

704

Chapitre 29 Fonctions

my
my my my my TYPE EXPR : ATTRIBUTS EXPR : ATTRIBUTS TYPE EXPR EXPR

Cet oprateur dclare une ou plusieurs variables prives comme nexistant que dans le bloc, le sous-programme, leval ou le fichier le plus intrieur les encadrant. Si plus dune valeur est liste, la liste doit tre place entre parenthses, car loprateur lie plus fortement que la virgule. Seuls les scalaires simples ou les tableaux et les hachages complets peuvent tre dclars de cette faon. Le nom de la variable ne peut pas tre qualifi par un paquetage, car les variables de paquetage sont toutes globalement accessibles par le biais de leur table de symboles correspondante tandis que les variables lexicales sont sans rapport avec une quelconque table de symboles. linverse de local, cet oprateur na rien voir avec les variables globales, sinon masquer une autre variable du mme nom dans sa porte (cest--dire, l o la variable prive existe). Cependant, une variable globale peut toujours tre atteinte sous sa forme qualifie par paquetage ou par le biais dune rfrence symbolique. La porte dune variable prive ne commence pas avant linstruction qui suit sa dclaration. Elle stend nimporte quel bloc contenu ensuite, jusqu la fin de la porte de la variable elle-mme. Cela signifie cependant que tout sous-programme que vous appelez dans la porte dune variable prive ne peut pas la voir, moins que le bloc qui dfinit le sous-programme lui-mme ne fasse textuellement partie de la porte de cette variable. Le terme technique consacr est porte lexicale, nous les appelons donc souvent variables lexicales. Dans la culture C, elles sont appeles variables auto, car elles sont automatiquement alloues et dsalloues respectivement lentre et la sortie de la porte. Vous pouvez si besoin assigner une valeur EXPR, ce qui vous permet dinitialiser les variables locales. (Si aucune initialisation explicite nest effectue, tous les scalaires sont initialiss la valeur indfinie et tous les tableaux et hachages la liste vide). Comme pour les affectations ordinaires, si lon utilise des parenthses autour des variables gauche (ou si la variable est un tableau ou un hachage), lexpression de droite est value dans un contexte de liste. Sinon, lexpression de droite est value dans un contexte scalaire. Par exemple, les paramtres formels de sous-programme peuvent tre nomms par une affectation de liste, comme ceci :
my ($amis, $romains, $paysans) = @_;

Mais prenez garde ne pas oublier les parenthses indiquant une affectation de liste, comme ceci :
my $pays = @_; # Est-ce correct ou pas ?

Ici, cest la longueur du tableau (cest--dire le nombre darguments du sous-programme) qui est assigne la variable, car le tableau est valu dans un contexte scalaire. Vous pouvez cependant employer laffectation scalaire pour un paramtre formel, tant que vous utilisez loprateur shift. En fait, comme les mthodes sont passes aux objets dans le premier argument, de nombreux sous-programmes mthodes commencent comme ceci :

customer_8566

Fonctions Perl par ordre alphabtique


sub simple_comme { my $obj = shift; my ($a,$b,$c) = @_; ... }

705

# affectation scalaire # affectation de liste

Si vous tentez de dclarer un sous-programme de porte lexicale avec my sub, Perl mourra avec le message que cette fonctionnalit na pas encore t implmente. (Sauf si bien sr, cette fonctionnalit a dj t implment.) Les TYPE et ATTRIBUTS sont optionnels, ce qui se justifie puisquils doivent tous deux tre considrs comme exprimentaux. Voici quoi ressemble une dclaration qui les utilise :
my Chien $medor :oreilles(courtes) :queue(longue);

Le TYPE, sil est spcifi, indique quelle sorte de scalaire ou de scalaires sont dclars dans EXPR, soit directement comme une ou plusieurs variables scalaires, soit indirectement par le biais dun tableau ou dun hachage. Si TYPE est le nom dune classe, on supposera que les scalaires contiennent des rfrences des objets de ce type, ou des objets compatibles avec ce type. En particulier, les classes drives sont considres comme compatibles. Cest--dire, en supposant que Colley soit drive de Chien, vous pouvez dclarer :
my Chien $lassie = new Colley;

Votre dclaration affiche que vous dsirez utiliser lobjet $lassie en accord avec son appartenance un objet Chien. Le fait que ce soit vraiment un objet Colley ne doit pas avoir dinf luence tant que vous vous lui faites faire des choses de Chien. Malgr la magie des mthodes virtuelles, limplmentation de ces mthodes de Chien peuvent trs bien tre dans la classe Colley, mais la dclaration ci-dessus ne parle que de linterface et pas de limplmentation. En thorie. De manire intressante, dans la version 5.6.0, la seule fois o Perl accorde une attention la dclaration de TYPE est lorsque la classe correspondante a dclar des champs avec le pragma use fields. Prises ensembles, ces dclarations permettent limplmentation dune classe en tant que pseudo-hachage de sexhiber au code qui se trouve lextrieur de la classe, permettant ainsi aux recherches dans le hachage dtre optimises par le compilateur comme tant des recherches dans un tableau. En un sens, le pseudo-hachage est linterface pour une telle classe, notre thorie reste donc intacte, si ce nest un peu cabosse. Pour plus dinformations sur les pseudo-hachages, voir la section Pseudo-hachages au chapitre 8, Rfrences. lavenir, dautres types de classes pourront interprter le TYPE diffremment. La dclaration de TYPE doit tre perue comme une interface de type gnrique qui pourra un jour tre instancie de diffrentes manires selon la classe. En fait, le TYPE pourra mme ne pas tre un nom de classe officiel. Nous rservons les noms de types en minuscules pour Perl, car lune des manires que nous prfrons pour tendre le type dinterface est dautoriser les dclarations de type de bas niveau comme int, num, str et ref. Ces dclarations ne seront pas destines un typage fort ; elles seront plutt des indications pour le compilateur, en lui disant doptimiser le stockage de la variable en supposant que cette variable sera le plus souvent utilise comme elle a t dclare. La smantique des scalaires restera peu prs la mme vous serez toujours capables dadditionner

customer_8566

706

Chapitre 29 Fonctions

deux scalaires str (N.d.T. : chanes) ou dafficher un scalaire int (N.d.T. : entier), exactement comme sils taient les scalaires polymorphes auxquels vous tes familiers. Mais avec une dclaration int, Perl pourra dcider de ne stocker que la valeur entire et doublier de sauver dans le cache la chane rsultante comme il le fait actuellement. Les boucles avec des variables de boucle int pourront tourner plus rapidement, spcialement dans le code compil en C. Les tableaux de nombres pourront en particulier tre stocks de manire plus compacte. Comme cas limite, la fonction interne vec deviendra mme obsolte alors que nous pourrons crire des dclarations comme :
my bit @chaine_de_bits;

La dclaration ATTRIBUTS est encore plus exprimentale. Nous navons pas fait grand chose de plus que rserver la syntaxe et prototyper linterface interne ; voir le pragma use attributes au chapitre 31 pour plus dinformations ce sujet. Le premier attribut que nous implmenterons est susceptible dtre constant :
my num $PI : constant = atan2(1,1) * 4;

Mais il y a beaucoup dautres possibilits, comme tablir des valeurs par dfaut pour les tableaux et les hachages ou laisser les variables partages entre des interprteurs cooprant. Comme linterface de type, linterface dattribut doit tre perue comme une interface gnrique, une sorte de cadre de travail pour inventer de nouvelles syntaxes et smantiques. Nous ne savons pas comment Perl voluera dans les dix prochaines annes. Nous savons seulement que nous pouvons le rendre plus simple pour nous-mmes en planifiant cela lavance. Voir galement local, our et la section Dclarations avec porte au chapitre 4.

new
new NOM_CLASSE new NOM_CLASSE LISTE

Il nexiste pas de fonction interne new. Il sagit plutt dun constructeur de mthode ordinaire (cest--dire un sous-programme dfini par lutilisateur) qui est dfini ou hrit par la classe NOM_CLASSE (cest--dire le paquetage) pour vous laisser construire des objets de type NOM_CLASSE. Beaucoup de constructeurs sont appels new , mais seulement par convention, juste pour jouer un tour aux programmeurs C++ en leur faisant croire quils savent ce quil se passe. Lisez toujours la documentation de la classe en question pour savoir comment appeler ses constructeurs ; par exemple, le constructeur qui cre une list box dans le widget Tk est juste appel Listbox(). Voir le chapitre 12.

next
next ETIQUETTE next

Loprateur next est semblable linstruction continue en C ; il dmarre litration suivante de la boucle dsigne par ETIQUETTE :
LIGNE: while (<STDIN>) { next LIGNE if /^#/; ... } # limine les commentaires

customer_8566

Fonctions Perl par ordre alphabtique

707

Sil y avait un bloc continue dans cet exemple, il sexcuterait immdiatement aprs linvocation de next. LorsquETIQUETTE est omise, la commande se rfre la boucle la plus intrieure lencadrant. Un bloc en soi-mme est smantiquement identique une boucle qui ne sexcute quune seule fois. Ainsi next peut quitter de manire anticipe un tel bloc (via le bloc continue, sil y en a un). next ne peut pas tre employ pour sortir dun bloc qui renvoie une valeur, comme eval {}, sub {} ou do {}, et ne doit pas tre utilis pour sortir dune opration grep ou map. Si les avertissements sont actifs, Perl vous prviendra si vous faites un next pour sortir dune boucle qui est hors de votre porte lexicale, comme une boucle dans une sous-routine appelante. Voir la section Instructions de boucle au chapitre 4.

no
no MODULE LISTE

Voir loprateur use, qui est linverse de no, plus ou moins. La plupart des modules standard ne non-importent rien, faisant de no une non-opration . Les modules pragmatiques ont tendance ici tre plus serviables. Si le MODULE nest pas trouv, une exception est leve.

oct
oct EXPR oct

Cette fonction interprte EXPR comme une chane octale et renvoie la valeur dcimale quivalente. Sil se trouve que EXPR commence par 0x , on linterprte comme une chane hexadcimale la place. Si EXPR dbute par 0b , on linterprte comme une chane de chiffres binaires. Ce qui suit convertit proprement en nombres nimporte quelle chane en base dcimale, binaire, octale ou hexadcimale dans la notation standard C ou C++ :
$val = oct $val id $val =~ /^0/;

Pour excuter la fonction inverse, utilisez sprintf avec le format appropri :


$perms = (stat("nom_fichier"))[2] & 07777; $perms_oct = sprintf "%lo", $perms;

La fonction oct est habituellement employe lorsquune donne sous forme de chane, comme 644 doit tre convertie vers un mode de fichier, par exemple. Bien que Perl convertisse automatiquement les chanes en nombres si besoin est, cette conversion automatique suppose que lon soit en base 10.

open
open HANDLE_FICHIER, MODE, LISTE open HANDLE_FICHIER, EXPR open HANDLE_FICHIER

!GUX

La fonction open associe un HANDLE_FICHIER interne la spcification dun fichier ex-

customer_8566

708

Chapitre 29 Fonctions

terne donne par EXPR ou LISTE. Elle peut tre appele avec un, deux ou trois arguments (ou plus si le troisime argument est une commande et que vous lancez au moins la version 5.6.1 de Perl). Si trois arguments ou plus sont prsents, le deuxime argument spcifie le MODE daccs avec lequel le fichier doit tre ouvert, et le troisime argument (LISTE) fournit le vritable nom de fichier ou la commande excuter, en fonction du MODE. Dans le cas dune commande, des arguments supplmentaires peuvent tre fournis si vous dsirez invoquer la commande directement sans impliquer un shell, un peu comme system ou exec. Sinon, la commande peut tre fournie comme un seul argument (le troisime), auquel cas la dcision dinvoquer le shell dpend du fait que la commande contienne ou non des mtacaractres du shell. (Nutilisez pas plus de trois arguments si les arguments sont des fichiers ordinaires ; cela ne fonctionnera pas.) Si le MODE nest pas reconnu, open lve une exception. Si seulement deux arguments sont prsents, on suppose que le mode et le nom de fichier ou de commande sont assembls dans le second argument. (Et si vous ne spcifiez aucun mode dans le second argument mais uniquement un nom de fichier, le fichier est alors ouvert en lecture seule pour raison de scurit.) Avec un seul argument, la variable scalaire de paquetage qui porte le mme nom (la variable, pas le paquetage !) que le HANDLE_FICHIER, doit contenir le nom du fichier et le mode optionnel :
$LOG = ">fichier_journal"; # $LOG ne doit pas tre dclare avec my ! open LOG or die "Impossible douvrir le fichier journal : $!";

Mais ne faites pas cela ! a manque de style. Oubliez que nous en avons parl. La fonction open renvoie vrai si elle russit, sinon undef. Si le open commence par un pipe sur un processus fils, la valeur de retour sera le PID de ce nouveau processus. Comme avec tout appel systme, vrifiez toujours la valeur de retour de open pour tre sr quil a march. Mais ce nest pas du C ou du Java, alors nemployez pas dinstruction if alors que loprateur or fait trs bien laffaire. Vous pouvez galement employer ||, mais dans ce cas, utilisez des parenthses autour du open. Si vous choisissez domettre les parenthses autour de lappel de fonction pour le changer en oprateur de liste, prenez garde bien utiliser or die aprs la liste plutt que || die , car la prsance de || est suprieure celle des oprateurs de liste comme open, et le || serait li votre dernier argument et non lopen tout entier :
open LOG, ">fichier_journal" || die "Impossible de crer le fichier journal : $!"; # FAUX open LOG, ">fichier_journal" or die "Impossible de crer le fichier journal : $!"; # ok

Cela semble plutt exagr, mais gnralement vous devriez insrer un quelconque caractre despacement pour que la fin de loprateur de liste vous saute aux yeux :
open LOG, ">fichier_journal" or die "Impossible de crer le fichier journal : $!";

Comme le montre cet exemple, largument HANDLE_FICHIER nest souvent quun simple identificateur (normalement en majuscules), mais il peut aussi tre une expression dont la valeur donne une rfrence vers le vritable handle de fichier. (La rfrence peut tre soit une rfrence symbolique vers le nom du handle de fichier, soit une rfrence en dur vers tout objet qui puisse tre interprt comme un handle de fichier.) On appelle

customer_8566

Fonctions Perl par ordre alphabtique

709

ceci un handle de fichier indirect, et toute fonction qui prend comme premier argument un HANDLE_FICHIER accepte les handles de fichiers aussi bien indirects que directs. Mais open est spcial, car si vous lui donnez une variable indfinie comme handle de fichier indirect, Perl dfinira automatiquement cette variable pour vous, cest--dire quelle sera autovivifie pour contenir la rfrence de handle de fichier adquat. Ceci a lavantage de fermer automatiquement le handle de fichier lorsquil ny a plus de rfrence sur lui, gnralement lorsque la variable quitte la porte courante :
{ my $hf; # (non initialise) open($hf, ">fichier_journal") # $hf est autovivifi or die "Impossible de crer le fichier journal : $!"; ... # faites ce que vous voulez avec $hf # fermeture de $hf ici

On peut lisiblement incorporer la dclaration my $hf lintrieur de lopen :


open my $hf, ">fichier_journal" or die

Le symbole > que vous venez de voir devant le nom de fichier est un exemple de mode. Historiquement, la forme avec deux arguments de open est apparue en premier. Le rcent ajout de la forme avec trois arguments vous permet de sparer le mode du nom de fichier, qui a lavantage dviter toute confusion possible entre les deux. Dans lexemple suivant, nous savons que lutilisateur nessaie pas douvrir un nom de fichier commenant par > . Nous pouvons tre srs quil spcifie un MODE valant > , ce qui ouvre en criture le fichier indiqu par EXPR, en le crant sil nexistait pas et en leffaant sil existait dj :
open(LOG, ">", "fichier_journal") or die "Impossible de crer le fichier journal : $!";

Dans les formes plus courtes, le nom de fichier et le mode se trouvent dans la mme chane. La chane est analyse un peu comme un shell typique traite les redirections de fichiers et de pipes. La chane est alors examine, par nimporte quelle extrmit si besoin, pour trouver les caractres spcifiant comment le fichier doit tre ouvert. Un espace est autoris entre le mode et le nom de fichier. Les modes qui indiquent comment ouvrir un fichier ressemblent aux symboles de redirection du shell. Le tableau 29-1 donne une liste de ces symboles. (Pour accder un fichier en combinant des modes douvertures non prsents dans cette table, voir la fonction de bas niveau sysopen.) Tableau 29-1. Modes pour open
Mode < CHEMIN > CHEMIN >> CHEMIN +< CHEMIN +> CHEMIN +>> CHEMIN Accs en lecture O N N O O O Accs en criture N O O O O O Ajout uniquement N N O N N O Crer si inexistant N O O N O O Vidage de lexistant N O N N O N

customer_8566

710
Tableau 29-1. Modes pour open
Mode | COMMANDE COMMANDE | Accs en lecture N O Accs en criture O N Ajout uniquement aucun aucun

Chapitre 29 Fonctions

Crer si inexistant aucun aucun

Vidage de lexistant aucun aucun

Si le mode est < ou rien du tout, un fichier existant est ouvert en lecture. Si le mode est > , le fichier est ouvert en criture, ce qui tronque les fichiers existants et cre ceux qui nexistent pas. Si le mode est >> , le fichier est cr si besoin et ouvert en ajout, et toutes les critures sont automatiquement places la fin du fichier. Si un nouveau fichier est cr parce que vous avez utilis > ou >> et que le fichier nexistait pas auparavant, les permissions daccs dpendront de lumask actuel du processus avec les rgles dcrites pour cette fonction. Voici quelques exemples courants :
open(INFO, "fichier_de_donnees") || die("Impossible douvrir le fichier de donnes : $!"); open(INFO, "< fichier_de_donnees") || die("Impossible douvrir le fichier de donnes : $!"); open(RESULTATS, "> stats_en_cours") || die("Impossible douvrir les stats en cours : $!"); open(LOG, ">> fichier_journal") || die("Impossible douvrir le fichier journal : $!");

Si vous prfrez la version avec moins de ponctuation, vous pouvez crire :


open INFO, "fichier_de_donnees" or die("Impossible douvrir le fichier de donnes : $!"); open INFO, "< fichier_de_donnees" or die("Impossible douvrir le fichier de donnes : $!"); open RESULTATS, "> stats_en_cours" or die("Impossible douvrir les stats en cours : $!"); open LOG, ">> fichier_journal" or die("Impossible douvrir le fichier journal : $!");

Lors dune ouverture en lecture, le nom de fichier spcial - se rfre STDIN. Lorsquil est ouvert en criture, ce mme nom de fichier spcial se rfre STDOUT. Normalement, on les spcifie respectivement avec <- et -> .
open(ENTREE, "-" ) or die; # rouvre lentre standard en lecture open(ENTREE, "<-") or die; # idem mais explicitement open(SORTIE, "->") or die; # rouvre la sortie standard en criture

De cette faon, lutilisateur peut fournir un programme un nom de fichier qui utilisera lentre ou la sortie standard, mais lauteur du programme na pas besoin dcrire de code particulier pour connatre ceci. Vous pouvez galement placer un + devant nimporte lequel de ces trois modes pour demander un accs en lecture/criture simultan. Cependant, le fait que le fichier soit vid ou cr et quil doit dj exister est toujours dtermin par votre choix du signe infrieur ou suprieur. Cela signifie que +< est toujours un meilleur choix pour des mises jour en lecture/criture, plutt que le mode douteux +> qui viderait tout dabord le fichier avant que vous puissiez y lire quoique ce soit. (Nutilisez ce mode que

customer_8566

Fonctions Perl par ordre alphabtique


si vous ne voulez relire que ce que vous venez dcrire.)
open(DBASE, "+<base_de_donnees") or die "Impossible douvrir la base de donnes en mise jour : $!";

711

Vous pouvez traiter un fichier ouvert en mise jour comme une base de donnes en accs direct et utiliser seek pour vous dplacer vers un nombre doctets particulier, mais les enregistrements de longueur variable rendent gnralement irralisables lemploi du mode lecture/criture pour mettre jour de tels fichiers. Voir loption de la ligne de commande -i au chapitre 19 pour une approche diffrente des mises jour. Si le premier caractre dans EXPR est un symbole pipe, open dclenche un nouveau processus et connecte un handle de fichier en criture seule avec la commande. De cette faon, vous pouvez crire dans ce handle et ce que vous y crivez sera pass lentre standard de cette commande. Par exemple :
open(IMPRIMANTE, "| lpr -Plp1) or die "Impossible de forker : $!"; print IMPRIMANTE "truc\n"; close(IMPRIMANTE) or die "chec de la fermeture de lpr : $?/$!";

Si le dernier caractre de EXPR est un symbole pipe, open lancera ici aussi un nouveau processus, mais cette fois connect un handle de fichier en lecture seule. Ceci permet tout ce que la commande crit sur sa sortie standard dtre pass dans votre handle pour tre lu. Par exemple :
open(RESEAU, "netstat -i -n |") or die "Impossible de forker : $!"; while (<RESEAU>) { ... } close RESEAU or die "Impossible de fermer netstat : $!/$?";

La fermeture explicite de tout handle de fichier pip entrane lattente du processus pre de la terminaison du processus fils et le retour dun code de statut dans $? ($CHILD_ERROR). Il est galement possible que close positionne $! ($OS_ERROR). Voir les exemples dans les descriptions de close et de system pour savoir comment interprter ces codes derreur. Toute commande pipe contenant des mtacaractres shell comme des jokers (N.d.T. : wildcards) ou des redirections dentre/sortie est passe votre shell canonique (/bin/sh sur Unix), ces constructions spcifiques au shell sont donc analyses en premier lieu. Si aucun mtacaractre nest trouv, Perl lance le nouveau processus lui-mme sans appeler le shell. Vous pouvez galement utiliser la forme trois arguments pour dmarrer des pipes. En utilisant ce style, lquivalent des ouvertures de pipe prcdentes serait :
open(IMPRIMANTE, "|-", "lpr -Plp1") or die "Impossible de forker : $!"; open(RESEAU, "-|", "netstat -i -n") or die "Impossible de forker : $!";

Ici le caractre moins dans le deuxime argument reprsente la commande du troisime argument. Ces commandes ninvoquent pas le shell, mais si vous souhaitez quaucun traitement du shell ne survienne, les nouvelles versions de Perl vous permettent dcrire :
open(IMPRIMANTE, "|-", "lpr", "-Plp1") or die "Impossible de forker : $!"; open(RESEAU, "-|", "netstat", "-i", "-n") or die "Impossible de forker : $!";

customer_8566

712

Chapitre 29 Fonctions

Si vous utilisez la forme deux arguments pour ouvrir un pipe ou la commande spciale - 7, un fork implicite est ralis en premier lieu. (Sur les systme qui ne savent pas forker, ceci lve une exception. Les systmes Microsoft ne supportaient pas le fork avant la version 5.6 de Perl.) Dans ce cas, le caractre moins reprsente votre nouveau processus fils, qui est une copie du pre. La valeur de retour de cet open forkant est lID du processus fils lorsquelle est examine par le pre, 0 lorsque cest par le fils et la valeur indfinie undef si le fork choue auquel cas, il ny a pas de fils. Par exemple :
defined($pid = open(DEPUIS_LE_FILS, "-|")) or die "Impossible de forker : $!"; if ($pid) { @lignes_pere = <DEPUIS_LE_FILS>; } else { print STDOUT @lignes_fils; }

# code du pre # code du fils

Le handle de fichier se comporte normalement pour le pre, mais pour le processus fils, lentre (ou la sortie) du pre est pipe depuis (ou vers) le STDOUT (ou le STDIN) du fils. Le processus fils ne voit pas le handle de fichier du pre comme tant ouvert. (Ceci est utilement indiqu par le PID de 0.) Gnralement vous devriez utiliser cette construction la place dun open pip classique lorsque vous voulez exercer plus de contrle sur la manire dont la commande pipe sexcute (comme lorsque vous excutez setuid) et que vous ne dsirez pas examiner si les commandes shells contiennent des mtacaractres. Les open pips suivant sont fortement quivalents :
open HF, "| tr a-z A-Z"; # pipe vers une commande shell open HF, "|-", tr, a-z, A-Z; # pipe vers une commande nue open HF, "|-" or exec tr, a-z, A-Z or die; # pipe vers un fils

tout comme celles-ci :


open HF, " cat -n fichier |"; # pipe vers une commande shell open HF, "-|", cat, -n fichier; # pipe vers une commande nue open HF, "-|" or exec cat, -n, fichier or die; # pipe vers un fils

Pour des utilisations plus labores de open fork, voir la section Soliloque au chapitre 16 et Nettoyage de votre environnement au chapitre 23, Scurit. Lorsque vous dmarrez une commande avec open, vous devez choisir soit lentre soit la sortie : cmd| pour la lecture ou |cmd pour lcriture. Vous ne pouvez pas utilisez open pour dmarrer une commande qui possdent des pipes la fois en entre et en sortie, comme la notation illgale (pour le moment) |cmd| semblerait lindiquer. Cependant, les routines standard de la bibliothque IPC::Open2 et IPC::Open3 vous donne une quivalence relativement proche. Pour plus de dtail sur les pipes double sens, voir la section Communication bidirectionnelle au chapitre 16. Vous pouvez galement spcifier, dans la plus pure tradition du Bourne Shell, une EXPR commenant par >&, auquel cas le reste de la chane est interprt comme le nom dun
7. Ou vous pouvez la considrer comme la porte de sortie de la commande des formes trois arguments ci-dessus.

customer_8566

Fonctions Perl par ordre alphabtique

713

handle de fichier (ou un descripteur de fichier, sil est numrique) que lon doit dupliquer en utilisant lappel systme dup2(2).8 Vous pouvez utiliser & aprs >, >>, +>, +>> et +<. (Le mode spcifi doit correspondre au mode du handle de fichier originel.) Une raison pour laquelle vous pourriez vouloir faire cela serait le cas o vous disposiez dores et dj un handle de fichier ouvert et que vous vouliez obtenir un autre handle de fichier qui soit rellement un duplicata du premier.
open(SORTIE_SAUVEE, ">&ERREUR_SAUVEE") or die "Impossible de dupliquer ERREUR_SAUVEE : $!"; open(MON_CONTEXTE, "<&4") or die "Impossible de dupliquer le descfic4 : $!";

Cela signifie que si une fonction attend un nom de fichier, mais si vous ne voulez pas lui en donner parce que vous disposez dj dun fichier ouvert, vous navez qu passer le handle de fichier prfix par une esperluette. Il vaut mieux tout de mme utiliser un handle pleinement qualifi, pour le cas o la fonction se trouve dans un autre paquetage :
une_fonction("&main::FICHIER_JOURNAL");

Une autre raison de dupliquer un handle de fichier est de rediriger temporairement un handle de fichier existant sans perdre la trace de la destination dorigine. Voici un script qui sauvegarde, redirige et restaure STDOUT et STDERR :
#!/usr/bin/perl open SORTIE_SAUVEE, ">&STDOUT"; open ERREUR_SAUVEE, ">&STDERR"; open STDOUT, ">truc.out" or die "Impossible de rediriger stdout"; open STDERR, ">&STDOUT" or die "Impossible de dupliquer stdout"; select STDERR; $| = 1; select STDOUT; $| = 1; # active le vidage de tampon automatique # active le vidage de tampon automatique

print STDOUT "stdout 1\n"; # ces flux dentre/sortie se propagent print STDERR "stderr 1\n"; # galement aux sous-processus system ("une commande"); # utilise les nouveaux stdout/stderr close STDOUT; close STDERR; open STDOUT, ">&SORTIE_SAUVEE"; open STDERR, ">&ERREUR_SAUVEE"; print STDOUT "stdout 2\n"; print STDERR "stderr 2\n";

Si le handle ou le descripteur de fichier est prcd par une combinaison &= au lieu dun simple &, alors au lieu de cr un descripteur de fichier compltement neuf, Perl fait de
8. Cela ne fonctionne pas (pour le moment) avec les objets dentre/sortie sur les rfrences de typeglobs par autovivification, mais vous pouvez toujours employer fileno pour aller chercher le descripteur de fichier et le dupliquer.

customer_8566

714

Chapitre 29 Fonctions

HANDLE_FICHIER un alias du descripteur existant en utilisant lappel fdopen(3) de la bibliothque C. Ceci est quelque peu plus parcimonieux en terme de ressources systme, bien que ce ne soit plus un gros problme de nos jours.
$df = $ENV{"DF_MON_CONTEXTE}; open(MON_CONTEXTE, "<&=$num_df" or die "fdopen sur le descripteur $num_fd impossible : $!\";

Les handles de fichiers STDIN, STDOUT et STDERR restent toujours ouvert travers un exec. Les autres handles de fichiers ne le restent pas, par dfaut. Sur les systmes qui supportent la fonction fcntl, vous pouvez modifiez le f lag close-on-exec (N.d.T. : indicateur de fermeture lors dun exec) pour un handle de fichier :
use Fcntl qw(F_GETFD F_SETFD); $flags = fcntl(HF, F_SETFD, 0) or die "Impossible de nettoyer le flag close-on-exec pour HF : $!\n";

Voir aussi la variable spciale $^F ($SYSTEM_MAX_FD) au chapitre 28. Avec les formes un ou deux arguments de open, vous devez faire attention lorsque vous utilisez une variable chane comme nom de fichier, puisque la variable peut contenir arbitrairement des caractres tranges (particulirement lorsque le nom du fichier a t obtenu partir dtranges caractres depuis Internet). Si vous ny prenez pas garde, certaines parties du nom de fichier peuvent tre interprtes comme une chane de MODE , des espaces ignorer, une spcification de duplication ou un signe moins. Voici une manire historiquement intressante de vous isoler :
$chemin =~ s#^(\s)#./$1#; open (HF, "< $chemin\0") or die "Impossible douvrir $chemin : $!";

Mais vous tes toujours vulnrables de plusieurs manires. la place, utiliser la forme trois arguments de open pour ouvrir proprement tout nom fichier arbitraire et sans aucun risque (supplmentaire) concernant la scurit :
open(HF, "<", $chemin) or die "Impossible douvrir $chemin : $!";

Dun autre ct, si ce que vous recherchez est un vritable appel systme dans le style de open(2) en C, avec les cloches et sirnes darrt qui sen suivent, alors investissez sur sysopen :
use Fcntl; sysopen(HF, $chemin, O_RDONLY) or die "Impossible douvrir $chemin : $!";

Si vous tes sur un systme qui fait la distinction entre les fichiers textes et binaires, vous pouvez avoir besoin de placer votre handle de fichier en mode binaire ou oubliez de faire cela, comme cela peut savrer pour viter de mutiler vos fichiers. Sur de tels systmes, si vous utilisez le mode texte avec des fichiers binaires, ou linverse, vous napprcierez certainement pas les rsultats. Les systmes qui ont besoin de la fonction binmode se distinguent des autres par le format employ pour les fichiers textes. Ceux qui sen passent, finissent chaque ligne avec un seul caractre correspondant ce que le C pense tre un saut de ligne, \n. Unix et Mac OS tombent dans cette catgorie. Les systmes dexploitation des autres varits VMS, MVS, MS-biduletrucmachinchouette et S&M traitent diffremment les entres/sorties dans les fichiers textes et binaires, ils ont donc besoin de binmode. Ou de son quivalent. Depuis la version 5.6 de Perl, vous pouvez spcifier le mode bi-

customer_8566

Fonctions Perl par ordre alphabtique

715

naire dans la fonction open sans un appel spar binmode. En tant que composantes de largument MODE (mais uniquement dans la forme trois arguments), vous pouvez spcifier diverses disciplines dentres/sorties. Pour obtenir lquivalent dun binmode, employez la forme trois arguments de open et donnez une discipline valant :raw aprs les autres caractres de MODE :
open(HF, "<:raw", $chemin) or die "Impossible douvrir $chemin : $!";

Puisquil sagit dune toute nouvelle fonctionnalit, il existera certainement plus de disciplines au moment o vous lirez ceci que lorsque nous lavons crit. Cependant, nous pouvons raisonnablement prdire quil y aura en toute vraisemblance des disciplines qui ressembleront pour toutes ou partie celles du tableau 29-2. Tableau 29-2. Disciplines dentres/sorties
Discipline :raw :text :def :latin1 :ctype :utf8 :utf16 :utf32 :uni :any :xml :crlf :para :slurp Signification Mode binaire ; ne pas traiter. Traitement par dfaut de texte. Dfaut dclar par use open . Le fichier doit tre en ISO-8859-1. Le fichier doit tre en LC_TYPE. Le fichier doit tre en UTF-8. Le fichier doit tre en UTF-16. Le fichier doit tre en UTF-32. Pressent de lUnicode (UTF-*). Pressent de lUnicode/Latin1/LC-CTYPE. Utilise lencodage spcifi dans le fichier. Pressent des sauts de lignes. Mode paragraphe. Mode par avalement tout rond.

Vous serez capables dempiler les disciplines susceptibles dtre empiles, ainsi, vous pourrez crire par exemple :
open(HF, "<:para:crlf:uni", $chemin) or die "Impossible douvrir $chemin : $!"; while ($para ) <HF>) { ... }

Ceci positionnera les disciplines : en lisant certaines formes dUnicode et en les convertissant vers le format interne de Perl UTF-8 si le fichier nest pas dores et dj en UTF-8 ; en cherchant les variantes des squences de fin de ligne et en les convertissant toutes vers \n, et ; en traitant le fichier paragraphe par paragraphe, un peu comme le fait $/="".

Si vous voulez positionner le mode douverture par dfaut (:def) autre chose que :text, vous pouvez dclarer ceci au tout dbut de votre fichier avec le pragma open :

customer_8566

716
use open IN => ":any", OUT => ":utf8";

Chapitre 29 Fonctions

En fait, ce serait vraiment beau si un jour ou lautre ctait la discipline :text par dfaut. Ceci ref lte bien lesprit du dicton : Soyez tolrant avec ce que vous acceptez et strict avec ce que vous produisez.

opendir
opendir HANDLE_REPERTOIRE, EXPR

!GUX

Cette fonction ouvre un rpertoire nomm EXPR pour le traiter par readdir, telldir, seekdir, rewinddir et closedir. La fonction renvoie vrai en cas de russite. Les handles de rpertoires possdent leur propre espace de nommage, spar de celui des handles de fichiers.

ord
ord EXPR ord

Cette fonction renvoie la valeur numrique (ASCII, Latin-1 ou Unicode) du premier caractre de EXPR. La valeur de retour est toujours non-signe. Si vous dsirez une valeur signe, utilisez unpack(c, EXPR). Si vous voulez convertir tous les caractres de la chane en une liste de nombres, utilisez unpack(U*, EXPR) la place.

our
our our our our TYPE EXPR : ATTRIBUTS EXPR : ATTRIBUTS TYPE EXPR EXPR

Un our dclare une ou plusieurs variables comme tant des variables globales valides lintrieur du bloc, du fichier ou de leval lencadrant. Cest--dire que lon dtermine la visibilit de our avec les mmes rgles quune dclaration my. Mais our ne cre pas de variable prive ; il permet simplement laccs sans entraves la variable de paquetage globale existante. Si plus dune valeur est liste, la liste doit tre place entre parenthses. Lutilisation principale dun our est de cacher la variable des effets dune dclaration use strict "vars" ; puisque la variable est masque comme une variable my, vous avez la permission dutiliser la variable dclare globale sans la qualifier avec son paquetage. Cependant, tout comme une variable my, cela ne marche que dans la porte lexicale de la dclaration our. En regard de ceci, our diffre de use vars, qui affecte le paquetage dans son entier et qui na pas de porte lexicale. our est galement semblable my en ce que vous tes autoris dclarer une variable avec un TYPE et des ATTRIBUTS. Voici la syntaxe :
our Chien $medor :oreilles(courtes) :queue(longue);

Au moment o nous crivons ceci, sa signification nest pas tout fait claire. Les attributs peuvent affecter soit la variable globale, soit linterprtation locale de $medor. Dun

customer_8566

Fonctions Perl par ordre alphabtique

717

ct, cela ressemblerait fort aux variables my pour les attributs que lon protge dun voile dans la vue locale actuelle de $medor, sans interfrer avec les autres vues de la variable globale dautres endroits. De lautre ct, si un module dclare $medor comme tant un Chien et quun autre dclare $medor en tant que Chat, vous pouvez finir avec des chiens miaulant et des chats aboyant. Cest un sujet de recherche active, ce qui est une manire polie de dire que nous ne savons pas de quoi nous parlons lheure actuelle. (Except que nous savons quoi faire avec une dclaration de TYPE lorsque la variable se rfre un pseudo-hachage voir Gestion des donnes dinstance au chapitre 12.) Une autre similitude entre our et my rside dans sa visibilit. Une dclaration our dclare une variable globale qui sera visible tout au long de sa porte lexicale, mme au-del des frontires de paquetages. Le paquetage dans lequel la variable est situe est dtermin lendroit de la dclaration, pas lendroit o on lutilise. Cela signifie que le comportement suivant est valide et quil est jug tre une fonctionnalit :
package Truc; our $machin; $machin = 582; package Machin print $machin; # $machin est $Truc::machin pour le reste de la # porte lexicale

# $affiche 582, comme si our avait t my

Toutefois, la distinction entre my qui cre une nouvelle variable prive et our qui expose une variable globale existante est importante, particulirement pour les affectations. Si vous combinez une affectation lexcution avec une dclaration our, la valeur de la variable globale ne disparatra pas une fois que le our sortira de la porte. Pour cela, vous avez besoin de local :
($x, $y) = ("un", "deux"); print "avant le bloc, x vaut $x, y vaut $y\n"; { our $x = 10; local our $y = 20; print "dans le bloc, x vaut $x, y vaut $y\n"; } print "aprs le bloc, x vaut $x, y vaut $y\n";

Cela affiche :
avant le bloc, x vaut un, y vaut deux dans le bloc, x vaut 10, y vaut 20 aprs le bloc, x vaut 10, y vaut deux

De multiples dclarations our dans la mme porte sont autorises si elles se trouvent dans des paquetages diffrents. Si elles se produisent dans le mme paquetage, Perl mettra des avertissements, si vous lui demandez de le faire.
use warnings; package Truc; our $machin; $machin = 20;

# dclare $Truc::machin pour le reste de la # porte lexicale

customer_8566

718
package Machin; our $machin = 30; print $machin; our $machin;

Chapitre 29 Fonctions

# dclare $Machin::machin pour le reste de la # porte lexicale # affiche 30 # met un avertissement

Voir aussi local, my et la section Dclarations avec porte au chapitre 4.

pack
pack CANEVAS, LISTE

Cette fonction prend une LISTE de valeurs ordinaires Perl, les convertit en une chane doctets en fonction du CANEVAS et renvoie cette chane. La liste darguments est complte ou tronque selon les besoins. Cest--dire que si vous fournissez moins darguments que nen requiert le CANEVAS, pack suppose que les arguments additionnels sont nuls. linverse, si vous fournissez plus darguments que nen requiert le CANEVAS, les arguments supplmentaires sont ignors. Les formats inconnus du CANEVAS lveront des exceptions. Le CANEVAS dcrit une structure de chane en tant que squence de champs. Chaque champ est reprsent par un seul caractre qui dcrit le type de la valeur et son encodage. Par exemple, un caractre de format valant N spcifie un entier non-sign de quatre octets dans lordre de la notation gros-boutiste (N.d.T. : big-endian). Les champs sont empaquets dans lordre donn par le CANEVAS. Par exemple, pour empaquet un entier sign dun octet et un nombre en virgule f lottante avec une simple prcision dans une chane, vous devez crire :
$chaine = pack("Cf", 244, 3.14);

Le premier octet de la chane renvoye a la valeur 244. Les octets restants reprsentent lencodage de 3.14 en tant que nombre f lottant en simple prcision. Lencodage particulier du nombre virgule f lottante dpend du matriel de votre ordinateur. Les points importants considrer lorsque vous utilisez pack sont : le type de donne (comme un entier, un nombre virgule f lottante ou une chane) ; lintervalle de valeurs (comme lorsque vos entiers occupent un, deux, quatre ou peut-tre mme huit octets ; ou si vous empaquetez des caractres 8-bits ou Unicode) ; si vos entiers sont signs ou non ; lencodage employer (comme un empaquetage de bits ou doctets en natif, en petit-boutiste ou en gros-boutiste.

Le tableau 29-3 liste les caractres de format et leurs significations. (Dautres caractres peuvent apparatre dans les formats ; ils seront dcrits plus tard.) Vous pouvez librement placer des espaces et des commentaires dans vos CANEVAS. Les commentaires commencent par le symbole # habituel et se prolongent jusqu la premire fin de ligne (sil y en a) dans le CANEVAS. Chaque lettre peut tre suivie par un nombre indiquant le compteur, que lon interprte comme le compteur de rptitions

customer_8566

Fonctions Perl par ordre alphabtique


Tableau 29-3. Caractres de canevas pour pack/unpack
Caractre a A b B c C d f h H i I l L n N p P q Q s S u U v V w x X Z @ Signification Une chane doctets, complte par des nuls. Une chane doctets, complte par des blancs.

719

Une chane de bits, dans lordre croissant des bits lintrieur de chaque octet (comme vec). Une chane de bits, dans lordre dcroissant des bits lintrieur de chaque octet. Une valeur caractre signe (entier 8-bits). Une valeur caractre non-signe (entier 8-bits) ; voir U pour Unicode. Un nombre virgule f lottante en double prcision au format natif. Un nombre virgule f lottante en simple prcision au format natif. Une chane hexadcimale, quartet de poids faible dabord. Une chane hexadcimale, quartet de poids fort dabord. Une valeur entire signe au format natif. Une valeur entire non-signe au format natif. Une valeur entire longue signe, toujours de 32 bits. Une valeur entire longue non-signe, toujours de 32 bits. Un court de 16 bits, dans lordre rseau (gros-boutiste). Un long de 32 bits, dans lordre rseau (gros-boutiste). Un pointeur sur une chane termine par un caractre nul. Un pointeur sur une chane de longueur fixe. Une valeur quad (entier de 64 bits) signe. Une valeur quad (entier de 64 bits) non-signe. Une valeur entire courte signe, toujours de 16 bits. Une valeur entire courte non-signe, toujours de 16 bits. Une chane uuencode. Un nombre en caractre Unicode. Un court de 16 bits dans lordre VAX (petit-boutiste). Un long de 32 bits dans lordre VAX (petit-boutiste). Un entier compress au format BER. Un octet nul (avance dun octet). Recule dun octet. Une chane doctets termine par un caractre nul (et complte par des nuls). Remplissage avec un caractre nul la position absolue.

ou la longueur en quelque sorte, selon le format. Avec tous les formats excepts a, A, b, B, h, H, P et Z, compteur est un compteur de rptition, pack engloutit autant de valeurs dans la LISTE. Un * pour le compteur signifie autant dentits quil en reste.

customer_8566

720

Chapitre 29 Fonctions

Les formats a, A et Z nengloutissent quune seule valeur, mais lempaqutent comme une chane doctets de longueur compteur, en la compltant avec des caractres nuls ou des espaces si besoin. Lorsquon dpaqute, A dpouille les espaces et les caractres nuls qui trane, Z dpouille tout ce qui se trouve aprs le premier caractre nul et a renvoie la donne littrale indemne. Lorsquon empaqute, a et Z sont quivalents. De mme, les formats b et B empaqutent une chane longue de compteur bits. Chaque octet du champ dentre gnre 1 bit dans le rsultat bas sur le bit le moins significatif de chaque octet dentre (cest--dire, sur ord($octet) % 2). Commodment, cela signifie que les octets 0 et 1 gnrent les bits 0 et 1. En partant du dbut de la chane dentre, chaque 8-tuple doctets est convertit vers un unique octet en sortie. Si la longueur de la chane dentre nest pas divisible par 8, le reste est empaquet comme sil tait complt par des 0s. De mme, durant le dpaquetage avec unpack les bits supplmentaires sont ignors. Si la chane dentre est plus longue que ncessaire, les octets supplmentaires sont ignors. Un * comme compteur signifie lutilisation de tous les octets du champ dentre. Durant le dpaquetage avec unpack, les bits sont convertis vers une chane de 0s et de 1s. Les formats h et H empaqutent une chane de compteur quartets (groupes de 4 bits souvent reprsents comme des chiffres hexadcimaux). Le format p empaqute un pointeur sur une chane termine par un caractre null. Il vous incombe de vous assurer que la chane nest pas une valeur temporaire (qui est susceptible dtre dsalloue avant que vous nayez fini dutiliser le rsultat empaquet) Le format P empaqute un pointeur vers une structure dont la taille est indique par compteur. Un pointeur nul est cr si la valeur correspondante pour p ou P est undef. Le caractre / permet dempaqueter et de dpaqueter des chanes dans lesquelles la structure empaquete contient un compteur sur un octet suivi par la chane elle-mme. On crit entit-longueur/entit-chane. Lentit-longueur peut tre nimporte quelle lettre canevas de pack et dcrit comment la valeur reprsentant la longueur est empaquete. Les canevas les plus susceptibles dtre utiliss sont ceux empaquetant des entiers comme n (pour les chanes Java), w (pour de lASN.1 ou du SNMP) et N (pour du XDR de Sun). Lentit-chane doit, prsent, tre A*, a* ou Z*. Pour unpack, la longueur de la chane est obtenue partir de lentit-longueur, mais si vous avez mis un *, elle sera ignore.
unpack C/a, "\04Gurusamy"; unpack a3/A* A*, 007 Bond J ; pack n/a* w/a*,bonjour,,le monde; # donne Guru # donne (Bond,J) # donne "bonjour, le monde"

unpack ne renvoie pas explicitement lentit-longueur. Lajout dun compteur la lettre de lentit-longueur nest pas susceptible dtre utile quoique ce soit, sauf si cette lettre est A, a ou Z. Lempaquetage avec une entit-longueur de a ou Z introduit des caractres nuls (\0), que Perl ne considre pas comme lgaux dans les chanes numriques. Les formats dentiers s, S, l et L peuvent tre immdiatement suivis par un ! pour signifier des entiers courts ou longs natifs la place de mesurer exactement 16 et 32 bits, respectivement. ce jour, cest un problme principalement pour les plates-formes 64 bits, o les entiers cours et longs natifs tel que les voient le compilateur local C peuvent tre compltement diffrents de ces valeurs. (i! et I! fonctionnent mais seulement cause de la compltude ; ils sont identiques i et I.)

customer_8566

Fonctions Perl par ordre alphabtique

721

La taille relle (en octets) des entiers, des courts, des longs et des longs longs natifs sur la plate-forme o Perl a t compil est galement disponible via le module Config :
use Config; print $Config{shortsize}, "\n"; print $Config{intsize}, "\n"; print $Config{longsize}, "\n"; print $Config{longlongsize}, "\n";

Le simple fait que Configure connaisse la taille dun long long , nimplique pas forcment que vous disposiez des formats q et Q. (Certains systmes en disposent, mais vous nen possdez certainement pas. Du moins pas encore.) Les formats dentiers dune longueur plus grande quun seul bit (s, S, i, I, l et L) sont intrinsquement non portables entre processeurs diffrents, car ils obissent lordre des octets natifs et au paradigme petit-boutiste/gros-boutiste. Si vous voulez des entiers portables, utilisez les formats n, N, v et V ; lordre de leurs bits et leur taille sont connus. Les nombres virgules f lottantes ne se trouvent que dans le format natif de la machine. cause de la varit des formats des f lottants et de labsence dune reprsentation rseau standard, il nexiste pas dinter-changes facilits. Cela signifie que si lon crit des donnes virgule f lottante empaquetes sur une machine, elles pourront ne pas tre lisibles sur une autre. Ceci est un problme mme lorsque les deux machines utilise larithmtique f lottante IEEE, car lordre (petit-boutiste/gros-boutiste) de la reprsentation en mmoire ne fait pas partie de la spcification IEEE. Perl utilise en interne des doubles pour tous les calculs en virgule f lottante, donc la conversion depuis un double vers un f loat, puis la conversion inverse perdra de la prcision. Cela signifie que unpack("f", pack("f", $truc)) ne sera gnralement pas gal $truc. Vous tes responsable de toute considration concernant les alignements ou les remplissages exigs par dautres programmes, particulirement par ces programmes crs par un compilateur C avec sa propre idiosyncrasie en matire de prsentation dune struct C sur larchitecture particulire en question. Vous devrez ajouter suffisamment de x durant lempaquetage pour compenser ceci. Par exemple, une dclaration C de :
struct machin { unsigned char c; float f; }

pourrait tre crite dans un format C x f , ou C x3 f , ou encore f C pour nen citer que quelques uns. Les fonctions pack et unpack grent leurs entres et leurs sorties comme des squences plates doctets car il ny a aucun moyen pour elles de savoir o vont les octets, n do ils viennent. Regardons quelques exemples. Cette premire paire empaqute des valeurs numriques dans des octets :
$sortie = pack "CCCC", 65, 66, 67, 68; $sortie = pack "C4", 65, 66, 67, 68; # $sortie eq "ABCD" # idem

Celui-ci fait la mme chose avec des lettres Unicode :


$machin = pack("U4",0x24b6,0x24b7,0x24b8,0x24b9);

customer_8566

722

Chapitre 29 Fonctions

Celui-l est similaire, avec une paire de caractres nuls rentrant en jeu :
$sortie = pack "CCxxCC", 65, 66, 67, 68 $sortie = pack "s2", 1, 2; # $sortie eq "AB\0\0CD"

Empaqueter vos entiers courts nimplique pas que vous soyez portable :
# "\1\0\2\0" en petit-boutiste # "\0\1\0\2" en gros-boutiste

Dans les paquets binaires et hexadcimaux, le compteur se rfre au nombre de bits ou de quartets, pas au nombre doctets produits :
$sortie = pack "B32", "01010000011001010111001001101100"; $sortie = pack "H8", "5065726c"; # les deux donnent "Perl"

La longueur dans un champ a ne sapplique qu une seule chane :


$sortie = pack "a4", "abcd", "x", "y", "z"; $sortie = pack "aaaa", "abcd", "x", "y", "z"; $sortie = pack "a" x 4, "abcd", "x", "y", "z"; # "abcd" # "axyz" # "axyz"

Pour contourner cette limitation, utilisez plusieurs spcificateurs :

Le format a remplit avec des caractres nuls :


$sortie = pack "a14", "abcdefg"; # "abcdefg\0\0\0\0\0\0\0"

Ce canevas empaqute un enregistrement de struct tm C (du moins sur certains systmes) :


$sortie = pack "i9pl", gmtime(), $tz, $toff;

Gnralement, le mme canevas peut galement tre utilis dans la fonction unpack, bien que certains formats se comportent diffremment, notamment a, A et Z. Si vous voulez joindre des champs de texte de taille fixe, utilisez pack avec un CANEVAS de format A ou a :
$chaine = pack("A10" x 10, @data);

Si vous voulez joindre des champs de texte de taille variable avec un sparateur, utilisez plutt la fonction join:
$chaine = join(" and ", @donnee); $chaine = join("", @donnee); # sparateur nul

Bien que tous nos exemples utilisent des chanes littrales comme canevas, il ny a rien qui vous interdise daller chercher vos donnes dans un fichier sur disque. Vous pouvez construire une base de donnes relationnelle complte autour de cette fonction. (Nous ne nous tendrons pas sur ce que cela prouverait sur votre nature.)

package
package ESPACE_DE_NOM package

Il ne sagit pas vraiment dune fonction, mais dune dclaration qui affirme que le reste de la porte la plus intrieure lencadrant appartient la table de symboles ou lespace de nom, indiqu. (La porte dune dclaration package est ainsi la mme que la porte dune dclaration my ou our.) lintrieur de cette porte, la dclaration force le com-

customer_8566

Fonctions Perl par ordre alphabtique

723

pilateur rsoudre tous les identificateurs non qualifis en les recherchant dans la table de symboles du paquetage dclar. Une dclaration package naffecte que les variables globales y compris celles sur lesquelles vous avez employ local et pas les variables lexicales dclares avec my. Elle affecte seulement les variables globales non qualifies ; celles qui sont qualifies avec leur propre nom de paquetage ignorent le paquetage actuellement dclar. Les variables globales dclares avec our ne sont pas qualifies et respectent par consquent le paquetage courant, mais seulement lendroit de leur dclaration, aprs quoi elles se comportent comme des variables my. Cest--dire que pour le reste de leur porte lexicale, les variables our sont cloues au paquetage courant au moment de leur dclaration, mme si une dclaration de paquetage ultrieure intervient. La dclaration package est gnralement la premire dun fichier inclure avec un oprateur require ou use, bien quelle puisse se trouver en tout endroit lgal pour une instruction. Lorsquon cre un fichier de module traditionnel ou orient objet, il est courant dappeler le paquetage avec le mme nom que le fichier pour viter toute confusion. (Il est galement courant de mettre la premire lettre du nom du paquetage en majuscule car les modules en minuscules sont interprts par convention comme tant des pragmas.) Vous pouvez passer dans un paquetage donn par plus plus dun endroit ; cela inf luence le choix de la table des symboles utilise par le compilateur pour le reste de ce bloc. (Si le compilateur rencontre un autre paquetage dclar au mme niveau, la nouvelle dclaration crase lancienne.) Votre programme principal est cens commencer par une dclaration package main. Vous pouvez vous rfrer des variables, des sous-programmes, des handles de fichier et des formats appartenant dautres paquetages en prfixant lidentificateur avec le nom du paquetage et un double deux-points : $Paquetage::Variable. Si le nom du paquetage est nul, le paquetage principal est pris par dfaut. Cest--dire que $::heureuse est quivalente $main::heureuse, tout comme $mainheureuse, que lon rencontre encore parfois dans danciens codes. Voici un exemple :
package main; $heureuse = "un poker de dames"; package Donne; $heureuse = "truque"; package Nimporte; print "Ma main heureuse est $main::heureuse.\n"; print "La donne heureuse est $Donne::heureuse.\n";

Ce qui affiche :
Ma main heureuse est un poker de dames. Ma donne heureuse est truque.

La table de symboles dun paquetage est stocke dans un hachage avec un nom se terminant par un double deux-points. La table de symboles du paquetage principal est par exemple appele %main::. On peut donc aussi accder au symbole *main::heureuse par $main::{"heureuse"}. Si ESPACE_DE_NOM est omis, il ny aura alors aucun paquetage courant et tous les identifiants devront tre pleinement qualifis ou dclars comme lexicaux. Cest encore plus strict quun use strict, puisque cela stend galement aux noms de fonctions.

customer_8566

724

Chapitre 29 Fonctions

Voir le chapitre 10, Paquetages, pour plus dinformations sur les paquetages. Voir my plus haut dans ce chapitre pour dautres considrations sur les portes.

pipe
pipe HANDLE_LECTURE, HANDLE_ECRITURE

!GU

Comme lappel systme correspondant, cette fonction ouvre deux pipes connects, voir pipe(2). Cet appel est presque toujours employ avant un fork, aprs lequel le lecteur du pipe doit fermer HANDLE_ECRITURE et celui qui crit doit fermer HANDLE_LECTURE. (Sinon le pipe nindiquera pas la fin de fichier celui qui lit quand celui qui crit le fermera.) Si vous lancez une boucle de processus par des pipes, un verrou mortel peut se produire moins dtre trs prudent. Notez de plus que les pipes de Perl utilisent des tampons dentres/sorties standard et quil vous faut donc positionner $| ($OUTPUT_AUTOFLUSH) sur votre HANDLE_ECRITURE pour vider les tampons aprs chaque opration de sortie, selon lapplication - voir select(handle de fichier de sortie). (Comme avec open, si lun des handle de fichier est indfini, il sera autovivifi.) Voici un petit exemple :
pipe(LISEZ_MOI, ECRIVEZ_MOI); unless ($pid = fork) { # fils defined $pid or die "Impossible de forker : $!"; close(LISEZ_MOI); for $i (1..5) { print ECRIVEZ_MOI "ligne $i\n" } exit; } $SIG{CHLD} = sub { waitpid($pid, 0) }; close(ECRIVEZ_MOI); @chaines = <LISEZ_MOI>; close(LISEZ_MOI); print "Reu: \n", @chaines;

Remarquez comment lcrivain ferme lextrmit de lecture et comment linverse le lecteur ferme lextrmit dcriture. Vous ne pouvez pas utiliser un seul pipe pour une communication double sens. Utilisez pour cela soit deux pipes diffrents, soit lappel systme socketpair. Voir la section Pipes au chapitre 16.

pop
pop TABLEAU pop

Cette fonction traite un tableau comme une pile elle dpile (enlve) et renvoie la dernire valeur du tableau en le raccourcissant dun lment. Si TABLEAU est omis, la fonction dpile @_ dans la porte lexicale des sous-programmes et formats ; elle dpile @ARGV dans la porte des fichiers (gnralement le programme principal) ou lintrieur de la porte lexicale tablie par les constructions eval CHAINE, BEGIN {}, CHECK {}, INIT {} et END {}. Elle entrane les mmes effets que :
$tmp = $TABLEAU{$#TABLEAU--};

customer_8566

Fonctions Perl par ordre alphabtique


ou que :
$tmp = splice @TABLEAU, -1;

725

Sil ny a pas dlment dans le tableau, pop renvoie undef. (Mais ne vous basez pas sur ceci pour vous dir que le tableau est vide si votre tableau continent des valeurs undef !) Voir galement push et shift. Pour dpiler plus dun lment, utilisez splice. Le premier argument de pop doit tre un tableau et non une liste. Pour obtenir le dernier lment dune liste, utilisez ceci :
( LISTE )[-1]

pos
pos SCALAIRE pos

Cette fonction renvoie lendroit de SCALAIRE o la dernire recherche m//g sest arrte. Elle renvoie le dcalage du caractre suivant celui qui correspondait. (Cest--dire que cest quivalent length($) + length($&).) Il sagit du dcalage o la prochaine recherche m//g sur cette chane dmarrera. Rappelez-vous que le dcalage dbut de la chane est 0. Par exemple :
$grafitto = "fee fie foe foo"; while ($grafitto =~ m/e/g) { print pos $grafitto, "\n"; }

affiche 2, 3, 7 et 11, les dcalages de chacun des caractres suivant un e . On peut assigner pos une valeur pour indiquer m//g do partir :
$grafitto = "fee fie foe foo"; pos $grafitto = 4; # Sauter le fee, commencer fie while ($grafitto =~ m/e/g) { print pos $grafitto, "\n"; }

Cela naffiche que 7 et 11. Lassertion \G ne recherche de correspondance qu lendroit spcifi par pos ce moment dans la chane dans laquelle on recherche. Voir la section Positions au chapitre 5.

print
print HANDLE _FICHIER print LISTE print LISTE

_!G

Cette fonction affiche une chane ou une liste de chanes spares par des virgules. Si la variable $\ ($OUTPUT_RECORD_SEPARATOR) est positionne, son contenu sera affich implicitement la fin de la liste. La fonction renvoie vrai en cas de russite, sinon faux. HANDLE_FICHIER peut tre un nom de variable scalaire (non indice), auquel cas la variable contient la nom du vritable handle de fichier ou une rfrence un objet handle de fichier dune quelconque sorte. HANDLE_FICHIER peut galement tre un bloc qui renvoie une telle valeur :

customer_8566

726
print { $OK ? "STDOUT" : "STDERR" } "$truc\n"; print { $handle_entrees_sorties[$i] } "$truc\n";

Chapitre 29 Fonctions

Si HANDLE_FICHIER est une variable et que le token suivant est un terme, elle peut tre prise tort pour un oprateur moins que vous ninterposiez un + ou ne mettiez des parenthses autour des arguments. Par exemple :
print $a - 2; # envoie $a - 2 sur le handle par dfaut (en gnral STDOUT) print $a (- 2); # envoie -2 sur le handle de fichier spcifi par $a print $a -2; # idem (rgles danalyse bizarres :-)

Si HANDLE_FICHIER est omis, la fonction affiche sur le handle de fichier de sortie actuellement slectionn, initialement STDOUT. Pour mettre le handle de fichier de sortie par dfaut autre chose que STDOUT, utilisez lopration select HANDLE_FICHIER.9 Si LISTE est galement omise, la fonction affiche $_. Comme print prend une LISTE en argument, tout lment de cette LISTE est valu dans un contexte de liste. Ainsi quand vous crivez :
print SORTIE <STDIN>;

ce nest pas la ligne suivante de lentre standard qui va tre affiche, mais toutes les lignes de lentre standard jusqu la fin du fichier, puisque cest ce que <STDIN> renvoie dans un contexte de liste. Si vous voulez autre chose, crivez :
print SORTIE scalar <STDIN>;

De mme, en se souvenant de la rgle si-a-ressemble--une-fonction-cest-une-fonction, faites attention ne pas faire suivre le mot-cl print dune parenthse gauche moins que la parenthse droite correspondante ne termine les arguments du print- interposez un + ou mettez des parenthses tous les arguments :
print (1+2)*3, "\n"; # mauvais print +(1+2)*3, "\n"; # ok print ((1+2)*3, "\n"); # ok

printf
printf HANDLE_FICHIER FORMAT, LISTE printf FORMAT, LISTE

_!G

Cette fonction affiche une chane formate sur HANDLE_FICHIER ou, sil est omis, sur le handle de fichier de sortie courant, initialement STDOUT. Le premier lment de LISTE doit tre une chane qui indique comme formater les lments suivants. La fonction est similaire printf (3) et fprintf (3). La fonction est exactement quivalente :
print HANDLE_FICHIER sprintf FORMAT, LISTE

sauf que $\ ($OUTPUT_RECORD_SEPARATOR) nest pas ajout la fin. Si use locale est actif, le caractre utilis comme sparateur de la partie dcimale dans les nombres virgule f lottante est affect par la locale LC_NUMERIC. Une exception nest leve que si un type de rfrence invalide est employ pour largu-

9. STDOUT nest donc pas vraiment le handle de fichier par dfaut pour print. Il est en fait le handle de fichier par dfaut du dfaut.

customer_8566

Fonctions Perl par ordre alphabtique

727

ment HANDLE_FICHIER. Les formats inconnus sont sauts sans modification. Ces deux situations dclenchent des avertissements si ceux-ci sont activs. Voir les fonctions print et sprintf ailleurs dans ce chapitre. La description de sprintf inclut la liste des spcifications des formats. Nous laurions volontiers reproduite ici, mais ce livre est dores et dj un dsastre cologique. Si vous omettez la fois le FORMAT et la LISTE, $_ est utilis mais dans ce cas, vous auriez d utiliser print. Ne tombez pas dans le pige dutiliser un printf lorsquun simple print aurait trs bien fait laffaire. La fonction print est bien plus efficace et bien moins sujette erreurs.

prototype
prototype FONCTION

Renvoie le prototype dune fonction dans une chane (ou undef si la fonction na pas de prototype). FONCTION est une rfrence vers, ou le nom de, la fonction pour laquelle vous dsirez trouver le prototype. Si FONCTION est une chane commenant par CORE::, la suite est prise en tant que nom pour les fonctions internes de Perl, et une exception est leve sil nexiste pas de telle fonction interne. Si la fonction interne nest pas surchargeable (comme qw//) ou si ses arguments ne peuvent pas tre exprims par un prototype (comme system), la fonction renvoie undef car la fonction interne ne se comporte pas vritablement comme une fonction Perl. Sinon, la chane dcrivant le prototype quivalent est renvoye.

push
push TABLEAU push

Cette fonction traite TABLEAU comme une pile et empile les valeurs de LISTE la fin du tableau. La taille de TABLEAU est allonge de la longueur de LISTE. La fonction renvoie cette nouvelle taille. La fonction push entrane les mmes effets que :
foreach $valeur (fonction_liste()) { $tableau[++$#tableau] = $valeur; }

ou que :
splice @tableau, @tableau, 0, fonction_liste();

mais est beaucoup plus performante ( la fois pour vous et pour votre ordinateur). Vous pouvez utilisez push associe avec shift pour construire une file ou un registre dcalage assez efficace :
for (;;) { push @tableau, shift @tableau; ... }

Voir galement pop et unshift.

customer_8566

728

Chapitre 29 Fonctions

q/CHAINE/
q/CHAINE/ qq/CHAINE/ qr/CHAINE/ qw/CHAINE/ qx/CHAINE/

Protections gnralises. Voir la section Choisissez vos dlimiteurs au chapitre 2. Pour les annotations de statut pour qx//, voir readpipe. Pour les annotations de statut pour qr//, voir m//. Voir galement Garder le contrle au chapitre 5.

quotemeta
quotemeta EXPR quotemeta

Cette fonction renvoie la valeur de EXPR avec tous les caractres non alphanumriques prcds dun backslash (\). (Cest--dire que tous les caractres ne correspondant pas /[A-Za-z_0-9]/ seront prcds dun backslash dans la chane renvoye, sans tenir compte des valeurs des locales.) Il sagit de la fonction interne implmentant lchappement \Q dans les contextes dinterpolation (comprenant les chanes entre guillemets, entre apostrophes inverses ou les motifs).

rand
rand EXPR rand

Cette fonction renvoie un nombre virgule f lottante pseudo-alatoire suprieur ou gal 0 et infrieur la valeur de EXPR. (EXPR doit tre positif.) Si EXPR est omise, la fonction renvoie un nombre virgule f lottante entre 0 et 1 (comprenant 0, mais excluant 1). rand appelle automatiquement srand sauf si la fonction srand a dj t appele. Voir galement srand. Pour obtenir une valeur entire, comme pour un lancer de d, combinez ceci avec int, comme dans :
$lancer = int(rand 6) +1; # $lancer est maintenant un entier # compris entre 1 et 6

Comme Perl utilise la fonction pseudo-alatoire de votre propre bibliothque C, comme random(3) ou drand48(3), la qualit de la distribution nest pas garantie. Si vous avez besoin dalatoire plus fort, comme pour de la cryptographie, vous devriez plutt consulter la documentation de random(4) (si votre systme possde un priphrique /dev/random ou /dev/urandom), le module Math::TrulyRandom de CPAN, ou un bon bouquin sur la gnration de nombres pseudo-alatoires en informatique, comme le second volume de Knuth.10

10. Knuth, D.E. The Art of Computer Programming, Seminumerial Algorithms, vol. 2, 3rd ed. (Reading, Mss.: Addison-Wesley, 1997). ISBN 0-201-89684-2.

customer_8566

Fonctions Perl par ordre alphabtique

729

read
read HANDLE_FICHIER, SCALAIRE, LONGUEUR, DECALAGE read HANDLE_FICHIER, SCALAIRE, LONGUEUR

!tGO

Cette fonction essaye de lire LONGUEUR octets de donnes dans la variable SCALAIRE depuis le HANDLE_FICHIER spcifi. La fonction renvoie le nombre doctets rellement lus ou 0 en fin de fichier. undef est renvoye en cas derreur. SCALAIRE est ajust la taille rellement lue. Le DECALAGE, sil est spcifi, indique lendroit de la variable partie duquel commencer crire des octets, vous pouvez ainsi lire au milieu dune chane. Pour copier des donnes du handle de fichier DEPUIS dans le handle VERS, vous pouvez crire :
while (read DEPUIS, $tampon, 16384) { print VERS $tampon; }

Linverse dun read est simplement print, qui connat dj la longueur de la chane crire, et qui peut crire une chane de nimporte quelle longueur. Ne faites pas lerreur demployer write, qui est uniquement utilis dans les formats. La fonction read de Perl est en fait implmente par la fonction dentre/sortie standard fread(3), ce qui fait que le vritable appel systme read(2) peut lire plus que LONGUEUR octets pour remplir le tampon dentre et que fread(3) peut faire plus dun appel systme read(2) pour remplir ce tampon. Vous pouvez spcifier lappel systme rel par sysread pour mieux contrler les entres/sorties. Les appels read et sysread ne doivent pas tre mlangs moins dtre adepte des sciences occultes (ou des soires cuir et chanes). Quelle que soit celle que vous employez, faites attention : lorsque vous lisez depuis un fichier contenant un encodage Unicode ou nimporte quel encodage sur plusieurs octets, les limites du tampon peuvent tomber au milieu dun caractre.

readdir
readdir HANDLE_REPERTOIRE

!TGU

Cette fonction lit les entres de rpertoire (qui ne sont que de simples noms de fichiers) depuis un handle de rpertoire ouvert par opendir. Dans un contexte scalaire, cette fonction renvoie lentre de rpertoire suivante si elle existe, undef sinon. Dans un contexte de liste, elle renvoie le reste des entres du rpertoire, ce qui donnera bien sr une liste nulle sil ny en a plus. Par exemple :
opendir(CE_REP, "." or die "srieusement endommag : $!"; @tous_les_fichiers = readdir CE_REP; closedir CE_REP; print "@tous_les_fichiers\n";

Ceci affiche tous les fichiers du rpertoire courant sur une seule ligne. Pour viter les entres . et .. , employez lune de ces incantations (quelle que soit celle laquelle vous pensez, elle sera moins illisible) :
@tous_les_fichiers @tous_les_fichiers @tous_les_fichiers @tous_les_fichiers = = = = grep grep grep grep { $_ ne . and $_ ne .. } readdir CE_REP; { not /^[.][.]?\z/ } readdir CE_REP; { not /^\.{1,2}\z/ } readdir CE_REP; !/^\.\.?\z/, readdir CE_REP;

customer_8566

730
Et pour viter tous les fichiers .*, crivez ceci :
@tous_les_fichiers = grep !/^\./, readdir CE_REP;

Chapitre 29 Fonctions

Pour ne lister que les fichiers texte, crivez :


@fichiers_texte = grep -T, readdir CE_REP;

Mais attention ce dernier exemple, car le rpertoire doit tre recoll au rsultat de readdir si ce nest pas le rpertoire courant comme ceci :
opendir(CE_REP, $chemin); or die "opendir $chemin impossible : $!" ; @fichiers_points = grep { /^\./ && -f } map { "$chemin/$_" } readdir(CE_REP); closedir CE_REP;

readline
readline HANDLE_FICHIER

!tG

Il sagit de la fonction interne implmentant loprateur <HANDLE_FICHIER>, mais vous pouvez lutiliser directement. La fonction lit lenregistrement suivant depuis HANDLE_FICHIER, qui peut tre un nom de handle de fichier ou une expression de handle de fichier indirect renvoyant soit le nom dun vritable handle de fichier, soit une rfrence quoique ce soit ressemblant une objet handle de fichier, comme un typeglob. (Les versions de Perl antrieures la 5.6 acceptent seulement un typeglob.) Dans un contexte scalaire, chaque appel lit et renvoie le prochain enregistrement jusqu ce que lon atteigne la fin de fichier, avec laquelle lappel suivant renvoie undef. Dans un contexte de liste, readline lit tous les enregistrements jusqu atteindre la fin de fichier et renvoie alors une liste denregistrements. Par enregistrements , il faut normalement entendre une ligne de texte, mais si la variable spciale $/ ($INPUT_RECORD_SEPARATOR) est diffrente de sa valeur par dfaut, loprateur avalera le texte diffremment. De mme, certaines disciplines en entre, comme :para (mode paragraphe) renverront des enregistrements par morceaux, autres que des lignes. Le positionnement de la discipline :slurp (ou $/ = undef) entranera lavalement du fichier entier. Lorsquon avale des fichiers tout rond dans un contexte scalaire, sil vous arrive de gober un fichier vide, readline renvoie "" la premire fois et undef toutes les fois suivantes. Si lon avale tout rond en partant du handle de fichier magique ARGV chaque fichier ren, voie une seule bouche (encore une fois, les fichiers vides renvoient ""), suivi par un seul undef lorsque tous les fichiers on t digrs. De plus amples dtails sur loprateur <HANDLE_FICHIER> sont donns dans la section Oprateurs dentre au chapitre 2.
$ligne $ligne $ligne $ligne = = = = <STDIN>; readline(STDIN); readline(*STDIN); readline(\*STDIN); # idem # idem # idem

open my $hf, "<&=STDIN" or die; bless $hf => UneVieilleClasse; $ligne = readline($hf); # idem

customer_8566

Fonctions Perl par ordre alphabtique

731

readlink
readlink EXPR readlink

_!TU

Cette fonction renvoie le nom dun fichier point par un lien symbolique. EXPR doit donner le nom dun fichier dont la dernire composante est un lien symbolique. Sil ne sagit pas dun lien symbolique, ou si les liens symboliques ne sont pas implments dans le systme de fichier, ou encore si une erreur se produit, la fonction renvoie la undef et vous devrez vrifier le code derreur dans $!. Prenez garde car le lien symbolique renvoy peut tre relatif lendroit spcifi. Par exemple, vous pouvez crire :
readlink "/usr/local/src/exprimez/vous.h"

et readlink pourrait renvoyer :


../exprimez.1.23/includes/vous.h

ce qui nest pas franchement utile moins que le rpertoire courant ne soit justement /usr/local/src/exprimez.

readpipe
readpipe scalar EXPR readpipe LIST ( ltude)

!?TXU

Il sagit de la fonction interne implmentant la construction protge qx// (connue galement en tant quoprateur apostrophes inverses). Elle est parfois commode lorsque vous avez besoin de spcifier votre EXPR dune manire qui ne serait pas pratique avec les apostrophes. Prenez garde car nous pourrions modifier lavenir cette interface pour supporter un argument LISTE qui la ferait plus ressembler la fonction exec, nimaginez donc pas quelle continuera fournir un contexte scalaire pour EXPR. Indiquez vous-mme scalar ou utilisez la forme avec LISTE. Qui sait, peut-tre cela fonctionnera-t-il au moment o vous lirez ceci.

recv
recv SOCKET, SCALAIRE, LONGUEUR, FLAGS

!tGOU

Cette fonction reoit un message sur une socket. Elle sattend recevoir LONGUEUR octets de donnes dans la variable SCALAIRE depuis le handle de fichier SOCKET. La fonction renvoie ladresse de lexpditeur, ou undef sil y a une erreur. SCALAIRE est ajust la longueur effectivement lue. Les FLAGS de la fonction sont les mmes que ceux de recv(2). Voir la section Sockets au chapitre 16.

redo
redo ETIQUETTE redo

Loprateur redo recommence le bloc dune boucle sans rvaluer la condition. Le bloc continue, sil existe, nest pas excut. Si lETIQUETTE est omise, loprateur se rfre la

customer_8566

732

Chapitre 29 Fonctions

boucle la plus interne lencadrant. Cet oprateur est normalement utilis par les programmes qui souhaitent dissimuler eux-mme ce qui vient dtre entr :
# Une boucle qui joint les lignes coupes par un antislash. while (<STDIN>) { if (s/\\\n$// && defined($ligne_suivante = <STDIN>)) { $_ .= $ligne_suivante; redo LIGNE; } print; # ou ce que vous voulez }

On ne peut pas utiliser redo pour sortir dun bloc qui renvoie une valeur comme eval {}, sub {} ou do {}, ni dune opration grep ou map. Si les avertissements sont actifs, Perl vous avertira si vous faites un redo dans une boucle qui ne se trouve pas dans votre porte lexicale courante. Un bloc en soi-mme est smantiquement identique une boucle qui ne sexcute quune seule fois. Ainsi redo lintrieur un tel bloc le changera en une construction de boucle. Voir la section Contrle de boucle au chapitre 4.

ref
ref EXPR ref

Loprateur ref renvoie une valeur vraie si EXPR est une rfrence, sinon faux. La valeur renvoye dpend du type dobjet auquel il est fait rfrence. Les types intgrs comprennent :
SCALAR ARRAY HASH CODE GLOB REF LVALUE IO::Handle

Si lobjet rfrenc a t consacr (avec bless) dans un paquetage, cest le nom du paquetage qui est renvoy. Vous pouvez voir ref comme une sorte doprateur typeof .
if (ref($r) eq "HASH") { print "r est une rfrence un hachage.\n"; } elsif (ref($r) eq "Bosse") { # Vilain, voir ci-dessous. print "r est une rfrence un objet Bosse.\n"; } elsif (not ref ($r)) { print "r nest pas du tout une rfrence.\n"; }

On considre que tester lgalit de votre classe dobjet avec une classe particulire est une erreur de style OO (orient objet), puisquune classe drive aura un nom diffrent mais devra permettre laccs aux mthodes de la classe de base. Il vaut mieux utiliser la mthode isa de la classe UNIVERSAL comme ceci :

customer_8566

Fonctions Perl par ordre alphabtique

733

if ($r->isa("Bosse")) { print "r est une rfrence un objet Bosse, ou une sous-classe.\n"; }

Il vaut mieux normalement ne rien tester du tout, puisque le mcanisme OO nenverra pas lobjet votre mthode sauf sil pense quelle est la plus approprie. Voir les chapitres 8 et 12 pour plus de dtails. Voir aussi la fonction reftype dans le pragma use attributes au chapitre 31.

rename
rename ANCIEN_NOM, NOUVEAU_NOM

Cette fonction change le nom dun fichier. Elle renvoie vrai en cas de succs et faux sinon. Elle ne fonctionnera pas (normalement) travers les frontires des systmes de fichiers, bien que sur un systme Unix, la commande mv puisse parfois tre utilise pour compenser cela. Si un fichier nomm NOUVEAU_NOM existe dj, il sera dtruit. Les systmes non-Unix peuvent comporter des restrictions supplmentaires. Voire le module standard File::Copy pour renommer les fichiers dun systme de fichiers lautre.

require
require VERSION require EXPR require

_!@X

Cette fonction exprime une sorte de dpendance envers son argument. Si largument est une chane, require charge et excute le code Perl trouv dans le fichier spar dont le nom est donn par la chane. Ceci est similaire lexcution dun do, mis part que require vrifie si le fichier de bibliothque a dj t charg et lve une exception si un quelconque problme est rencontr. (On peut donc lutiliser pour exprimer des dpendances de fichiers sans se soucier dune duplication de la compilation.) Comme ses cousines do et use, require sait comment rechercher le chemin dinclusion, stock dans le tableau @INC et sait galement mettre jour %INC en cas de succs. Voir le chapitre 28. Le fichier doit renvoyer vrai comme dernire valeur pour indiquer lexcution russie du code dinitialisation, il est donc habituel de terminer ce genre de fichier par un 1;, moins que vous ne soyez srs quil renverra vrai de toute faon. Si largument de require est un numro de version de la forme 5.6.2, require exige que la version de Perl entrain dtre excut soit gale ou suprieure ce numro de version. (Perl accepte galement un nombre virgule f lottante comme 5.005_03 pour une compatibilit avec les anciennes versions de Perl, mais cette forme est maintenant fortement dconseille car les foules venant dautres cultures ne la comprenne pas.) Ainsi, un script qui requiert Perl version 5.6 peut commencer par :
require 5.6.0 # ou require v5.6.0

et les versions plus anciennes de Perl choueront. Cependant, comme tous les require, la vrification est ralise lors de lexcution. Vous pouvez prfrer crire use 5.6.0

customer_8566

734

Chapitre 29 Fonctions

pour un test la compilation. Voir aussi $PERL_VERSION au chapitre 28. Si largument de require est le nom dnud dun paquetage (voir package), require suppose que le suffixe est automatiquement .pm, facilitant ainsi le chargement de modules standard. Cela ressemble use, mis part le fait que cela se produit lexcution et non la compilation et que la mthode dimport nest pas appele. Par exemple, pour charger Socket.pm sans introduire aucun symbole dans le package courant, crivez ceci :
require Socket; # au lieu de "use Socket;"

Mais on peut toutefois obtenir le mme effet avec ce qui suit, qui procure lavantage de donner des avertissements la compilation si Socket.pm ne peut tre trouv :
use Socket ();

Lutilisation de require sur un nom dnud de paquetage remplace galement tout :: dans le nom dun paquetage par le sparateur de rpertoires de votre systme, gnralement /. En dautres termes, si vous essayez ceci :
require Machin::Truc; # un formidable nom dnud

la fonction require cherchera le fichier Machin/Truc.pm dans les rpertoires spcifis par le tableau @INC. Mais si vous essayez cela :
$classe = Machin::Truc; require $classe; # $classe nest pas un nom dnud

ou encore cela :
require "Machin::Truc"; # un littral entre guillemets nest pas un #nom dnud

la fonction require recherchera le fichier Machin::Truc dans le tableau @INC et se plaindra de ne pas y trouver Machin::Truc. Si cela arrive, vous pouvez faire ceci :
eval "require $classe";

Voir galement les commandes do FICHIER, use, le pragma use lib et le module standard FindBin.

reset
reset EXPR reset

On use (ou on abuse) de cette fonction gnralement au dbut dune boucle ou dans un bloc continue la fin dune boucle, pour nettoyer les variables globales ou rinitialiser les recherches ?? pour quelles puissent nouveau fonctionner. LEXPR est interprte comme une liste de caractres uniques (les tirets sont autoriss pour les intervalles). Toutes les variables scalaires et tous les tableaux et hachages commenant par lune de ces lettres sont remises dans leur tat dorigine. Si lEXPR est omise, les recherches de correspondance unique (?MOTIF?) sont rinitialises pour correspondre nouveau. La fonction rinitialise les variables ou les recherches uniquement pour le package courant. Elle renvoie toujours vrai. Pour rinitialiser toutes les variables en X , crivez ceci :
reset X;

customer_8566

Fonctions Perl par ordre alphabtique


Pour rinitialiser toutes les variables en minuscules, crivez cela :
reset a-z;

735

Enfin, pour ne rinitialiser que les recherches en ??, crivez :


reset;

La rinitialisation de A-Z dans le package principal main nest pas recommande car les tableaux et hachages ARGV INC, ENV et SIG seront probablement balays. , Les variables lexicales (cres par my) ne sont pas affectes. Lemploi de reset est vaguement dprci car il efface un peu trop facilement des espaces de noms entiers et parce que loprateur ?? est lui-mme vaguement dprci. Voir galement la fonction delete_package() du module standard Symbol et la discussion entire sur les compartiments scuriss dans la section Compartiments scuriss au chapitre 23.

return
return EXPR return

Cet oprateur entrane le retour immdiat de la sous-routine courante (ou de leval ou du do FICHIER) avec la valeur spcifie. Toute tentative dutiliser return en dehors de ces trois endroits lve une exception. Remarquez galement quun eval ne peut pas faire un return pour le compte de la sous-routine qui a appel leval. EXPR peut tre value dans un contexte de liste, scalaire ou vide, selon la manire dont la valeur de retour sera utilis, ce qui peut varier dune excution lautre. Cest--dire que lexpression fournie sera value dans le contexte de linvocation du sous-programme. Si le sous-programme a t appel dans un contexte scalaire, EXPR est galement value dans un contexte scalaire. Si le sous-programme a t appel dans un contexte de liste, EXPR est galement value dans un contexte de liste. Un return sans argument renvoie la valeur scalaire undef dans un contexte scalaire et une liste vide () dans un contexte de liste, et (naturellement) rien du tout dans un contexte vide. Le contexte de lappel au sous-programme peut tre dtermin de lintrieur du sous-programme par la fonction (mal nomme) wantarray.

reverse
reverse LISTE

Dans un contexte de liste, cette fonction renvoie une valeur liste compose des lments de LISTE dans lordre inverse. La fonction peut tre utilise pour crer des squences dcroissantes :
for (reverse 1 .. 10) { ... }

Comme les hachages se transforment en listes quand ils sont passs en tant que LISTE, reverse peut galement tre employe pour inverser un hachage, supposer que les valeurs soient uniques :
%machintruc = reverse %trucmachin;

customer_8566

736

Chapitre 29 Fonctions

Dans un contexte scalaire, la fonction concatne tous les caractres de LISTE et renvoie alors linverse, caractre par caractre, de la chane rsultante. Petite astuce : linversion dune liste trie par une fonction dfinie par lutilisateur peut parfois tre plus facilement accomplie en triant dabord la liste dans le sens oppos.

rewinddir
rewinddir HANDLE_REPERTOIRE

!GU

Cette fonction se positionne au dbut du rpertoire pour la routine readdir sur HANDLE_REPERTOIRE. La fonction peut ne pas tre disponible sur toutes les machines supportant readdir rewindir meurt si elle nest pas implmente. Elle renvoie vrai en cas de succs, faux sinon.

rindex
rindex CHAINE, SOUS_CHAINE, POSITION rindex CHAINE, SOUS_CHAINE

Cette fonction agit exactement comme index mis part le fait quelle renvoie la position de la dernire occurrence de SOUS_CHAINE dans CHAINE (un index inverse). La fonction renvoie $[-1 si aucune SOUS_CHAINE na t trouve. Comme $[ est le plus souvent 0 de nos jours, la fonction renvoie presque toujours -1. POSITION, si elle est spcifie, est la position la plus droite qui puisse tre renvoye. Pour scruter une chane lenvers, crivez :
$pos = length $chaine; while (($pos = rindex $chaine, $a_chercher, $pos) >= 0) { print "Trouv en $pos\n"; $pos--; }

rmdir
rmdir REPERTOIRE rmdir

_!X

Cette fonction supprime le rpertoire spcifi par REPERTOIRE si ce rpertoire est vide. Si la fonction russit, elle renvoie vrai ; sinon, elle renvoie faux. Voir galement le module File::Path si vous voulez dabord supprimer le contenu du rpertoire et si vous nenvisagez pas dappeler le shell avec rm -r, pour une raison ou une autre. (Si par exemple vous ne disposez pas de shell ou de commande rm, parce que vous navez pas encore PPT11.)

11. N.d.T. : Perl Power Tools: The Unix Reconstruction Project, un projet dont le but avou est : de manire assez simple, de rimplmenter le jeu de commandes classiques Unix en Perl pur, et de nous amuser autant que possible en faisant cela .

customer_8566

Fonctions Perl par ordre alphabtique

737

s///
s///

tOX

Loprateur de substitution. Voir la section Oprateurs de correspondance de motif au chapitre 5.

scalar
scalar EXPR

Cette pseudo-fonction peut tre utilise dans une LISTE pour forcer EXPR tre value dans un contexte scalaire quand lvaluation dans un contexte de tableau produirait un rsultat diffrent. Par exemple :
my ($var_suivante) = scalar <STDIN>;

empche <STDIN> de lire toutes les lignes depuis lentre standard avant deffectuer laffectation, puisquune affectation une liste (mme une my liste) donne un contexte de liste. (Sans lutilisation de scalar dans cet exemple, la premire ligne de <STDIN> serait toujours assigne $var_suivante, mais les lignes suivantes seraient lues et poubellises, puisque la liste laquelle nous sommes en train dassigner ne peut recevoir quune seule valeur scalaire.) Bien sr, il serait plus simple et moins encombrant denlever les parenthses, transformant ainsi le contexte de liste en un contexte scalaire :
my $var_suivante = <STDIN>;

Puisquune fonction print est un oprateur de LISTE, il vous faudrait crire :


print "La longueur est ", scalar(@TABLEAU), "\n";

pour afficher la longueur de @TABLEAU. Il nexiste aucune fonction list correspondant scalar, puisquen pratique, on na jamais besoin de forcer lvaluation dans un contexte de liste. Car toute opration demandant une LISTE fournit dj un contexte de liste ses arguments de liste, et ceci gratuitement. Comme scalar est un oprateur unaire, si vous utilisez accidentellement une liste entre parenthses pour lEXPR, cette dernire se comportera comme une expression scalaire avec des virgules, en valuant tous les lments sauf le dernier dans un contexte vide et renvoyant llment final valu dans un contexte scalaire. Cest rarement ce que vous voulez. La seule instruction suivante :
print uc(scalar(&machin,$truc)),$bidule;

est lquivalent (im)moral de ces deux instructions :


&machin; print(uc($truc),$bidule);

Voir le chapitre 2 pour plus de dtails sur le sparateur virgule. Voir la section Prototypes au chapitre 6 pour plus dinformations sur les oprateurs unaires.

seek
seek HANDLE_FICHIER, DECALAGE, DEPART

!G

customer_8566

738

Chapitre 29 Fonctions

Cette fonction positionne le pointeur de fichier pour HANDLE_FICHIER, exactement comme lappel dentre/sortie standard fseek(3). La premire position dans un fichier correspond un dcalage de 0, et non de 1. Les dcalages se rfrent des positions en octets, et non des numros de ligne. En gnral, comme les longueurs de ligne varient, il nest pas possible daccder un numro de ligne prcis sans lire tout le fichier jusqu cet endroit, moins que toutes vos lignes ne soient dune longueur fixe ou que vous ayez construit un index convertissant les numros de lignes en dcalages doctets. (Les mmes restrictions sappliquent aux positions des caractres dans un fichier avec des encodages de caractres de longueur variable : le systme dexploitation ne sait pas ce que sont les caractres, il ne connat que des octets.) HANDLE_FICHIER peut tre une expression dont la valeur donne un vritable nom de handle de fichier ou une rfrence vers quoique ce soit ressemblant un objet handle de fichier. La fonction renvoie vrai en cas de succs, faux sinon. Pour des raisons pratiques, la fonction peut calculer pour vous des dcalages depuis diverses positions dans le fichier. La valeur de DEPART indique la position partir de laquelle votre DECALAGE commencera : 0, pour le dbut du fichier ; 1, pour la position courante dans le fichier ; ou 2, pour la fin du fichier. Le DECALAGE peut tre ngatif pour un DEPART de 1 ou de 2. Si vous dsirez employer des valeurs symboliques pour DEPART, vous pouvez utiliser SEEK_SET, SEEK_CUR et SEEK_END importe depuis les modules IO::Seekable ou POSIX, ou depuis la version 5.6 de Perl, depuis le module Fcntl. Si vous voulez connatre la position dans le fichier pour sysread ou syswrite, nemployez pas seek ; les consquences des tampons des entres/sorties standards rendent la position systme dans un fichier imprvisible et non portable. Utilisez sysseek la place. cause des rgles rigoureuses du C ANSI, vous devez sur certains systmes faire un seek chaque fois que vous basculez entre une lecture et une criture. Parmi dautres effets, ceci peut avoir comme consquence dappeler la fonction clearerr(3) de la bibliothque standard dentre/sortie. Un DEPART de 1 (SEEK_CUR) avec un DECALAGE de 0 est utile pour ne pas bouger de la position courante dans le fichier :
seek(TEST,0,1);

Cette fonction savre intressante notamment pour suivre la croissance dun fichier, comme ceci :
for (;;) { while (<JOURNAL>) { gnoquer($_) } sleep 15; seek LOG,0,1; }

# Traiter la ligne courante

# RAZ erreur de fin de fichier

Le seek final rinitialise lerreur de fin de fichier sans bouger le pointeur. Si cela ne fonctionne pas, selon limplmentation de la bibliothque C dentres/sorties standards, alors il vous faut plutt ce genre de code :
for (;;) { for ($pos_cour = tell FILE; <FILE>; $pos_cour = tell FILE) { gnoquer($_) # Traiter la ligne courante } sleep $un_moment;

customer_8566

Fonctions Perl par ordre alphabtique


seek FILE, $pos_cour, 0; } # RAZ erreur de fin de fichier

739

Des stratgies similaires peuvent tre employes pour conserver les adresses de seek pour chaque ligne dans tableau.

seekdir
seekdir HANDLE_REPERTOIRE, POSITION

!GU

Cette fonction fixe la position courante pour le prochain appel readdir sur HANDLE_REPERTOIRE. POSITION doit tre une valeur renvoye par telldir. Cette fonction comporte les mmes dangers relatifs un possible compactage du rpertoire que la routine de la bibliothque systme correspondante. La fonction peut ne pas tre implmente partout o lest readdir. Elle ne lest certainement pas si readdir est absente.

select (handle de fichier de sortie)


select HANDLE_FICHIER select

Pour des raisons historiques, il existe deux oprateurs select totalement distincts lun de lautre. La section suivante dcrit lautre. Cette version de loprateur select renvoie le handle de fichier de sortie actuellement slectionn et, si HANDLE_FICHIER est fourni, fixe le handle par dfaut courant pour la sortie. Cela a deux consquences : dabord, un write ou un print sans handle de fichier sadressera ce handle par dfaut. Ensuite, les variables spciales relatives la sortie se rfreront ce handle de fichier de sortie. Par exemple, sil faut fixer un format den-tte identique pour plus dun handle de fichier de sortie, il vous faudrait faire ceci :
select RAPPORT1; $^ = mon_en_tete; select RAPPORT2; $^ = mon_en_tete;

Mais remarquez que cela laisse RAPPORT2 comme handle de fichier actuellement slectionn. Ce qui est un comportement antisocial condamnable puisque cela peut rellement dmolir les routines print ou write de quelquun dautre. Les routines de bibliothque bien crites laissent le handle de fichier slectionn courant dans ltat o elles lont trouv en entrant. cet effet, HANDLE_FICHIER peut tre une expression dont la valeur donne le nom du vritable handle de fichier. Il vous est donc possible de sauvegarder et de restaurer le handle de fichier actuellement slectionn :
my $ancien_hf = select STDERR; $| = 1; select $ancien_hf;

ou de manire idiomatique (mais nettement plus absconse) :


select((select(STDERR), $| = 1)[0])

Cet exemple fonctionne en construisant une liste compose de la valeur renvoye par select(STDERR) (qui slectionne STDERR par effet de bord) et $| = 1 (qui est toujours 1), mais vide le tampon de STDERR, maintenant slectionn, par effet de bord. Le premier lment de cette liste (le handle de fichier prcdemment slectionn) est maintenant utilis comme un argument vers le select extrieur. trange, nest-ce pas ? Cest ce

customer_8566

740

Chapitre 29 Fonctions

que vous obtenez quand vous connaissez juste assez de Lisp pour tre dangereux. Vous pouvez galement utiliser le module standard SelectSaver pour restaurer automatiquement le select prcdent la sortie de la porte. Maintenant que nous avons expliqu tout cela, nous devons souligner que vous naurez que rarement besoin dutiliser cette forme de select, car la plupart des variables spciales auxquelles vous pouvez vouloir accder possdent des mthodes denrobage orientes objet. Donc, au lieu daccder directement $|, vous pouvez crire :
use IO::Handle; # Malheureusement, ce *nest pas* un petit module STDOUT->autoflush(1);

Et lexemple prcdent de format peut tre cod comme suit :


use IO::Handle; RAPPORT1->format_top_name("mon_en_tete"); RAPPORT2->format_top_name("mon_en_tete");

select (descripteurs de fichiers prts)


select BITS_LEC, BITS_ECR, BITS_ERR, MINUTEUR

!U

La forme quatre arguments de select est totalement indpendante de loprateur select prcdemment dcrit. Celui-ci sert dcouvrir lesquels (sil en existe) de vos descripteurs de fichiers sont prts effectuer une entre ou une sortie, ou informer dune condition dexception. (Ce qui vous vite une scrutation.) Elle appelle lappel systme select(2) avec les masques de bits que vous avez spcifis, qui peuvent tre construits grce fileno et vec, comme ceci :
$lec_entree = $ecr_entree = $err_entree = "; vec($lec_entree, fileno(STDIN), 1) = 1; vec($ecr_entree, fileno(STDOUT), 1) = 1; $err_entree = $lec_entree | $ecr_entree;

Si vous voulez faire un select sur plusieurs handles de fichier, il peut tre prfrable dcrire une routine :
sub bits_hf { my @liste_hf = @_; my $bits; for (@liste_hf) { vec($bits, fileno($_), 1) = 1; } return $bits; } $lec_entree = bits_hf(qw(STDIN TTY MA_SOCK));

Si vous dsirez utiliser les mmes masques de bits de faon rptitive (et cest plus efficace), la manire la plus courante est :
($nb_trouves, $temps_restant) = select( $lec_sortie=$lec_entree, $ecr_sortie=$ecr_entree, $err_sortie=$err_entree, $minuteur);

Ou pour bloquer jusqu ce quun descripteur de fichiers soit prt :

customer_8566

Fonctions Perl par ordre alphabtique


$nb_trouves = select( $lec_sortie=$lec_entree, $ecr_sortie=$ecr_entree, $err_sortie=$err_entree, undef);

741

Comme vous pouvez le constater, lappel de select dans un contexte scalaire renvoie seulement $nb_trouves, soit le nombre de descripteurs de fichiers prts trouvs. Lastuce $ecr_sortie=$ecr_entree fonctionne car la valeur dune affectation est le ct gauche, ce qui fait que $ecr_sortie est dabord modifi par laffectation, puis par le select, alors que $ecr_entree reste inchang. Chaque argument peut galement valoir undef. Le MINUTEUR, sil est spcifi, est en secondes12, et peut ventuellement comporter une virgule. (Un dlai de 0 effectue une scrutation.) Toutes les implmentations ne sont pas capables de renvoyer le $temps_restant. Dans ce cas, elles renverront toujours un $temps_restant gal au $minuteur fourni. Le module standard IO::Select fournit une interface plus amicale select, surtout parce quil effectue pour vous toutes les oprations sur les masques de bits. Un des emplois possibles de select consiste endormir un processus avec une rsolution plus fine que ce quadmet sleep, ceci en spcifiant undef pour tous les masques de bits. Ainsi pour vous endormir pendant (au moins) 4,75 secondes, utilisez :
select undef, undef, undef, 4.75;

(Le triple undef peut ne pas fonctionner sur certains systmes non-UNIX, et il vous faut alors mettre fallacieusement au moins un masque de bits un descripteur de fichier qui ne sera jamais prt.) Il est dangereux de mlanger des entres/sorties bufferises (comme read ou <HANDLE>) avec select, lexception de ce que permet POSIX, et mme dans ce cas, uniquement sur les systmes rellement POSIX. Employez plutt sysread.

semctl
semctl CLEF, NUM_SEM, CMD, ARG

!U

Cette fonction invoque lappel systme semctl(2) des IPC System V Vous devrez proba. blement dabord faire use IPC::SysV pour obtenir les dfinitions de constantes correctes. Si CMD vaut IPC_STAT ou GETALL, ARG doit alors tre une variable qui contiendra la structure semid_ds ou le tableau des valeurs de smaphore qui sont renvoys. Comme pour ioctl et fcntl, les valeurs renvoyes sont undef en cas derreur, 0 but true (N.d.T. : 0 mais vrai) pour zro ou sinon la valeur rellement renvoye. Voir galement le module IPC::Semaphore. Cette fonction nest disponible que sur les systmes supportant les IPC System V .

semget
semget CLEF, NB_SEM S, TAILLE, FLAGS

!U

12. N.d.T. : les anglophones ont la chance de dire timeout, ce qui vite toute confusion dans les units de temps !

customer_8566

742

Chapitre 29 Fonctions

Cette fonction invoque lappel systme semget(2) des IPC System V Vous devrez proba. blement dabord faire use IPC::SysV pour obtenir les dfinitions de constantes correctes. La fonction renvoie lID du smaphore ou undef en cas derreur. Voir galement le module IPC::Semaphore. Cette fonction nest disponible que sur les systmes supportant les IPC System V .

semop
semop CLEF, CHAINE_OP

!U

Cette fonction invoque lappel systme semop(2) des IPC System V pour raliser des oprations sur les smaphores, comme signaler ou attendre la libration. Vous devrez probablement dabord faire use IPC::SysV pour obtenir les dfinitions de constantes correctes. CHAINE_OP doit tre un tableau empaquet de structures semop. Vous pouvez construire chaque structure semop en crivant pack("s*", $num_sem, $op_sem, $flags_sem). Le nombre doprations de smaphores est donn par la longueur de CHAINE_OP La fonc. tion renvoie vrai si elle a russi, faux en cas derreur. Le code qui suit attend sur le smaphore $num_sem de lensemble de smaphores identifi par $id_sem :
$op_sem = pack "s*", $semnum, -1, 0; semop $id_sem, $op_sem or die "Problme de smaphore : $!\n";

Pour envoyer un signal au smaphore, il vous suffit de remplacer -1 par 1. Voir galement le module IPC::Semaphore. Cette fonction nest disponible que sur les systmes supportant les IPC System V .

send
send SOCKET, MSG, FLAGS, VERS send SOCKET, MSG, FLAGS

!GU

Cette fonction envoie un message sur une socket. Elle prend les mmes f lags que lappel systme du mme nom voir send(2). Sur des sockets non connectes, vous devez spcifier une destination VERS laquelle envoyer les donnes, ce qui fait que le send de Perl fonctionne comme sendto(2). La fonction send renvoie le nombre doctets envoys, ou undef en cas derreur. (Certains systmes traitent improprement les sockets comme des objets diffrents de simples descripteurs de fichiers, ce qui vous oblige toujours utiliser send et recv sur les sockets au lieu des oprateurs dentre/sortie standards.) Une erreur quau moins lun de nous fait frquemment est de confondre le send de Perl avec le send de C en crivant :
send SOCK, $tampon, $length $tampon # FAUX

Ceci chouera mystrieusement selon le rapport exig par le systme entre la longueur de la chane et les bits de FLAGS. Voir la section Passage de message au chapitre 16 pour plus dexemples.

customer_8566

Fonctions Perl par ordre alphabtique

743

setpgrp
setpgrp PID, GRP_P

!XU

Cette fonction modifie le groupe de processus courant (GRP_P) pour le PID spcifi (employez un PID gal 0 pour le processus courant). Linvocation de setpgrp lvera une exception sur une machine nimplmentant pas setpgrp(2). Attention : certains systmes ignoreront les arguments fournis et feront toujours setpgrp(0, $$)}. Ce sont heureusement les arguments que lon fournit gnralement. Si les arguments sont omis, ils vaudront 0,0 par dfaut. La version BSD 4.2 de setpgrp nacceptait aucun argument, mais pour BSD 4.4, cest un synonyme de la fonction setpgid. Pour une meilleure portabilit (du moins thorique), utilisez directement la fonction setpgid du module POSIX. Ou, si vous voulez changer votre script en dmon, la fonction POSIX::setsid() peut aussi bien faire laffaire. Remarquez que la version POSIX de setpgrp naccepte pas darguments, seul setpgrp(0,0) est donc portable.

setpriority
setpriority QUOI, QUI, PRIORITE

!XU

Cette fonction modifie la PRIORITE courante dun processus, dun groupe de processus ou dun utilisateur, tel que spcifis par QUOI et QUI. Voir setpriority(2). Son invocation lvera une exception sur une machine o setpriority(2) nest pas implmente. Pour faire un nice sur votre processus de quatre units vers le bas (la mme chose que dexcuter votre programme avec nice(1)), essayez :
setpriority 0, 0, getpriority(0, 0) + 4;

Linterprtation dune priorit donne peut varier dun systme dexploitation lautre. Certaine priorits ne sont pas accessibles aux utilisateurs sans privilges. Voir galement le module BSD::Resource de CPAN.

setsockopt
setsockopt SOCKET, NIVEAU, NOM_OPTION, VALEUR_OPTION

!GU

Cette fonction applique loption de socket requise. La fonction renvoie undef en cas dchec. NIVEAU spcifie quelle couche de protocole est vise par lappel, ou SOL_SOCKET pour la socket elle-mme qui se trouve au sommet de toutes les couches. VALEUR_OPTION peut tre undef si vous ne voulez pas passer dargument. Il est courant dappliquer loption SO_REUSEADDR, pour contourner le fait que lon ne peut pas faire de bind vers une adresse donne alors que la connexion TCP prcdente sur ce port est toujours en train de se demander sil faut en finir. Cela peut ressembler ceci :
use Socket; socket(SOCK, ...) or die "Impossible de crer une socket : $!\n"; setsockopt(SOCK, SOL_SOCKET, SO_REUSEADDR, 1) or warn "setsockopt impossible : $!\n";

Voir setsockopt(2) pour les autres valeurs possibles.

customer_8566

744

Chapitre 29 Fonctions

shift
shift TABLEAU shift

Cette fonction enlve la premire valeur du tableau et la renvoie, rduisant ainsi le tableau dun lment et dplaant toutes les autres dune unit vers le bas. (Ou vers le haut, ou vers la gauche, selon votre vision du tableau. Nous aimons bien vers la gauche.) Sil ny a pas dlments dans le tableau, la fonction renvoie undef. Si TABLEAU est omis, la fonction dcale @_ dans la porte lexicale des sous-programmes et des formats ; elle dcale @ARGV dans les portes de fichiers (gnralement, le programme principal) ou lintrieur de la porte lexicale tablie par les constructions eval CHAINE, BEGIN {}, CHECK {}, INIT {} et END {}. Les sous-programmes commencent souvent par recopier leurs arguments dans des variables lexicales et peuvent utiliser shift pour ce faire :
sub marine { my $brasse = shift; my $poissons = shift; my $o2 = shift; # ... } while (defined($_ /^[^-]/ /^-w/ /^-r/ die "Argument } # profondeur 13 # nombre de poissons # concentration en oxygne

shift est galement employ pour traiter les arguments au dbut de votre programme :
= shift)) { && do { unshift @ARGV, $_; last }; && do { $AVERTISSEMENTS = 1; next }; && do { $RECURSION = 1; last }; inconnu $_\n";

Vous pouvez galement considrer les modules Getopt::Std et GetOpt::Long pour traiter les argument de votre programme. Voir galement unshift, push, pop et splice. Les fonctions shift et unshift font la mme chose lextrmit gauche dun tableau que push et pop lextrmit droite.

shmctl
shmctl ID, CMD, ARG

!U

Cette fonction invoque lappel systme shmctl(2) des IPC System V Vous devrez probable. ment dabord faire use IPC::SysV pour obtenir les dfinitions de constantes correctes. Si CMD vaut IPC_STAT, ARG doit alors tre une variable qui contiendra la structure shmid_ds renvoye. Comme pour ioctl et fcntl, les valeurs renvoyes sont undef en cas derreur, 0 but true (N.d.T. : 0 mais vrai) pour zro ou sinon la valeur rellement renvoye. Cette fonction nest disponible que sur les systmes supportant les IPC System V .
13. N.d.T. : unit gale 1828 mm.

customer_8566

Fonctions Perl par ordre alphabtique

745

shmget
shmget CLEF, TAILLE, FLAGS

!U

Cette fonction invoque lappel systme shmget(2) des IPC System V La fonction renvoie . lID du segment de mmoire partage ou undef en cas derreur. Avant lappel, faites use IPC::SysV . Cette fonction nest disponible que sur les systmes supportant les IPC System V .

shmread
shmread ID, VAR, POS, TAILLE

!U

Cette fonction lit depuis lID de segment de mmoire partage en commenant la position POS sur la longueur TAILLE (en sy attachant, puis en copiant les donnes qui sy trouvent et enfin en sen dtachant). VAR doit tre une variable qui contiendra les donnes lues. La fonction renvoie vrai en cas de russite et faux en cas derreur. Cette fonction nest disponible que sur les systmes supportant les IPC System V .

shmwrite
shmwrite ID, CHAINE, POS, TAILLE

!U

Cette fonction crit sur lID de segment de mmoire partage en commenant la position POS sur la longueur TAILLE (en sy attachant, puis en y copiant des donnes et enfin en sen dtachant). Si CHAINE est trop longue, seulement TAILLE octets seront utiliss ; si TAILLE est trop courte, des caractres nuls sont crit pour remplir TAILLE octets. La fonction renvoie vrai en cas de russite et faux en cas derreur. Cette fonction nest disponible que sur les systmes supportant les IPC System V (Vous . tes certainement fatigus de lire ceci nous commenons tre fatigus de lcrire.)

shutdown
shutdown SOCKET, COMMENT

!GU

Cette fonction arrte une connexion socket de la manire indique par COMMENT. Si COMMENT vaut 0, toute rception ultrieure est interdite. Si COMMENT vaut 1, toute mission ultrieure est interdite. Si COMMENT vaut 2, tout est interdit.
shutdown(SOCK, 0); shutdown(SOCK, 1); shutdown(SOCK, 2); # plus de lectures # plus dcritures # plus du tout dentres/sorties

Ceci est utile avec les sockets lorsque vous voulez prvenir lautre ct que vous avez fini dcrire mais pas de lire, ou vice versa. Cest galement une forme plus dtermine de fermeture car elle empche toute copie de ces descripteurs dtenus par des processus forks. Imaginez un serveur qui veut lire la requte de son client jusqu la fin de fichier, puis envoyer une rponse. Si le client appelle close, cette socket nest maintenant plus valide pour les entres/sorties, aucune rponse ne pourra donc tre renvoye. la place, le

customer_8566

746

Chapitre 29 Fonctions

client doit utiliser shutdown pour fermer la moiti de la connexion :


print SERVEUR, "ma requete\n"; shutdown(SERVEUR, 1); $reponse = <SERVEUR>; # envoi de donnes # envoi de fin de ligne; plus dcritures # mais vous pouvez encore lire

(Si vous tes arriv ici pour savoir comment arrter un systme, vous devrez excuter un programme externe cet effet. Voir system.)

sin
sin EXPR sin

Dsol, mme si cet oprateur voque des choses malicieuses aux anglophones14, il ne fait que renvoyer le sinus de EXPR (exprime en radians). Pour lopration inverse,vous pouvez utiliser la fonction asin des modules Math::Trig ou POSIX, ou utiliser cette relation :
sub asin { atan2($_[0], sqrt(1 - $_[0] * $_[0])) }

sleep
sleep EXPR sleep

Cette fonction endort le script pendant EXPR secondes, ou ternellement si EXPR est omise. Elle renvoie le nombre de secondes rellement passes dormir. Elle peut tre interrompue en envoyant un signal SIGALRM au processus. Sur certains systmes anciens, le repos peut durer jusqu une seconde de moins que ce que demandiez, selon la manire de compter les secondes. La plupart des systmes modernes dorment toujours durant la priode entire. Ils peuvent cependant sembler dormir plus que cela, car lordonnanceur dun systme multitches peut ne pas donner tout de suite la main votre processus. Sil est disponible, lappel select (descripteurs de fichiers prts) peut vous donner une meilleure rsolution. Vous pouvez galement employer syscall pour appeler les routines getitimer(2) et setitimer(2) supporte par certains systmes Unix. Vous ne pouvez probablement pas mlanger des appels alarm avec ceux sleep, car sleep est souvent implment en utilisant alarm. Voir galement la fonction sigpause du module POSIX.

socket
socket SOCKET, DOMAINE, TYPE, PROTOCOLE

!GXU

Cette fonction ouvre une socket du type spcifi et lattache au handle de fichier SOCKET. DOMAIN, TYPE et PROTOCOLE sont spcifis comme pour socket(2). Si le handle de fichier SOCKET est indfini, il sera autovivifi. Avant dutiliser cette fonction, votre programme doit contenir la ligne :
use Socket;
14. N.d.T. : en anglais sin signifie pch .

customer_8566

Fonctions Perl par ordre alphabtique

747

Cela vous donne accs aux constantes appropries. La fonction renvoie vrai en cas de russite. Vois les exemple dans la section Sockets au chapitre 16. Sur les systmes qui supportent le f lag close-on-exec pour les fichiers, ce f lag sera positionn pour le nouveau descripteur de fichier ouvert, comme le dtermine la valeur de $^F. Voir la variable $^F ($SYSTEM_FD_MAX) au chapitre 28.

socketpair
socketpair SOCKET1, SOCKET2, DOMAINE, TYPE, PROTOCOLE

!GXU

Cette fonction cre une paire de sockets non nommes dans le domaine spcifi, dun type spcifi. DOMAINE, TYPE et PROTOCOLE sont spcifis de la mme manire que pour socketpair(2). Si lun des arguments sockets (SOCKET1 ou SOCKET2) est indfini, il sera autovivifi. La fonction renvoie vrai en cas de succs, sinon faux. Sur un systme o socketpair(2) nest pas implment, lappel cette fonction lve une exception. Cette fonction est gnralement utilise juste avant un fork. Lun des processus rsultants doit fermer SOCKET1 et lautre SOCKET2. Vous pouvez utiliser ces sockets de manire bidirectionnelle, au contraire des handles de fichiers crs par la fonction pipe. Certains systmes dfinissent pipe en termes de socketpair, auquel cas un appel pipe(Lec, Ecr) est quivalent pour lessentiel :
use Socket; socketpair(Lec, Ecr, AF_UNIX, SOCK_STREAM, PF_UNSPEC); shutdown(Lec, 1); # plus dcritures pour le lecteur shutdown(Ecr, 0); # plus de lectures pour lcrivain

Sur les systmes qui supportent le f lag close-on-exec pour les fichiers, ce f lag sera positionn pour le nouveau descripteur de fichier ouvert, comme le dtermine la valeur de $^F. Voir la variable $^F ($SYSTEM_FD_MAX) au chapitre 28. Voir galement lexemple la fin de la section Communication bidirectionnelle au chapitre 16.

sort
sort SUB_UTILISATEUR LISTE sort BLOC LISTE sort LISTE

Cette fonction trie la LISTE et renvoie la valeur liste trie. Elle trie par dfaut dans le sens de comparaison standard des chanes (les valeurs indfinies tant tries avant les chanes vides dfinies, qui sont tries avant tout le reste). Lorsque le pragma use locale est actif, sort LISTE trie LISTE selon la locale courante LC_COLLATE. SUB_UTILISATEUR, sil est spcifi, est le nom dun sous-programme qui renvoie un entier infrieur, gal ou suprieur 0, selon la manire dont les lments du tableau doivent tre ordonns. (Les oprateurs <=> et cmp peuvent tre utiliss pour effectuer facilement des comparaisons de nombres et de chanes pouvant donner trois rsultats.) Si un SUB_UTILISATEUR est donn mais que cette fonction est indfinie, sort lve une exception. Pour des raisons defficacit, le code dappel normal des sous-programmes est court-circuit, ce qui a pour consquences que : le sous-programme ne peut pas tre rcursif (ni

customer_8566

748

Chapitre 29 Fonctions

contenir doprateur de contrle de boucle qui vous ferait sortir du bloc ou de la routine) et que les deux lments comparer lui sont passs non via @_, mais en positionnant temporairement les variables globales par $a et $b dans le paquetage o sort a t compil (voir les exemples ci-dessous). Les variables $a et $b tant passes en tant qualias des valeurs relles, ne les modifiez pas dans le sous-programme. Le sous-programme de comparaison doit bien se comporter. Sil renvoie des rsultats inconsistants (en disant un jour que $x[1] est infrieur $x[2] et en prtendant le contraire le lendemain), les consquences sont alatoires. (Cest une autre raison de ne pas modifier $a et $b.) SUB_UTILISATEUR peut tre un nom de variable scalaire (non indice), dont la valeur fournit le nom du sous-programme utiliser. (Un nom symbolique plutt quune rfrence en dur est autoris mme lorsque le pragma use strict refs est actif.) En lieu et place de SUB_UTILISATEUR, on peut fournir un BLOC, sorte de sous-programme anonyme en ligne. Pour un tri numrique ordinaire, crivez ceci :
sub numerique { $a <=> $b } @tri_par_nombre = sort numerique 53,29,11,32,7;

Pour trier dans lordre dcroissant, il vous suffit dappliquer reverse aprs le sort, ou dinverser lordre de $a et $b dans le sous-programme de tri :
@decroissant = reverse sort numerique 53,29,11,32,7; sub inverse_numerique { $b <=> $a } @decroissant = sort inverse_numerique 53,29,11,32,7;

Pour trier des chanes sans tenir compte de la casse (majuscules/minuscules), passez $a et $b lc avant la comparaison :
@desordonnee = qw/moineau Autruche ALOUETTE moqueurchat geaiBLEU/; @ordonnee = sort { lc($a) cmp lc($b) } @desordonnee;

(Avec Unicode, lemploi de lc pour la canonisation de la casse est plus ou moins prfrable lutilisation de uc car certaines langues diffrencient les majuscules pour les titres des majuscules ordinaires. Mais cela ne compte pas pour un tri ASCII basique, et si vous voulez trier convenablement de lUnicode, vos routines de canonisation seront bien plus imaginatives que lc.) Le tri des valeurs dun hachage est une utilisation courante de la fonction sort. Par exemple, si un hachage %montant_ventes enregistre les ventes de diffrents services, une recherche dans le hachage lintrieur de la routine de tri permet aux clefs du hachage dtre tries selon leurs valeurs correspondantes :
# tri dans lordre dcroissant des ventes par service sub par_vente { $montant_ventes{$b} <=> $montant_ventes{$a} } for $serv (sort par_vente keys %montant_ventes) { print "$serv => $montant_ventes{$serv}\n"; }

Vous pouvez effectuer des niveaux supplmentaires de tri en faisant des comparaisons en cascade laide des oprateurs || ou or. Cela marche parfaitement car les oprateurs

customer_8566

Fonctions Perl par ordre alphabtique

749

de comparaison renvoient convenablement 0 pour une quivalence, ce qui les fait entrer dans la comparaison suivante. Ici les clefs de hachage sont tries tout dabord selon les montants des ventes associes puis selon les clefs elles-mmes (dans le cas o deux dpartements ou plus auraient le mme montant de ventes) :
sub par_vente_puis_serv { $montant_ventes{$b} <=> $montant_ventes{$a} || $a cmp $b } for $serv (sort par_vente_puis_serv keys %montant_ventes) { print "$serv => $montant_ventes{$serv}\n"; }

En supposant que @enregs est un tableau de rfrences sur des hachages, dans lequel chaque hachage comporte des champs comme PRENOM, NOM, AGE, TAILLE et SALAIRE, la routine suivante met au dbut de la liste trie les enregistrements pour les personnes les plus riches, puis les plus grandes, ensuite les plus jeunes et enfin les premires dans lordre alphabtique :
sub prospecte { $b->{SALAIRE} <=> $a->{SALAIRE} || $b->{TAILLE} <=> $a->{TAILLE} || $a->{AGE} <=> $b->{AGE} || $a->{NOM} cmp $b->{NOM} || $a->{PRENOM} cmp $b->{PRENOM} } @triee = sort prospecte @enregs;

Toute information utile qui drive de $a et de $b peut servir de base une comparaison dans une routine de tri. Par exemple, si les lignes dun texte doivent tre tries selon des champs particuliers, split peut tre utilis dans la routine de tri pour driver les champs :
@lignes_triees = sort { @champs_a = split /:/, $a; @champs_b = split /:/, $b; $champs_a[3] <=> $champs_b[3] || $champs_a[0] cmp $champs_b[0] || $champs_b[2] <=> $champs_a[2] || ... } @lignes; # champs spars par deux points

# tri numrique sur le 4me champ, puis # tri de chanes sur le 1er champ, puis # tri numrique dcroissant sur le 3me # champ # etc.

Toutefois, puisque sort excute la routine de tri plusieurs fois en utilisant diffrentes

customer_8566

750

Chapitre 29 Fonctions

paires de valeurs pour $a et $b, lexemple prcdent redcoupera chaque ligne avec split plus souvent que ncessaire. Pour viter le cot de drivations rptes comme lclatement de lignes pour comparer leurs champs, excutez la drivation une seule fois par valeur avant le tri et sauvegardez linformation drive. Ici, on cre des tableaux anonymes pour encapsuler chaque ligne ainsi que le rsultat de son clatement :
@temp = map { [$_, split /:/] } @lignes;

Puis, on trie les rfrences du tableau :


@temp = sort { @champs_a = @$a[1..$#$a]; @champs_b = @$b[1..$#$b]; $champs_a[3] <=> $champs_b[3] || $champs_a[0] cmp $champs_b[0] || $champs_b[2] <=> $champs_a[2] || ... } @temp; # tri numrique sur le 4me champ, puis # tri de chanes sur le 1er champ, puis # tri numrique dcroissant sur le 3me # champ # etc.

Maintenant que les rfrences du tableau sont tries, on peut rcuprer les lignes dorigine partir des tableaux anonymes :
@lignes_triees = map { $_->[0] } @temp;

Si lon rassemble tout cela, cette technique map-sort-map, souvent appele transformation schwartzienne15, peut tre accomplie en une seule instruction :
@lignes_triees= map { $_->[0] } sort { @champs_a = @$a[1..$#$a]; @champs_b = @$b[1..$#$b]; $champs_a[3] <=> $champs_b[3] || $champs_a[0] cmp $champs_b[0] || $champs_b[2] <=> $champs_a[2] || ... } map { [$_, split /:/] } @lignes;

Ne dclarez pas $a et $b en tant que variables lexicales (avec my). Elles sont globales au paquetage (bien quexemptes des restrictions habituelles concernant les variables globales lorsque vous employez use strict). Vous devez cependant vous assurer que la rou-

15. N.d.T. : du nom de lillustre co-auteur des prcdentes ditions de cet ouvrage : Randal L. Schwartz.

customer_8566

Fonctions Perl par ordre alphabtique

751

tine de tri se trouve bien dans le mme package, ou sinon qualifier $a et $b avec le nom du paquetage de lappelant (voir la fonction caller). Ceci tant dit, dans la version 5.6, vous pouvez crire des sous-programmes de tri avec la mthode standard de passage darguments (et , sans concidence aucune, utiliser des sous-programmes XS comme routines de tri), pourvu que vous dclariez le sous-programme de tri avec un prototype valant ($$). Et dans ce cas, vous pouvez en fait dclarer $a et $b comme variables lexicales :
sub numerique ($$) { my ($a, $b) = @_; $a <=> $b; }

Et un jour ou lautre, lorsque des prototypes complets auront t implments, vous crirez seulement :
sub numerique ($a, $b) { $a <=> $b }

et nous serons alors plus ou moins revenus notre point de dpart.

splice
splice splice splice splice TABLEAU, DECALAGE, LONGUEUR, LISTE TABLEAU, DECALAGE, LONGUEUR TABLEAU, DECALAGE TABLEAU

Cette fonction enlve les lments dsigns par DECALAGE et LONGUEUR dans un TABLEAU, et les remplace par les lments de LISTE, sil en existe. Si DECALAGE est ngatif, la fonction compte rebours depuis la fin du tableau, mais si cela vous faisait atterrir avant le dbut du tableau, une exception est leve. Dans un contexte de liste, splice renvoie les lments supprims du tableau. Dans un contexte scalaire, elle renvoie le dernier lment enlev ou undef sil ny en a pas. Si le nombre de nouveaux lments nest pas gal au nombre danciens lments, le tableau augmente ou diminue en taille selon les besoins, et la position des lments qui suivent cette tranche ajoute ou enleve est dcale en consquence. Si LONGUEUR est omise, la fonction enlve tout partir de DECALAGE. Si DECALAGE est omis, le tableau est vid au fur et mesure quil est lu. Les colonnes suivantes sont quivalentes ( supposer que $[ vaille 0) :
Mthode directe push(@a, $x, $y) pop(@a) shift(@a) unshift(@a, $x, $y) $a[$x] = $y (@a, @a =()) quivalent splice splice(@a, @a, 0, $x, $y) splice(@a, -1) splice(@a, 0, 1) splice(@a, 0, 0, $x, $y) splice(@a, $x, 1, $y) splice(@a)

La fonction splice peut galement servir dcouper la liste darguments passe un sous-programme. En supposant par exemple que les longueurs de liste sont passes

customer_8566

752
avant les listes elles-mmes :

Chapitre 29 Fonctions

sub eq_liste { # compare deux valeurs de liste my @a = splice(@_, 0, shift); my @b = splice(@_, 0, shift); return 0 unless @a == @b; # mme longueur ? while (@a) { return 0 if pop(@a) ne pop(@b); } return 1; } if (eq_liste($long, @machin[1..$long], scalar(@truc), @truc)) { }

Toutefois, il serait probablement plus propre de se contenter dutiliser des rfrences sur des tableaux pour faire cela.

split
split /MOTIF/, EXPR, LIMITE split /MOTIF/, EXPR split /MOTIF/ split

_t

Cette fonction recherche des dlimiteurs dans une chane EXPR et lclate en une liste de sous-chanes, en renvoyant la valeur liste rsultante dans un contexte de liste, ou le nombre de sous-chanes dans un contexte scalaire.16 Les dlimiteurs sont dtermins par la correspondance rpte dun motif, en utilisant lexpression rgulire donne dans MOTIF. Les dlimiteurs peuvent donc tre de nimporte quelle taille et ne sont pas forcment la mme chane chaque recherche. (Les dlimiteurs ne sont gnralement pas renvoys, mais voyez les exceptions ci-dessous.) Si le MOTIF ne correspond rien, split renvoie la chane dorigine comme une sous-chane unique. Sil trouve une occurrence, vous obtenez deux sous-chanes, et ainsi de suite. Vous pouvez donner au MOTIF des modificateurs dexpressions rgulires, comme /MOTIF/i, /MOTIF/x, etc. Lorsque vous clatez avec un motif valant /^/, le modificateur //m est implicite. Si LIMITE est spcifie et positive, la fonction clate la chane en, au plus, ce nombre de champs (bien quelle puisse lclater en moins si elle ne trouve pas assez de dlimiteurs). Si LIMITE est ngative, elle est traite comme si une LIMITE arbitrairement grande avait t spcifie. Si LIMITE est omise, les champs nuls qui restent sont limins du rsultat (ce dont les utilisateurs potentiels de pop feraient bien de se souvenir). Si EXPR est omise, la fonction clate la chane $_. Si MOTIF est galement omis ou sil sagit dun espace littral, " ", la fonction clate sur les caractres despacement, /s+/, aprs avoir limin tout espacement en dbut de chane. On peut clater des chanes de nimporte quelle longueur :
@cars @champs @mots @lignes = = = = split split split split //, /:/, " ", /^/, $mot; $ligne; $paragraphe; $tampon;

16. Un contexte scalaire entrane galement le fait que split crive son rsultat dans @_, mais cet usage est dprci.

customer_8566

Fonctions Perl par ordre alphabtique

753

Un motif capable de correspondre soit la chane vide, soit quelque chose de plus long que la chane vide (par exemple, un motif compos dun seul caractre modifi par un * ou un ?) clatera la valeur de EXPR en caractres spars partout o il correspond la chane vide entre les caractres ; les correspondances non-nulles passeront outre les occurrences du dlimiteur comme habituellement. (En dautres termes, un motif ne trouvera pas de correspondance en plus dun endroit, mme avec une longueur de zro.) Par exemple :
print join :, split / */, la vtre;

produira :l:a:v:o:t:r:e . Les espaces ont disparu car ils ont provoqu une correspondance non-nulle. Dans un cas trivial, le motif nul // se contente dclater la chane en caractres spars, et les espaces ne disparaissent pas. (Pour une correspondance de motif normale, un motif // rpterait le dernier motif de correspondance russie, mais le motif de split ne tombe pas dans cette crevasse.) Le paramtre LIMITE peut tre utilis pour nclater quune partie dune chane :
($login, $mot_de_passe, $reste) = split /:/, $_, 3;

Nous vous encourageons clater des listes de noms comme ceci afin dautodocumenter votre code. (Pour des raisons de vrification derreurs, remarquez que $reste serait indfini sil y avait moins de 3 champs.) Quand une liste se voit assigner une valeur, si LIMITE est omise, Perl fournit une LIMITE suprieure de 1 au nombre de variables de la liste pour viter un travail inutile. Pour la liste ci-dessus, LIMITE aurait t de 4 par dfaut, et $reste naurait reu que le troisime champ et non le reste de la ligne. Dans des applications o le temps compte, il vaut mieux ne pas clater en plus de champs que ce dont vous avez vraiment besoin. (Le problme avec les langages puissants, cest quils vous laissent parfois tre des idiots en puissance.) Nous avons dit plus haut que les dlimiteurs ntaient pas renvoys, mais si le MOTIF contient des parenthses, les champs habituellement renvoys viennent sintercaler entre chaque occurrence des dlimiteurs entre parenthses qui est galement inclue dans la liste rsultante. Voici un exemple simple :
split /([-,])/, "1-10,20";

produit la valeur de liste :


(1, -, 10, ,, 20)

Sil y a plus de parenthses, un champ est renvoy pour chaque paire, mme si certaines ne donnent pas de correspondances, auquel cas des valeurs indfinies sont renvoyes ces positions. Ainsi, si vous crivez :
split /(-)|(,)/, "1-10,20";

vous obtiendrez la valeur :


(1, -, undef, 10, undef, ,, 20)

Largument /MOTIF/ peut tre remplac par une expression spcifiant les motifs qui varient lexcution. Comme pour les motifs ordinaires, pour ne compiler lexcution quune seule fois, utilisez /$variable/o. Il existe un cas spcial o la spcification dun espace unique (" ") clate sur les caractres despacement tout comme split sans argument. split(" ") peut donc tre utilis pour muler le comportement de awk par dfaut. Alors quau contraire split(/ /)

customer_8566

754

Chapitre 29 Fonctions

vous donnera autant de champs nuls initiaux quil existe despaces en en-tte. (Par ailleurs, si lon fournit une chane au lieu dune expression rationnelle, elle sera de toute faon interprte comme une expression rationnelle.) Vous pouvez utiliser cette proprit pour supprimer les espaces au dbut et la fin dune chane et pour rassembler les squences de caractres despacement conscutifs en un seul espace :
$chaine = join( , split( , $chaine));

Lexemple suivant clate un en-tte de message RFC-822 en un hachage contenant $tete{$Date}, $tete{Subject}, et ainsi de suite. Il utilise lastuce dassigner une liste de paire un hachage, en se basant sur le fait que les dlimiteurs alternent avec des champs dlimits. Il emploie les parenthses pour renvoyer les parties de chaque dlimiteur comme faisant partie de la valeur de liste renvoye. Comme le motif de split garantit le renvoi des lments en paires par la vertu de contenir un seul jeu de parenthses, laffectation du hachage est sr de recevoir une liste compose de paires clef/valeur, o chaque clef est le nom dun champ den-tte. (Cette technique fait malheureusement perdre des informations sur plusieurs lignes avec le mme champ de clef, comme les lignes Received-By. Ah, et puis zut. . . .)
$entete =~ s/\n\s+/ /g; # Runit les lignes de continuation. %tete = (PREAMBULE, split /^(\S*?):\s*/m, $entete);

Lexemple suivant traite les entres dun fichier Unix passwd(5). Vous pourriez viter le chomp, auquel cas $shell se terminerait par un saut de ligne.
open MOT_DE_PASSE, /etc/passwd; while (<MOT_DE_PASSE>) { chomp; # supprime le saut de ligne final ($login, $mot_de_passe, $uid, $gid, $nom_reel, $rep, $shell) = split /:/; ... }

Voici comment traiter chaque mot de chaque ligne de chaque fichier dentre pour crer un hachage des frquences de mots :
while (<>) { foreach $mot (split) { $compteur{$mot}++; } }

Linverse de split est effectu par join (sauf que join ne peut joindre quavec le mme dlimiteur entre tous les champs). Pour clater une chane sur des champs de longueur fixe, employez unpack.

sprintf
sprintf FORMAT, LISTE

Cette fonction renvoie une chane formate suivant les conventions habituelles de printf gouvernes par la fonction sprintf de la bibliothque C. Voir sprintf (3) ou printf (3) sur votre systme pour une explication des principes gnraux. La chane FORMAT contient du texte comprenant des spcificateurs de champs auxquels les lments de LISTE sont substitus, raison dun lment par champ.

customer_8566

Fonctions Perl par ordre alphabtique

755

Perl ralise son propre formatage pour sprintf il mule la fonction C sprintf, mais il ne lutilise pas.17 Il en rsulte que toutes les extensions non-standard dans votre fonction sprintf (3) locale ne sont pas accessibles depuis Perl. Le sprintf de Perl permet dutiliser les conversions universellement connues qui sont montres dans le tableau 29-4. Tableau 29-4. Formats pour sprintf
Champ %% %c %s %d %u %o %x %e %f %g Signification Un signe pourcent. Un caractre avec le nombre donn. Une chane. Un entier sign, en dcimal. Un entier non-sign, en dcimal. Un entier non-sign, en octal. Un entier non-sign, en hexadcimal. Un nombre virgule f lottante, en notation scientifique. Un nombre virgule f lottante, en notation dcimale fixe. Un nombre virgule f lottante, en notation %e ou %f.

De plus, Perl permet dutiliser les conversion suivantes, largement supportes :


Champ %X %E %G %b %p %n Signification Comme %x, mais avec des lettres majuscules. Comme %e, mais avec un E majuscule. Comme %g, mais avec un E majuscule (si cest applicable). Un entier non-sign, en binaire. Un pointeur (affiche ladresse de la valeur Perl en hexadcimal). Spcial : sauvegarde le nombre de caractres de sortie jusque l dans la prochaine variable de la liste darguments.

Enfin, pour une compatibilit antrieure (et nous voulons vraiment dire antrieure ), Perl permet dutiliser ces conversions inutiles mais largement supportes :
Champ %i %D Signification Un synonyme pour %d. Un synonyme pour %ld.

17. Mise part pour les nombres virgule f lottante, et mme dans ce cas, seulement les modificateurs standards sont autoriss.

customer_8566

756
Champ %U %O %F Signification Un synonyme pour %lu. Un synonyme pour %lo. Un synonyme pour %f.

Chapitre 29 Fonctions

Perl permet dutiliser les f lags suivants universellement connus entre le % et le caractre de conversion :
Flag espace + 0 # nombre .nombre Signification Prfixe un nombre positif par un espace. Prfixe un nombre positif par un signe plus. Justifie le champ vers la gauche. Utilise des zros, et non des espaces, pour justifier vers la droite. Prfixe un octal non nul par "0" et un hexadcimal non nul par "0x". Largeur minimale du champ. Prcision : chiffres aprs la virgule pour les nombres virgule f lottante, longueur maximale pour les chanes, longueur minimale pour les entiers. Interprte lentier comme un type C long ou unsigned long. Interprte lentier comme un type C short ou unsigned short (si aucun f lag nest fourni, lentier est interprt comme un type C int ou unsigned).

l h

Il existe galement ces deux f lags spcifiques Perl :


Flag V v Signification Interprte lentier comme le type entier standard de Perl. Interprte la chane comme un vecteur dentiers, affichs comme des nombres spars soit par des points, soit par une chane arbitraire reue depuis la liste darguments lorsque le f lag est prcd par *.

Si votre Perl connat les quads (entiers de 64 bits) soit parce que la plate-forme les supporte nativement, soir parce que Perl a t spcialement compil avec cette possibilit, alors les caractres d u o x X b i D U O affichent des quads et ils peuvent optionnellement tre prcds par ll, L ou q. Par exemple, %lld %16LX %qo. Si Perl connat les longs doubles (ceci requiert que la plate-forme supporte les longs doubles), les f lags e f g E F G peuvent optionnellement tre prcd par ll ou L. Par exemple, %llf %Lf. L o un nombre pourrait apparatre dans les f lags, un astrisque ( * ) peut tre utilis en lieu et place, auquel cas Perl utilise la prochaine entit dans la liste darguments comme le nombre donn (cest--dire, comme le champ de largeur ou de prcision). Si un champ de largeur, obtenu avec * est ngatif, il entrane les mmes effets quun f lag - : une justification vers la gauche.

customer_8566

Fonctions Perl par ordre alphabtique

757

Le f lag v est utilis pour afficher les valeurs ordinales de caractres dans des chanes arbitraires :
sprintf sprintf sprintf sprintf "la version est v%vd\n", $^V; "ladresse est %vd\n", $adr; "ladresse est %*vX\n", $adr; "les bits sont %*vb\n", " ", $bits; # # # # version adresse adresse chanes de Perl IPv4 IPv6 de bits alatoires

sqrt
sqrt EXPR sqrt

_@

Cette fonction renvoie la racine carre de EXPR. Pour les autre racines, comme la racine cubique, vous pouvez utiliser loprateur ** pour lever quelque chose une puissance fractionnaire. Nessayez par lune de ces approches avec des nombres ngatifs, car cela devient un problme lgrement plus complexe (et lve une exception). Mais il existe un module standard pour soccuper de cela aussi :
use Math::Complex; print sqrt(-2); # affiche 1.4142135623731i

srand
srand EXPR srand

Cette fonction positionne la graine alatoire pour loprateur rand. Si EXPR est omise, elle utilise une valeur semi-alatoire fournie par le noyau (si il supporte le priphrique /dev/urandom) ou base sur lheure et la date courante et le PID, entre autres choses. Il nest gnralement pas du tout ncessaire dappeler srand, car si on ne lappelle pas explicitement, loprateur rand linvoque implicitement. Toutefois, ce ntait pas vrai dans les version de Perl antrieures 5.004, donc si votre script a besoin de tourner avec des versions de Perl plus anciennes, il doit appeler srand. Les programmes appels frquemment (comme les scripts CGI) qui nutilisent que time ^ $$ pour gnrer une graine alatoire peuvent les deux tiers du temps tre victimes de la proprit mathmatique a^b == (a+1)^(b+1). Alors ne faites pas cela. la place, utilisez :
srand( time() ^ ($$ + ($$ << 15)) );

Vous aurez besoin de plus dune graine plus alatoire que celle par dfaut pour faire de la cryptographie. Sur certains systmes le priphrique /dev/urandom est appropri. Sinon, la mthode habituelle est de faire une somme de contrle (N.d.T. : checksum) sur la sortie compresse dun ou plusieurs programmes donnant ltat du systme dexploitation en tenant compte du changement rapide de ces tats. Par exemple :
srand (time ^ $$ ^ unpack "%L*", ps wwaxl | gzip);

Si vous tes particulirement concerns par ce problme, regardez le module Math::TrulyRandom dans CPAN. Nappelez pas srand plusieurs fois dans un programme moins de savoir exactement ce que vous faites et pourquoi vous le faites. Le but de cette fonction est dinitialiser une

customer_8566

758

Chapitre 29 Fonctions

graine pour la fonction rand pour quelle puisse produire un rsultat diffrent chaque lancement du programme. Ne lappelez quune seule fois au dbut, faute de quoi rand ne gnrera pas de nombres alatoires !

stat
stat HANDLE_FICHIER stat EXPR stat

_!G

Dans un contexte scalaire, cette fonction renvoie un boolen indiquant si lappel a russi. Dans un contexte de liste, elle renvoie une liste de 13 lments donnant ltat dun fichier, quil soit ouvert via HANDLE_FICHIER ou nomm par EXPR. Elle est gnralement utilise comme suit :
($periph,$inode,$mode,$nb_liens,$uid,$gid,$type_periph,$taille, $date_a,$date_m,$date_c, $taille_bloc,$blocs) = stat $nom_fichier;

Tous les champs ne sont pas supports par tous les systmes dexploitation, les champs non-supports renvoient 0. Voici les significations des champs : Tableau 29-5. Champs renvoys par stat
Index 0 1 2 3 4 5 6 7 8 9 10 11 12 Champ $periph $inode $mode $nb_liens $uid $gid $type_periph $taille $date_a $date_m $date_c $taille_bloc $blocs Signification Numro de priphrique du systme de fichier. Numro dinode. Mode du fichier (type et permissions). Nombre de liens (en dur) vers le fichier. UID numrique du propritaire du fichier. GID numrique du groupe dsign du fichier. Identificateur du priphrique (pour les fichiers spciaux seulement). Taille totale du fichier, en octets. Dernire date daccs au fichier en secondes depuis lorigine. Dernire date de modification du fichier en secondes depuis lorigine. Date de changement de linode (et non de cration !) en secondes depuis lorigine. Taille de bloc prfr pour les entres/sorties sur le systme de fichier. Nombre de blocs rellement allous.

$periph et $inode, pris ensemble, identifient un fichier de manire unique. Les $taille_bloc et $blocs ne sont dfinis que sur les systmes de fichiers drivs de BSD. Le champ $blocs (sil est dfini) est donn en blocs de 512 octets. La valeur de

customer_8566

Fonctions Perl par ordre alphabtique

759

$blocs*512 peut normment diffrer de $taille pour des fichiers contenant des blocs non allous, ou trous , qui ne sont pas compts dans $blocs. Si on passe stat le handle de fichier spcial compos dun soulign, aucune collection dinformations na lieu, mais le contenu actuel de la structure datant du dernier stat, lstat ou du dernier test de fichier en dpendant (comme -r, -w ou -x) sont renvoys. Comme le mode comprend la fois le type du fichier et ses permissions, vous devez masquer la partie du type et faire printf ou sprintf avec "%o" si vous voulez voir les permissions relles :
$mode = (stat($nom_fichier))[2]; printf "Les permissions sont %04o\n", $mode & 07777;

Le module File::stat fournit un mcanisme daccs simplifi, orient par nom :


use File::stat; $sb = stat($nom_fichier); printf "Le fichier est %s, sa taille %s, ses permission %04o, date_m %s\n", $nom_fichier, $sb->size, $sb->mode & 07777, scalar localtime $sb->mtime;

Vous pouvez galement importer les dfinitions symboliques des divers bits de mode depuis le module Fcntl. Voir la documentation en ligne pour plus de dtail. Astuce : si vous navez seulement besoin que de la taille du fichier, essayez loprateur de test de fichier -s, qui renvoie directement la taille en octets. Il existe galement des tests de fichiers qui renvoie lge du fichier en nombre de jours.

study
study SCALAIRE study

Cette fonction prend du temps supplmentaire pour tudier SCALAIRE afin danticiper de nombreuses recherches de motifs sur la chane avant quelle ne soit ensuite modifie. Ceci peut ou non faire gagner du temps, selon la nature et le nombre de motifs de vos recherches, et selon la distribution des frquences de caractres dans la chane recherche il vaut mieux que vous compariez les temps dexcution avec et sans study pour voir ce qui tourne le plus vite. Les boucles qui cherchent de nombreuses chanes courtes et constantes (y compris les parties constantes de motifs plus complexes) sont celles qui bnficieront le plus de study. Si tous vos motifs sont des chanes constantes, ancres au dbut, study ne vous sera daucun secours car aucune scrutation ne sera effectue. Vous ne pouvez avoir quun seul study (N.d.T. : tude) actif la fois ; si vous tudiez un scalaire diffrent, le premier est d-tudi . study fonctionne de la manire suivante : une liste chane de chacun des caractres de la chane est construite de faon savoir, par exemple, o se trouvent tous les caractres k . Pour chaque chane, le caractre le plus rare est slectionn, en se fondant sur des tables de frquence statiques construites par des programmes C sur du texte anglais. Seuls les endroits contenant ce caractre rare sont examins. Par exemple, voici une boucle qui insre des entres dindex avant toute ligne contenant un certain motif :
while (<>) { study;

customer_8566

760
print ".IX machin\n" if /\bmachin\b/; print ".IX truc\n" if /\btruc\b/; print ".IX bidule\n" if /\bbidule\b/; ... print; }

Chapitre 29 Fonctions

Pendant cette recherche sur /\bmachin\b/, seuls les endroits de $_ contenant h seront examines car h est plus rare que les autres lettres. En gnral, le gain est indiscutable, sauf dans des cas pathologiques. La seule question est de savoir si cela fait gagner plus de temps que de construire dabord la liste chane. Si vous devez rechercher des chanes que vous ne connaissez quau moment de lexcution, vous pouvez construire un boucle complte sous forme de chane et levaluer pour viter la recompilation systmatique de tous vos motifs. Ceci, associ $/ pour entrer des fichiers complets en un seul enregistrement, peut tre extrmement rapide, souvent plus rapide que des programmes spcialiss comme fgrep(1). La routine suivante scrute une liste de fichiers (@fichiers) pour trouver une liste de mots @mots), et affiche les noms des fichiers contenant une correspondance sans tenir compte de la casse :
$recherche = while (<>) { study;; foreach $mot (@mots) { $recherche .= "++\$vu{\$ARGV} if /\\b$mot\\b/i;\n"; } $recherche .= "}"; @ARGV = @fichiers; undef $/; # gobe chaque fichier en entier eval $recherche; # pied au plancher die $@ if $@ # en cas dchec de eval $/ = "\n"; # remet le dlimiteur dentre normal foreach $fichier (sort keys(%vu)) { print $fichier, "\n"; }

Maintenant que nous avons loprateur qr//, les evals compliqus lexcution comme celui ci-dessus sont moins indispensables. Ceci fait la mme chose :
@motifs = (); foreach $mot (@mots) { push @motifs, qr/\b$mot\b/i; } @ARGV = @fichiers; undef $/; # gobe chaque fichier en entier while (<>) { for $motif (@motifs) { $vu{$ARGV}++ if /$motif/; } } $/ = "\n"; # remet le dlimiteur dentre normal foreach $fichier (sort keys(%vu)) { print $fichier, "\n"; }

customer_8566

Fonctions Perl par ordre alphabtique

761

sub
Dclarations nommes :
sub sub sub sub sub sub sub sub sub sub sub sub NOM PROTO ATTRS NOM ATTRS NOM PROTO NOM NOM NOM NOM NOM PROTO ATTRS BLOC ATTRS BLOC PROTO BLOC BLOC

Dfinitions nomme :

Dfinitions anonymes :
PROTO ATTRS BLOC ATTRS BLOC PROTO BLOC BLOC

La syntaxe des dclarations et dfinitions de sous-programmes parat complique, mais elle est vraiment assez simple en pratique. Tout est bas sur la syntaxe :
sub NOM PROTO ATTRS BLOC

Les quatre arguments sont tous optionnels ; la seule restriction est que les champs prsents doivent tre prsents dans cet ordre ; et que vous devez utiliser au moins un des champs NOM ou BLOC. Pour le moment nous ignorerons les champs PROTO et ATTRS ; ce sont seulement des modificateurs de la syntaxe de base. Les champs NOM et BLOC sont les parties importantes pour faire court : Si vous navez quun NOM mais pas de BLOC, il sagit dune dclaration de ce nom (et si jamais vous voulez appelez le sous-programme, vous devrez fournir plus tard une dfinition avec la fois NOM et BLOC). Les dclarations nommes sont spcialement utiles pour que lanalyseur syntaxique traite un nom de manire spciale sil sait quil sagit dun sous-programme dfini par lutilisateur. Vous pouvez appelez ceci un sous-programme ou une fonction ou encore un oprateur, exactement comme les fonctions internes. Ces dclarations sont parfois appeles dclarations anticipes. Si vous avez la fois un NOM et un BLOC, il sagit dune dfinition standard dun sousprogramme nomm (et galement une dclaration, si vous navez pas dclar le nom prcdemment). Les dfinitions nommes sont spcialement utiles car le BLOC associe un vritable sens (le corps du sous-programme) la dclaration. Cest exactement ce que cela signifie lorsque nous disons quelle dfinit le sous-programme au lieu de simplement le dclarer. La dfinition ressemble toutefois la dclaration, en ce que le code lencadrant ne la voit pas, et quelle ne renvoie pas de valeur en ligne avec laquelle vous pourriez rfrencer le sous-programme. Si vous navez quun BLOC mais pas de NOM, il sagit dune dfinition sans nom, cest-dire, un sous-programme anonyme. Puisquelle na pas de nom, ce nest absolument pas une dclaration, mais un oprateur rel qui renvoie lexcution une rfrence vers le corps du sous-programme anonyme. Cest extrmement utile pour

customer_8566

762

Chapitre 29 Fonctions

traiter du code en tant que donne. Cela vous permet de passer de menus morceaux de code en tant que fonctions de rappel (N.d.T. : callbacks), ou peut-tre mme en tant que fermetures si loprateur de dfinition sub se rfre des variables lexicales qui se trouvent lextrieur de son propre code. Cela signifie que diffrents appels au mme oprateur sub feront la comptabilit ncessaire pour conserver la visibilit de la version correcte de chacune de ces variables lexicales le temps o la fermeture existe, mme si la porte dorigine des variables lexicales a t dtruite. Dans chacun de ces trois cas, soit lun, soit les deux arguments PROTO et ATTRS peuvent apparatre aprs le NOM et avant le BLOC. Un prototype est une liste de caractres entre parenthses qui indique lanalyseur syntaxique comment traiter les arguments dune fonction. Les attributs sont introduits par un deux-points et fournissent des informations supplmentaires lanalyseur concernant la fonction. Voici une dfinition typique qui inclut tous les quatre champs :
num_ch_cmp ($$) : locked { my ($a, $b) = @_; return $a <=> $b || $a cmp $b; }

pour plus de dtails sur les listes dattributs et leur manipulation, voir le pragma attributes au chapitre 31. Voir galement le chapitre 6 et la section Sous-programmes anonymes au chapitre 8.

substr
subtsr EXPR, DECALAGE, LONGUEUR, REMPLACEMENT subtsr EXPR, DECALAGE, LONGUEUR subtsr EXPR, DECALAGE

@GO

Cette fonction extrait une sous-chane de la chane donne par EXPR et la renvoie. La sous-chane est extraite en commenant DECALAGE caractres depuis le premier. (Remarque : si vous avez fait le malin avec $[, le dbut de la chane nest pas 0, mais comme vous avez t sage (nest-ce pas ?) il ny a pas de problme). Si DECALAGE est ngatif, la sous-chane dmarre cette distance de la fin de la chane. Si LONGUEUR est omise, toute la fin de la chane est renvoye. Si LONGUEUR est ngative, la longueur est calcule pour laisser ce nombre de caractres depuis la fin de la chane. Sinon, LONGUEUR indique la longueur de la sous-chane extraire, ce quoi vous pouviez vous attendre. Vous pouvez utiliser substr comme une lvalue (quelque chose laquelle on peut assigner une valeur), auquel cas EXPR doit aussi en tre une. Si lon assigne une valeur dune longueur infrieure LONGUEUR, la chane sera raccourcie et si lon assigne une valeur dune longueur suprieure LONGUEUR, la chane sallongera pour sen accommoder. Il vous faudra peut-tre complter ou couper la valeur avec sprintf ou loprateur x pour conserver une chane de mme longueur. Si vous tentez une affectation dans une zone non-alloue aprs la fin la chane, substr lve une exception. Pour prfixer la valeur courante de $var par la chane "Achille" , crivez :
substr($var, 0, 0) = "Achille";

Pour remplacer le premier caractre de $var par "Talon" , crivez :


substr($var, 0, 1) = "Talon";

customer_8566

Fonctions Perl par ordre alphabtique


Et enfin, pour remplacer le dernier caractre de $var par "Lefuneste" , crivez :
substr($var, -1, 1) = "Lefuneste";

763

Une alternative lutilisation de substr en tant que lvalue est lemploi de la chane REMPLACEMENT comme quatrime argument. Ceci vous permet de remplacer des partie de lEXPR et de renvoyer ce quil y avait avant en une seule opration, exactement comme vous pouvez le faire avec splice. Le prochain exemple remplace galement le dernier caractre de $var par "Lefuneste" et met la chane remplace dans $avant :
$avant = substr($var, -1, 1, "Lefuneste");

substr en tant que lvalue nest pas rserve seulement aux affectations. Cet exemple remplace les espaces par des points, mais seulement dans les 10 derniers caractres de la chane :
substr($var, -10) =~ s/ /./g;

symlink
symlink ANCIEN_NOM, NOUVEAU_NOM

!XU

Cette fonction cre un nouveau nom de fichier li symboliquement lancien nom de fichier. La fonction renvoie vrai en cas de succs, sinon faux. Sur les systmes ne supportant pas les liens symboliques, elle lve une exception lexcution. Pour viter cela, utilisez eval pour intercepter lerreur potentielle :
$symlink_existe = eval { symlink("", ""); 1 };

Ou utilisez le module Config. Soyez prudent si vous fournissez un lien symbolique relatif, car cela sera interprt relativement la position du lien symbolique lui-mme, et non votre rpertoire de travail courant. Voir galement link et readlink plus haut dans ce chapitre.

syscall
syscall LISTE

!OXU

Cette fonction invoque lappel systme (nous voulons dire un appel systme, et pas une commande shell) spcifi dans le premier argument de la liste en passant les lments restants comme arguments lappel systme. (Beaucoup dentre eux sont maintenant plus directement disponibles par le biais de modules comme POSIX). La fonction lve une exception si syscall(2) nest pas implment. Les arguments sont interprts comme suit : si un argument donn est numrique, largument est pass comme un entier C. Sinon, cest un pointeur sur la valeur chane qui est pass. Vous devez vous assurer que la chane est assez longue pour recevoir tout rsultat pouvant y tre crit ; sinon vous chercher la copie du cur du programme (core dump). Vous ne pouvez pas utiliser une chane littrale (ou toute autre chane en lecture seule) comme argument de syscall car Perl doit prvoir que lon puisse crire dans tout pointeur de chane. Si vos arguments entiers ne sont pas des littraux et nont jamais t interprts dans un contexte numrique, vous devrez peut-tre leur ajouter 0 pour les forcer ressembler des nombres. syscall renvoie toute valeur retourne par lappel systme invoqu. Daprs les con-

customer_8566

764

Chapitre 29 Fonctions

ventions de codage C, si lappel systme choue, syscall renvoie -1 et positionne $! (errno). Certains appels systme renvoient lgitimement -1 en cas de russite. La manire approprie de grer de tels appels systme et dassigner $!=0; avant lappel et de vrifier la valeur de $! si syscall renvoie -1. Tous les appels systme ne sont pas accessibles de cette manire. Par exemple, Perl peut passer jusqu 14 arguments votre appel systme, ce qui doit normalement suffire en pratique. Il existe cependant un problme avec les appels systme qui renvoient des valeurs multiples. Prenez syscall(&SYS_pipe) : il renvoie le numro de fichier de lextrmit de lecture du pipe quil cre. Il ny a aucun de moyen de rcuprer le numro de fichier de lautre extrmit. Vous pouvez viter ce type de problme en utilisant pipe la place. Pour rsoudre le problme gnrique, crivez des XSUB (modules de sous-programmes externes, un dialecte de C) pour accder aux appels systme directement. Puis mettez votre nouveau module sur CPAN et devenez mondialement populaire. Le sous-programme suivant renvoie lheure courante en tant que nombre virgule f lottante plutt que le nombre entier de secondes renvoy par time. (Il ne fonctionne que sur les machines qui supporte lappel systme gettimeofday(2).)
sub heure_precise() { package main; # pour le prochain require require syscall.ph; # prpare le tampon pour quil soit de la taille de deux entiers # longs de 32-bits my $tv = pack("LL", ()); syscall(&SYS_gettimeofday, $tv, undef) >=0 or die "gettimeofday : $!"; my ($secondes, $microsecondes) = unpack("LL", $tv); return $secondes + ($microsecondes /1_000_000); }

Imaginez que Perl ne supporte pas lappel systme setgroups(2)18, mais que votre noyau limplmente. Vous pourriez toujours latteindre de cette manire :
require syscall.ph; syscall(&SYS_setgroups; scalar @nouveaux_gids, pack("i*", @nouveaux_gids)) or die "setgroups : $!";

Vous devrez peut-tre lancer h2ph, comme lindiquent les instructions dinstallations de Perl, pour crer syscall.ph. Certains systmes peuvent ncessiter la place un canevas pour pack de "II". Encore plus perturbant, la fonction syscall suppose une quivalence de taille entre les types C int, long et char*. Essayez de ne pas considrer syscall comme le parangon de la portabilit. Voir le module Time::HiRes de CPAN pour une approche plus rigoureuse des problmes de dates et dheures dune granularit plus fine.

sysopen
sysopen HANDLE_FICHIER, NOM_FICHIER, MODE, MASQUE sysopen HANDLE_FICHIER, NOM_FICHIER, MODE
18. Bien quil le supporte via $(.

!G

customer_8566

Fonctions Perl par ordre alphabtique

765

La fonction sysopen ouvre le fichier dont le nom est donn par NOM_FICHIER et lassocie avec HANDLE_FICHIER. Si HANDLE_FICHIER est une expression, sa valeur est employe comme le nom du handle de fichier ou comme une rfrence sur ce dernier. Si HANDLE_FICHIER est une variable dont la valeur est indfinie, une valeur sera cre pour vous. La valeur de retour est vrai si lappel russit, sinon faux. Cette fonction est une interface directe lappel open(2) de votre systme dexploitation suivi par un appel de bibliothque fdopen(3). En tant que tel, vous devrez ici prtendre tre un peu un programmeur C. Les valeurs possibles et les f lags de bits du paramtre MODE sont disponibles via le module Fcntl. Puisque des systmes diffrents supportent des f lags diffrents, ne comptez pas sur la disponibilit de tous les f lags sur votre systme. Consultez votre page de manuel open(2) ou son quivalent local pour plus de dtails. Nanmoins, les f lags suivants devrait tre prsents sur tout systme disposant dune bibliothque C raisonnable :
Flag O_RDONLY O_WRONLY O_RDWR O_CREAT O_EXCL O_APPEND O_TRUNC O_NONBLOCK Signification Lecture seule. criture seule. Lecture et criture. Cre le fichier sil nexiste pas. choue si le fichier existe dj. Ajoute la fin du fichier. Tronque le fichier. Accs non-bloquant.

Beaucoup dautres options sont toutefois possibles. Voici quelques f lags moins communs :
Flag O_NDELAY O_SYNC Signification Ancien synonyme pour O_NONBLOCK crit un bloc jusqu ce que la donne soit physiquement crite vers le matriel sous-jacent. On peut galement voir ici O_ASYNC, O_DSYNC et O_RSYNC. flock avec LOCK_EX ( titre consultatif seulement). flock avec LOCK_SH ( titre consultatif seulement). choue si le fichier nest pas un rpertoire. choue si le dernier composant du chemin est un lien symbolique. Effectue un binmode pour les systmes Microsoft. Un O_TEXT peut galement parfois exister pour obtenir le comportement oppos. Certains systmes en ont besoin pour les fichiers de plus de 2 GO. Louverture dun fichier de terminal ne le fera pas devenir le terminal de contrle du processus si vous nen aviez pas encore. Habituellement ce f lag nest plus ncessaire.

O_EXLOCK O_SHLOCK O_DIRECTORY O_NOFOLLOW O_BINARY O_LARGEFILE O_NOCTTY

customer_8566

766

Chapitre 29 Fonctions

Le f lag O_EXCL ne sert pas pour les verrous : ici, lexclusivit signifie que si le fichier existe dj, sysopen choue. Si le fichier nomm par NOM_FICHIER nexiste pas et que le MODE inclue le f lag O_CREAT, alors sysopen cre le fichier avec les permissions initiales dtermines par largument MASQUE (ou 0666 sil est omis) et modifi par le umask courant de votre processus. Cette valeur par dfaut est raisonnable : voir la dfinition de umask pour une explication. Les handles de fichiers ouverts avec open et sysopen peuvent tre utiliss de manire interchangeable. Vous navez pas besoin dutiliser sysread et ses amis simplement parce que vous avez ouvert le fichier avec sysopen, et rien ne vous en empche si vous lavez ouvert avec open. Les deux sont capables de choses que lautre ne peut pas faire. Un open traditionnel peut ouvrir des pipes, forker des processus, positionner des disciplines, dupliquer des handles de fichiers et convertir un numro descripteur de fichier vers un handle de fichier. De plus, il ignore les caractres despacement au dbut ou la fin du nom de fichier et respecte la particularit de - en tant que nom de fichier spcial. Mais lorsquil sagit douvrir de vritables fichiers, sysopen peut faire tout ce quopen fait. Les exemples suivants montrent les appels quivalents ces deux fonctions. Nous avons omis les vrifications or die $! pour plus de clart, mais assurez-vous de toujours vrifier les valeurs de retour dans vos programmes. Nous nous restreindrons nemployer que les f lags disponibles sur virtuellement tous les systmes dexploitations. Il sagit simplement dun moyen de contrler les valeurs que vous rassemblez par un OU en utilisant loprateur de bit | pour les passer dans largument MODE . Ouvrir un fichier en lecture :
open(HF, "<", $chemin); sysopen(HF, $chemin, O_RDONLY);

Ouvrir un fichier en criture, en crant un nouveau fichier si besoin ou en tronquant un fichier existant :
open(HF, ">", $chemin); sysopen(HF, $chemin, O_WRONLY | O_TRUNC | O_CREAT);

Ouvrir un fichier en ajout, en le crant si besoin :


open(HF, ">>", $chemin); sysopen(HF, $chemin, O_WRONLY | O_APPEND | O_CREAT);

Ouvrir un fichier en mise jour, le fichier devant dj exister :


open(HF, "+<", $chemin); sysopen(HF, $chemin, O_RDWR);

Et voici ce que vous pouvez faire avec sysopen mais pas avec un open traditionnel : Ouvrir et crer un fichier en criture, le fichier ne devant pas dj exister :
sysopen(HF, $chemin, O_WRONLY | O_EXCL | O_CREAT);

Ouvrir un fichier en ajout, le fichier devant dj exister :


sysopen(HF, $chemin, O_WRONLY | O_APPEND);

Ouvrir un fichier en mise jour, en crant un nouveau fichier si besoin :


sysopen(HF, $chemin, O_RDWR | O_CREAT);

customer_8566

Fonctions Perl par ordre alphabtique


Ouvrir un fichier en mise jour, le fichier ne devant pas dj exister :
sysopen(HF, $chemin, O_RDWR | O_EXCL | O_CREAT);

767

Ouvrir un fichier en criture seule sans bloquer, mais sans crer le fichier sil nexiste pas :
sysopen(HF, $chemin, O_WRONLY | O_NONBLOCK);

Le module FileHandle, dcrit au chapitre 32, offre un ensemble de synonymes orients objet (plus quelques nouvelles fonctionnalits) pour ouvrir des fichiers. Vous tes cordialement invits utiliser les mthodes appropries de FileHandle19 sur tout handle cr avec open, sysopen, pipe, socket ou accept, mme si vous navez pas employ le module pour initialiser ces handles.

sysread
sysread HANDLE_FICHIER, SCALAIRE, LONGUEUR, DECALAGE sysread HANDLE_FICHIER, SCALAIRE, LONGUEUR

!@tGO

Cette fonction tente de lire LONGUEUR octets de donnes dans la variable SCALAIRE depuis le HANDLE_FICHIER spcifi en utilisant lappel systme de bas niveau read(2). La fonction renvoie le nombre doctets rellement lus, ou 0 en fin de fichier. Elle renvoie undef en cas derreur. La taille de SCALAIRE sera ajuste la longueur effectivement lue. Le DECALAGE, sil est spcifi, indique partir do lire dans la chane, afin de pouvoir lire au milieu dune chane utilise comme tampon. Voir syswrite pour un exemple dutilisation de DECALAGE. Une exception est leve si LONGUEUR est ngative ou si DECALAGE pointe lextrieur de la chane. Prparez-vous grer vous-mme les problmes (comme les appels systme interrompus) que les entres/sorties standards grent habituellement pour vous. Comme sysread passe outre les entres/sorties standards, ne mlangez pas sysread avec dautres type de lectures, ni avec print, printf, write, seek, tell ou eof moins dtre adepte des sciences occultes (ou des soires cuir et chanes). De mme, soyez sil vous plat prvenus que lors de la lecture dans un fichier contenant de lUnicode ou tout autre encodage sur plusieurs octets, les frontires du tampon peuvent tomber au milieu dun caractre.

sysseek
sysseek HANDLE_FICHIER, POSITION, DEPART

!G

Cette fonction affecte la position systme du HANDLE_FICHIER en utilisant lappel systme lseek(2). Elle passe outre les entres/sorties standard, ainsi les mlanges avec des lectures (autres que par sysread), ou avec print, printf, write, seek, tell ou eof peuvent semer la confusion. HANDLE_FICHIER peut tre une expression dont la valeur donne le nom du handle de fichier. Les valeurs de DEPART sont 0 pour mettre se positionner exactement POSITION, 1 pour se positionner la position courante plus POSITION et 2 pour se positionner EOF plus POSITION (en gnral, ngative). Pour DEPART, vous pouvez utiliser les constantes SEEK_SET, SEEK_CUR et SEEK_END des modules standards IO::See19. En fait, les mthodes de IO::File ou IO::Handle.

customer_8566

768

Chapitre 29 Fonctions

kable et POSIX ou, depuis la version 5.6 de Perl, du module Fcntl qui est plus portable et plus pratique. La fonction renvoie la nouvelle position ou undef en cas dchec. Une position de zro est renvoye comme tant la chane spciale 0 but true (N.d.T. : 0 mais vrai), qui peut tre utilis numriquement sans produire davertissements.

system
system CHEMIN LISTE system CHEMIN

!?X

Cette fonction excute pour vous tout programme existant sur le systme et renvoie le code de retour de ce programme et non sa sortie. Pour capturer la sortie dune commande, utilisez les apostrophes inverses ou qx// la place. La fonction system fonctionne exactement comme exec, hormis le fait quelle effectue dabord un fork puis, quaprs lexec, elle attende que le programme excut se termine. Cest--dire quelle lance le programme et revient quand ce dernier a fini, au contraire dexec, qui remplace le programme en train de tourner par le nouveau et qui donc ne revient jamais si le remplacement russit. Le traitement des paramtres varie selon le nombre darguments, comme dans la description dexec, y compris le fait de dterminer si le shell sera appel et si vous avez menti au programme propos de son nom en spcifiant un CHEMIN spar. tant donn que system et les apostrophes inverses bloquent les signaux SIGINT et SIGQUIT, lenvoi de lun de ces signaux (provenant par exemple dun Control-C) au programme en train de tourner ninterrompt pas votre programme principal. Mais lautre programme qui est en train de tourner reoit bien le signal. Vrifiez la valeur de retour de system pour voir si le programme que vous avez lanc sest termin proprement ou pas.
@args = ("commande", "arg1", "arg2"); system(@args) == 0 or die "system @args a chou : $?";

La valeur de retour est le statut de sortie du programme tel que renvoy par lappel systme wait(2). Avec les smantiques traditionnelles, pour obtenir la vritable valeur de sortie, divisez par 256 ou faites un dcalage de 8 bits vers la gauche. Ceci car loctet de poids faible contient quelque chose dautre. (Deux choses en fait.) Les sept bits de poids faible indiquent le numro du signal qui a tu le processus (sil y en a un) et le huitime bit indique si le processus a fait une copie du cur du programme (core dump). Vous pouvez vrifier toutes les possibilits dchec, y compris les signaux et les core dumps, en inspectant $? ($CHILD_ERROR) :
$valeur_sortie = $? >> 8; $num_signal = $? & 127; $coeur_copie = $? & 128; # ou 0x7f, ou 0177, ou 0b0111_1111 # ou 0x80, ou 0200, ou 0b1000_0000

Lorsque le programme a t lanc travers un shell20 car vous aviez un seul argument
20. Cest--dire /bin/sh par dfinition, ou tout ce qui a un sens sur votre plate-forme, mais pas le shell que lutilisateur utilise ce moment.

customer_8566

Fonctions Perl par ordre alphabtique

769

et que cet argument contenait des mtacaractres du shell, les codes de retours normaux sont sujets aux caprices et aptitudes supplmentaires du shell. En dautres termes, dans ces circonstances, vous pouvez tre incapable de retrouver linformation dtaille dcrite prcdemment.

syswrite
syswrite HANDLE_FICHIER, SCALAIRE, LONGUEUR, DECALAGE syswrite HANDLE_FICHIER, SCALAIRE, LONGUEUR syswrite HANDLE_FICHIER, SCALAIRE

!@G

Cette fonction tente dcrire LONGUEUR octets de donnes depuis la variable SCALAIRE vers le HANDLE_FICHIER spcifi en utilisant lappel systme write(2). La fonction renvoie le nombre doctets rellement crits, ou undef en cas derreur. Le DECALAGE, sil est spcifi, indique partir de quel endroit de la chane il faut commencer crire. (Si par exemple la chane vous sert par exemple de tampon, ou quil vous faut reprendre une criture partielle.) Un DECALAGE ngatif spcifie que lcriture doit partir de ce nombre doctets depuis la fin de la chane. Si SCALAIRE est vide, le seul DECALAGE permis est 0. Une exception est leve si LONGUEUR est ngative ou si DECALAGE pointe lextrieur de la chane. Pour copier des donnes du handle de fichier DEPUIS vers le handle de fichier VERS, vous pouvez utiliser quelque chose comme :
use Errno qw/EINTR/; $taille_bloc = (stat FROM)[11] ||16384; # taille de bloc prfre ? while ($lng = sysread DEPUIS, $tamp, $taille_bloc) { if (!defined $lng) { next if $! == EINTR; die "Erreur systme sur read : $!\n"; } $decalage = 0; while ($lng) { # Gre les critures partielles. $ecrit = syswrite VERS, $tamp, $lng, $decalage; die "Erreur systme sur write : $!\n" unless defined $ecrit; $decalage += $ecrit; $lng -= $ecrit; } }

Prparez-vous grer par vous-mme les problmes que les entres/sorties standards traitent habituellement pour vous, telles que les critures partielles. Comme syswrite passe outre les entres/sorties standards de la bibliothque C, ne mlangez pas dappels syswrite avec des lectures (autres que sysread), des critures (comme print, printf ou write) ou dautres oprations dentres/sorties comme seek, tell ou eof moins dtre adepte des sciences occultes.21

21. Ou des soires cuir et chanes.

customer_8566

770

Chapitre 29 Fonctions

tell
tell HANDLE_FICHIER tell

Cette fonction renvoie la position actuelle dans le fichier (en octets, sur une base de zro) pour HANDLE_FICHIER. Gnralement, cette valeur est passe la fonction seek un moment ultrieur pour revenir la position courante. HANDLE_FICHIER peut tre une expression donnant le nom du handle de fichier rel ou une rfrence sur un objet handle de fichier. Si HANDLE_FICHIER est omis, la fonction renvoie la position dans le dernier fichier lu. Les positions ne sont significatives que sur les fichiers ordinaires. Les priphriques, les pipes et les sockets ne connaissent pas les positions. Il nexiste pas de fonction systell. Utilisez sysseek(HF, 0, 1) pour cela. Voir seek pour un exemple expliquant comment utiliser tell.

telldir
telldir HANDLE_REPERTOIRE

GU

Cette fonction renvoie la position courante des routines readdir sur HANDLE_REPERTOIRE. Cette valeur peut tre fournie seekdir pour accder un endroit particulier dun rpertoire. La fonction comporte les mmes dangers relatifs un possible compactage du rpertoire que la routine de la bibliothque systme correspondante. Cette fonction peut ne pas tre implmente partout o lest readdir. Mme si cest le cas, aucun calcul ne peut tre fait avec la valeur de retour. Il sagit seulement dune valeur opaque, qui na de signification que pour seekdir.

tie
tie VARIABLE, NOM_CLASSE, LISTE

Cette fonction relie une variable une classe de paquetage qui fournit limplmentation de la variable. VARIABLE est la variable (scalaire, tableau ou hachage) ou le type glob (reprsentant un handle de fichier) qui doit tre reli. NOM_CLASSE est le nom dune classe implmentant des objets du type appropri. Tous les arguments additionnels sont passs la mthode constructeur appropri, soit lun des constructeurs parmi TIESCALAR, TIEARRAY ou TIEHASH. (Si la mthode approprie nest pas trouve, une exception est leve.) Ces arguments sont gnralement similaires ceux que lon enverrait la fonction dbm_open(3) du C, mais leur signification dpend du paquetage. Lobjet renvoy par le constructeur est son tour renvoy par la fonction tie, ce qui savre utile si vous voulez accder dautres mthodes de NOM_CLASSE. (On peut aussi accder lobjet par le biais de la fonction tied). Ainsi, une classe reliant un hachage une implmentation ISAM peut fournir une mthode supplmentaire pour traverser squentiellement un ensemble de clefs (le S de ISAM), puisque vos implmentations habituelles de DBM ne peuvent pas le faire. Les fonctions comme keys et values peuvent renvoyer dnormes valeurs de listes quand elles sont appliques de grands objets comme des fichiers DBM. Vous pouvez prfrer utiliser la fonction each pour parcourir ces derniers. Par exemple :

customer_8566

Fonctions Perl par ordre alphabtique


use NDBM_File; tie %ALIAS, "NDBM_File", "/etc/aliases", 1, 0 or die "Impossible douvrir les alias : $!\n"; while (($clef,$val) = each %ALIAS) { print $clef, = , $val, "\n"; } untie %ALIAS;

771

Une classe implmentant un hachage doit comprendre les mthodes suivantes :


TIEHASH CLASSE, LISTE FETCH SOI, CLEF STORE SOI, CLEF, VALEUR DELETE SOI, CLEF CLEAR SOI EXISTS SOI, CLEF FIRSTKEY SOI NEXTKEY SOI, CLEF_PRECEDENTE DESTROY SOI

Une classe implmentant un tableau ordinaire doit comprendre les mthodes suivantes :
TIEARRAY CLASSE, LISTE FETCH SOI, INDICE STORE SOI, INDICE, VALEUR FETCHSIZE SOI STORESIZE SOI, COMPTEUR CLEAR SOI PUSH SOI, LISTE POP SOI SHIFT SOI UNSHIFT SOI LISTE SPLICE SOI, DECALAGE, LONGUEUR, LISTE EXTEND SOI, COMPTEUR DESTROY SOI

Une classe implmentant un scalaire doit comprendre les mthodes suivantes :


TIESCALAR CLASSE, LISTE FETCH SOI STORE SOI, VALEUR DESTROY SOI

Une classe implmentant un handle de fichier doit comprendre les mthodes suivantes :
TIEHANDLE CLASSE, LISTE READ SOI, SCALAIRE, LONGUEUR, DECALAGE READLINE SOI GETC SOI WRITE SOI, SCALAIRE, LONGUEUR, DECALAGE PRINT SOI, LISTE PRINTF SOI, FORMAT, LISTE CLOSE SOI DESTROY SOI

customer_8566

772

Chapitre 29 Fonctions

Les mthodes indiques ci-dessus nont pas toutes besoin dtre implmentes: Les modules Tie::Hash, Tie::Array, Tie::Scalar et Tie::Handle fournissent des classes de bases qui ont des mthodes par dfaut raisonnables. Voir chapitre 14, Variables attaches, pour un commentaire dtaill de ces mthodes. linverse de dbmopen, la fonction tie ne fera pas automatiquement un use ou un require vous devez le faire vous-mme explicitement. Voir les modules DB_File et Config qui fournissent des implmentations intressantes de tie.

tied
tied VARIABLE

Cette fonction renvoie une rfrence vers lobjet qui sous-tend le scalaire, le tableau, le hachage ou le typeglob contenu dans VARIABLE (la mme valeur qui a t renvoye lorigine par lappel tie, qui a li la variable au paquetage). Elle renvoie la valeur indfinie si VARIABLE nest pas attache un paquetage. Vous pouvez par exemple utiliser :
ref tied %hachage

pour savoir quel paquetage votre hachage est attach. ( supposer que vous layez oubli).

time
time

Cette fonction renvoie le nombre de secondes coules depuis le 1er janvier 1970, UTC, 00::00::00.22 La valeur renvoye est accepte par gmtime et localtime pour servir aux comparaisons avec les dates de modification et daccs renvoyes par stat et pour tre passe utime.
$debut = time(); system("une commande lente"); $fin = time(); if ($fin - $debut > 1) { print "Le programme a commenc : ", scalar localtime($debut), "\n"; print "Le programme a fini : ", scalar localtime($fin), "\n"; }

times
times

Dans un contexte de liste, cette fonction renvoie un tableau quatre lments donnant les temps utilisateur et systme, en secondes (probablement fractionnaires), pour ce processus et pour les fils de ce processus qui sont termins.
($utilisateur, $systeme, $cutilisateur, $csysteme) = times(); printf "Ce pid et ses fils ont consomm %.3f secondes\n", $utilisateur + $systeme + $cutilisateur + $csysteme;
22. Que lon appelle aussi epoch , origine ne pas confondre avec l pope , qui se rapporte la conception dUNIX. (Dautres systmes dexploitation ont une origine diffrente, pour ne pas parler de leur pope.)

customer_8566

Fonctions Perl par ordre alphabtique

773

Dans un contexte scalaire, elle ne renvoie que le temps utilisateur. Par exemple, pour mesurer la vitesse dexcution dune section de code Perl :
$debut = times(); ... $fin = times(); printf "Nous avons mis %.2f secondes CPU en temps utilisateur\n", $fin - $debut;

tr///
tr/// y///

Il sagit de loprateur de traduction (appel aussi translation), qui ressemble loprateur y/// du programme sed dUNIX, en mieux, selon lhumble opinion de tout le monde. Voir le chapitre 5.

truncate
truncate HANDLE_FICHIER, LONGUEUR truncate EXPR, LONGUEUR

!GUX

Cette fonction tronque le fichier ouvert sur HANDLE_FICHIER, ou nomm par EXPR, la longueur spcifie. La fonction lve une exception si truncate(2) ou un quivalent nest pas implment sur le systme. (Il est toujours possible de tronquer un fichier en nen recopiant que le dbut, si vous disposez de lespace disque ncessaire.) La fonction renvoie vrai en cas de succs, undef sinon.

uc
uc EXPR uc

_t

Cette fonction renvoie une version en majuscules de EXPR. Il sagit de la fonction interne implmentant lchappement \U dans les chanes entre guillemets. Perl essayera de faire de quil faut pour respecter les valeurs actuelles de votre locale, mais nous travaillons toujours sur les interactions avec Unicode. Voir la page de manuel perllocale pour les dernires avances. Dans tous les cas, lorsque Perl utilise les tables Unicode, uc convertit en majuscules plutt quen capitales de titres. Voir ucfirst pour les conversions en capitales de titres.

ucfirst
ucfirst EXPR ucfirst

_t

Cette fonction renvoie une version de EXPR avec la premire lettre en majuscule (titlecased, mise en capitale de titre dans le jargon Unicode). Il sagit de la fonction interne implmentant lchappement \u dans les chanes entre guillemets. Votre locale LC_CTYPE actuelle peut tre respecte si vous faites un use locale et si vos donnes ne ressemblent pas de lUnicode, mais nous ne garantissons rien pour le moment.

customer_8566

774

Chapitre 29 Fonctions

Pour forcer la premire lettre en capitale et tout le reste en minuscules, utilisez :


ucfirst lc $mot

ce qui est quivalent "\u\L$mot".

umask
umask EXPR umask

XU

Cette fonction fixe le umask (masque utilisateur) du processus et renvoie lancien en utilisant lappel systme umask(2). Votre umask indique au systme dexploitation quels bits de permissions dsactiver au moment de crer un nouveau fichier, y compris les fichiers qui sont des rpertoires. Si EXPR est omise, la fonction se contente de renvoyer le umask courant. Par exemple, pour sassurer que les bits utilisateur sont activs et que les bits autres sont dsactivs, essayez quelque chose comme :
umask((umask() & 077) | 7); # ne change pas les bits "groupe"

Rappelez-vous quun umask est un nombre, habituellement donn en octal ; ce nest pas une chane de chiffres octaux. Voir aussi oct, si tout ce que vous avez est une chane. Rappelez-vous galement que les bits dumask sont le complment des permissions ordinaires. Les permissions Unix rwxr-x--- sont reprsentes comme trois ensembles de trois bits, ou trois chiffres octaux : 0750 (le 0 du dbut indique un octal et ne compte pas comme un des chiffres). Puisque les bits dumask sont complmentaires, ils reprsentent des bits de permissions dsactives. Les valeurs de permission (ou mode ) que vous fournissez mkdir ou sysopen sont modifis par votre umask, ainsi mme si vous dites sysopen de crer un fichier avec les permissions 0777, si votre umask vaut 0022, le fichier est cr avec les permissions 0755. Si votre umask valait 0027 (le groupe ne peux pas crire, les autres ne peuvent ni lire, ni crire, ni excuter), alors passer sysopen un MASQUE de 0666 crerait un fichier avec un mode de 0640 (puisque 0666 & ~0027 vaut 0640). Voici quelques conseils : donnez un mode de cration valant 0666 pour les fichiers normaux (pour sysopen) et un de 0777 la fois pour les rpertoires (pour mkdir) et pour les fichiers excutables. Cela donne aux utilisateurs la libert de choisir : sils veulent des fichiers protgs, ils choisiront des umasks de processus de 022, 027 ou mme le masque particulirement antisocial de 077. Les programmes ne doivent que rarement, si ce nest jamais, prendre des dcisions stratgiques quil vaut mieux laisser lutilisateur. Les exceptions cette rgle sont les programmes qui crivent des fichiers qui doivent rester privs : fichiers mails, cookies de navigateurs web, fichiers .rhosts, et ainsi de suite. Si umask(2) nest pas implment sur votre systme et que vous essayez de restreindre votre propre accs (cest--dire, si (EXPR & 0700) > 0), vous dclencherez une exception lexcution. Si umask(2) nest pas implment sur votre systme et que vous nessayez pas de restreindre votre propre accs, la fonction renverra simplement undef.

undef
undef EXPR undef

customer_8566

Fonctions Perl par ordre alphabtique

775

undef est le nom sous lequel nous nous rfrons labstraction connue sous le nom de la valeur indfinie. Il se trouve aussi quil sagit dune fonction bien nomme qui renvoie toujours la valeur indfinie. Nous mlangeons les deux avec joie. Par concidence, la fonction undef rend explicitement indfinie une entit si vous passer son nom comme argument. Largument EXPR, sil est spcifi, soit tre une lvalue. partir de l, vous ne pouvez utilisez quune valeur scalaire, un tableau complet, un hachage complet, un nom de sous-programme (en utilisant le prfixe &) ou un typeglob. Toute la mmoire associe lobjet sera rcupre (mais pas renvoye au systme, pour la plupart des systme dexploitation). La fonction undef ne fera probablement pas ce que vous attendez delle sur la plupart des variables spciales. Lutiliser sur des variables en lecture seule, comme $1, lve une exception. La fonction undef est un oprateur unaire, non un oprateur de liste, vous ne pouvez donc rendre indfini quune seule chose la fois. Voici quelques exemples dutilisation dundef en tant quoprateur unaire :
undef undef undef undef undef undef $bidule; $machin{truc}; @tableau %hachage; &monsp; *xyz # Diffrent de delete $machin{truc};

# Dtruit $xyz, @xyz, %xyz, &xyz, etc.

Sans son argument, undef nest utilis que pour sa valeur :


select(undef, undef, undef, $sieste); return (wantarray ? () : undef) if $dans_les_choux; return if $dans_les_choux; # mme chose

Vous pouvez utiliser undef comme un emplacement dans la partie gauche dune affectation de liste, auquel cas la valeur correspondante de la partie droite est simplement rejete. part cela, vous ne pouvez pas utiliser undef en tant que lvalue.
($a, $b, undef, $c) = &truc; # Ignore la troisime valeur renvoye

De plus, nessayez pas de comparer quoique ce soit avec undef a ne fait pas ce que vous pensez. Tout ce que a fait, cest comparer avec 0 ou la chane vide. Utilisez la fonction defined pour dterminer si une valeur est dfinie.

unlink
unlink LISTE unlink

_!X

Cette fonction supprime une liste de fichiers.23 La fonction renvoie le nombre de fichiers effectivement supprims. Quelques exemples simples :

23. En fait, sous un systme de fichier POSIX, elle supprime les entres de rpertoire (fichiers) qui se rfrent aux vritables fichiers. Comme un fichier peut tre rfrenc (li) depuis plus dun rpertoire, le fichier lui-mme nest pas dtruit avant que la dernire rfrence pointant sur lui ne soit efface.

customer_8566

776
$cpt = unlink a, b, c; unlink @partants; unlink glob("*.orig");

Chapitre 29 Fonctions

La fonction unlink ne supprime pas les rpertoires moins dtre super-utilisateur et que loption de la ligne de commande -U soit donne Perl. Mme dans ces conditions, vous tes prvenus que leffacement dun rpertoire est susceptible dinf liger des dommages svres dans votre systme de fichiers. Employez plutt rmdir. Voici une commande rm trs simple avec une vrification derreurs qui ne lest pas moins :
#!/usr/bin/perl @impossible = grep {not unlink}, @ARGV; die "$0: unlink de @impossible impossible\n" if @impossible;

unpack
unpack CANEVAS, EXPR

Cette fonction fait linverse de pack : elle dveloppe une chane (EXPR) reprsentant une structure de donnes et lclate selon le CANEVAS en une liste de valeurs quelle renvoie. Dans un contexte scalaire, elle peut tre employe pour dpaqueter une seule valeur. Le CANEVAS est ici peu prs du mme format que pour la fonction pack - il spcifie lordre et le type des valeurs dpaqueter. Voir pack pour une description plus dtaille de CANEVAS. Un lment invalide dans le CANEVAS ou une tentative dplacement lextrieur de la chane avec les formats x, X ou @, lve une exception. La chane est dcoupe en morceaux dcrits dans le CANEVAS. Chaque morceau est converti sparment en une valeur. Gnralement, les octets de la chane sont le rsultat dun pack ou ils reprsentent une structure C dun certain type. Si le compteur de rptitions dun champ est plus grand que ce que le reste dans la chane en entre le permet, le compteur de rptitions est dcrment en douce. (Normalement, vous devriez de toute faon utiliser un compteur de rptitions valant ici *.) Si la chane en entre est plus grande que ce que dcrit le CANEVAS, le reste de la chane est ignor. La fonction unpack est galement trs utile pour les donnes de texte brut, pas seulement pour les donnes binaires. Supposez que vous ayez un fichier de donnes qui contiendrait des enregistrements ressemblant ceci :
2000 1999 1998 1997 1996 1995 1994 1993 1992 Ingrid Caven Premire ligne Confidence pour confidence La bataille Le chasseur Zro Le testament franais Un aller simple Le rocher de Tanios Texaco Jean-Jacques Schuhl Jean-Marie Laclavetine Paule Constant Patrick Rambaud Roze Pascale Andr Makine Didier Van Cauwelaert Amin Maalouf Patrick Chamoiseau

vous ne pouvez pas utiliser split pour dcomposer les champs car ils nont pas de sparateur distinct. la place, les champs sont dtermins par leur dcalage doctets dans

customer_8566

Fonctions Perl par ordre alphabtique

777

lenregistrement. Ainsi mme sil sagit dun enregistrement de texte ordinaire, puisquil est compos dans un format fixe, vous pouvez utiliser unpack pour le dcomposer :
while (<>) { ($annee, $titre, $auteur) = unpack("A4 x A26 A*", $_); print "$auteur a gagn le prix Goncourt $annee pour $titre\n"; }

Voici un programme uudecode complet :


#!/usr/bin/perl $_ = <> until ($mode,$fichier) = /^begin\s*(\d*)\s*(\S*)/; open(SORTIE,"> $fichier") if $fichier ne ""; while (<>) { last if /^end/; next if /[a-z]/; next unless int((((ord() - 32) & 077) + 2) / 3) == int(length() / 4); print SORTIE unpack "u", $_; } chmod oct $mode, $fichier;

En plus des champs autoriss dans pack, vous pouvez prfixer un champ par %nombre pour produire une somme de contrle des entits sur nombre bits au lieu des entits ellesmmes. La valeur par dfaut est une somme de contrle de 16 bits. La somme de contrle est calcule en additionnant les valeurs numriques des valeurs dveloppes (pour les champs de chanes, on additionne ord($car) et pour les champs de bits, on additionne les zros et les uns). Par exemple, ce qui suit calcule le mme nombre que le programme sum(1) de System V :
undef $/; $somme_controle = unpack ("%32C*", <>) % 65536;

Lexemple suivant compte de faon efficace le nombre de bits positionns dans un vecteur de bits :
$bits_a_1 = unpack "%32b*", $masque_de_select;

Voici un dcodeur simple MIME (BASE 64) :


while (<>) { tr#A-Za-z0-9+/##cd; tr#A-Za-z0-9+/# -_#; $lng = pack("c", 32 + 0.75*length); print unpack("u", $len . $_); } # # # # enlever les caractres non-base 64 convertir au format uuencod calculer loctet de longueur uudcoder et afficher

unshift
unshift TABLEAU, LISTE

Cette fonction fait linverse de shift. (Ou linverse de push, selon le point de vue.) Elle ajoute une LISTE au dbut du tableau et renvoie le nombre actualis dlments dans le tableau :
unshift @ARGV, -e, $cmd unless $ARGV[0] =~ /^-/;

customer_8566

778

Chapitre 29 Fonctions

Remarquez que la LISTE est ajoute en entier au dbut, et non un lment la fois, les lments ajouts au dbut restent donc dans le mme ordre. Utilisez reverse pour les inverser.

untie
untie VARIABLE

Brise le lien existant entre une variable ou un typeglob contenu dans VARIABLE et le paquetage auquel elle tait lie. Voir tie et lintgralit du chapitre 14, mais tout particulirement la section Un pige subtil du dliement.

use
use use use use use use use MODULE VERSION LISTE MODULE VERSION () MODULE VERSION MODULE LISTE MODULE () MODULE VERSION

!@

La dclaration use charge un module, sil na pas dj t charg auparavant, et importe depuis ce module des sous-programmes et des variables dans le paquetage courant. (En langage technique, elle importe depuis le module donn des smantiques dans votre paquetage.) La plupart des dclarations use ressemblent :
use MODULE LISTE ;

Ce qui est exactement quivalent :


BEGIN { require MODULE ; import MODULE LISTE ; }

Le BEGIN force le require et le import se produire au moment de la compilation. Le require sassure que le module est charg en mmoire sil ne lest pas dj. Limport nest pas une fonction interne cest simplement un appel ordinaire de mthode dans le package nomm par MODULE pour demander ce module de mettre la liste des fonctionnalits dans le package courant. Le module peut implmenter sa mthode dimportation de la manire qui lui plat, bien que la plupart choisissent simplement de driver leur mthode dimportation par hritage de la classe Exporter qui est dfinie dans le module Exporter. Voir le chapitre 11, Modules et le module Exporter pour plus dinformations. Si aucune mthode import ne peut tre trouve, lappel est abandonn sans un mot. Si vous ne voulez pas altrer votre espace de nom, fournissez explicitement une liste vide :
use MODULE ();

Ce qui est exactement quivalent :


BEGIN { require MODULE ; }

Si le premier argument de use est un numro de version comme 5.6.2, la version courante de Perl en train de sexcuter doit tre au moins aussi rcente que la version sp-

customer_8566

Fonctions Perl par ordre alphabtique

779

cifie. Si la version actuelle de Perl est infrieur VERSION, un message derreur est affich et linterprteur Perl se termine immdiatement. Ceci est trs utile pour vrifier la version courante de Perl avant de charger des modules de bibliothque qui dpendent des nouvelles versions, puisque de temps en temps, nous avons besoin de casser les mauvaises fonctionnalits des anciennes versions de Perl. (Nous nessayons pas de casser plus de choses que ncessaire. En fait nous essayons souvent de casser moins de choses que ncessaire.) Et puisque nous parlons de ne pas casser certaines choses, Perl accepte encore les anciens numros de versions de la forme :
use 5.005_03;

Toutefois, pour mieux saligner avec les standards de lindustrie, Perl 5.6 accepte dsormais (et nous prfrons voir) la syntaxe sous forme dun triplet :
use 5.6.0; # Soit, version 5, sous-version 6, correctif 0.

Si largument VERSION est prsent aprs MODULE, alors le use appellera la mthode VERSION de la classe MODULE avec la VERSION donne comme argument. Remarquez quil ny pas de virgule aprs VERSION ! La mthode VERSION par dfaut, qui est hrite de la classe UNIVERSAL, meurt en gmissant si la version donne est plus leve que la valeur de la variable $Module::VERSION. Voir le chapitre 32 pour une liste des modules standards. Comme use fournit une interface largement ouverte, les pragmas (directives de compilation) sont galement implments via des modules. Les pragmas actuellement implmentes comprennent :
use use use use use use use use use use autouse Carp => qw(carp croak); bytes; constant PI => 4 * atan2(1,1); diagnostics; integer; lib /opt/projets/spectre/lib; locale; sigtrap qw (die INT QUIT); strict qw(subs vars refs); warnings "deprecated";

La plupart des ces modules pragmatiques importent des dfinitions dans la porte lexicale courante. (Au contraire des modules ordinaires, qui nimportent des symboles que dans le paquetage courant, qui a une rapport minime avec la porte lexicale courante autre que le fait que la porte lexicale est compile avec ce paquetage lesprit. Ceci pour dire que. . . oh et puis zut, voyez le chapitre 11.) Il existe une dclaration correspondante, no, qui dsimporte toutes les significations importes lorigine avec use qui sont devenues depuis, heu, sans importance :
no no no no integer; strict refs; utf8; warnings "unsafe";

Voir le chapitre 31 pour une liste des pragmas standards.

customer_8566

780

Chapitre 29 Fonctions

utime
utime LISTE

!XU

Cette fonction change les dates daccs et de modification sur chacun des fichiers de la liste. Les deux premiers lments de la liste doivent tre les dates daccs et de modification en numrique, dans cet ordre. La fonction renvoie le nombre de fichiers changs avec succs. La date de modification dinode de chaque fichier est fixe la date courante. Voici un exemple dune commande touch qui met la date de modification du fichier (en supposant que vous en tes le propritaire) environ un mois dans le futur :
#!/usr/bin/perl # touch_mois - antidate les fichiers maintenant + 1 mois $jour = 24 * 60 * 60; # 24 heures en secondes $plus_tard = time() + 30 * $jour; # 30 jours, cest environ un mois utime $plus_tard, $plus_tard, @ARGV;

et voici un exemple un peu plus sophistiqu dune commande qui fait un touch avec quelques notions de contrle derreurs :
#!/usr/bin/perl # touch_mois - antidate les fichiers maintenant + 1 mois $plus_tard = time() + 30 * 24 * 60 * 60; @impossibles = grep {not utime $plus_tard, $plus_tard, $_} @ARGV; die "touch impossible de @impossibles.\n" if @impossibles;

Pour lire les dates de fichiers existants, utilisez stat et passez les champs appropris localtime ou gmtime pour laffichage.

values
values HACHAGE

Cette fonction renvoie une liste constitue de toutes les valeurs du HACHAGE indiqu. Les valeurs sont renvoyes dans un ordre apparemment alatoire, mais cest le mme que celui produit par les fonctions keys ou each pour le mme hachage. Curieusement, pour trier un hachage par ses valeurs, vous aurez besoin habituellement de la fonction keys, regardez donc lexemple dans la description de keys. Vous pouvez modifier les valeurs dun hachage en utilisant cette fonction car la liste renvoye contient des alias des valeurs et pas simplement des copies. (Dans les versions prcdentes, vous aviez besoin dutiliser pour ce faire une portion de hachage.)
for (@hachage{keys %hachage}) { s/machin/truc/g } # ancienne manire for (values %hachage) { s/machin/truc/g } # modifie maintenant # les valeurs

Lemploi de values sur un hachage li un fichier DBM important est vou produire une liste toute aussi volumineuse, ce qui vous donnera un processus important. Il peut tre prfrable pour vous dutiliser dans ce cas la fonction each, qui parcourra les entres de hachage une une, sans les absorber en une liste gargantuesque.

customer_8566

Fonctions Perl par ordre alphabtique

781

vec
vec EXPR, DECALAGE, BITS

La fonction vec fournit un stockage compact de listes dentiers non-signs. Ces entiers sont empaquets et compresss autant que possible dans une chane Perl ordinaire. La chane dans EXPR est traite comme une chane de bits construite partir dun nombre arbitraire dlments selon la longueur de la chane. DECALAGE spcifie lindice de llment particulier qui vous intresse. Les syntaxes pour lire et crire llment sont les mmes, puisque vec stocke la valeur de llment selon que vous utilisiez un contexte lvalue ou rvalue. BITS spcifie ltendue dun lment en bits, ce qui doit tre exprim en puissance de 2 : 1, 2, 4, 8, 16 ou 32 (et galement 64 sur certaines plates-formes). (Une exception est leve si une quelconque autre valeur est utilise.) Chaque lment peut ainsi contenir un entier compris dans lintervalle 0..(2**BITS)-1. Pour les plus petites tailles, on empaqute dans chaque octet autant dlments que possible. Lorsque BITS vaut 1, il y a huit lments par octets. Lorsque BITS vaut 2, il y a quatre lments par octets. Lorsque BITS vaut 4, il y a deux lments (habituellement appels des quartets) par octets. Et ainsi de suite. Les entiers plus grands quun octet sont stocks dans lordre gros-boutise (N.d.T. : big-endian). Une liste dentiers non-signs peut tre stocke dans une simple variable scalaire en les assignant individuellement la fonction vec. (Si EXPR nest pas une lvalue valide, une exception est leve.) Dans lexemple suivant les lments font tous 4 bits de large :
$chaine_bits = ""; $decalage = 0; foreach $nb (0, 5, 5, 6, 2, 7, 12, 6) { vec($chaine_bits, $decalage++, 4) = $num; }

Si un lment est crit aprs la fin de la chane, Perl tendra dabord la chane avec suffisamment doctets zro. Les vecteurs stocks dans la variable scalaire peuvent par la suite tre atteints en spcifiant le DECALAGE correct :
$nb_elements = length($chaine_bits)*2; # 2 lments par octet

foreach $decalage (0 .. nb_elements-1) { print vec($chaine_bits, $decalage, 4), "\n"; }

Si llment slectionn se situe aprs la fin de la chane, une valeur de 0 est renvoye. Les chanes cres avec vec peuvent galement tre manipules avec les oprateurs logiques |, &, ^ et ~. Ces oprateurs postulent quune opration de vecteurs de bits est dsire quand les deux oprandes sont des chanes.Voir des exemples de ceci au chapitre 3, Oprateurs unaires et binaires, dans la section Oprateurs sur les bits. Si BITS == 1, une chane de bits peut tre cre pour stocker une srie de bits dans un seul scalaire. Lordre est tel que lon garanti que vec($chaine_bits,0,1) part du bit le

customer_8566

782
plus faible du premier octet de la chane.
@bits = (0,0,1,0, 1,0,1,0, 1,1,0,0, 0,0,1,0); $chaine_bits = ""; $decalage = 0;

Chapitre 29 Fonctions

foreach $bit (@bits) { vec($chaine_bits, $decalage++, 1) = $bit; } print "$chaine_bit\n"; # "TC", i.e. 0x54, 0x43

Une chane de bits peut tre convertie vers ou depuis une chane de 1 et de 0 en donnant un canevas de b* pack ou unpack. Dans lautre sens, pack peut tre utilis avec un canevas de b* pour crer la chane de bits depuis une chane de 1 et de 0. Lordre est compatible avec celui que vec attend.
chaine_bits = pack "b*", join(", @bits); print "$chaine_bits\n"; # "TC" comme prcdemment

unpack peut tre utilis pour extraire la liste de 0 et de 1 de la chane de bits.


@bits = split (//, unpack("b*", $chaine_bits)); print "@bits\n"; # 0 0 1 0 1 0 1 0 1 1 0 0 0 0 1 0

Si vous connaissez la longueur exacte en bits, celle-ci peut tre utilise en lieu et place de * . Voir select pour des exemples supplmentaires dutilisation de bitmaps gnres avec vec. Voir pack et unpack pour des manipulations de donnes binaires un niveau suprieur.

wait
wait

!?U

Cette fonction attend quun processus fils se termine et renvoie le PID du processus dcd, ou -1 sil ny a pas de processus fils (ou sur certains systmes, si les processus fils sont automatiquement enterrs). Le statut est renvoy dans $? comme nous lavons dcrit pour la fonction system. Si vous obtenez des processus fils zombies, vous devrez appeler cette fonction, ou waitpid. Sil ny a pas de fils, contrairement votre attente, il sest probablement produit un appel system, une fermeture de pipe ou des apostrophes inverses entre le fork et le wait. Ces constructions provoquent galement une attente avec wait(2) et peuvent avoir rcolt votre processus fils. Utilisez waitpid pour viter ce problme.

waitpid
waitpid PID, FLAGS

!?U

Cette fonction attend quun certain processus fils se termine et renvoie le PID quand le processus est mort, -1 sil ny a pas de fils, ou 0 si les FLAGS spcifient un appel non-bloquant et que le processus nest pas encore mort. Le statut du processus mort est renvoy dans $? comme nous lavons dcrit pour la fonction system. Pour obtenir les valeurs va-

customer_8566

Fonctions Perl par ordre alphabtique

783

lides des f lags, vous devrez importer le tag de groupe dimportation ":sys_wait.h" depuis le module POSIX. Voici un exemple qui ralise une attente non-bloquante des processus zombies :
use POSIX ":queue"; do { $fils = waitpid(-1, &WNOHANG); } until $fils == -1;

Sur les systmes qui nimplmentent pas les appels systme waitpid(2) et wait4(2), les FLAGS ne peuvent tre spcifis qu 0. En dautres termes, vous pouvez attendre l un PID spcifique, mais vous ne pouvez le faire en mode non-bloquant. Sur certains systmes, une valeur de retour de -1 peut signifier que les processus fils sont automatiquement enterrs car vous avez fait $SIG{CHLD} = IGNORE.

wantarray
wantarray

Cette fonction renvoie vrai si le contexte du sous-programme actuellement en train de sexcuter demande une valeur tableau et faux sinon. La fonction renvoie une valeur dfinie fausse ("") si le contexte appelant demande un scalaire et la valeur indfinie fausse (undef) si le contexte appelant ne demande rien de particulier, cest--dire sil sagit dun contexte vide. Voici quelques exemples dusages typiques :
return unless defined wantarray; my @a = calcul_complique(); return wantarray ? @a : \@a; # ne se proccupe pas den faire plus

Voir galement caller. Cette fonction aurait vraiment d sappeler wantlist mais nous lavons baptise alors que les contextes de listes sappelaient encore contextes de tableaux.

warn
warn LISTE warn

Cette fonction produit un message derreur en affichant LISTE sur STDERR exactement comme die, mais sans essayer de sortir ou de lancer une exception. Par exemple :
warn "Dbogage actif" if $debug;

Si LISTE est vide et que $@ contient dj une valeur (gnralement issue dun eval prcdent), la chane "\t...caught" est ajoute la fin de $@ sur STDERR. (De manire similaire celle dont die propage les erreurs, except le fait que warn ne propage (lve nouveau) pas lexception.) Si la chane de message fournie est vide, le message Warning: Somethings wrong 24 est utilis.

24. N.d.T. : Littralement : Avertissement : Il y a quelque chose de mauvais .

customer_8566

784

Chapitre 29 Fonctions

Si la chane de message fournie ne se termine pas par un saut de ligne, les informations concernant le fichier et le numro de ligne sont automatiquement ajoutes la fin. La fonction warn na aucun rapport avec loption de la ligne de commande de Perl -w, mais elle peut tre utilise en conjonction avec cette dernire, comme lorsque vous voulez muler le comportement interne :
warn "Quelque chose de foncirement mauvais\n" if $^W;

Aucun message nest affich si un gestionnaire pour $SIG{__WARN__} est install. Il appartient au gestionnaire den dcider si le message lui semble appropri. Une chose que vous pourriez vouloir faire est de promouvoir un simple avertissement en exception :
local $SIG{__WARN__} = sub { my $msg = shift; die $msg if $msg =~ /nest pas numrique/; }

La plupart des gestionnaires doivent donc faire prendre leurs dispositions pour afficher les avertissements quils nont pas prvu de grer, en appelant nouveau warn dans le gestionnaire. Ceci est tout fait sr ; il ny aura pas de boucles sans fin car les routines __WARN__ ne sont pas appeles depuis des routines __WARN__. Ce comportement diffre un peu de celui des gestionnaires de $SIG{__DIE__} (qui ne suppriment pas le texte derreur mais qui peuvent la place appeler une nouvelle fois die pour le changer). Lemploi dun gestionnaire __WARN__ donne un moyen particulirement puissant de taire tous les avertissements, mme ceux qui sont pourtant qualifis dobligatoires. Parfois, vos aurez besoin dencapsuler cela dans un bloc BEGIN{} pour que ce soit pris en compte ds la compilation :
# nettoie *tous* les avertissements la compilation BEGIN { $SIG{__WARN__} = sub { warn $_[0] if $AVERTISSEMENTS_ACTIFS } } my $truc = 10; my $truc = 20; # pas davertissement propos des my $truc # dupliqus mais, bon, vous lavez voulu ! # pas davertissements la compilation ou lexcution jusquici; $AVERTISSEMENTS_ACTIFS = 1; # avertissements lexcution activs # partir dici warn "\$truc est vivant et vaut $truc !"; # dnonce tout

Voir le pragma use warnings pour le contrle de la porte lexicale des avertissements. Voir les fonctions carp et cluck du module Carp pour dautres moyens de produire des messages davertissement.

write
write HANDLE_FICHIER write

!@G

Cette fonction crit un enregistrement format (qui peut tre multilignes) vers le handle de fichier spcifi, en utilisant le format associ ce handle de fichier voir la section Variables de format au chapitre 7. Par dfaut, le format dun fichier est celui qui a le mme nom que le handle de fichier. Toutefois, le format dun handle de fichier peut tre modifi en changeant la variable $~ aprs avoir fait un select sur ce handle :

customer_8566

Fonctions Perl par ordre alphabtique


$ancien_hf = select(HANDLE); $~ = "NOUVEAU_NOM"; select($ancien_hf);

785

ou en crivant :
use IO::Handle; HANDLE->format_name("NOUVEAU_NOM");

Puisque les formats sont mis dans lespace de nom dun paquetage, il se peut que vous deviez qualifier le nom du format si le format a t dclar dans un paquetage diffrent :
$~ = "Autre_Paquetage::NOUVEAU_NOM";

Le traitement de len-tte de formulaire est automatiquement gr : sil ny a plus assez de place sur la page courante pour lenregistrement format, la page est avance en crivant un saut de page, un format de haut de page spcial est utilis pour formater le nouvel en-tte de page, et lenregistrement est enfin crit. Le nombre de lignes restant sur la page courante se trouve dans la variable $-, qui peut tre mise 0 pour forcer quune nouvelle page soit prise au prochain write. (Vous devrez peut tre selectionner dabord le handle de fichier.) Par dfaut, le nom du format de haut de page est celui du handle de fichier auquel est ajout _TOP , mais il peut tre modifi en changeant la variable $^ aprs avoir fait un select sur ce handle ou en crivant :
use IO::Handle; HANDLE->format_top_name("NOUVEAU_NOM_TOP");

Si HANDLE_FICHIER nest pas spcifi, ce qui est crit sort sur le handle de fichier de sortie par dfaut, qui est STDOUT au dpart mais peut tre chang par la forme un seul argument de loprateur select. Si HANDLE_FICHIER est une expression, celle-ci est value pour dterminer le vritable HANDLE_FICHIER lexcution. Si un format spcifi ou le format de len-tte de page courant nexiste pas, une exception est leve. La fonction write nest pas linverse de read. Utilisez print pour une simple criture de chane. Si vous avez consult cette entre parce que vous voulez court-circuiter les entres/sorties standard, regardez syswrite.

y///
y///

Il sagit de loprateur de traduction (appel aussi translation), galement connu sous le nom de tr///. Voir le chapitre 5.

customer_8566

customer_8566

La bibliothque standard Perl


La distribution standard de Perl contient bien plus que lexcutable perl qui excute vos scripts. Elle inclue galement des centaines de modules remplis de code rutilisable. Comme les modules standards sont disponibles partout, si vous utilisez lun dentre eux dans votre programme, vous pouvez faire tourner votre programme partout o Perl est install, sans tapes dinstallation supplmentaires.

30

Bibliothquologie
Avant dnumrer ces modules dans les prochains chapitres, passons quelque peu en revue la terminologie dans laquelle nous nageons jusquau cou. espace de noms Les noms sont conservs dans un espace de noms afin de ne pas les confondre avec des noms identiques dans des espaces diffrents. Ainsi reste ne pas confondre les espaces de noms entre eux. Il existe deux manires dviter cela : leur donner des noms uniques ou leur attribuer des emplacements uniques. Perl vous laisse faire les deux : les espaces de noms nomms sappellent des paquetages et les espaces de noms anonymes sont appels portes lexicales. Puisque les portes lexicales ne peuvent pas stendre au-del dun fichier et puisque les modules standards sont (au minimum) de la taille dun fichier, il sensuit que toutes les interfaces de modules doivent employer des espaces de noms nomms (des paquetages) si quelquun doit les utiliser depuis lextrieur du fichier. paquetage Un paquetage est un mcanisme standard de Perl pour dclarer un espace de noms nomm. Il sagit dun mcanisme trs simple pour rassembler des fonctions et des variables qui ont des points communs. Tout comme deux rpertoires peuvent contenir tous deux un fichier (diffrent) sappelant fred, deux parties dun programme Perl peuvent, chacune de leur ct, avoir leur propre variable $fred ou leur propre fonction &fred. Mme si ces variables ou ces fonctions semblent avoir le mme nom, ces noms rsident dans des espaces de noms distincts grs par la dclaration

customer_8566

788

Chapitre 30 La bibliothque standard Perl

package. Les noms de paquetages sont utiliss pour identifier la fois des modules et des classes, comme nous lavons dcrit au chapitre 11, Modules et au chapitre 12, Objets. bibliothque Le terme bibliothque (library) est malheureusement suremploy dans la culture Perl. De nos jours, nous utilisons normalement le terme pour dsigner lensemble des modules Perl installs sur votre systme. Historiquement, une bibliothque Perl tait galement un simple fichier contenant une collection de sous-programmes partageant un objectif commun. Un tel fichier est souvent suffix par .pl, pour perl library . Nous employons toujours cette extension pour des morceaux varis de code Perl que vous incorporez avec do FICHIER ou require. Bien quil ne sagisse pas dun module part entire, un fichier de bibliothque se dclare gnralement lui-mme comme tant dans un paquetage distinct, ainsi les variables et les sous-programmes quil contient peuvent tre rassembles et ninterfrent pas accidentellement avec dautres variables dans votre programme. Il ny a pas dextension de fichier obligatoire ; en outre, on rencontre souvent dautres .pl comme nous le verrons plus loin dans ce chapitre. Ces fichiers de bibliothques simples et sans structure ont t largement supplants par les modules. module Un module Perl est un fichier de bibliothque conforme certaines conventions spcifiques qui autorisent un ou plusieurs fichiers implmentant ce module tre rentrs avec une seule dclaration use la compilation. Les noms de fichier des modules doivent toujours se terminer par .pm, car la dclaration use le prsuppose. La dclaration use convertira galement le sparateur de paquetage :: vers votre sparateur de rpertoire quel quil soit afin que la structure des rpertoires dans votre bibliothque Perl puisse ref lter la structure de votre paquetage. Le chapitre 11 dcrit comment crer vos propres modules Perl. classe Une classe est juste un module qui implmente des mthodes pour les objets associs au nom du paquetage du module. Si les modules orients objet vous intressent, voyez le chapitre 12. pragma Un pragma est juste un module spcial qui fait joujou avec les boutons internes de Perl. Voir le chapitre 31, Modules de pragmas. extension Une extension est un module Perl qui, en plus de charger un fichier .pm, charge galement un bibliothque partage implmentant en C ou en C++ la smantique du module. programme Un programme Perl est un code conu pour tourner en tant quentit indpendante ; il est galement connu sous le nom de script lorsque vous ne voulez pas que quiconque en attende un peu trop, sous le nom dapplication lorsquil est

customer_8566

Visite guide de la bibliothque Perl

789

volumineux et compliqu, sous le nom dexcutable lorsque celui qui lappelle ne se soucie pas du langage dans lequel il a t crit, ou encore sous le nom de solution industrielle lorsquil cote une fortune. Les programmes Perl existent en tant que code source, bytecode ou code machine natif. Sil sagit de quelque chose que vous pouvez lancer depuis la ligne de commande, nous lappellerons un programme.

Visite guide de la bibliothque Perl


Vous gagnerez normment de temps si vous faites leffort de vous familiariser avec la bibliothque Perl standard, car il ny a aucune raison de rinventer la roue. Nous devons toutefois vous avertir que cette collection contient un vaste champ de matires premires. Bien que certaines bibliothques soit extrmement utiles, dautres peuvent tre sans aucun rapport avec vos besoins. Par exemple, si vous ncrivez que du code Perl pur 100 %, les modules qui supportent le chargement dynamique dextensions C et C++ ne vont pas beaucoup vous aider. Perl sattend trouver les modules de bibliothque quelque part dans son chemin dinclusion (N.d.T. : include ) de bibliothque, @INC. Ce tableau spcifie la liste ordonne des rpertoires o Perl cherche lorsque vous chargez du code de bibliothque en utilisant les mots clefs do, require ou use. Vous pouvez facilement afficher la liste de ces rpertoires en appelant Perl avec loption -V pour Version Vraiment Verbeuse, ou avec ce , simple code :
% perl -le "print foreach @INC" /usr/libdata/perl5/sparc-openbsd/5.00503 /usr/local/libdata/perl5/sparc-openbsd/5.00503 /usr/libdata/perl5 /usr/local/libdata/perl5 /usr/local/libdata/perl5/site_perl/sparc-openbsd /usr/libdata/perl5/site_perl/sparc-openbsd /usr/local/libdata/perl5/site_perl /usr/libdata/perl5/site_perl .

Il ne sagit que dun exemple daffichage possible. Chaque installation de Perl utilise ses propres chemins. Le point important est que, malgr la variation des contenus selon la politique de votre constructeur et de celle de linstallation sur votre site, vous pouvez compter sur toutes les bibliothques standards qui sont installes avec Perl. Si vous voulez retrouver lendroit depuis lequel un fichier a t rellement charg, consultez la variable %INC. Pour un fichier de module, vous pouvez trouver exactement o Perl la trouv avec cette commande :
% perldoc -l MODULE

Si vous regardez les rpertoires de @INC et leurs sous-rpertoires, vous trouverez diffrentes sortes de fichiers installs. La plupart ont des noms se terminant par .pm, mais certains se finissent par .pl, .ph, .al ou .so. Ceux qui vous intressent le plus sont dans la premire catgorie car un suffixe .pm indique que le fichier est un module Perl authentique. Nous en dirons plus sur ceux-l dans un instant. Le peu de fichiers que vous verrez l finissant par .pl sont ces vieilles bibliothques Perl que nous avons mentionnes plus haut. Ils sont inclus pour garder une compatibilit

customer_8566

790

Chapitre 30 La bibliothque standard Perl

avec danciennes versions de Perl datant des annes 80 et du dbut des annes 90. Ainsi, le code Perl qui marchait, disons en 1990, doit continuer bien se comporter sans histoires mme si vous avez install une version moderne de Perl. Lorsque vous tes en train dcrire du code nouveau, vous devez toujours prfrer, lorsque cest possible, utiliser la version avec .pm plutt que celle avec .pl. Ainsi, les modules ne pollueront pas votre espace de noms comme beaucoup des vieux fichiers .pl le font. Une remarque propos de lemploi de lextension .pl : elle signifie Perl library (bibliothque Perl), et non pas programme Perl. Bien que lextension .pl soit utilise pour identifier les programmes Perl sur les serveurs web qui ont besoin de distinguer, dans le mme rpertoire, les programmes excutables des contenus statiques, nous vous suggrons demployer un suffixe de .plx la place pour indiquer un programme Perl excutable. (Le mme conseil vaut pour les systmes dexploitation qui choisissent les interprteurs en se basant sur les extensions des noms de fichiers.) Les fichiers avec des extensions .al sont de petits morceaux de modules plus grands qui sont automatiquement chargs lorsque vous utiliser leur fichier parent .pm. Si vous construisez le plan de votre module en utilisant loutil standard h2xs qui est fourni avec Perl (et si vous navez pas employer le f lag Perl -A), la procdure make install utilisera le module Autoloader pour crer pour vous ces petits fichiers .al. Les fichiers .ph sont construits par le programme h2ph, un outil quelque peu vieillissant mais parfois toujours utile pour convertir des directives de prprocesseur C vers du Perl. Les fichiers .ph rsultants contiennent des constantes parfois ncessaires aux fonctions de bas niveau comme ioctl, fnctl ou syscall. (De nos jours la plupart de ces valeurs sont disponibles, plus facilement et de manire plus portable, dans des modules standards comme POSIX, Errno, Fcntl ou Sockets.) Voir perlinstall pour savoir comment installer ces composants optionnels mais parfois importants. La dernire extension que vous pourriez rencontrer en errant ici et l est .so (ou ce que votre systme emploie pour les bibliothques partages). Ces fichiers .so sont des portions de modules dextension qui sont dpendantes de la plate-forme. Elles sont crites en C ou en C++ et il faut les compiler pour obtenir le code objet relogeable dynamiquement. Lutilisateur final na de toute faon pas besoin dtre au courant de leur existence car elles sont masques par linterface du module. Lorsque le code de lutilisateur dit require Module ou use Module, Perl charge Module.pm et lexcute, ce qui laisse le module attirer lui toute autre partie ncessaire, comme Module.so ou tous les composant .al autochargs. En fait, le module peut charger tout ce qui lui plat, y compris 582 autres modules. Il peut tlcharger lintgralit de CPAN sil le veut et pourquoi pas les archives des deux dernires annes de freshmeat.net. Un module nest pas simplement un morceau de code statique en Perl. Cest un agent actif qui arrive comprendre comment implmenter pour vous une interface. Il peut suivre toutes les conventions standards, ou pas. Il lui est permis de tout faire pour pervertir la signification du reste de votre programme, y compris jusqu convertir le reste de votre programme en SPITBOL. Ce genre de canular est considr comme tant parfaitement loyal pour autant quil soit bien document. Lorsque vous utilisez un tel module Perl, vous acceptez son contrat, non un contrat standard crit par Perl. Vous feriez donc mieux de lire les petits caractres de la notice.

customer_8566

Modules de pragmas

31

Un pragma est un type particulier de module qui affecte la phase de compilation de votre programme. Certains modules de pragmas (ou pragmata, pour faire court, ou pragmas, pour faire encore plus court) peuvent galement affecter la phase dexcution de votre programme. Voyez-les comme des indications donnes au compilateur. Comme ils ont besoin dtre visibles la compilation, ils ne fonctionnent que lorsquils sont invoqus par un use ou un no, car lorsquun require ou un do sexcute, la compilation est finie depuis longtemps. Par convention, les noms de pragmas sont crit en minuscules car les noms de modules en minuscules sont rservs pour la distribution Perl elle-mme. Lorsque vous crivez vos propres modules, utilisez au moins une lettre majuscule pour viter dentrer en conf lit avec les noms de pragmas. Au contraire des modules ordinaires, la plupart des pragmas limitent leurs effets au reste du bloc le plus interne encadrant lendroit do ils ont t appels. En dautres termes, ils sont limits une porte lexicale, exactement comme les variables my. Habituellement, la porte lexicale dun bloc extrieur couvre tout bloc intrieur inclus dans le premier, mais un bloc intrieur peut contredire un pragma de porte lexicale provenant dun bloc extrieur avec linstruction no :
use strict; use integer; { no strict refs; no integer; # ... }

# permet les rfrences symboliques # reprend larithmtique en virgule flottante

Plus encore que les autres modules inclus dans la distribution Perl, les pragmas forment une partie intgrale et essentielle de lenvironnement de compilation en Perl. Il est difficile de bien utiliser le compilateur si vous ne savez pas comment lui passer des indications, nous produirons donc un effort supplmentaire dcrire les pragmas.

customer_8566

792

Chapitre 31 Modules de pragmas

Un autre point auquel il faut prter attention est le fait que nous utilisons souvent les pragmas pour prototyper des fonctionnalits qui seront plus tard encodes dans une syntaxe relle . Ainsi vous verrez dans quelques programmes des pragmas dprcis comme use attrs dont la fonctionnalit est maintenant directement supporte par la syntaxe de dclaration des sous-programmes. De mme, use vars est en cours de remplacement par les dclarations our. Et use subs peut un jour tre remplac par un attribut override dans les dclarations de sous-programmes ordinaires. Nous ne sommes pas extrmement presss de casser les anciennes pratiques mais nous pensons assurment que les nouvelles pratiques sont plus jolies.

use attributes
sub une_fonct : method; my $fermeture = sub : method { }; use attributes; @liste_attrs = attributes::get(\&une_fonct);

Le pragma attributes a deux objectifs. Le premier est de fournir un mcanisme interne pour dclarer des listes dattributs, qui sont des proprits optionnelles associes aux dclarations de sous-programmes et (dans un futur proche) aux dclarations de variables. (Puisquil sagit dun mcanisme interne, vous ne devriez pas en gnral utiliser ce pragma directement.) Le second objectif est de fournir un moyen de rcuprer ces listes dattributs lexcution en appelant la fonction attribute::get. Dans cette fonctionnalit, attributes est juste un module standard et non un pragma. Perl ne gre actuellement quun petit nombre dattributs en interne. Les attributs spcifiques un paquetage sont autoriss par le biais dun mcanisme dextension exprimental dcrit dans la section Package-specific Attribute Handling (N.d.T. : gestion dattributs spcifiques un paquetage) de la page de man attributes(3). Le positionnement des attributs intervient la compilation ; la tentative de positionner un attribut inconnu provoque une erreur de compilation. (Lerreur peut tre intercepe avec eval, mais elle continuera darrter la compilation lintrieur du bloc eval.) Il nexiste actuellement que trois attributs internes implments pour les sous-programmes : locked, method et lvalue. Voir le chapitre 6, Sous-programmes et le chapitre 7, Threads, pour une discussion approfondie sur ces attributs. Il nexiste pas actuellement dattributs internes pour les variables comme il y en a pour les sous-programmes mais nous en avons plusieurs en tte que nous aimons bien, comme constant. Le pragma attributes fournit deux sous-programmes pour un usage gnrique. Ils peuvent tre imports si vous les demandez : get Cette fonction renvoie une liste (qui peut tre vide) des attributs lorsquon lui donne un seul paramtre en entre, lequel est une rfrence un sous-programme ou une variable. La fonction lve une exception en invoquant Carp::croak si on lui passe des arguments invalides.

customer_8566

use autouse
reftype

793

Cette fonction se comporte plus ou moins comme la fonction interne ref mais elle renvoie toujours le type de donne sous-jacent intrinsque Perl ou la valeur rfrence, en ignorant tout paquetage dans lequel elle pourrait avoir t consacre. Des dtails plus prcis sur la gestion des attributs sont toujours en cours de discussion, vous feriez donc mieux de consulter la documentation en ligne de votre distribution de Perl pour savoir quel est ltat en cours.

use autouse
use autouse Carp => qw(carp croak); carp "Cet appel carp a t prdclar avec autouse\n";

Ce pragma fournit un mcanisme pour une demande de chargement lexcution dun module particulier si et seulement si une fonction de ce module est rellement appele. Il accomplit ceci en donnant une souche (stub) de fonction qui est remplace par lappel rel lorsquon la dclenche. Dans lesprit, ce mcanisme est similaire au comportement des modules standards AutoLoader et SelfLoader. Pour faire court, cest une astuce de performance qui facilite le dmarrage plus rapide (en moyenne) de votre programme Perl en vitant la compilation de modules qui pourraient ne jamais tre appels durant une excution donne du programme. Le comportement de autouse est li au fait que le module soit dj charg ou non. Par exemple, si le module Module est dj charg, alors la dclaration :
use autouse Module => qw(fonc1 fonc2($;$) Module::fonc3);

est quivalente la simple importation de deux fonctions :


use Module qw(fonc1 fonc2);

Cela suppose que Module dfinisse fonc2 avec le prototype ($;$) et que fonc1() et fonc3() naient pas de prototype. (Plus gnralement, cela suppose galement que Module utilise la mthode import du module standard Exporter ; sinon, une exception est leve.) Dans tous les cas, la dclaration Module::fonc3 est ignore puisquelle est certainement dj dclare. Si, dun autre ct, Module na pas encore t charg lorsque le pragma autouse est analys, ce dernier dclare les fonctions fonc1 et fonc2 dans le paquetage courant. Il dclare galement une fonction Module::fonc3 (ce que lon pourrait analyser comme tant lgrement anti-social, si ce nest que labsence du module Module aurait des consquence encore plus anti-sociales). Lorsque ces fonctions sont appeles, elles sassurent que le Module en question est charg et elles sont alors remplaces par les appels aux fonctions relles qui viennent dtre charges. Puisque le pragma autouse dplace des portions de votre programme depuis la compilation vers lexcution, cela peut avoir des ramifications dplaisantes. Par exemple, si le module sur lequel vous avez appliqu autouse possde une phase dinitialisation qui sattend tre passe au plus tt, celle-ci pourra ne pas arriver assez tt. Lemploi de autouse peut galement masquer des bogues dans votre code lorsque dimportantes vrifications sont dplaces de la compilation vers lexcution. En particulier, si le prototype que vous avez spcifi dans la ligne autouse est faux, vous

customer_8566

794

Chapitre 31 Modules de pragmas

ne le dcouvrirez pas avant que la fonction correspondante soit excute (ce qui peut se produire des mois ou des annes plus tard, pour une fonction rarement appele). Pour rsoudre partiellement ce problme, vous pouvez crire votre code ainsi durant votre phase de dveloppement :
use Chasse; use autouse Chasse => qw(tolle($) clameur($&)); clameur "Cette clameur a t prdclare avec autouse\n";

La premire ligne sassure que les erreurs dans votre spcification des arguments soient trouves assez tt. Lorsque votre programme passe de la phase de dveloppement la phase de production, vous pouvez mettre en commentaire le chargement ordinaire du module Chasse et laisser seulement lappel autouse. De cette manire, vous obtenez de la scurit pendant le dveloppement et des performances durant la production.

use base
use base qw(Mere Pere);

Ce pragma permet un programmeur de dclarer aisment une classe drive base sur les classes parentes listes. La dclaration ci-dessus est peu prs quivalente :
BEGIN { require Mere; require Pere; push @ISA, qw(Mere Pere) }

Le pragma use base soccupe de chaque require ncessaire. Lorsque vous tes dans la porte du pragma strict vars, use base vous laisse faire (effectivement) un assignement de @ISA sans avoir dclarer dabord our @ISA. (Puisque le pragma use base intervient lors de la compilation, il vaut mieux viter de titiller @ISA dans votre coin lors de lexcution.) Mais au-del de ceci, use base possde une autre proprit. Si lune des classes de base nommes utilise les facilits de use fields dcrites plus loin dans ce chapitre, alors le pragma initialise les attributs spciaux de champs du paquetage depuis la classe de base. (Lhritage multiple des classes de champs nest pas support. Le pragma use base lve une exception si plus dune des classes de base nommes possde des champs.) Toute classe de base qui na pas encore t charge lest automatiquement via require. Toutefois, le fait que lon doive ou non charger un paquetage dune classe de base avec require est dtermin, non pas par linspection habituelle de %INC, mais par labsence dune variable globale $VERSION dans le paquetage de base. Cette astuce vite Perl dessayer en boucle (et dchouer) de charger une classe de base qui ne se trouve pas dans le fichier que lon appelle par require (car, par exemple, elle est charge en tant que faisant partie du fichier dun autre module). Si $VERSION nest pas dtecte aprs avoir russi charger le fichier, use base dfinira $VERSION dans le paquetage de base, en la positionnant la chane -1, defined by base.pm .

customer_8566

use blib

795

use blib
Depuis la ligne de commande :
% perl -Mblib programme [args...] % perl -Mblib=REP programme [args...]

Depuis votre programme Perl :


use blib; use blib REP ;

Ce pragma est en premier lieu un moyen de tester arbitrairement les programmes Perl pour dcouvrir une version non-installe dun paquetage grce loption de la ligne de commande de Perl -M. Il suppose que la structure de vos rpertoires a t produite par le module standard ExtUtils::MakeMaker. Le pragma cherche une structure de rpertoire blib commenant depuis un rpertoire nomm REP (ou le rpertoire courant si lon nen a spcifi aucun) et sil ny trouve pas de rpertoire blib, il revient en arrire travers vos rpertoires .. , en remontant jusquau cinquime niveau dans les rpertoires parents.

use bytes
use bytes; no bytes;

Le pragma use bytes dsactive la smantique des caractres pour le reste de la porte lexicale dans lequel il apparat. Le pragma no bytes peut tre employ pour inverser les effets de use bytes lintrieur de la porte lexicale courante. Perl prsume normalement une smantique de caractres en prsence dune donne sous forme de caractres (cest--dire, une donne note comme tant dans un encodage de caractre particulier). Pour comprendre les implications et les diffrences entres les smantiques de caractres et les smantiques doctets, voir le chapitre 15, Unicode. Une visite Tokyo peut galement tre utile.

use charnames
use charnames COMMENT; print "\N{SPEC_CAR} est un drle de caractre" ;

Ce pragma de porte lexicale permet aux caractres nomms dtre interpols vers des chanes en utilisant la notation \N{SPEC_CAR} :
use charnames :full; print "\N{GREEK SMALL LETTER SIGMA} est appele sigma.\n"; use charnames :short; print "\N{greek:Sigma} est appele sigma.\n"; use charnames qw(cyrillic greek); print "\N{sigma} est sigma en grec et \N{be} est b en cyrillique.\n";

customer_8566

796

Chapitre 31 Modules de pragmas

Le pragma supporte les valeurs :full et :short pour le paramtre COMMENT, ainsi que des noms de scripts spcifiques.1 Largument COMMENT dtermine comment rechercher le caractre spcifi par SPEC_CAR dans \N{SPEC_CAR}. Si :full est prsent, SPEC_CAR est dabord cherch dans les tables de caractres Unicode en tant que nom complet de caractre Unicode. Si :short est prsent et que SPEC_CAR est de la forme NOM_SCRIPT:NOM_CAR, NOM_CAR est recherch en tant que lettre dans le script NOM_SCRIPT. Si COMMENT contient des noms de scripts spcifiques, SPEC_CAR est recherch en tant que NOM_CAR dans chacun des scripts donns et dans lordre spcifi. Pour la recherche de NOM_CAR dans un script NOM_SCRIPT donn, le pragma regarde dans la table des noms standards Unicode sil peut trouver des motifs ayant la forme de :
NOM_SCRIPT CAPITAL LETTER NOM_CAR NOM_SCRIPT SMALL LETTER NOM_CAR NOM_SCRIPT LETTER NOM_CAR

Si NOM_CAR est entirement en minuscules (comme dans \N{sigma}), la variante CAPITAL est ignore. Vous pouvez crire votre propre module fonctionnant comme le pragma charnames mais dfinissant diffremment les noms de caractres. Toutefois, linterface pour cela est toujours exprimentale, consultez donc son tat courant dans la page de man.

use constant
use use use use use use use constant constant constant constant constant constant constant TAILLE_TAMPON UNE_ANNEE PI DEBOGAGE ORACLE NOM_UTILISATEUR INFOS_UTILISATEUR => => => => => => => 4096; 365.2425 * 24 * 60 * 60; 4 * atan2 1, 1; 0; oracle@cs.indiana.edu; scalar getpwuid($<); getpwuid($<);

sub deg_rad { PI * $_[0] / 180 } print "Cette ligne ne fait rien" unless DEBOGAGE; # Les rfrences peuvent tre dclares en tant que constantes use constant C_HACHAGE => { truc => 42 }; use constant C_TABLEAU => [ 1,2,3,4 ]; use constant C_PSEUDO_HACH => [ { truc => 1 }, 42]; use constant C_CODE => sub { "mord $_[0]\n" }; print C_HACHAGE->{truc}; print C_TABLEAU->{$i]; print C_PSEUDO_HACH->{truc};

1. Nous ne voulons pas dire par l des scripts Perls. Nous voulons dire des scripts comme dans certains styles particuliers de lettres crites, comme le romain ou le grec ou le cyrillique. Malheureusement, script est le terme technique pour cela et nous navons pas beaucoup de chance de persuader le Consortium Unicode dadopter un terme diffrent.

customer_8566

use constant
print C_CODE->{"moi"}; print C_HACHAGE->[10];

797

# erreur la compilation

Ce pragma dclare le symbole nomm comme tant une constante immuable2 avec la valeur scalaire ou de liste donne. Vous devez faire une dclaration spare pour chaque symbole. Les valeurs sont values dans un contexte de liste. Vous pouvez outrepasser cela avec scalar comme nous lavons fait ci-dessus. Puisque les constantes ne commencent pas par un $, vous ne pouvez pas les interpoler directement dans les chanes entre guillemets, bien que ce soit possible indirectement :
print "La valeur de PI est @{[ PI ]}.\n";

Comme les constantes de liste sont renvoyes en tant que listes, et non en tant que tableaux, vous devez indicer une constante reprsentant un valeur de liste en utilisant des parenthses supplmentaires comme vous le feriez avec toute autre expression de liste :
$rep_maison = INFO_UTILISATEUR[7]; $rep_maison = (INFO_UTILISATEUR)[7]; # FAUX # ok

Bien que lon recommande dcrire les constantes entirement en majuscules pour les faire ressortir et pour aider viter les collisions potentielles avec dautres mots-clefs et noms de sous-programmes, il ne sagit que dune convention. Les noms de constantes doivent commencer par une lettre mais celle-ci na pas besoin dtre en majuscule. Les constantes ne sont pas prives dans la porte lexicale dans laquelle elles apparaissent. Elle sont plutt de simples sous-programmes sans argument dans la table de symboles du paquetage o a lieu la dclaration. Vous pouvez vous rfrez une constante CONST depuis un paquetage Autre en crivant Autre::CONST. Approfondissez la notion dinsertion en ligne (N.d.T. : inlining) de tels sous-programmes la compilation en lisant la section Substitution en ligne de fonctions constantes au chapitre 6. Comme dans toutes les directives use, use constant intervient la compilation. Ainsi, placer une dclaration de constante lintrieur dune instruction conditionnelle comme if ($truc) { use constant ... } est une incomprhension totale. Si lon omet la valeur pour un symbole, ce dernier prendra la valeur undef dans un contexte scalaire ou la liste vide dans un contexte de liste. Mais il vaut probablement mieux dclarer ceux-ci explicitement :
use constant CAMELIDE use constant MAISON_CHAMEAU => (); => undef;

Restrictions de use constant


Les listes constantes ne sont pas actuellement insres en ligne de la mme manire que les scalaires. Et il nest pas possible davoir un sous-programme ou un mot clef du mme nom quune constante. Cest probablement une Bonne Chose. Vous ne pouvez pas dclarer plus dune constante nomme la fois :
use constant TRUC => 4, MACHIN => 5; # FAUX

2. Implmente comme un sous-programme sans argument et renvoyant toujours la mme constante.

customer_8566

798

Chapitre 31 Modules de pragmas

Ceci dfini une constante nomme TRUC qui renvoie une liste (4, "MACHIN", 5). Vous devez plutt crire :
use constant TRUC => 4; use constant MACHIN => 5;

Vous allez au-devant des problmes si vous utilisez une constante dans un contexte qui met automatiquement les mots bruts entre guillemets. (Ceci est pas vrai pour tout appel de sous-programme, pas seulement pour les constantes.) Par exemple vous ne pouvez pas crire $hachage{CONSTANTE} car CONSTANTE serait interprte comme une chane. Utilisez $hachage{CONSTANTE()} ou $hachage{+CONSTANTE} pour empcher le mcanisme de mise entre guillemets de se mettre en branle. De mme, puisque loprateur => met entre guillemets son oprande de gauche si cette dernire est un nom brut, vous devez crire CONSTANTE() => valeur au lieu de CONSTANTE => valeur. Un jour, vous serez capables dutiliser un attribut constant dans les dclarations de variables :
my $PI : constant = 4 * atan2(1,1);

Ceci possde tous les avantages dtre une variable plutt quun sous-programme, mais tous les inconvnients de ne pas tre encore implment.

use diagnostics
use diagnostics; use diagnostics -verbose; enable diagnostics; disable diagnostics; # activ la compilation # activ lexcution # dsactiv lexcution

Ce pragma tend les diagnostics ordinaires, laconiques et supprime les avertissements dupliqus. Il augmente les versions abrges avec les descriptions plus explicites et plus agrables que lon peut trouver au chapitre 33, Messages de diagnostic. Comme les autres pragmas, celui-ci affecte galement la phase de compilation de votre programme, pas seulement la phase dexcution. Lorsque vous utilisez use diagnostics au dbut de votre programme, loption Perl -w de la ligne de commande est automatiquement active en mettant $^W 1. La suite de votre entire compilation sera alors sujette des diagnostics amliors. Ces derniers sont toujours envoys vers STDERR. En raison des interactions entre les rsultats dexcution et de compilation, et parce que ce nest souvent pas une trs bonne ide, vous ne devriez pas utiliser no diagnostics pour dsactiver les diagnostics la compilation. Vous pouvez nanmoins contrler leur comportement lexcution en utilisant les mthodes enable et disable, pour respectivement les activer et les dsactiver. (Assurez-vous davoir dabord fait le use ou sinon vous serez incapables daccder aux mthodes.) Le f lag -verbose affiche dabord lintroduction de la page man de perldiag avant tout autre diagnostic. La variable $diagnostics::PRETTY peut tre positionne (avant le use) pour gnrer de meilleures squences dchappement pour les pagineurs comme less(1) ou more(1) :

customer_8566

use diagnostics
BEGIN { $diagnostics::PRETTY = 1 } use diagnostics;

799

Les avertissements envoys par Perl et dtects par ce pragma ne sont affichs quune seule fois chacun. Ceci est utile lorsque vous tes pris dans une boucle qui gnre encore et toujours le mme avertissement (comme une valeur non-initialise). Les avertissements gnrs manuellement, comme ceux dcoulant des appels warn ou carp, ne sont pas affects par ce mcanisme de dtection des duplications. Voici quelques exemples dutilisation du pragma diagnostics. Le fichier suivant dclenche coup sr quelques erreurs tant la compilation qu lexcution :
use diagnostics; print NULLE_PART "rien\n"; print STDERR "\n\nCe message devrait rester tel quel.\n"; warn "\tAvertissement utilisateur"; print "\nTESTEUR DE DIAGNOSTIC : Entrez un <RETOUR_CHARIOT> ici : "; my $a, $b = scalar <STDIN>; print "\n"; print $x/$y;

ce qui affiche :
Parenthesis missing around "my" list at diagtest line 6 (#1) (W parenthesis) You said something like my $foo, $bar = @_; when you meant my ($foo, $bar) = @_; Remember that "my", "our", and "local" bind tighter than comma. Name "main::NULLE_PART" used only once: possible typo at diagtest line 2 (#2) (W once) Typographical errors often show up as unique variable names. If you had a good reason for having a unique name, then just mention it again somehow to suppress the message. The our declaration is provided for this purpose. Name "main::b" used only once: possible typo at diagtest line 6 (#2) Name "main::x" used only once: possible typo at diagtest line 8 (#2) Name "main::y" used only once: possible typo at diagtest line 8 (#2) Filehandle main::NULLE_PART never opened at diagtest line 2 (#3) (W unopened) An I/O operation was attempted on a filehandle that was never initialized. You need to do an open() or a socket() call, or call a constructor from the FileHandle package. Ce message devrait rester tel quel.

customer_8566

800

Chapitre 31 Modules de pragmas


Avertissement utilisateur at diagtest line 4.

TESTEUR DE DIAGNOSTIC : Entrez un <RETOUR_CHARIOT> ICI : Use of uninitialized value in division (/) at diagtest line 8 (#4) (W uninitialized) An undefined value was used as if it were already defined. It was interpreted as a "" or a 0, but maybe it was a mistake. To suppress this warning assign a defined value to your variables. Illegal division by zero at diagtest line 8 (#5) (F) You tried to divide a number by 0. Either something was wrong in your logic, or you need to put a conditional in to guard against meaningless input. Uncaught exception from user code: Illegal division by zero at diagtest line 8.

Les messages de diagnostic sont tirs du fichier perldiag.pod. Si un gestionnaire $SIG{__WARN__} existant est dtect, il sera toujours respect, mais seulement aprs que la fonction diagnostics::splainthis (lintercepteur de $SIG{__WARN__} pour le pragma) aura fait son travail pour vos avertissements. Perl ne supporte pas lheure actuelle les empilements de gestionnaires, cest donc le mieux que nous puissions faire pour linstant. Il existe une variable $diagnostics::DEBUG que vous pouvez positionner si vous tes dincurables curieux propos des genres de choses qui sont interceptes.
BEGIN { $diagnostics::DEBUG = 1 } use diagnostics;

use fields
Dans le module Animal :
package Animal; use strict; use fields qw(nom poids _Animal_id); my $ID = 0; sub new { my Animal $obj = shift; unless (ref $obj) { $obj = fields::new($obj); $obj->{_Animal_id} = "ceci est lID secret de lAnimal"; } $obj->{nom} = "H, toi !"; $obj->{poids} = 20; return $obj; } 1;

Dans un programme spar, demo_animal :

customer_8566

use fields
use Animal; my Animal $rock = new Animal; $rock->{nom} = "quartz"; $rock->{poids} = "2kg"; $rock->{_Animal_id} = 1233; $rock->{couleur} = "bleu";

801

# lexicalement typ

# attribut priv # gnre une erreur de compilation

Dans le module Chien :


package Chien; use strict; use base Animal; use fields qw(nom pedigree);

# # # use fields qw(remue _Chien_prive) # sub new { my $classe = shift; my $obj = fields::new{$classe}; $obj_>SUPER::new(); # $obj->{pedigree} = "aucun"; # return $obj; }

hrite les champs et mthodes dAnimal surcharge lattribut nom dAnimal et ajoute un nouvel attribut pedigree non-partag avec Animal

initialise les champs de base initialise ses propres champs

Dans un programme spar, demo_chien :


use Chien; my Chien $medor = new Chien $medor->{nom} = "Theloneus" $medor->{poids} = "30lbs"; $medor->{pedigree} = "btard"; $medor->{couleur} = brun; $medor->{_Animal_pid} = 3324; # # # # lexicalement typ non-hrit hrit non-hrit

# gnre une erreur de compilation # gnre une erreur de compilation

Le pragma fields fournit une mthode pour dclarer les champs de classe dont le type peut tre vrifi la compilation. Ceci repose sur une fonctionnalit connue sous le nom de pseudo-hachages : si une variable lexicale type (my Animal $rock) contient une rfrence (lobjet Animal) et est utilise pour accder un lment de hachage ($rock>{nom}), sil existe un paquetage du mme nom que le type dclar, et si ce paquetage a positionn des champs de classe en utilisant le pragma fields, alors lopration se change en accs un tableau lors de la compilation, pourvu que le champ spcifi soit valide. Le pragma base apparent combinera les champs des classes de base et ceux dclars avec le pragma fields. Ceci rend permet lhritage de champ de bien fonctionner. Les noms de champ qui commencent par un caractre soulign sont rendus privs pour la classe et invisibles dans les sous-classes. Les champs hrits peuvent tre surchargs mais gnreront un avertissement si les avertissements sont activs. La consquence de tout ceci est que vous pouvez avoir des objets avec des champs nomms qui soient aussi compacts que des tableaux avec un accs aussi rapide. Cependant,

customer_8566

802

Chapitre 31 Modules de pragmas

ceci ne fonctionne que tant que lon accde aux objets travers des variables convenablement types. Si les variables ne sont pas types, laccs est uniquement vrifi lexcution, votre programme tourne donc plus lentement car il doit accder la fois un hachage et un tableau. En plus des dclarations de champs, les fonctions suivantes sont supportes : new La fonction fields::new cre et consacre un pseudo-hachage dans la classe spcifie (qui peut galement tre spcifie en passant un objet de cette classe). Lobjet est cr avec les champs dclars auparavant pour cette classe avec le pragma fields. Ceci autorise lcriture dun constructeur comme ceci :
package Creature::Sons; use fields qw(chat chien oiseau); sub new { my Creature:Sons $obj = shift; $obj = fields::new($obj) unless ref $obj; $obj->{chat} = miaule; # lment scalaire @$obj{chien, oiseau} = (aboie,siffle); # tranche return $obj; }

phash La fonction fields::phash cre et initialise un pseudo-hachage brut (non-consacr). Vous devriez toujours utiliser cette fonction pour crer des pseudo-hachages au lieu de le faire directement, au cas o nous dcidions de changer limplmentation. Si le premier argument de phash est une rfrence un tableau, le pseudo-hachage sera cr avec des clefs provenant de ce tableau. Si le second argument est fourni, ce doit tre galement une rfrence un tableau dont les lments seront utiliss comme valeurs. Si le second tableau contient moins dlments que le premier, les lments restants du pseudo-hachage ne seront pas initialiss. Ceci est particulirement utile pour crer un pseudo-hachage partir des arguments dun sous-programme :
sub chien_option { my $option = fields::phash([qw(nom grade matricule)], [@_]); }

Vous pouvez aussi passer une liste de paires clef/valeur qui sera utilise pour construire le pseudo-hachage :
my $option = fields::phash(nom => "Joe", grade => "capitaine", matricule => 42); my $pseudo_hachage = fields::phash(%args);

Pour plus dinformation sur les pseudo-hachages, voir la section Pseudo-hachages au chapitre 8, Rfrences. Limplmentation actuelle conserve les champs dclars dans le hachage %FIELDS du paquetage appelant, mais cela peut changer dans les prochaines versions, il vaut donc mieux vous fier linterface de ce pragma pour grer vos champs.

customer_8566

use filetest

803

use filetest
$lecture_peut_etre_possible = -r "fichier" # utilise les bits de mode { use filetest access; $lecture_vraiment_possible = -r "fichier" # dpiste plus srieusement } $lecture_peut_etre_possible = -r "fichier; # utilise nouveau les #bits de mode

Ce pragma de porte lexicale indique au compilateur de changer le comportement des oprateurs unaires de test de fichier -r, -w, -x, -R, -W et -X, documents au chapitre 3, Oprateurs unaires et binaires. Le comportement par dfaut de ces tests de fichiers est dutiliser les bits de mode renvoys par les appels de la famille de stat. Toutefois, ce nest peut-tre pas toujours la faon correcte de faire, comme lorsquun systme de fichiers comprends les ACL (Access Control Lists, listes de contrle daccs). Dans les environnement o cela compte, comme AFS, le pragma use filetest peut aider les oprateurs de permissions renvoyer des rsultats plus cohrents avec dautres outils. Il peut y avoir une lgre baisse de performance pour les oprateurs de test de fichier affects lorsquon les utilise avec use filetest, car sur certains systmes les fonctionnalits tendues ont besoin dtre mules. Attention : toute notion dutilisation de tests de fichiers dans des objectifs de scurit est une cause perdue davance. La porte est grande ouverte pour des situations de concurrence (race conditions), car il ny a aucun moyen de garantir que les permissions ne changeront pas entre le test et lopration effective. Si vous tes ne serait-ce quun peu srieux avec la scurit, vous nutiliserez pas doprateurs de test de fichier pour dcider si quelque chose va marcher ou pas. la place, essayez de lancer lopration relle puis testez si lopration a russi ou non. (Vous devriez de toute faon faire cela.) Voir la section Gestion des problmes de synchronisation au chapitre 23, Scurit.

use filetest access


Actuellement une seule importation, access, est implmente. Lappel de use filetest access active lemploi daccess(2) ou dappels systmes quivalents lorsquon lance des tests de fichier ; symtriquement, no filetest access le dsactive. Cette fonctionnalit tendue de test de fichier nest utilise que lorsque loprande de loprateur (ou, si vous prfrez, largument de la fonction unaire) est un vritable nom de fichier, et non un handle de fichier.

use integer
use integer; $x = 10 / 3; # $x vaut maintenant 3, et non 3.33333333333333333

Ce pragma de porte lexicale indique au compilateur dutiliser des oprations entires partir de ce point et jusqu la fin du bloc lencadrant. Sur la plupart des machines, cela infuence peu la majorit des calculs mais sur celles qui ne disposent pas de coprocesseur arithmtique, cela peut entraner une diffrence de performance dramatique.

customer_8566

804

Chapitre 31 Modules de pragmas

Remarquez que ce pragma affecte certaines oprations numriques, pas les nombres eux-mme. Par exemple, si vous lancez ce code :
use integer; $x = 1.8; $y = $x + 1; $z = -1.8;

vous vous retrouverez avec $x == 1.8, $y == 2 et $z == -1. Le cas de $z sexplique par le fait quun - unaire compte comme une opration, ainsi la valeur 1.8 est tronque un avant que son bit de signe soit invers. De mme, les fonctions qui attendent des nombres virgule f lottante, comme sqrt ou les fonctions trigonomtriques, recevront et renverront toujours des nombres virgule mme sous use integer. Ainsi sqrt(1.44) vaut 1.2 mais 0 + sqrt(1.44) vaut maintenant seulement 1. Larithmtique entire native, telle quelle est fournie par votre compilateur C, est utilise. Cela signifie que la propre smantique de Perl pour les oprations arithmtiques peut ne pas tre prserve. Une source dennuis frquente est le modulo des nombres ngatifs. Perl le calcule dune faon mais votre matriel peut le faire dune autre manire :
% perl -le print (4 % -3) -2 % perl -Minteger -le print (4 % -3) 1

use less
use less; use use use use use less less less less less CPU; memory; time; disk; fat; # AUCUN NEST IMPLMENT

# gant avec "use locale";

Actuellement non-implment, ce pragma est destin donner un jour des indications au compilateur, au gnrateur de code ou linterprteur pour activer certains quilibrages. Il ny a aucun mal demander utiliser moins (use less) de quelque chose alors que Perl ne sait pas comment rduire ce quelque chose lheure actuelle.

use lib
use lib "$ENV{HOME}/libperl"; no lib "."; # ajoute ~/libperl # enlve cwd

Ce pragma simplifie la manipulation de @INC la compilation. Il est gnralement utilis pour ajouter des rpertoires supplmentaires dans le chemin de recherche de Perl pour quensuite les instructions do, require et use trouvent les fichiers de bibliothque qui ne se situent pas dans le chemin de recherche par dfaut de Perl. Il est particulire-

customer_8566

use lib

805

ment important avec use, puisque ce dernier intervient galement la compilation et que laffectation ordinaire de @INC (cest--dire lexcution) arriverait trop tard. Les paramtres de use lib sont ajouts au dbut du chemin de recherche de Perl. crire use lib LISTE revient peu prs au mme qucrire BEGIN { unshift(@INC, LISTE) }, mais use lib LISTE inclut le support des rpertoires spcifiques une plate-forme. Pour chaque rpertoire $rep donn dans sa liste darguments, le pragma list vrifie galement si un rpertoire nomm $rep/$nom_architecture/auto existe ou non. Si cest le cas, le rpertoire $rep/$nom_architecture/auto est suppos correspondre un rpertoire spcifique la plate-forme et il est donc ajout @INC (devant $rep). Pour viter les ajouts redondants qui ralentissent les temps daccs et gaspillent une petite quantit de mmoire, les entres dupliques qui restent dans @INC sont supprimes lorsque des entres sont ajoutes. Normalement, vous ne devez quajouter des rpertoires dans @INC. Si vous avez vraiment besoin denlever des rpertoires de @INC, prenez garde ne supprimer que ceux que vous avez vous-mme ajouts ou ceux dont vous tes certains quils ne sont pas ncessaires dautres modules dans votre programme. Dautres modules peuvent avoir ajout dans votre tableau @INC des rpertoires dont ils avaient besoin pour que leurs oprations soient correctement effectues. Le pragma no lib supprime de @INC toutes les instances de chaque rpertoire nomm. Il dtruit galement tous les rpertoires correspondants spcifiques la plate-forme, tels que nous les avons dcrits plus haut. Lorsque le pragma lib est charg, il sauvegarde la valeur courante de @INC dans le tableau @lib::ORIG_INC, afin de copier ce tableau dans le vritable @INC pour restaurer la valeur originale. Mme si @INC inclut gnralement le rpertoire courant, point ( . ), Ce nest vraiment pas aussi utile que vous pouvez le penser. Premirement, lentre point vient la fin, pas au dbut. Ainsi les modules installs dans le rpertoire courant ne prennent pas soudainement le dessus sur les versions globales au systme. Vous pouvez crire use lib "." si cest ce que vous voulez vraiment. Plus ennuyeux, il sagit du rpertoire courant du processus Perl, et non du rpertoire o le script a t install, ce qui enlve toute fiabilit cet ajout de . . Si vous crez un programme, plus quelques modules utiliss par ce programme, il marchera tant que vous dveloppez, mais cela cessera lorsque vous ne le lancerez pas depuis le rpertoire o se trouvent les fichiers. Une solution pour cela est dutiliser le module standard FindBin :
use FindBin; use lib $FindBin::Bin; # o le script a-t-il t install ? # utilise galement ce rpertoire pour lib

Le module FindBin essaie de deviner le chemin complet vers le rpertoire o a t install le programme du processus en train de tourner. Nutilisez pas ceci dans des objectifs de scurit car les programmes malveillants peuvent dordinaire le dtourner en essayant suffisamment nergiquement. Mais moins que vous nessayez intentionnellement de casser le module, il devrait marcher comme prvu. Le module procure une variable $Findbin::Bin (que vous pouvez importer) qui contient lemplacement o le programme a t install, tel que le module la devin. Vous pouvez alors utiliser le pragma lib pour ajouter ce rpertoire votre tableau @INC, produisant ainsi un chemin relatif lexcutable.

customer_8566

806

Chapitre 31 Modules de pragmas

Certains programmes sattendent tre installs dans un rpertoire bin et trouvent alors leurs modules de bibliothque dans les fichiers cousins installs dans un rpertoire lib au mme niveau que bin. Par exemple, des programmes peuvent se trouver dans /usr/ local/apache/bin ou /opt/perl/bin et les bibliothques dans /usr/local/apache/lib et /opt/perl/ lib. Ce code en tient soigneusement compte :
use FindBin qw(Bin); use lib "$Bin/../lib";

Si vous vous retrouvez spcifier le mme use lib dans plusieurs programmes sans rapport les uns avec les autres, vous pouvez envisager de positionner la place la variable denvironnement PERL5LIB. Voir la description de la variable denvironnement PERL5LIB au chapitre 19, Linterface de la ligne de commande.
# syntaxe pour sh, bash, ksh ou zsh $ PERLLIB=$HOME/libperl; export PERL5LIB # syntaxe pour csh ou tcsh $ setenv PERL5LIB ~/libperl

Si vous voulez utiliser des rpertoires optionnels uniquement pour ce programme sans changer son code source, regardez du ct de loption de la ligne de commande -I :
% perl -I ~/libperl chemin-programme args

Voir le chapitre 19 pour plus dinformations sur lemploi de -I dans la ligne de commande.

use locale
@x = sort @y; { use locale; @x = sort @y; } @x = sort @y; # tri dans lordre ASCII # tri dans lordre dfini par les locales # nouveau tri dans lordre ASCII

Ce pragma de porte lexicale indique au compilateur dactiver (ou de dsactiver, avec no locale) lemploi des locales POSIX pour les oprations intrinsques. Lactivation des locales indique aux fonctions de conversions de casse (majuscule/minuscule) de Perl et au moteur de recherche de motifs de respecter lenvironnement de votre langue, en autorisant les signes diacritiques3, etc. Si ce pragma est actif et que votre bibliothque C connat les locales POSIX, Perl recherche la valeur de votre variable denvironnement LC_CTYPE pour les expressions rgulires et LC_COLLATE pour les comparaisons de chanes comme celles de sort. Comme les locales sont plus une forme de nationalisation que dinternationalisation, lemploi des locales peut interfrer avec Unicode. Voir le chapitre 15 pour plus dinformations sur linternationalisation.

3. N.d.T. : signe qui donne un caractre de lalphabet une valeur spciale.

customer_8566

use open

807

use open
use open IN => ":crlf", OUT => ":raw";

Le pragma open dclare une ou plusieurs disciplines par dfaut pour les oprations dentres/sorties. Chaque oprateur open et readpipe (cest--dire qx// ou les apostrophes inverses) dcouvert lintrieur de la porte lexicale de ce pragma et qui ne spcifie pas ses propres disciplines utilisera celles dclares par dfaut. Ni open avec un ensemble explicite de disciplines, ni sysopen en toute circonstance, ne sont inf luencs par ce pragma. Seules les deux disciplines :raw et :crlf sont actuellement implmentes (cependant au moment o nous crivons cela, nous esprons quune discipline :utf8 le soit galement bientt). Sur les systmes ancestraux qui font la distinction entre ces deux modes de conversions lors de louverture de fichiers, la discipline :raw correspond au mode binaire et :crlf au mode texte . (Ces deux disciplines nont actuellement aucun effet sur les plates-formes o binmode nen a pas non plus, mais seulement pour le moment ; voir la fonction open au chapitre 29, Fonctions, pour une description plus dtaille des smantiques que nous esprons en ce qui concerne les diverses disciplines.) Le support exhaustif des disciplines dentres/sorties nest pas encore implment ce jour. Lorsquelles seront enfin supportes, ce pragma servira comme lune des interfaces pour dclarer les disciplines par dfaut pour toutes les entres/sorties. ce moment-l, les disciplines par dfaut dclares avec ce pragma seront accessibles par le biais de la discipline spciale nomme :DEFAULT et exploitables lintrieur des constructeurs de handles qui autorisent la spcification de disciplines. Cela rendra possible lempilement de nouvelles disciplines par-dessus celles par dfaut.
open (HF, "<:para :DEFAULT", $fichier) or die "impossible douvrir $fichier : $!";

Lorsquil sera complet, le support des disciplines dentres/sorties permettra toutes les disciplines supportes de fonctionner sur toutes les plates-formes.

use overload
Dans le module Nombre :
package Nombre; use overload "+" => \&mon_addition"; "-" => \&ma_soustraction"; "*=" => \&mon_produit_par";

Dans votre programme :


use Nombre; $a = new Nombre 57; $b = $a +5;

Les oprateurs internes fonctionnent bien avec des chanes et des nombres mais nont que peu de sens lorsquon les applique des rfrences dobjets (puisque, contrairement C ou C++, Perl ne permet pas de faire de larithmtique de pointeur). Le pragma overload vous laisse redfinir les significations de ces oprations internes lorsque vous

customer_8566

808

Chapitre 31 Modules de pragmas

les appliquez des objets de votre cru. Dans lexemple prcdent, lappel au pragma redfinit trois opration sur des objets Nombre : laddition appellera la fonction Nombre::mon_addition, la soustraction appellera la fonction Nombre::ma_soustraction et loprateur dassignement accompagn dune multiplication appellera la mthode mon_produit_par de la classe Nombre (ou de lune de ses classes de base). Nous disons que ces oprateurs sont surchargs (overloaded) car des significations supplmentaires les recouvrent (et non parce quils ont trop de significations - quoique cela peut galement tre le cas). Pour plus dinformations sur la surcharge, voir le chapitre 13, Surcharge.

use re
Ce pragma contrle lutilisation des expressions rgulires. On peut linvoquer de quatre faons : " taint " et " eval ", qui ont une porte lexicale, plus " debug " et " debugcolor " qui nen ont pas.
use re taint; # Le contenu de $corresp est marqu si $gribouille tait aussi marqu. ($corresp) = ($gribouille =~ /(.*)$/s); # Permet linterpolation de code : use re eval; $motif = (?{ $var = 1 }); # excution de code insr /alpha${motif}omega/; # nchouera pas moins dtre lanc # avec -T et que $motif soit marqu use re debug; /^(.*)$/s; # comme "perl -Dr" # affichage dinformations de dbogage # durant la compilation et lexcution # comme debug, mais avec un affichage # en couleur

use re debugcolor

Lorsque use re taint est actif et quune chane marque est la cible de lexpression rgulire, les variables numrotes de lexpression rgulire et les valeurs renvoys par loprateur m// dans un contexte de liste sont galement marques. Ceci est trs utile lorsque les oprations dexpressions rgulires sur des donnes marques ne sont pas voues extraire des sous-chanes scurises mais effectuer dautres transformations. Voir la discussion sur le marquage au chapitre 23. Lorsque use re eval est actif, une expression rgulire a le droit de contenir des assertions excutant du code Perl, qui sont de la forme (?{...}), mme si lexpression rgulire contient des variables interpoles. Lexcution des segments de code rsultant de linterpolation de variables lintrieur des expressions rgulires nest pas habituellement permise pour des raisons de scurit : vous ne voulez pas que des programmes qui lisent des motifs depuis des fichiers de configuration, des arguments de la ligne de commande ou des champs de formulaires CGI, se mettent subitement excuter un code arbitraire sils ne sont pas conus pour sattendre cela. Cet emploi du pragma permet uniquement aux chanes non-marques dtre interpoles ; les donnes marques causeront toujours la leve dune exception (si vous activez la vrification des marquages).

customer_8566

use sigtrap
Voir galement le chapitre 5, Correspondance de motifs et le chapitre 23.

809

lintention de ce pragma, linterpolation dexpressions rgulires prcompiles (produites par loprateur qr//) nest pas considre comme une interpolation de variable. Nanmoins, lorsque vous construisez le motif qr//, use re eval doit tre actif si lune de ses chanes interpoles contient des assertions de code. Par exemple :
$code = (?{ $n++ }); $chaine = \b\w+\b . $code; $ligne =~ /$chaine/; $motif = qr/$chaine/; $ligne =~ /$motif/; # # # # # assertion de code construit la chane interpoler ceci a besoin de use re eval ceci galement mais pas ceci

Avec use re debug, Perl met des message de dbogage la compilation et lexcution dexpressions rgulires. Laffichage est identique celui obtenu en lanant un dbogueur Perl (lun de ceux compils en passant -DDEBUGGING au compilateur C) et en excutant alors votre programme Perl avec loption de la ligne de commande de Perl -Dr. Selon la complexit de votre motif, laffichage rsultant peut vous noyer. Lappel de use re debugcolor permet un affichage plus color qui peut savrer utile, pourvu que votre terminal comprenne les squences de couleurs. Positionner votre variable denvironnement PERL_RE_TC avec une liste de proprits termcap(5) pertinentes, spares par des virgules, pour faire ressortir laffichage. Pour plus de dtails, voir le chapitre 20, Le dbogueur Perl.

use sigtrap
use use use use use use use sigtrap; sigtrap qw(stack-trace old-interface-signals); # idem sigtrap qw(BUS SEGV PIPE ABRT); sigtrap qw(die INT QUIT); sigtrap qw(die normal-signals); sigtrap qw(die untrapped normal-signals); sigtrap qw(die untrapped normal-signals stack-trace any error-signals);

Le pragma sigtrap installe pour vous quelques gestionnaires de signaux simples pour vous viter de vous en inquiter. Ceci est trs utile dans les situations o les signaux nonintercepts causeraient des dysfonctionnement dans votre programme; comme lorsque vous avez des blocs END {}, des destructeurs dobjets ou dautres traitements lancer la fin de votre programme quelle que soit la faon dont il se termine. Le pragma sigtrap fournit deux gestionnaires de signaux simples que vous pouvez utiliser. Lun apporte Perl une trace de la pile et lautre lance une exception ordinaire via die. Vous pouvez aussi fournir votre propre gestionnaire au pragma pour quil linstalle. Vous pouvez spcifier des ensembles de signaux prdfinis intercepter ; vous pouvez galement donner votre propre liste explicite de signaux. Le pragma peut optionnellement installer des gestionnaires uniquement pour les signaux qui nauraient sinon pas t grs. Les arguments passs use sigtrap sont traits dans lordre. Lorsquun nom de signal fourni par lutilisateur ou le nom dun des ensembles de signaux prdfinis de sigtrap est rencontr, un gestionnaire est immdiatement install. Lorsquil y a une option, celle-ci naffecte que les gestionnaires installs ensuite en traitant la liste darguments.

customer_8566

810

Chapitre 31 Modules de pragmas

Gestionnaires de signaux
Ces options ont pour effet de dcider quel gestionnaire sera utilis pour les signaux installs ensuite : stack-trace Ce gestionnaire fourni par le pragma affiche une trace de la pile dexcution Perl vers STDERR et tente alors de faire une copie du cur du programme (core dump). Il sagit du gestionnaire de signaux par dfaut. die Ce gestionnaire fourni par le pragma appelle die via Carp::croak avec un message indiquant le signal reu. handler VOTRE_GESTIONNAIRE VOTRE_GESTIONNAIRE sera utilis comme gestionnaire pour les signaux installs ensuite. VOTRE_GESTIONNAIRE peut tre nimporte quelle valeur valide pour un assignement de %SIG. Souvenez-vous que le fonctionnement correct de beaucoup dappels de la bibliothque C (en particulier les appels dentres/sorties standards) nest pas garanti lintrieur dun gestionnaire de signaux. Pis encore, il est difficile de deviner quels morceaux du code de la bibliothque C sont appels depuis tel ou tel morceau du code Perl. (Dun autre ct, nombre de signaux que sigtrap intercepte sont un peu vicieux ils vous feront tourner en bourrique de toute faon, alors a ne cote pas grand chose dessayer de faire quelque chose, nest-ce pas?)

Listes prdfinies de signaux


Le pragma sigtrap inclut quelques listes prdfinies de signaux intercepter : normal-signals Il sagit des signaux quun programme peut normalement sattendre rencontrer et qui le font, par dfaut, se terminer. Ce sont les signaux HUP INT, PIPE et TERM. , error-signals Il sagit des signaux qui dordinaire indiquent un srieux problme avec linterprteur Perl ou avec votre programme. Ce sont les signaux ABRT, BUS, EMT, FPE, KILL, QUIT, SEGV, SYS et TRAP . old-interface-signals Il sagit des signaux qui sont intercepts par dfaut sous une ancienne version de linterface de sigtrap. Ce sont les signaux ABRT, BUS, EMT, FPE, KILL, PIPE, QUIT, SEGV , SYS, TERM et TRAP Si aucun signal ou aucune liste de signaux nest pass use sig. trap, on utilise cette liste. Si votre plate-forme nimplmente pas un signal particulier cit dans les listes prdfinies, le nom de ce signal sera discrtement ignor. (Le signal lui-mme ne peut pas tre ignor car il nexiste pas.)

customer_8566

use sigtrap

811

Autres arguments de sigtrap


untrapped Ce token supprime les gestionnaires pour tous les signaux lists ultrieurement sils ont dj t intercepts ou ignors. any Ce token installe des gestionnaires pour tous les signaux lists ultrieurement. Il sagit du comportement par dfaut. signal Tout argument qui ressemble un nom de signal (cest--dire qui correspond au motif /^[A-Z][A-Z0-9]*$/ enjoint sigtrap de grer ce signal. nombre Un argument numrique requiert que le numro de version du pragma sigtrap soit au moins nombre. Ceci fonctionne exactement comme la plupart des modules ordinaires qui ont une variable de paquetage $VERSION.
% perl -Msigtrap -le print $sigtrap::VERSION 1.02

Exemples de sigtrap
Fournit une trace de la pile pour les signaux utilisant lancienne interface :
use sigtrap;

Idem, mais plus explicite :


use sigtrap qw(stack-trace old-interface-signals);

Fournit une trace de la pile uniquement pour les quatre signaux lists :
use sigtrap qw(BUS SEGV PIPE ABRT);

Meurt (via die) sur rception du signal INT ou QUIT :


use sigtrap qw(die INT QUIT);

Meurt (via die) sur rception de lun des signaux HUP INT, PIPE ou TERM : ,
use sigtrap qw(die normal-signals);

Meurt (via die) sur rception de HUP INT, PIPE ou TERM cela prs quon ne change , pas le comportement pour les signaux qui ont dj t intercepts ou ignors ailleurs dans le programme :
use sigtrap qw(die untrapped normal-signals);

Meurt (via die) sur rception de nimporte quel signal normal-signals non-intercept actuellement ; de plus, fournit une trace arrire de la pile dexcution sur rception de lun des signaux error-signals :
use sigtrap qw(die untrapped normal-signals stack-trace any error-signals);

Installe la routine mon_gestionnaire comme gestionnaire pour les signaux normalsignals :


use sigtrap handler => \&mon_gestionnaire, normal-signals;

customer_8566

812

Chapitre 31 Modules de pragmas

Installe la routine mon_gestionnaire comme gestionnaire pour les signaux normalsignals ; de plus, fournit une trace arrire de la pile dexcution sur rception de lun des signaux error-signals :
use sigtrap qw(handler mon_gestionnaire normal-signals stack-trace error-signals);

use strict
use strict; use strict "vars"; use strict "refs"; use strict "subs"; use strict; no strict "vars"; # Installe les trois restrictions. # Les variables doivent tre prdclares. # Les rfrences symboliques sont interdites. # Les chanes brutes doivent tre entre guillemets. # Installe toutes les restrictions # puis renonce lune dentre elles.

Ce pragma de porte lexicale modifie quelques rgles basiques propos de ce que Perl considre comme tant du code lgal. Quelquefois, ces restrictions semblent trop strictes pour de la programmation occasionnelle, comme lorsque vous ne faites quessayer de programmer la hte un filtre de cinq lignes. Plus votre programme est gros, plus vous devez tre strict avec lui. Actuellement, vous devez tre strict avec trois choses : subs, vars et refs. Si aucune liste dimportation nest fournie, les trois restrictions sont prises en compte.

strict refs
Cet exemple gnre une erreur lexcution si vous utilisez des rfrences symboliques, intentionnellement ou pas. Voir le chapitre 8, Rfrences pour plus dinformations.
use strict refs; $ref = \$truc; print $$ref; $ref = "truc"; print $$ref; # Enregistre une rfrence "relle" (en dur). # Drfrencement ok. # Enregistre le nom dune variable globale (de paquetage). # FAUX, erreur lexcution avec strict refs.

Les rfrences symboliques sont suspectes pour diverses raisons. Il est tonnamment ais, mme pour des programmeurs bien intentionns, de les invoquer accidentellement ; strict refs lempche. Au contraire des rfrences relles, les rfrences symboliques ne peuvent se rfrer qu des variables globales. Elles ne possdent pas de compteur de rfrences. Il existe souvent un meilleur moyen daccomplir ce que vous fates : au lieu de rfrencer un symbole dans une table de symboles globale, utilisez un hachage pour sa propre mini-table de symboles. Cest plus efficace, plus lisible et moins sujet engendrer des erreurs. Nanmoins, certains types de manipulations valides ncessitent vraiment un accs direct la table de symboles globale du paquetage pour les noms de variables et de fonctions. Par exemple, il se peut que vous vouliez examiner la liste @EXPORT de la superclasse @ISA dun paquetage donn dont vous ne connaissez pas le nom lavance. Ou

customer_8566

use strict

813

vous pourriez vouloir installer toute une kyrielle dappels de fonctions qui seraient toutes des alias de la mme fermeture. Cest seulement l que les rfrences symboliques sont les plus utiles, mais pour les utiliser alors que use strict est actif, vous devez dabord annuler la restriction " ref " :
# construit un groupe daccesseurs pour les attributs for my $nom_meth (qw/ nom grade matricule/) { no strict refs; *$nom_meth = sub { $_[0]->{ __PACKAGE__ . $nom_meth }; }

strict vars
Dans cette restriction, une erreur de compilation est dclenche si vous essayez daccder une variable qui nest pas conforme au moins un de ces critres : Prdfinie par Perl, comme @ARGV %ENV et toutes les variables globales avec des , signes de ponctuation comme $. ou $_. Dclare avec our (pour une variable globale) ou my (pour une variable lexicale). Importe depuis un autre paquetage. (Le pragma use vars simule une importation, mais utilisez our la place.) Pleinement qualifie en utilisant le nom de son paquetage et le double deux-points sparateur de paquetage.

Lemploi seul dun oprateur local nest pas suffisant pour rendre heureux use strict vars car, malgr son nom, cet oprateur ne change pas le fait quune variable nomme soit globale ou non. Il donne seulement la variable une nouvelle valeur temporaire durant un bloc lors de lexcution. Vous devrez toujours employer our pour dclarer une variable globale ou my pour dclarer une variable lexicale. Vous pouvez toutefois localiser un our :
local our $loi = "martiale";

Les variables globales prdfinies par Perl sont dispenses de ces exigences. Ceci sapplique aux variables globales de tout le programme (celles forces dans le paquetage main comme @ARGV ou $_) et aux variables par paquetage comme $a ou $b, qui sont normalement utilise par la fonction sort. Les variables par paquetage utilises par les modules comme Exporter ont toujours besoin dtre dclares en utilisant our :
our @EXPORT_OK = qw(nom grade matricule);

strict subs
Cette restriction oblige Perl traiter les mots simples comme des erreurs de syntaxe. Un mot simple (bareword ou bearword dans certains dialectes) est un nom simple ou un identificateur qui na aucune autre interprtation force par le contexte. (Le contexte est souvent forc par la proximit dun mot clef ou dun token ou par la prdclaration du mot en question.) Historiquement, les mots simples taient interprts comme des chanes sans guillemets ou apostrophes. Cette restriction rend cette interprtation illgale. Si vous avez lintention de lutiliser en tant que chane, mettez-la entre guillemets ou entre apostrophes. Si vous avez lintention de lutiliser en tant que fonction, prdclarez-la ou employez des parenthses.

customer_8566

814

Chapitre 31 Modules de pragmas

Comme cas particulier de contexte forc, souvenez-vous quun mot qui apparat entre des accolades ou du ct gauche de loprateur => compte comme sil tait entre apostrophes et nest donc pas sujet cette restriction.
use strict subs; $x = n_importe_quoi; $x = n_importe_quoi(); sub n_importe_quoi; $x = n_importe_quoi; # FAUX : erreur de mot simple ! # Par contre, cela marche toujours. # Prdclaration de fonction. # Maintenant ok.

# Ces utilisations sont permises car => met entre apostrophes : %hachage = (rouge => 1, vert => 2, bleu => 3); $num_rouge = $hachage{rouge}; # Ok, les accolades mettent entre # apostrophes ici.

# Mais pas celles-ci : @nums = @hachage{bleu, vert}; @nums * @hachage{"bleu", "vert"}; @nums = @hachage{qw/bleu vert/};

# # # #

Faux : erreur de mot simple. Ok, les mots sont maintenant entre guillemets. Idem.

use subs
use subs qw/am stram gram/; @x = am 3..10; @x = gram stram @x;

Ce pragma prdclare tous les noms de la liste darguments comme tant des sous-programmes standards. Lavantage ici est que vous pouvez maintenant utiliser ces fonctions sans parenthses en tant quoprateurs de listes, exactement comme si vous les aviez dclares vous-mmes. Ce nest pas forcment aussi utile que des dclarations compltes car cela ne permet pas dutiliser des prototypes ou des attributs comme dans :
sub am(@); sub stram(\@) : locked; sub gram($) : lvalue;

Puisquil est bas sur le mcanisme dimportation standard, le pragma use subs na pas de porte lexicale mais une porte de paquetage. Cest--dire que les dclarations sont effectives pour la totalit du fichier dans lequel elles apparaissent, mais seulement pour le paquetage courant. Vous ne pouvez pas annuler de telles dclarations avec no subs.

use vars
use vars qw($bricole @refait %vu);

Ce pragma, autrefois utilis pour dclarer une variable globale, est maintenant quelque peu dprci en faveur du modificateur our. La dclaration prcdente seffectue mieux

customer_8566

use warnings
en utilisant :
our($bricole, @refait, %vu};

815

ou mme :
our $bricole = "F"; our @refait = "A" .. $bricole; our %vu = ();

Peu importe que vous utilisiez lune ou lautre de ces possibilits, rappelez-vous quelles portent toutes sur des variables globales de paquetage, et non sur des variables lexicales ayant la porte du fichier.

use warnings
use warnings; no warnings; # Revient importer "all". # Revient annuler limportation de "all". use warnings::register; if (warnings::enabled()) { warnings::warn("un avertissement"); } if (warnings::enabled("void")) { warnings::warn("void", "un avertissement"); }

Ce pragma de porte lexicale permet un contrle souple sur les avertissements internes de Perl, la fois ceux mis par le compilateur et ceux provenant du systme dexcution. Autrefois, le seul contrle que vous aviez sur le traitement des avertissements de votre programme se faisait par le biais de loption de la ligne de commande -w ou de la variable $^W. Bien quutile, ces solutions tendaient faire du tout-ou-rien. Loption -w active des avertissements dans des morceaux de code que vous pouvez ne pas avoir crits, ce qui est parfois problmatique pour vous et embarassant pour lauteur original. Lemploi de $^W, soit pour activer, soit pour dsactiver des blocs de code, peut savrer moins quoptionnel car il ne fonctionne que durant lexcution et non pendant la compilation.4 Un autre problme est que cette variable globale tout le programme possde une porte dynamique et non lexicale. Cela signifie que si vous lactivez dans un bloc et quensuite vous appelez partir de l un autre code, vous risquez ici encore dactiver des avertissements dans du code qui nest pas dvelopp avec exactement de tels standards lesprit. Le pragma warnings contourne ces limitations en possdant une porte lexicale, des mcanismes durant la compilation qui permettent un contrle plus fin sur lendroit o les avertissements peuvent ou ne peuvent pas tre dclenchs. Une hirarchie de catgories davertissements (voir la figure 31-1) a t dfinie pour permettre aux groupes davertissements dtre activs ou dsactivs sparment les uns des autres. (La catgorisation exacte est exprimentale et sujette modifications.) Ces catgories peuvent tre combines en passant des arguments multiples use ou no :
4. En labsence de blocs BEGIN, bien entendu.

customer_8566

816

Chapitre 31 Modules de pragmas

Figure 31-1. Catgories des avertissements Perl

customer_8566

use warnings
use warnings qw(void redefine); no warnings qw(io syntax untie);

817

Si des instances multiples du pragma warnings sont actives pour un groupe donn, leurs effets se cumulent :
use warnings "void"; ... use warnings "io"; ... no warnings "void"; # Seuls les avertissements "void" sont actifs. # Les avertissements "void" et "io" sont # maintenant tous deux actifs. # Seuls les avertissements "io" sont maintenant # actifs.

Pour donner des erreurs fatales pour tous les avertissements activs par un pragma warnings particulier, utilisez le mot FATAL devant la liste dimportation. Ceci est trs utile lorsque vous aimez mieux quune certaine condition, qui dordinaire naurait caus quun avertissement, arrte votre programme. Supposez par exemple que vous considriez lemploi dune chane invalide en tant que nombre (qui normalement aurait donn une valeur de 0) si incorrect que vous vouliez que cet acte effront tue votre programme. Pendant que vous y tes, vous dcidez que lutilisation de valeurs non-initialises en lieu et place de chanes relles ou de valeurs numriques doit galement tre la cause dun suicide immdiat :
{ use warnings FATAL => qw(numeric unitialized); $x = $y + $z; }

Maintenant, si $y ou $z ne sont pas initialises (cest--dire, contiennent la valeur scalaire spciale undef) ou si elles contiennent des chanes qui ne se convertissent pas proprement en valeurs numriques, au lieu de continuer gentiment son chemin ou tout au plus dmettre une petite complainte si vous aviez activ -w, votre programme lvera maintenant une exception. (Pensez cela comme du Perl tournant en mode Python.) Si vous ninterceptez pas les exceptions, elles causeront une erreur fatale. Le texte de lexception est le mme que celui qui serait normalement apparu dans le message davertissement. Le pragma warnings ignore loption de la ligne de commande -w et la valeur de la variable $^W ; les configurations du pragma sont prioritaires. Toutefois, le drapeau -W de la ligne de commande passe outre le pragma, en activant totalement les avertissements dans tous le code lintrieur de votre programme, y compris le code charg avec do, require ou use. En dautres termes, avec -W, Perl prtend que chaque bloc de votre programme possde un pragma use warnings all. Pensez-y comme un lint(1) pour les programmes Perl. (Mais voyez galement la documentation en ligne du module B::Lint.) Le drapeau -X de la ligne de commande fonctionne linverse. Il prtend que chaque bloc a un no warnings all activ. Plusieurs fonctions sont fournies pour assister les auteurs de modules qui veulent que les fonctions de leur module se comportent comme les fonctions internes en respectant la porte lexicale de lappelant (cest--dire, de manire ce que les utilisateurs du module puissent lexicalement activer ou dsactiver les avertissements que le module pourrait mettre) :

customer_8566

818
warnings::register

Chapitre 31 Modules de pragmas

Enregistre le nom du module courant comme une nouvelle catgorie davertissements, afin que les utilisateurs du module puissent en stopper les avertissements. warnings::enabled(CATEGORIE) Renvoie vrai si la catgorie CATEGORIE est active dans la porte lexicale du module appelant. Sinon, renvoie faux. Si CATEGORIE nest pas fournie, le nom du paquetage courant est utilis. warnings::warn(CATEGORIE, MESSAGE) Si le module appelant na pas positionn CATEGORIE FATAL , affiche MESSAGE sur STDERR. Si le module appelant a positionn CATEGORIE FATAL , affiche MESSAGE sur STDERR, puis meurt. Si CATEGORIE nest pas fournie, le nom du paquetage courant est utilis.

customer_8566

Modules standards

32

Ldition prcdente de ce livre couvrait de manire trs complte et dfinitive tous les modules faisant partie de la distribution standard de Perl. Si nous avions refait la mme chose ici, vous auriez payez de livre le double, sans parler de ce que vous auriez d payer au chiropracteur aprs avoir essay de porter le livre jusqu chez vous. Ces dernires annes, de plus en plus de modules ont t inclus dans la distribution standard ; nous en sommes ce jour environ deux cents. Certains dentre eux, comme CGI, proposent eux-mmes une documentation remarquablement approfondie. Et si vous utilisez la distribution de Perl ActiveState, votre bibliothque standard est encore plus raffine. Ainsi, nous vous offrons la place une numration complte des modules standards, classs par type, accompagns dune brve description. Puis, cerise sur le gteau, nous avons slectionn quelques uns de nos modules favoris, vous en donnant des exemples dutilisation classique, suivis dune courte description de leur fonctionnement, juste pour que vous y gotiez un peu. Les descriptions sont suggestives plutt que compltes et quasiment tous les modules ont dautres fonctionnalits que celles que nous montrons. Toutefois, une documentation complte de tous les modules standards est incluse dans chaque distribution de Perl, vous navez donc qu rechercher les dtails sur votre propre systme en utilisant le programme perldoc, la commande man(1) de votre systme ou votre navigateur prfr. Voir la section Documentation en ligne de la prface. Demandez votre expert maison si vous ne trouvez pas les documents, car ils sont quasi certainement quelque part sur votre systme. Et mme si ils ny sont pas, vous pouvez toujours les lire au format pod directement dans les modules eux-mmes car toute la documentation des modules est insre dans le fichier de module (.pm) lui correspondant et le format pod a t conu pour tre assez lisible. (Pas comme, disons, HTML.)

Listes par type


Le nom des modules ordinaires commence par une majuscule. Des noms en minuscules indiquent des pragmas dont vous trouverez la documentation au chapitre 31, Modules de pragmas, plutt que dans le prsent chapitre.

customer_8566

820

Chapitre 32 Modules standards

Types de donnes
Ces modules tendent le systme de typage de Perl (ou plutt ses lacunes) de diverses manires.
Module Class::Struct constant integer Math::BigFloat Math::BigInt Mah::Complex Math::Trig overload Symbol Time:Local Description Cre des classes dobjets Perl ressemblant struct . Dclare des scalaires et des listes constantes. Force Perl faire de larithmtique avec des entiers au lieu de nombres virgule f lottante. Calcule avec des nombres virgule f lottante dune longueur arbitraire. Calcule avec des entiers de longueur arbitraire. Calcule avec des nombres complexes et les fonctions mathmatiques associes. Charge beaucoup de fonctions trigonomtriques. Surcharge les oprateurs Perl sur des objets. Manipule les tables de symboles de Perl et gnre des typeglobs anonymes. Calcule efficacement la date et lheure origine selon locatime ou gmtime.

Traitement des chanes, traitement de textes linguistiques, analyse et recherche


Ces modules agissent avec (ou sur) des textes.
Module Search::Dict Text::Abbrev Text::ParseWords Text::Soundex Text::Tabs Text::Wrap Description Effectue une recherche binaire dune chane dans un fichier texte tri. Cre une table dabbrviation partir dune liste. Analyse du texte dans une liste de tokens ou dans un tableau de tableaux. Utilise lalgorithme Soundex de Knuth. Dveloppe ou rduit les tabulations comme expand(1) ou unexpand(1). quilibre des lignes pour former des paragraphes simples.

customer_8566

Listes par type

821

Traitement des options, arguments, paramtres et fichiers de configurations


Ces modules traitent votre ligne de commande.
Module Getopt::Long Getopt::Std Description Traite des options tendues de la ligne de commande dans une forme longue (-xyz). Traite des options dun seul caractre avec regroupement doptions.

Noms de fichier, systmes de fichiers et verrouillage de fichiers


Ces modules fournissent des mthodes daccs aux fichiers sur plusieurs plates-formes.
Module Cwd File::Basename File::CheckTree File::Compare File::Copy File::DosGlob File::Find File::Glob File::Path File::Spec File::Spec::Functions File::Spec::Mac File::Spec::OS2 File::Spec::Unix File::Spec::VMS File::Spec::Win32 File::stat Description Obtient le chemin du rpertoire de travail courant. Dcompose de manire portable le nom dun chemin en ses composants : rpertoire, nom de base et extension. Lance plusieurs tests de fichiers sur un ensemble darborescences de rpertoires. Compare de manire portable les contenus de fichiers ou de handles de fichiers. Copie de manire portable des fichiers ou des handles de fichiers ou dplace des fichiers. Ralise des globs dans le style Microsoft. Parcourt une arborescence de fichiers comme find(1). Utilise des globs dans le style Unix. Cre ou supprime de manire portable une srie de rpertoires. Utilise des oprations portables sur les fichiers (interface oriente objet). Utilise des oprations portables sur les fichiers (interface fonctionnelle). Utilise des oprations sur les fichiers pour Mac OS. Utilise des oprations sur les fichiers pour OS/2. Utilise des oprations sur les fichiers pour Unix. Utilise des oprations sur les fichiers pour VMS. Utilise des oprations sur les fichiers pour Microsoft. Supplante les fonctions stat et lstat avec une interface utilisant des mthodes.

customer_8566

822

Chapitre 32 Modules standards

Utilitaires pour les handles de fichiers, les handles de rpertoires et les flux dentres/sorties
Ces modules fournissent un accs orient objet aux fichiers, aux rpertoires et aux IPC.
Module DirHandle FileCache FileHandle IO IO::Dir IO::File IO::Handle IO::Pipe IO::Poll IO::Seekable IO::Select SelectSaver Description Utilise des mthodes objets pour les handles de rpertoires. Garde plus de fichiers ouverts simultanment en criture que votre systme ne le permet. Utilise des mthodes objets pour les handles de fichiers. Fournit un frontal pour charger tous les modules IO::Dir, IO::File, IO::Handle, IO::Pipe, IO::Seekable et IO::Socket. Utilise des mthodes objets pour les handles de rpertoires. Utilise des mthodes objets en rapport avec les fichiers pour les handles de fichiers. Utilise des mthodes objets gnriques pour les handles de fichiers/ Utilise des mthodes objets pour les pipes. Fournit une interface oriente objet lappel systme poll(2). Utilise des mthodes objets pour les objets dentres/sorties dans lesquels on peut faire des recherches (avec seek). Utilise une interface oriente objet facilitant lappel systme select(2). Sauvegarde et restaure les handles de fichiers slectionns.

Internationalisation et locales
Ces modules vous aident dans vos activits extra-amricaines.
Module bytes charnames I18N::Collate locale utf8 Description Force lancienne smantique oriente octets. Dfinit les noms de caractres utiliss dans les squences dchappements \N{nom} pour les chanes littrales. Compare des donnes scalaires de 8 bits selon la locale courante (dprci). Utilise ou vite les locales POSIX pour les oprations internes. Bascule explicitement sur le support UTF-8 et Unicode.

customer_8566

Listes par type

823

Interfaces au systme dexploitation


Ces modules ajustent votre interface au systme dexploitation.
Module Fcntl filetest open POSIX Shell sigtrap Sys::Hostname Sys::Syslog Time::gmtime Time::localtime Time::tm User::grent User::pwent Description Charge les dfinitions de fcntl.h de la bibliothque C en tant que constantes Perl. Contrle les oprateurs de tests de fichiers (-r, -w, etc.) pour les systmes non-traditionnels. Positionne les disciplines par dfaut pour les appels la fonction open. Utilise linterface Perl POSIX 1003.1. Lance des commandes shells de manire transparente lintrieur de Perl. Active une gestion simple des signaux. Essaye de manire portable tous les moyens imaginables pour dterminer le nom de lhte courant. Utilise les fonctions syslog(3) de la bibliothque C. Supplante la fonction interne gmtime par une interface mthodes. Supplante la fonction interne localtime par une interface mthodes. Fournit lobjet interne Time::localtime. utilis par Time::gmtime et

Supplante les fonctions internes getgr* par une interface mthodes. Supplante les fonctions internes getpw* par une interface mthodes.

Communication rseau et interprocessus


Ces modules fournissent des interfaces abstraites ct des interfaces basiques que nous avons dcrites au chapitre 16, Communication interprocessus.
Module IO::Socket IO::Socket::INET IO::Socket::UNIX IPC::Msg Description Utilise une interface oriente objet gnrique pour les communications sur des sockets. Utilise une interface oriente objet pour les sockets du domaine Internet. Utilise une interface oriente objet pour les sockets du domaine Unix (locales). Utilise des mthodes objets pour travailler avec les messages System V (classe objet SysV Msg IPC).

customer_8566

824
Module IPC::Open2 IPC::Open3 IPC::Semaphore IPC::SysV Net::hostent Net::netent Net::Ping Net::protoent Net::servent Socket Description

Chapitre 32 Modules standards

Ouvre un processus en lecture et criture simultanes. Ouvre un processus pour lire, crire et grer les erreurs. Utilise des mthodes objets pour les smaphores System V. Dfinit des constantes pour tous les mcanismes des IPC System V. Supplante les fonctions internes gethost* par une interface mthodes. Supplante les fonctions internes getnet* par une interface mthodes. Vrifie si un hte distant est joignable. Supplante les fonctions internes getproto* par une interface mthodes. Supplante les fonctions internes getserv* par une interface mthodes. Charge les dfinitions et les fonctions manipulant des structures de socket.h de la bibliothque C.

World Wide Web


Ces modules interfacent le WWW. Vous devez en avoir entendu parler.
Module CGI CGI::Apache CGI::Carp CGI::Cookie CGI::Fast CGI::Pretty CGI::Push Description Accde aux formulaires CGI et la gnration performante et automatique de HTML. Fait fonctionner vos scripts CGI sous lAPI Perl-Apache. crit dans le journal derreurs CGI de httpd(8) (ou dautres). Lit et crit des cookies HTTP. Utilise le protocol Fast CGI. Produit du code HTML agrablement format. Ralise des scripts CGI server-push (N.d.T. : sollicits par le serveur).

Interfaces DBM
Ces modules chargent diverses bibliothques de gestion de bases de donne.
Module AnyDBM_File DB_File Description Fournit une infrastructure pour de multiples bibliothques DBM. Fournit un accs li avec tie la bibliothque db(3) (Berkeley DB, version 1.x).

customer_8566

Listes par type


Module GDBM_File NDBM_File SDBM_File Description Fournit un accs li avec tie la bibliothque gdbm(3). Fournit un accs li avec tie la bibliothque ndbm(3).

825

Fournit un accs li avec tie aux fichiers sdbm(3) (simple DBM).

Interfaces utilisateurs
Ces modules fournissent une API dcente pour les entres/sorties de linterface en ligne de commande.
Module Term::Cap Term::Complete Term::Readline Description Utilise la bibliothque termcap(3). Ralise une compltion programmable par des commandes sur des listes de mots. Utilise lun des nombreux paquetages readline.

Authentification, scurit et encryptage


Ces modules fonctionnent avec les espaces mmoires protgs dans lesquels sexcutent les programmes.
Module Opcode Description Active ou dsactive les lors codes doprations (opcodes) de la compilation de code Perl en vue dune utilisation avec le module Safe. Restreint les oprations non-sres lors de la compilation. Compile et excute du code dans des compartiments restreints.

ops Safe

Langage Perl, extensions et mcanismes internes


( ne pas confondre avec les intentions et les mcanismes externes.)
Module attributes attrs base Data::Dumper DB Devel::DProf Description Consulte ou positionne les attributs dun sous-programme ou dune variable. Consulte ou positionne les attributs dun sous-programme ou dune variable (obsolte). tablit lhritage des classes de base la compilation. Srialise des structures de donnes Perl. Accde lAPI exprimentale du dbogueur Perl. Profile lexcution dun programme Perl.

customer_8566

826
Module Devel::Peek diagnostics Dumpvalue English Env Errno Fatal fields less re strict subs vars Description

Chapitre 32 Modules standards

Charge des outils de dbogage de donnes pour les programmeurs XS. Force des avertissements verbeux et limine les duplications. Affiche lcran des valeurs de donnes. Utilise des noms de variables plus longs pour les variables internes avec une ponctuation. Accde aux variables denvironnement dans %ENV en tant que scalaires ordinaires. Charge les dfinitions de errno.h de la bibliothque C et lie la variable %! avec tie. Remplace les fonctions internes avec des versions levant des exceptions lors dun chec. Lors de la compilation dclare les donnes attributs dune classe et vrifie les accs ces donnes. Demande moins de quelque chose de la part de Perl (nonimplment). Altre le comportement par dfaut des expressions rgulires. Restreint les constructions bcles. Prdclare les noms de sous-programmes dans le paquetage courant. Prdclare des variables globales (obsolte voir our au chapitre 29.

Classes commodes
Ces modules fournissent des classes de base et dautres facilits.
Module Tie::Array Tie::Handle Tie::Hash Tie::RefHash Tie::Scalar Tie::SubstrHash UNIVERSAL Description Fournit une classe de base pour les tableaux lis avec tie. Fournit une classe de base pour les handles lis avec tie. Fournit une classe de base pour les hachages lis avec tie. Fournit des rfrences comme clefs de hachage. Fournit une classe de base pour les scalaires lis avec tie. Fournit une interface similaire aux hachages pour une table de taille fixe avec des clefs de longueur fixe. Fournit une classe de base pour toutes les classes (rfrences consacres).

customer_8566

Listes par type

827

Avertissements et exceptions
Que faire lorsque les choses se passent mal.
Module Carp warnings Description Fournit des routines qui font des warn et des die avec la perspective de lappelant. Contrle les avertissements lintrieur de la porte lexicale.

Support de documentation
Il existe une quantit de documentation supporter.
Module Pod::Checker Pod::Functions Pod::Html Pod::InputObjects Pod::Man Pod::Parser Pod::Select Pod::Text Pod::Text::Color Pod::Text::Termcap Pod::Usage Description Vrifie les erreurs de syntaxes des documents pod (utilis par podchecker(1)) . Liste les fonctions internes par type. Convertit les fichiers pod en HTML (utilis par pod2html(1)). Gre le support de documentation. Convertit du pod en format troff(1) pour le systme man(1) (utilis par pod2man(1)). Fournit une classe de base pour crer des filtres et des traducteurs de pod. Extrait des sections de pod depuis lentre (utilis par podselect(1)). Convertit des donnes pod en texte format en ASCII (utilis par pod2text(1)). Convertit des donnes pod en texte format en ASCII avec les squences dchapement ANSI pour les couleurs. Convertit des donnes pod en texte ASCII avec les squences dchappement spcifiques du terminal. Affiche un message dutilisation driv de la documentation pod incluse dans le source.

Support dinstallation de module


Ces modules aident dautres modules sauter travers diffrents cerceaux.
Module AutoLoader AutoSplit autouse Description Charge des sous-programmes la demande. clate un paquetage pour lautochargement. Diffre le chargement dun module jusqu ce quune fonction de ce module soit utilise.

customer_8566

828
Module blib Config CPAN Devel::SelfStubber DynaLoader Exporter ExtUtils::Command ExtUtils::Embed ExtUtils::Install ExtUtils::Installed ExtUtils::Liblist ExtUtils::MakeMaker ExtUtils::Manifest ExtUtils::Miniperl ExtUtils::Mkbootstrap ExtUtils::Mksymlists ExtUtils::MM_Cygwin ExtUtils::MM_OS2 ExtUtils::MM_Unix ExtUtils::MM_VMS ExtUtils::MM_Win32 ExtUtils::Packlist ExtUtils::testlib FindBin lib SelfLoader Description

Chapitre 32 Modules standards

Utilise la bibliothque depuis la version non-installe dune extension par Makemaker. Accde aux informations de configuration de Perl. Interroge, rapatrie et construit des modules Perl depuis des sites CPAN. Gnre des souches (N.d.T. : stubs) pour un module en utilisant le module SelfLoader. Charge dynamiquement des bibliothques C ou C++ en tant quextensions Perl. Implmente une mthode dimportation par dfaut pour les modules traditionnels. Fournit des utilitaires pour remplacer les commandes externes populaires dans un Makefile. Fournit des utilitaires pour inclure du Perl dans des programmes C ou C++. Installe des fichiers dans la bibliothque Perl du systme. Gre linventaire des modules installe. Dtermine quelles bibliothques utiliser et comment les utiliser. Cre un Makefile pour une extension Perl. Charge des outils pour crire et vrifier un fichier MANIFEST. crit du code C pour perlmain.c. Crer un fichier damorage (bootstrap) pour tre utilis par DynaLoader. crit des fichiers doptions de lditeur de liens pour les extensions dynamiques. Supplante lesmthodes se comportant la manire dUnix dans ExtUtils::MakeMaker. Supplanteles mthodes se comportant la manire dUnix dans ExtUtils::MakeMaker. Fournit des mthodes utilises par ExtUtils::MakeMaker. Supplante les mthodes se comportant la manire dUnix dans ExtUtils::MakeMaker. Supplante les mthodes se comportant la manire dUnix dans ExtUtils::MakeMaker. Gre les fichiers .packlist. Ajoute des rpertoires blib/* @INC. Localise le rpertoire dinstallation pour le programme Perl en train de tourner. Manipule @INC lors de la compilation. Charge des fonctions uniquement la demande.

customer_8566

Listes par type


Module XSLoader Description

829

Charge dynamiquement des bibliothques C ou C++ en tant quextensions Perl.

Support de dveloppement
Ces modules soccupent des mesures de temps et des tests, pour voir dans quelles proportions votre code ne tourne ni plus rapidement, ni plus proprement.
Module Benchmark Test Test::Harness Description Compare les temps dexcution de diffrentes versions de code. Utilise une infrastructure simple pour crire des scripts de test. Lance des scripts de test standards avec des statistiques.

Compilateur Perl et gnrateur de code


Ces modules supportent des gnrateurs de code vers des sorties (N.d.T. : backends) diverses et varies pour Perl.
Module B B::Asmdata B::Assembler B::Bblock B::Bytecode B::C B::CC B::Debug B::Deparse B::Disassembler B::Lint B::Showlex B::Stash B::Terse B::Xref Description Charge des gnrateurs de code Perl (alias le compilateur Perl ). Fournit une donne autognre sur les oprations atomiques Perl pour produire du bytecode. Assemble du bytecode Perl. Parcours les blocs basiques dans larbre syntaxique. Utilise la sortie en bytecode du compilateur Perl. Utilise la sortie de traduction en C du compilateur Perl. Utilise la sortie traduction optimise en C du compilateur Perl. Parcours larbre syntaxique Perl en affichant les infos de dbogage propos des oprations atomiques. Utilise la sortie du compilateur Perl pour reproduire du code Perl. Dsassemble du bytecode Perl. Dcle les constructions doteuses. Montre les variables lexicales utilises dans des fonctions ou des fichiers. Montre quelles tables de symboles sont charges. Parcours larbre syntaxique Perl en affichant des infos laconiques propos des oprations atomiques. Gnre des rapports avec des rfrences croises pour les programmes Perl.

customer_8566

830
Module ByteLoader O Description

Chapitre 32 Modules standards

Charge du code Perl compil en bytecode. Fournit une interface gnrique aux sorties (backends) du compilateur Perl.

Modules relatifs Microsoft


Si vous possdez la distribution Perl pour les systmes Microsoft provenant dActiveState, les modules suivants, qui sont uniquement pour Microsoft, sont dores et dj inclus pour vous. Si vous avez juste t chercher les sources de la distribution standard (en voulant peut-tre la compiler avec lmulateur denvironnement Unix de Cygwin) mais que vous tournez sur Wintel, vous pouvez obtenir tous ces modules depuis CPAN.
Module Win32::ChangeNotify Win32::Console Win32::Event Win32::EventLog Win32::File Win32::FileSecurity Win32::IPC Win32::Internet Win32::Mutex Win32::NetAdmin Win32::NetResource Win32::ODBC Win32::OLE Win32::OLE::Const Win32::OLE::Enum Win32::OLE::NLS Win32::OLE::Variant Win32::PerfLib Win32::Process Win32::Semaphore Win32::Service Win32::Sound Win32::TieRegistry Description Surveille les vnements relatifs aux fichiers et aux rpertoires. Utilise la console Win32 et les fonctions du mode caractre. Utilise les objets vnemetns Win32 depuis Perl. Traite les journaux dvnements Win32 depuis Perl. Gre les attributs de fichier en Perl. Gre les FileSecurity Discretion Access Control Lists (Listes de contrle daccs discret aux fichiers scuriss) en Perl. Charge la classe de base pour les objets de synchronisation Win32. Accde aux fonctions de WININET.DLL. Utilise les objets mutex Win32 en Perl. Gre les groupes et utilisateurs rseaux en Perl. Gre les ressources rseaux en Perl. Utilise les extensions ODBC pour Win32. Utilise les extensions dautomatisation OLE. Extrait les dfinitions de constantes depuis TypeLib. Utilise OLE Automation Collection Objects (objets collections dautomatisation OLE). Utilise OLE National Langage Support (support de langages nationaux OLE). Cre et modifie les variables OLE VARIANT. Accde au compteur de performance de Windows NT. Cre et manipule des processus. Utilise les objets smaphores Win32. Gre les services du systme. Joue avec les sons Windows. Trifouille la base de registres.

customer_8566

Benchmark
Module Win32API::File Win32API::Net Win32API::Registry Description

831

Accde aux appels bas niveau de lAPI systme Win32 pour les fichiers et les rpertoires. Gre les comptes LanManager de Windows NT. Accde aux appels bas niveau de lAPI systme Win32 depuis WINREG.H.

Benchmark
use Benchmark qw(timethese cmpthese timeit countit timestr); # Vous pouvez toujours passer du code sous forme de chanes : timethese $compteur, { Nom1 => ...code1..., Nom2 => ...code2..., }; # Ou sous forme de rfrences des sous-programmes : timethese $compteur, { Nom1 => sub { ...code1... }, Nom2 => sub { ...code2... }, }; cmpthese $compteur, { Nom1 => ...code1..., Nom2 => ...code2..., }; $t = timeit $compteur, code; print "$compteur boucles de code ont pris : ", timestr($t), "\n"; $t = countit $temps, code; $compteur = $t->iters; print "$compteur boucles de code ont pris : ", timestr($t), "\n";

Le module Benchmark peut vous aider dterminer lequel parmi plusieurs choix possibles sexcute le plus rapidement. La fonction timethese lance les segments de codes spcifis le nombre de fois demand et rapporte combien de temps a pris chaque segment. Vous pouvez obtenir un joli diagramme tri si vous appelez cmpthese de la mme faon. Les segments de codes peuvent tre passs sous forme de rfrences de fonctions au lieu de chanes (en fait, il faut que ce soit des rfrences de fonctions si vous utiliser des variables lexicales provenant de la porte de lappelant), mais la surcharge engendre par lappel peut inf luencer les mesures de temps. Si vous ne demandez pas assez ditrations pour avoir une bonne mesure, la fonctions met un avertissement. Des interfaces de bas niveau sont disponibles pour lancer un seul morceau de code soit un certain nombre de fois (timeit), soit un certain nombre de secondes (countit). Ces

customer_8566

832

Chapitre 32 Modules standards

fonctions renvoient des objets Benchmark (voir une description dans la documentation en ligne). Avec countit, vous savez que cela a tourn pendant assez longtemps pour viter les avertissements, car vous aviez spcifi un temps dexcution minimum. Pour tirer le meilleur profit du module Benchmark, vous aurez besoin dun peu dentranement. En gnral, il nest pas suffisant de lancer deux ou trois algorithmes sur le mme jeu de donnes, car les mesures de temps ne ref ltent que la manire dont ces algorithmes se sont bien comport sur ce jeu de donnes prcis. Pour obtenir une meilleure impression sur le cas gnral, vous aurez besoin de lancer plusieurs ensembles de benchmarks en faisant varier les jeux de donnes utiliss. Par exemple, imaginez que vous vouliez savoir le meilleur moyen dobtenir la copie dune chane sans ses deux derniers caractres. Vous pensez quatre faons de faire cela (il y en a dautres bien sr) : chop deux fois, copier et substituer, ou utiliser substr soit sur la partie gauche, soit sur la partie droite dun assignement. Vous testez ces algorithmes sur des chanes de longueur 2, 200 et 20_000 :
use Benchmark qw/countit cmpthese/; sub lancer($) { countit(5, @_) } for $taille (2, 200, 20_000) { $c = "." x $taille; print "\nTAILLE_DONNEES = $taille\n"; cmpthese { chop2 => lancer q{ $t = $c; chop $t; chop $t; }, subs => lancer q{ ($t = $c) =~ s/..\Z//s; }, substr_g => lancer q{ $t = $c; substr($t, -2) = "; }, substr_d => lancer q{ $t = substr($c, 0, length($c) -2); }, }; }

ce qui affiche :
TAILLE_DONNEES = 2 Rate substr_g substr_g 579109/s -subs 593574/s 2% chop2 903371/s 56% substr_d 920343/s 59% TAILLE_DONNEES = 200 Rate subs 561402/s substr_g 574852/s substr_d 610907/s chop2 737478/s subs -2% -52% 55% chop2 substr_d -36% -37% -34% -36% --2% 2% --

subs substr_g substr_d --2% -8% 2% --6% 9% 6% -31% 28% 20%

chop2 -24% -22% -17% --

customer_8566

Carp
TAILLE_DONNEES = 20000 Rate substr_d substr_d 35885/s -subs 65113/s 81% substr_g 65472/s 82% chop2 66837/s 86%

833

subs substr_g -45% -45% --1% 1% -3% 2%

chop2 -46% -3% -2% --

Avec de petits jeux de donnes, lalgorithme substr_d tourne 2% plus rapidement que lalgorithme chop2 , mais sur de grands jeux de donnes, il tourne 46% plus lentement. Sur des jeux de donnes vides (aucun de montr ici), le mcanisme de substitution est le plus rapide. Il ny a donc pas de solution meilleure que les autres dans tous les cas possibles et mme ces mesures ne racontent pas toute lhistoire, puisque vous tes toujours la merci de votre systme dexploitation et de la bibliothque C avec laquelle Perl a t compil. Ce qui est bon pour vous peut devenir mauvais pour quelquun dautre. Cela prend un certain temps pour tre adroit avec les benchmarks. Entretemps, cela facilite les choses dtre un bon menteur.

Carp
use Carp; croak "Nous en sommes l !"; use Carp qw(:DEFAULT cluck); cluck "Voil comment nous sommes arrivs l !";

Le module Carp vous permet dcrire des modules dont les fonctions rapportent les erreurs de la mme faon que les oprateurs internes du point de vue de lutilisateur du module. Le module Carp fournit des routines que vous utilisez pratiquement comme les fonctions internes standard warn et die, mais qui changent le nom de fichier et le numro de ligne de faon ce que lerreur ait lair de provenir du code utilisateur plutt que de votre code. En bref, Carp est un moyen formidable de renvoyer la faute sur quelquun dautre que soi. Il existe en fait quatre fonctions. La fonction carp marche comme loprateur warn mais avec les informations sur le nom de fichier et le numro de ligne relatives lappelant. La fonction croak marche comme die en levant une exception mais en donnant l encore des informations relatives lappelant. Si vous prfrez une longue complainte, utilisez cluck et confess au lieu de carp et croak respectivement, et vous obtiendrez une trace complte de la pile rapportant qui a appel qui et arm de quels arguments (sans aucun dote le colonel Moutarde, dans la bibliothque avec une clef anglaise). Vous devez importer cluck explicitement car il nest pas export normalement. Les gens ne veulent pas en gnral des traces compltes de la pile pour de simples avertissements, pour une raison ou pour une autre.

CGI
use CGI qw(:standard); $qui = param("Nom");

customer_8566

834
$tel = param("Telephone"); @choix = param("Choix");

Chapitre 32 Modules standards

Le module CGI vous aide grer des formulaires HTML, spcialement les formulaires en plusieurs tapes o il est critique de passer dune tape une autre. Lexemple extrmement simple ci-dessus sattend traiter un formulaire avec deux paramtres prenant des valeurs scalaires, comme des champs de texte ou des boutons radios et un autre prenant une valeur multiple, comme des listes droulantes spcifies avec MULTIPLE . Le module est encore plus sympathique que cela plusieurs niveaux, en supportant des fonctionnalits comme le traitement des cookies, les valeurs persistantes pour les caddies multicrans et la gnration automatique de listes HTML et de tables que vous pouvez extraire dune base de donnes pour nen citer que quelques unes. Le support de lexcution grande vitesse de scripts Perl prcompils via les services de mod_perl dApache est galement fourni. Le livre de chez OReilly & Associates Writing Apache Modules with Perl and C, de Lincoln Stein et Doug MacEachern, vous dira tout sur ce sujet.

CGI::Carp
use CGI::Carp; warn "Celle-ci est une complainte"; die "Mais celle-l est srieuse"; # # # # Estampille avec le nom du programme et la date Mais ne cause pas derreur serveur 500

use CGI::Carp qw(carpout); # Importe cette fonction open(LOG, "> >/var/tmp/mon_cgi-log" or die "Impossible dajouter mon_cgi-log : $!\n"; carpout(*LOG); # Utilise maintenant le journal # derreurs spcifique au programme use CGI::Carp qw(fatalsToBrowser); die "Les messages derreurs fatales sont maintenant envoys aussi au navigateur";

Le module CGI::Carp fournit des versions des fonctions internes Perl warn et die, plus les fonctions carp, cluck, confess et croak du module Carp qui sont plus parlantes et plus sres galement. Elles sont plus parlantes car chaque message inclut la date et lheure avec le nom du programme qui a mis les messages, ce qui est une aide prcieuse lorsque vous utilisez un fichier journal partag par une centaine de programmes diffrents qui le polluent tous en mme temps avec un millier de messages diffrents. Le module est galement agrable pour les surfeurs du Web, puisque la mort prmature dun script CGI a tendance causer des erreurs absconses Server 500 lorsque len-tte HTTP correcte ne part pas du serveur avant que votre programme ne trpasse, et ce module sassure que cela ne se produit pas. La fonction carpout redirige tous les avertissements et toutes les erreurs vers le handle de fichier spcifi. La directive fatalsToBrowser envoie galement une copie de tels messages au navigateur de lutilisateur. Ces services facilitent le dbogage des problmes dans les scripts CGI.

customer_8566

Class::Struct

835

Class::Struct
use Class::Struct; struct Chef => { nom => $, salaire => $, debut => $, }; struct Boutique => { proprio => $, adrs => @, stock => %, patron => Chef }; $magasin = Boutique->new(); $magasin->proprio(Abdul Alhazred); $magasin->adrs(0, Miskatonic University); $magasin->adrs(1, Innsmouth, Mass.); $magasin->stock("livres", 208); $magasin->stock("charmes", 3); $magasin->stock("potions", "aucune"); $magasin->patron->nom(Dr. L. P. Hache); $magasin->patron->salaire(folie); $magasin->patron->debut(scalar localtime); # # # # # # Cre un constructeur Boutique->new(). La mthode proprio() accde maintenant un scalaire. Et la mthode adresse() accde un tableau. Et la mthode stock() accde un hachage. Initialise avec Chef->new(). # # # # # Cre un constructeur Chef->new(). La mthode nom() accde maintenant une valeur scalaire. Ainsi que salaire(). Ainsi que debut().

Le module Class:Struct fournit un moyen de dclarer une classe ayant des objets dont les champs sont dun certain type. La fonction qui fait cela est appele struct. Comme les structures denregistrements ne sont pas des types de base en Perl, chaque fois que vous dsirez crer une classe pour fournir un objet ressemblant une donne denregistrement, vous devez dfinir une mthode constructeur ainsi que des mthodes accesseurs pour chaque donne de champ, quelquefois appeles mthodes wrapper . La fonction struct du module Class::Struct vous soulage de cette tche en crant une classe la vole. Vous navez qu lui communiquer quelles doivent tre les donnes membres, ainsi que leur type. La fonction cre une mthode constructeur appele new dans le paquetage spcifi par le premier argument, plus une mthode accesseur dattribut pour chaque membre, comme spcifi par le second argument, qui doit tre une rfrence de hachage. Les types de champ sont spcifis, soit en tant que types internes en utilisant les symboles habituels $ , @ , % et & , soit en tant quune autre classe en employant le nom de la classe. Le type de chaque champ sera forc lorsque vous essayerez de modifier la valeur. Beaucoup de modules standards utilisent Class:Struct pour crer leur objets et accesseurs, y compris Net::hostent et User::pwent, dont vous pouvez regardez les sources et vous en servir comme modles. Voir galement les modules CPAN Tie::SecureHash et

customer_8566

836

Chapitre 32 Modules standards

Class::Multimethods pour des approches plus labores de lautognration de classes et de mthodes accesseurs. Voir la section Gestion des donnes dinstance au chapitre 12, Objets.

Config
use Config; if ($Config{cc} =~ /gcc/) { print "Ce perl a t compil avec GNU C.\n"; } use Config qw(myconfig config_sh config_vars); print myconfig(); # comme perl -V sans aucun motif print config_sh(); # donne absolument tout config_vars qw/osname osvers archname/;

Le mcanisme de configuration utilis pour compiler et installer Perl rassemble une profusion dinformations sur votre systme. Le module Config exporte par dfaut une variable de hachage lie avec tie, nomme %Config, qui donne accs environ 900 valeurs de configuration diffrentes. (Ces valeurs sont galement accessibles travers loption -V:MOTIF de la ligne de commande de Perl.) Config fournit galement trois fonctions qui donnent un accs ces valeurs dans le style du shell, comme montr cidessus. Par exemple, le dernier appel pourrait afficher :
osname=linux; osvers=2.4.2; archname=i386-linux;

La documentation en ligne du module dcrit les variables de configuration et leurs valeurs possibles. Prenez garde si vous dplacez votre excutable perl vers un systme autre que celui sur lequel il a t compil, ces valeurs peuvent ne pas ref lter la ralit actuelle ; par exemple, si vous faites tourner un binaire Linux ou Solaris sur un systme BSD.

CPAN
# Obtient un shell CPAN interactif. %perl -MCPAN -e shell # Senquiert juste des recommandations de mise niveau. % perl -MCPAN -e CPAN::Shell->r # Installe le module indiqu en mode batch. % perl -MCPAN -e "install Class::Multimethods"

Le module CPAN est une interface automatise et conviviale au Comprehensive Perl Archive Network, dcrit au chapitre 22, CPAN. Au contraire de la plupart des modules que vous pouvez rencontrer, il est destin tre invoqu depuis la ligne de commande, exactement comme un petit programme. La premire fois que vous lappelez, le module vous demande le site miroir CPAN par dfaut et dautres renseignements dont il a besoin. Aprs cela, vous pouvez lancer son shell interactif pour faire des requtes et slec-

customer_8566

Cwd

837

tionner des modules installer, demander au module des recommandations sur les modules devant tre remis niveau ou simplement lui faire installer un module particulier.

Cwd
use Cwd; $rep = getcwd(); use Cwd chdir; chdir "/tmp"; # O suis-je ?

# Met jour $ENV{PWD}.

use Cwd realpath; print realpath("/usr////spool//mqueue/../");

# affiche /var/spool

Le module Cwd fournit des fonctions indpendantes de la plate-forme pour dterminer le rpertoire de travail courant de votre processus. Cest mieux que de lancer un shell excutant pwd(1) car les systmes non-conformes POSIX ne garantissent pas quils connaissent une telle commande et Perl ne se limite pas uniquement tourner sur les plates-formes POSIX. La fonction getcwd, laquelle est exporte par dfaut, renvoie le rpertoire de travail courant en utilisant le mcanisme rput pour tre le plus sr sur la plate-forme courante. Si vous importez la fonction chdir, elle supplante loprateur interne avec celui du module, lequel met jour la variable denvironnement $ENV{PWD} ; les commandes que vous pourriez lancer ensuite et qui tiendraient compte de cette variable auraient alors une vision cohrente de leur univers. La fonction realpath rsout dans son argument reprsentant un nom de chemin tous les liens symboliques et tous les composants de chemin relatif afin de renvoyer un chemin complet de rpertoire sous une forme canonique, exactement comme realpath(3).

Data::Dumper
use Data::Dumper; print Dumper($magasin);

Lorsquon lutilise sur lexemple tir de la dfinition de Class::Struct, ceci affiche :


$VAR1 = bless( { Boutique::patron => bless( { Chef::salaire => folie, Chef::nom => Dr. L. P. Hache, Chef::debut => Fri Apr 13 19:33:04 2001 }, Chef ), Boutique::stock => { livres => 208, charmes => 3, potions => aucune },

customer_8566

838

Chapitre 32 Modules standards


Boutique::proprio => Abdul Alhazred, Boutique::adrs => [ Miskatonic University, Innsmouth, Mass. ] }, Boutique );

La fonction Dumper du module Data::Dumper prend une liste de scalaires (incluant des rfrences, qui peuvent mme se rfrer des objets) et renvoie une chane affichable ou evaluable qui reproduit prcisment une copie fidle de loriginal. Vous pouvez utiliser ceci pour crire une version de sauvegarde dune structure de donne dans un fichier ordinaire sur disque ou dans un fichier DBM, ou encore la passer un autre processus via un pipe ou une connexion socket. Ce module peut tre utilis avec les modules MLDBM de CPAN et DB_File pour implmenter un fichier DBM mme de stocker de manire transparente des valeurs de donnes complexes, et non seulement des chanes plat. Dautres module de transformation en chanes (stringification) (ou srialisation, ou formatage de prsentation, marshalling) incluent Storable et FreezeThaw, tous deux disponibles depuis CPAN.

DB_File
use DB_File;

Lie avec tie un hachage un fichier dans le style de DBM :


tie(%hachage, "DB_File", $fichier) # Ouvre une base de donnes. or die "Impossible douvrir $fichier : $!"; $v = $hachage{"clef"}; $hachage{"clef"} = "valeur"; untie %hachage; # Extrait depuis la base de donnes. # Positionne une valeur dans la base.

Lie avec tie un hachage un fichier B-tree (arbre balanc ou quilibr), mais continue dy accder en tant que hachage DBM ordinaire :
tie(%hachage, "DB_File", "mon_arbre", O_RDWR|O_CREAT, 0666, $DB_BTREE) or die "Impossible douvrir le fichier mon_arbre : $!"; while (($c, $v) = each %hachage) { print "$c => $v\n"; } # Parcourt dans lordre

Lie avec tie un tableau un fichier texte brut :


tie(@lignes, "DB_File", $fic_texte, O_RDWR|O_CREAT, 0666, $DB_NUM_ENREG) or die "Impossible douvrir le fichier texte $fic_texte : $!"; # crit quelques lignes dans le fichier, en crasant les anciennes. $lignes[0] = "premire ligne"; $lignes[1] = "deuxime ligne"; $lignes[2] = "troisime ligne"; push @lignes, "pnultime", "dernire"; # Met deux lignes la fin # du fichier

customer_8566

Dumpvalue
$wc = scalar @lignes; $derniere = pop @lignes;

839
# Compte le nombre de lignes # Supprime et extrait la dernire # ligne

Le module DB_File donne un accs li avec tie une DB Berkeley.1 La fonction tie vous donne par dfaut une base de donnes standard dans le style de DBM, avec certaines fonctionnalits que lon ne retrouve dans aucune bibliothque DBM : il nexiste pas de limites de taille ni pour les clefs, ni pour les valeurs et vos donnes sont stockes dans un format indpendant de lordre des octets. Le deuxime mcanisme de tie utilise des B-trees (arbres balancs ou quilibrs) pour vous donner un vritable fichier ISAM (Indexed Sequential Access Method, mthode daccs squentiel index), cest--dire un hachage dont les clefs sont automatiquement tries dans lordre alphabtique par dfaut, mais configurable par lutilisateur. Le troisime mcanisme de tie lie un tableau un fichier denregistrements (des lignes de texte par dfaut) de faon ce que les modifications dans le tableau se rpercutent automatiquement sur le disque. Ceci simule un accs alatoire par numro de ligne dans un fichier texte ordinaire. Linterface standard est conforme la version 1.x de Berkeley DB ; si vous souhaitez employer les nouvelles fonctionnalits disponibles dans Berkeley 2.x ou 3.x, utilisez plutt le module BerkeleyDB de CPAN. partir de la version 2.x, Berkeley DB supporte intrinsquement le verrouillage, ce qui ntait pas le cas dans les versions prcdentes. Voir la section Verrouillage de fichier du chapitre 16 pour un description de la manire sre dont vous pouvez verrouillez nimporte quel type de fichier de base de donnes en utilisant flock sur un fichier smaphore.

Dumpvalue
use Dumpvalue; Dumpvalue->new->dumpValue($magasin);

Lorsquon lutilise sur lexemple tir de la dfinition de Class::Struct, ceci affiche :


Boutique::adrs => ARRAY(0x816d548) 0 Miskatonic University 1 Innsmouth, Mass. Boutique::patron => Chef=HASH(0x80f1538) Chef::debut => Fri Apr 13 19:33:04 2001 Chef::nom => Dr. L. P. Hache Chef::salaire => folie Boutique::proprio => Abdul Alhazred Boutique::stock => HASH(0x81976d0) charmes => 3 livres => 208 potions => aucune

Il sagit dun autre module facilitant laffichage de donnes complexes. Il nest pas tant
1. Pourvu que vous ayez la bibliothque installe sur votre systme. Sinon, vous pouvez la compiler et linstaller assez facilement.

customer_8566

840

Chapitre 32 Modules standards

destin au formatage de prsentation (marshalling) qu un affichage agrable. Il est utilis par la commande x du dbogueur Perl. En tant que tel, il offre une quantit impressionnante doptions pour contrler le format de sortie. Il donne galement accs aux tables de symboles de paquetages de Perl pour vider le contenu dun paquetage entier.

English
use English; # Utilise des noms dans le style de awk $RS = "; # au lieu de $/ while (<>) { next id $NR < 10; # au lieu de $. ... } # Idem, mais encore plus long la Cobol $INPUT_RECORD_SEPARATOR = "; while (<>) { next if $INPUT_LINE_NUMBER < 10; ... }

Le module English fournit des alias encombrants pour les variables internes destination des prodigieux dactylos qui ont une haine viscrale des identificateurs non-alphabtiques (et un amour viscral pour la touche Blocage Majuscules, ou Caps Lock). Comme avec toutes les importations, ces alias ne sont disponibles que dans le paquetage courant. Les variables sont toujours accessibles sous leur vritable noms. Par exemple, un fois que vous avez fait un use de ce module, vous pouvez utiliser $PID si $$ vous drange ou $PROGRAM_NAME si $0 vous donne mal au cur. Certaines variables ont plus dun alias. Voir le chapitre 28, Noms spciaux pour une description complte de toutes les variables internes et de leur alias en anglais tirs du module English.

Errno
use Errno; unless (open(HF, $chemin)) { if ($!{ENOENT}) { # Nous navons pas besoin dimporter ceci ! warn "$chemin nexiste pas\n"; else { warn "chec de louverture de $chemin : $!"; } } use Errno qw(EINTR EIO :POSIX) if ($! == ENOENT) { ... }

Le module Errno rend accessibles les noms symboliques pour lensemble des valeurs de statut derreur lorsquun appel systme choue, mais il ne les exporte pas toutes par d-

customer_8566

Exporter

841

faut. Le module na quun seul tag dexportation, :POSIX , qui nexporte que les symboles dfinis dans le standard POSIX 1003.1. Le module rend galement magique la variable globale %! en utilisant tie. Vous pouvez indicer le hachage %! en employant nimporte quelle valeur valide derrno sur votre systme, pas seulement les valeurs POSIX, et sa valeur nest vraie que sil sagit de lerreur actuelle.

Exporter
Dans votre fichier Mon_Module.pm :
package Mon_Module; use strict; use Exporter; our $VERSION = 1.00; our @ISA = qw(Exporter); our @EXPORT = qw(f1 %h); our @EXPORT_OK = qw(f2 f3); our %EXPORT_TAGS = ( a => [qw(f1 f2 f3)], b => [qw(f2 %h)], ); # Votre code ici. 1; # Ou suprieure...

# Symboles imports par dfaut. # Symboles imports seulement sur demande. # Mappage pour :raccourcis.

Depuis un programme ou un autre module qui fait un use du vtre :


use use use use Mon_Module; # Mon_Module (); # Mon_Module "f1", "f2", "%h"; # Mon_Module qw(:DEFAULT f3); # # use Mon_Module "f4"; # Importe tout ce quil a dans @Export. Charge le module sans rien importer. Deux fonctions et une variable. Tout ce quil y a dans @Export + une fonction. Erreur fatale car f4 nest pas exporte.

Ds que quelquun invoque une dclaration use pour charger votre module, il appelle la mthode import depuis votre module pour rapatrier tous les symboles dont il a besoin dans le paquetage de lappelant. Votre module (celui qui fait les exportations) peut dfinir la mthode import comme il le souhaite, mais la manire standard est den hriter partir du module de classe Exporter. Cest ce que fait le code ci-dessus. Le module Exporter sert de classe de base pour les modules qui souhaitent tablir leur propres exportations. Curieusement, les modules orients objet nutilisent gnralement pas Exporter, puisquils nexportent normalement rien (les appels de mthodes nont pas besoin dtre exports). Toutefois, le module Exporter lui-mme est accessible de manire oriente objet cause du tableau @ISA que vous avez install, comme dans notre exemple. Lorsquun autre programme ou quun autre module fait un use de votre module, vous utiliserez automatiquement la mthode Exporter::import par le biais de lhritage.

customer_8566

842

Chapitre 32 Modules standards

Le tableau @EXPORT du module contient une liste de symboles (des fonctions et mme des variables) que le code appelant importe automatiquement avec une instruction use sans rien dautre. Le tableau @EXPORT_OK est compos des symboles qui peuvent tre imports si on les demande nommment. Le numro $VERSION est consult si linstruction use demande une version particulire (ou plus rcente) du module. Beaucoup, beaucoup dautres fonctionnalits sont disponibles. Voir le chapitre 11, Modules, ainsi que la page de man en ligne du module Exporter.

Fatal
Le module Fatal fait chouer les fonctions plus spectaculairement. Il remplace les fonctions qui normalement retournent faux en cas dchec avec des sur-couches qui lvent une exception si la vritable fonction renvoie faux. Ainsi, vous pouvez utiliser en toute sret ces fonctions sans tester explicitement leur valeur de retour chaque appel. Les fonctions dfinies par lutilisateur et les fonctions internes peuvent toutes tre enrobes, sauf les fonctions internes qui ne peuvent pas tre exprimes par des prototypes. Une tentative de supplanter une fonction interne non-enrobable lve une exception. Ceci inclut system, print, printf, exec, split, grep et map ou plus gnriquement, toute FONC pour laquelle prototype "CORE::FONC" renvoie faux, y compris la fonction prototype elle-mme. Si le symbole :void apparat dans la liste dimportation, les fonctions cites ensuite dans la liste se limitent lever une exception lorsque la fonction est appele dans un contexte void cest--dire, lorsque la valeur renvoye est ignore. (Faites attention la dernire instruction dans un sous-programme.) Par exemple :
use Fatal qw(:void open close); # open proprement vrifi, aucune exception nest donc leve en cas dchec. if (open(HF, "< /rien_de_tel") { warn "aucun /rien de tel : $!"; } # close improprement vrifi, une exception est donc leve en cas dchec. close HF;

Fcntl
use use use use use Fcntl; Fcntl ":flock"; Fcntl ":seek"; Fcntl ":mode"; Fcntl ":Fcompat"; # # # # # Importe Importe Importe Importe Importe les constantes standard de fcntl.h. les constantes LOCK_*. SEEK_CUR, SEEK_SET et SEEK_END. les constantes de test de stat S_*. les constantes F*.

Le module Fcntl fournit des constantes employer avec diverses fonctions internes de Perl. Lensemble import par dfaut inclut des constantes comme F_GETFL et F_SETFL pour fcntl, SEEK_SET et SEEK_END pour seek et sysseek et O_CREAT et O_EXCL pour sysopen. Les tags dimportation supports incluent :flock pour accder aux constantes LOCK_EX, LOCK_NB, LOCK_SH et LOCK_UN pour flock ; :mode pour aller chercher les constantes de sys/stat.h comme S_IRUSR et S_ISFIFO ; :seek pour obtenir les trois arguments de seek et sysseek ; et :Fcompat pour avoir les symboles dsuets commenant par un F mais pas par F_ , comme FAPPEND, FASYNC et FNONBLOCK. Voir la

customer_8566

File::Basename

843

documentation en ligne du module Fcntl et la documentation de votre systme dexploitation pour les appels systmes concerns, comme fcntl(2), lseek(2), open(2) et stat(2).

File::Basename
use File::Basename; $nom_complet = "/usr/local/src/perl-5.6.1.tar.gz"; $fichier = basename($nom_complet); # fichier= "perl-5.6.1.tar.gz" $rep = dirname($nom_complet); rep="/usr/local/src" ($fichier,$rep,$ext) = fileparse($nom_complet, qr/\..*/); # rep="/usr/local/src/" fichier="perl-5" ext=".6.1.tar.gz" ($fichier,$rep,$ext) = fileparse($nom_complet, qr/\.[^.]*/); # rep="/usr/local/src/" fichier="perl-5.6.1.tar" ext=".gz" ($fichier,$rep,$ext) = fileparse($nom_complet, qr/\.\D.*/); # rep="/usr/local/src/" fichier="perl-5.6.1" ext=".tar.gz" ($fichier,$rep,$bak) = fileparse("/tmp/fichier.bak", qr/~+$/, qr/\.(bak|orig|save)/) # rep="/tmp/" fichier="fichier" bak=".bak"; ($fichier,$rep,$bak) = fileparse("/tmp/fichier~", qr/~+$/, qr/\.(bak|orig|save)/) # rep="/tmp/" fichier="fichier" bak="~";

Le module File::Basename fournit des fonctions pour dcomposer les noms de chemin en leurs composants individuels. La fonction dirname sort la portion reprsentant le rpertoire et basename la portion ne reprsentant pas le rpertoire. La fonction plus labore fileparse distingue dans le nom du chemin complet, le nom du rpertoire, le nom du fichier et le suffixe ; vous devez fournir une liste dexpressions rgulires dcrivant les suffixes qui vous intressent. Les exemples ci-dessus illustrent comment le choix de motifs pour le suffixe affecte le rsultat. Par dfaut, ces fonctions analysent des noms de chemin selon les conventions natives de votre plate-forme. La fonction fileparse_set_fstype slectionne les rgles danalyse pour une plate-forme diffrente, comme fileparse_set_fstype("VMS") pour analyser les noms utilisant les rgles de VMS, mme lorsque lon tourne sur des systmes non-VMS.

File::Compare
use File::Compare; printf "fichier_A et fichier_B sont %s.\n",

customer_8566

844

Chapitre 32 Modules standards


compare("fichier_A","fichier_B") ? "diffrents" : "identiques";

use File::Compare cmp; sub arranger($) { my $ligne = $_[0]; for ($ligne) { s/\^s+//; # Coupe les espaces au dbut. s/\s+$//; # Coupe les espaces la fin. } return uc($ligne); } if (not cmp("fichier_A", "fichier_B", sub {arranger $_[0] eq arranger $_[1]} ) { print "fichier_A et fichier_B sont peu prs pareils.\n"; }

Le module File::Compare fournit une fonction, compare, qui compare le contenu des deux fichiers quon lui passe. Elle renvoie 0 si les fichiers contiennent les mmes donnes, 1 sils contiennent des donnes diffrentes et -1 si lon a rencontr une erreur en accdant les fichiers cits. Si vous passez comme troisime argument une rfrence de sous-programme, cette fonction est appele rptitivement pour dterminer si deux lignes sont quivalentes. Pour assurer la compatibilit avec le programme cmp(1), vous pouvez explicitement importer la fonction en tant que cmp. (Ceci naffecte pas loprateur binaire cmp.)

File::Copy
use File::Copy; copy("/tmp/fichier_A", "/tmp/fichier_A.orig") or die "copie choue : $!"; copy("/etc/motd", *STDOUT) or die "copie choue : $!"; move("/tmp/fichier_A", "/tmp/fichier_A.orig") or die "dplacement chou : $!"; use File::Copy qw/cp mv/; # Importe les noms Unix habituels. cp("/tmp/fichier_A", "/tmp/fichier_A.orig") or die "copie choue : $!"; mv("/tmp/fichier_A", "/tmp/fichier_A.orig") or die "dplacement chou : $!";

Le module File::Copy exporte deux fonctions, copy et move, qui respectivement copie ou renomme leur premier argument vers leur second, de la mme manire quun appel aux commandes Unix cp(1) et mv(1) (noms que vous pouvez utiliser si vous les importez explicitement). La fonction copy accepte galement comme arguments des handles de fichiers. Ces fonctions renvoient vrai lorsquelle fonctionnent et faux lorsquelles chouent, en positionnant $! ($OS_ERROR) de manire approprie. (Malheureusement, vous ne pouvez pas dire si quelque chose comme Permission denied sapplique au premier fichier ou au second.) Ces fonctions sont en quelque sorte un compromis entre le confort et la prcision. Elles ne supportent pas les nombreuses options et optimisations de cp(1) et mv(1), comme la copie rcursive, la copie de sauvegarde automatique, la conservation des dates et heures originales et des informations sur les propritaires des fichiers, ou la confirmation interactive. Si vous avez besoin de ces fonctionnalits, il

customer_8566

File::Find

845

vaut certainement mieux appeler les versions de votre plate-forme pour ces commandes.2 Gardez bien lesprit que tous les systmes ne supportent pas les mmes commandes ou nemploient pas les mmes options pour ces commandes.
system("cp -R -pi /tmp/rep1 /tmp/rep2) == 0 or die "le statut de la commande externe cp est $?";

File::Find
use File::Find; # Affiche tous les rpertoires en-dessous du rpertoire courant. find sub { print "$File::Find::name\n" if -d }, "."; # Calcule lespace total utilis par les fichiers des rpertoires lists. @reps = @ARGV ? @ARGV : (.); my $tot = 0; find sub { $tot += -s }, @reps; print "@reps contiennent $tot octets\n"; # Modifie le comportement par dfaut pour traverser les liens # symboliques et visiter les sous-rpertoires en premier find { wanted => \&ma_fonction, follow => 1, bydepth=>1 }, ".";

La fonction find du module File::Find descend rcursivement dans des rpertoires. Son premier argument doit tre une rfrence une fonction et tous les arguments suivants doivent tre des rpertoires. La fonction est appele pour chaque fichier des rpertoires lists. lintrieur de cette fonction, la variable $_ est positionne avec le nom de base du fichier actuellement visit et le rpertoire de travail courant du processus est par dfaut mis ce rpertoire. La variable de paquetage $File::Find::name est le nom de chemin complet du fichier visit. Une autre convention dappel prend comme premier argument une rfrence un hachage contenant des spcifications doptions, incluant wanted , bydepth , follow , follow_fast , follow_skip , no_chdir , untaint , untaint_pattern et untaint_skip , comme le dtaille compltement la documentation en ligne. Ce module est galement utilis par le programme de conversion standard find2perl(1) qui vient avec la distribution Perl.

File::Glob
use File::Glob :glob; @liste = <*.[Cchy]>; # Supplante le glob interne. # Utilise maintenant le glob POSIX, pas le # glob csh.

use File::Glob qw(:glob csh_glob);


2. Ou aller chercher les versions PPT si votre plate-forme est un dfi pour ces outils. N.d.T. : Perl Power Tools : The Unix Reconstruction Project, un projet dont le but avou est : Notre objectif est, de manire assez simple, de rimplmenter le jeu de commandes classiques Unix en Perl pur, et de nous amuser autant que possible en faisant cela. .

customer_8566

846

Chapitre 32 Modules standards

@sources = bsd_glob("*.{C,c,h,y,pm,xs}", GLOB_CSH); @sources = csh_glob("*.{C,c,h,y,pm,xs}"); # (idem) use File::Glob :glob; # appelle glob avec des arguments supplmentaires $rep_maison = bsd_glob(~hackerjr, GLOB_TILDE | GLOB_ERR); if (GLOB_ERROR) { # Une erreur sest produite en dveloppant le rpertoire maison }

La fonction bsd_glob du module File::Glob implmente la routine glob(3) de la librairie C. Un second argument facultatif contient des options gouvernant des proprits supplmentaires de correspondances. Le tag dimportation :glob importe la fois la fonction et les options ncessaires. Le module implmente galement une fonction csh_glob. Cest elle que loprateur interne de Perl glob et loprateur de globalisation de fichiers GLOBPAT appellent rellement. Appeler csh_glob revient (en grande partie) appeler bsd_glob de cette manire :
bsd_glob(@_ ? $_[0] : $_, GLOB_BRACE | GLOB_NOMAGIC | GLOB_QUOTE | GLOB_TILDE);

Si vous importez le tag :glob, tous les appels aux oprateurs internes de globalisation de fichiers dans le paquetage courant appelleront alors rellement la fonction du module bsd_glob la place de la fonction csh_glob. Une raison pour laquelle vous voudriez faire cela, bien que bsd_glob soccupe de motifs comprenant des espaces, est que csh_glob sen occupe dune manire, heu, historique. Les anciens scripts criraient <*.c *.h> pour globaliser les deux motifs. De toute faon, aucune des fonctions nest gne par des espaces dans les vritables noms de fichiers. La fonction bsd_glob prend un argument contenant le motif de globalisation de fichiers (et pas un motif dexpression rgulire) plus un argument facultatif pour les options. Les noms de fichiers commenant par un point ne correspondent pas moins de le demander spcifiquement. La valeur de retour est inf luence par les options du second argument, qui doivent tre des bits joints entre eux par des OU :3 GLOB_BRACE Traite en amont la chane pour dvelopper les chanes {motif,motif,...} comme csh(1) le ferait. Le motif {} nest pas dvelopp pour des raisons historiques, surtout pour faciliter la saisie des motifs de find(1). GLOB_CSH Synonyme de GLOB_BRACE | GLOB_NOMAGIC | GLOB_QUOTE | GLOB_TILDE GLOB_ERR Renvoie une erreur lorsque la fonction bsd_glob rencontre un rpertoire quelle ne peut ouvrir ou lire. Dordinaire, bsd_glob saute les erreurs pour rechercher dautres correspondances.

3. cause des restrictions de syntaxe dans loprateur interne glob, il se peut que vous deviez appeler la fonction en tant que bsd_glob si vous voulez lui passer le second argument.

customer_8566

File::Glob
GLOB_MARK Ajoute un slash la fin des rpertoires. GLOB_NOCASE

847

Par dfaut, les noms de fichiers sont sensibles la casse (majuscules/minuscules) ; cette options fait que bsd_glob ignore les diffrences de casse. (Mais voir ci-dessous les exceptions sur les systmes la MS-DOS). GLOB_NOCHECK Si le motif ne correspond aucun nom de chemin, alors bsd_glob renvoie une liste uniquement constitue du motif, comme le fait /bin/sh. Si loption GLOB_QUOTE est positionne, les consquences quelle entrane sont prsentes dans le motif renvoy. GLOB_NOMAGIC Idem que GLOB_NOCHECK mais le motif nest renvoy que sil ne contient aucun des caractres spciaux *, ? ou [. NOMAGIC est l pour simplifier limplmentation du comportement historique de globalisation de csh(1) et ne devrait probablement pas tre utilis ailleurs. GLOB_NOSORT Par dfaut, les noms de chemins sont tris dans un ordre croissant (en utilisant les comparaisons de caractres habituelles, sans respecter les valeurs des locales). Cette option vite ce tri avec comme rsultat une lgre amlioration de la vitesse. GLOB_QUOTE Utilise le caractre antislash \ pour les protections : chaque occurrence dans le motif dun antislash suivi par un caractre est remplace par ce caractre, vitant les interprtations spciales du caractre en question. (Mais voir ci-dessous les exceptions sur les systmes la MS-DOS). GLOB_TILDE Autorise lemploi de motifs dont le premier composant du chemin est ~UTILISATEUR. Si UTILISATEUR est omis, le tilde lui-mme (ou suivi par un slash) reprsente le rpertoire maison de lutilisateur courant. La fonction bsd_glob renvoie une liste (qui peut tre vide) des chemins correspondants, cette liste pouvant devenir marque si cela importe votre programme. En cas derreur, GLOB_ERROR sera vrai et $! ($OS_ERROR)sera positionne avec lerreur systme standard. Il est granti que GLOB_ERROR sera faux sil ne se passe aucune erreur, et de valoir soit GLOB_ABEND, sinon GLOB_NOSPACE. (GLOB_ABEND signifie que la fonction bsd_glob sest arrte cause dune erreur et GLOB_NOSPACE cause dun manque de mmoire.) Si bsd_glob a dj trouv des chemins correspondant lorsque lerreur se produit, elle renvoie la liste des noms de fichiers trouvs jusque l mais positionne aussi GLOB_ERROR. Remarquez que cette implmentation de bsd_glob diffre de la plupart des autres en ce quelle ne considre pas ENOENT et ENOTDIR comme des conditions darrt sur erreur. la place, elle poursuit son traitement malgr ces erreurs, sauf si loption GLOB_ERR est positionne. Si aucune option nest donne, les comportements par dfaut de votre systme sont respects, cest--dire que les noms de fichiers qui diffrent seulement par leur casse seront confondus sur VMS, OS/2, les vieux Mac OS (mais pas Mac OS X) et les systmes Micro-

customer_8566

848

Chapitre 32 Modules standards

soft (mais pas lorsque Perl a t compil avec Cygwin). Si vous ne donnez aucune option et que vous voulez toujours que ce comportement sapplique, vous devez alors inclure GLOB_NOCASE dans les options. Quelque soit le systme sur lequel vous tes, vous pouvez modifier votre comportement par dfaut en important lavance les options :case ou :nocase. Sur les systmes la MS-DOS, lantislash est un caractre sparateur de rpertoires valide.4 Dans ce cas, lemploi dun antislash comme caractre de protection (via GLOB_QUOTE) interfre avec lemploi de lantislash en tant que sparateur de rpertoires. La meilleure solution (la plus simple et la plus portable) est dutiliser des slashs comme sparateurs de rpertoires, des antislashs pour les protections. De toute faon, cela na rien voir avec les attentes de certains utilisateurs, ainsi les antislashs (sous GLOB_QUOTE) ne protgent que les mtacaractres de globalisation [, ], {, }, -, ~ et \ lui-mme.Tous les autres antislashs sont passs inchangs, si vous parvenez en avoir avec le propre mcanisme de Perl pour la protection par antislashs dans les chanes. Cela peut prendre jusqu quatre antislashs pour finalement correspondre un seul dans le systme de fichier. Ceci est tellement compltement dlirant que mme les utilisateurs des systmes la MS-DOS devraient srieusement penser employer des slashs. Si vous voulez vraiment utiliser des antislashs, jetez un il au module standard File::DosGlob qui est plus susceptible de correspondre vos gots que la globalisation de fichiers la mode Unix.

File::Spec
use File::Spec; # style orient objet $chemin = File::Spec->catfile("sous_rep", "fichier"); # sous_rep/fichier sur Unix, OS2 ou Mac OS X # sous_rep:fichier sur les (vieux) Macs dApple # sous_rep\fichier sur Microsoft $chemin = File::Spec->catfile("", "rep1", "rep2", "fichier"); # /rep1/rep2/fichier sur Unix, OS2 ou Mac OS X # :rep1:rep2:fichier sur les (vieux) Macs dApple # \rep1\rep2\fichier sur Microsoft use File::Spec::Unix; $chemin = File::Spec->catfile("sous_rep", "fichier"); # sous_rep/fichier (mme si excut sur des systmes non-Unix) use File::Spec::Mac; $chemin = File::Spec->catfile("sous_rep", "fichier"); # sous_rep:fichier use File::Spec::Win32;

4. Bien que techniquement, le slash aussi du moins aussi longtemps que cela concerne les noyaux et les appels systmes ; les commandes shell sont remarquablement moins bien claires.

customer_8566

File::stat
$chemin = File::Spec->catfile("sous_rep", "fichier"); # sous_rep\fichier # Utilise plutt linterface fonctionnelle. use File::Spec::Functions; $chemin = catfile("sous_rep", "fichier");

849

La famille de modules File::Spec vous permet de construire des chemins utilisant des rpertoires et des noms de fichiers sans coder en dur les sparateurs de rpertoires spcifiques aux plates-formes. Les systmes supports incluent Unix, VMS, Mac et Win32. Ces modules offrent tous une mthode de classe catfile qui concatne chaque composant de chemin en utilisant le sparateur de chemin spcifique la plate-forme. Le module File::Spec renvoie des rsultats diffrents selon votre plate-forme courante. Les autres renvoient des rsultat spcifique la plate-forme en question. Le module File::Spec::Functions fournit une interface fonctionnelle.

File::stat
use File::stat; $st = stat($fichier) or die "stat de $fichier impossible : $!"; if ($st->mode & 0111 and $st->nlink > 1) { print "$fichier est excutable et possde plusieurs liens\n"; } use File::stat ":FIELDS"; stat($fichier) or die "stat de $fichier impossible : $!"; if ($st_mode & 0111 and $st_nlink > 1) { print "$fichier est excutable et possde plusieurs liens\n"; } @infos_stat = CORE::stat($fichier); # Utilise la fonction interne, # mme si elle est supplante

Le module File::stat fournit une interface mthode aux fonctions internes Perl stat et lstat en les remplaant par des versions renvoyant une objet File::stat (ou undef en cas dchec). Cet objet possde des mthodes nommes de manire renvoyer le champ de la structure du mme nom depuis lappel systme habituel stat(2) ; il sagit de dev, ino, mode, nlink, uid, gid, rdev, size, atime, mtime, ctime, blksize et blocks. Vous pouvez galement importer les champs de la structure dans votre propre espace de noms en tant que variables ordinairex en utilisant le tag dimportation :FIELDS . (Les oprateurs internes stat et lstat continuent tre supplants.) Ces champs se prsentent comme des variables scalaires avec un st_ au dbut du nom du champ. Cest--dire que la variable $st_dev correspond la mthode $st->dev.

File::Temp
use File::Temp qw(tempfile tempdir); $rep = tempdir(CLEANUP => 1); ($hf, $fichier) = tempfile(DIR => $rep);

customer_8566

850

Chapitre 32 Modules standards

($hf, $fichier) = tempfile($exemple, DIR => $rep); ($hf, $fichier) = tempfile($exemple, SUFFIX => ".data"); $hf = tempfile(); use File::Temp :mktemp; ($hf, $fichier) = mkstemp("fic_tmpXXXXX"); ($hf, $fichier) = mkstemps("fic_tmpXXXXX", $suffixe); $rep_tmp = mkdtemp($exemple); $fichier_non_ouvert = mktemp($exemple);

Nouveaut dans la version 5.6.1 de Perl, le module File::Temp fournit des fonctions pratiques pour crer et ouvrir de manire sre des fichiers temporaires. Il vaut mieux utiliser ce module quessayer de choisir vous-mme un fichier temporaire. Sinon, vous tomberez dans les mmes piges que tout le monde avant vous. Ce module vous protge aussi bien des situations de concurrence (race conditions) que du danger demployer des rpertoires o dautres peuvent crire ; voir le chapitre 23, Scurit. La fonction tempfile renvoie la fois un handle de fichier et un nom de fichier. Le plus sr est dutiliser ce qui est dj ouvert et dignorer compltement le nom de fichier (except peut-tre pour les messages derreurs). Une fois que le fichier est ferm, il est automatiquement supprim. Pour assurer une compatibilit avec la bibliothque C, le tag dimportation :mktemp donne un accs aux fonctions dont les noms sont familiers aux programmeurs C, mais sil vous plat, souvenez-vous que les noms de fichiers sont toujours moins srs que les handles de fichiers.

FileHandle
use FileHandle; $hf = new FileHandle; if ($hf->open("< fichier")) { print $ligne while defined($ligne = $hf->getline); $hf->close; } $pos = $hf->getpos; # comme tell() $hf->setpos($pos); # comme seek() ($hf_lec, $hf_ecr) = FileHandle::pipe(); autoflush STDOUT, 1;

Le module FileHandle sert surtout de mcanisme pour dissimuler les variables de Perl contenant des ponctuations sous des appellations plus longues, davantage dans le style orient objet. Il est fourni pour assurer une compatibilit avec des versions antrieures mais maintenant il sagit vritablement dun frontal vers plusieurs modules plus spcifiques, comme IO::Handle et IO::File.5 Sa meilleure proprit est laccs de bas niveau
5. Comme il charge beaucoup de code, ce module vous cote environ un mga-octet en mmoire.

customer_8566

FileHandle

851

quil fournit vers certaine fonctions rares de la bibliothque C (clearerr(3), fgetpos(3), fsetpos(3) et setvbuf (3)).
Variable $| $, $\ $/ $. $% $= $$~ $^ $: $^L Mthode autoflush output_field_separator output_record_separator input_record_separator input_line_number format_page_number format_lines_per_page format_lines_left format_name format_top_name format_line_break_characters format_formfeed

Au lieu dcrire :
$hfs = select(HANDLE ); $~ = UnFormat; $| = 1; select($hfs);

vous pouvez juste crire :


use FileHandle; Handle->format_name(UnFormat); Handle->autoflush(1);

Actuellement, trois mthodes (output_field_separator, output_record_separator et input_record_separator) ne font que prtendre tre des mthodes par handle : les positionner sur un handle affecte tous les handles de fichiers. Elles sont ainsi seulement supportes en tant que mthodes de classes, pas en tant que mthodes par handle de fichier. Cette restriction sera peut-tre abandonne un jour. Pour obtenir un handle de fichier de porte lexicale, au lieu dutiliser lautovivifiation de handle de fichier :
open my $hf, "< un_fichier" or die "impossible douvrir un_fichier : $!";

on peut crire :
use FileHandle; my $hf = FileHandle->new("< un_fichier") or die "impossible douvrir un_fichier : $!";

FileHandle hrite de IO::File, qui lui-mme hrite de IO::Handle et IO::Seekable. Les fonctionnalits du module sont virtuellement toutes accessibles plus efficacement via les appels purs et basiques de Perl, sauf pour les suivants, qui peuvent ne pas tous tre implments sur les plates-formes non-Unix :

customer_8566

852
HANDLE->blocking(EXPR)

Chapitre 32 Modules standards

Appel avec un argument, active les entres/sorties non-bloquantes si largument est faux et dsactive les entres/sorties non-bloquantes (cest--dire active les entres/sorties bloquantes) sil est vrai. La mthode renvoie la prcdente valeur positionne (ce qui est toujours le comportement actuel si aucun argument nest donn). En cas derreur, blocking positionne $! et renvoie undef. Ceci pourrait tre accompli avec fcntl directement mais linterface FileHandle est plus simple utiliser. HANDLE->clearerr Appelle la fonction clearerr(3) de la bibliothque C pour efface les indicateurs internes du handle pour la fin de fichier et le statut derreur. HANDLE->error Appelle la fonction ferror(3) de la bibliothque C pour tester lindicateur derreur pour le handle donn, en renvoyant si cet indicateur interne est positionn ou non. Lindicateur derreur ne peut tre rinitialis fiablement que via la mthode clearerr. (Certains systmes le rinitialisent galement en appelant loprateur seek.) HANDLE->formline(IMAGE, LISTE) Cela revient au mme que de sauvegarder lancienne variable daccumulateur ($^A), dappeler la fonction formline avec lIMAGE et la LISTE donnes, dafficher le contenu rsultant de laccumulateur vers le handle donn et enfin de restaurer laccumulateur original. Par exemple, voici comment afficher une variable reprsentant un texte long en allant la ligne la colonne 72 :
use FileHandle; STDOUT->formline("^" . ("<" x 72) . "~~\n", $texte_long);

HANDLE->getpos Appelle la fonction getpos(3) de la bibliothque C, offrant ainsi une interface alternative tell. Sur certains systmes (non-Unix), la valeur renvoye peut tre un objet complexe et getpos et setpos peuvent tre la seul manire de repositionner de manire portable un f lux de texte. HANDLE->new_tmpfile Appelle la fonction tmpfile(3) de la bibliothque C pour crer un nouveau fichier temporaire ouvert en mode lecture-criture et renvoie un handle sur ce f lux. Sur les systmes o cest possible, le fichier temporaire est anonyme, cest--dire quil est supprim avec unlink aprs sa cration tout en restant ouvert. Vous devez utiliser cette fonction ou POSIX::tmpnam comme dcrit dans le module POSIX pour crer de manire sre un fichier temporaire sans vous exposer aux problmes de scurits annexes mais nanmoins srieux avec les situations de concurrence (N.d.T. : race conditions). Depuis la version 5.6.1 de Perl, le module File::Temp est maintenant linterface recommande. HANDLE->setbuf(TAMPON) Appelle la fonction setbuf (3) de la bibliothque C avec la variable TAMPON donne. La mthode passe undef pour indiquer une sortie qui nutilisent pas le mcanisme de tampon. Une variable utilise comme tampon par setbuf ou setvbuf ne doit pas

customer_8566

Getopt::Long

853

tre modifie daucune manire jusqu ce que le handle soit ferm ou jusqu ce que la fonction setbuf ou setvbuf soit appele nouveau. Sinon il peut en rsulter une corruption de mmoire qui vous ferait de la peine. HANDLE->setpos(EXPR) Appelle la fonction fsetpos(3) de la bibliothque C, offrant ainsi une autre interface seek. Largument ne doit tre quune valeur correcte renvoye par getpos, comme dcrit prcdemment. HANDLE->setvbuf(TAMPON, TYPE, TAILLE) Appelle la fonction setvbuf (3) de la bibliothque C avec le TAMPON donn. Les constantes standards de la bibliothque C _IONBF (sans utilisation dun tampon), _IOLBF (tampon vid ligne par ligne) et _IOFBF (mcanisme complet de tampon) sont disponibles pour le champ TYPE si elles sont explicitement importes. Voir la mise en garde dans setbuf. HANDLE->sync Appelle la fonction fsync(3) de la bibliothque C pour synchroniser un fichier dans un tat en-mmoire vers le support physique. Remarquez que sync nagit pas sur le handle mais sur le descripteur de fichier, toute donne conserve dans les tampons ne sera donc pas synchronise moins que le tampon ne soit tout dabord vid (N.d.T. : flushed). HANDLE->untaint Marque le handle de fichier ou de rpertoire en lui fournissant une donne nonmarque. Lorsque lon tourne en mode marqu (voir le chapitre 23), les donnes lues depuis des fichiers externes sont considrs comme tant indignes de confiance. Ninvoquez pas cette mthode aveuglment : vous court-circuiteriez les meilleures tentatives de Perl pour vous protger de vous-mme.

Getopt::Long
Si votre programme fait :
use Getopt::Long; GetOptions("verbeux" => \$verbeux, "debogage" => \$debogage, "sortie=s" => \$sortie);

il peut tre appel ainsi depuis la ligne de commande :


% % % % % prog prog prog prog prog --verbeux autres arguments ici --debogage autres arguments ici -v -d autres arguments ici --sortie=un_fichier autres arguments ici -s un_fichier autres arguments ici

Le module Getopt::Long fournit une fonction GetOptions pour traiter les options de la ligne de commande avec des noms assez longs. Il inclut un support pour des choses comme les options en abrg, les arguments typs comme boolen, chane, entier ou virgule f lottante, les variables de tableaux pour les options rptes, les routines de va-

customer_8566

854

Chapitre 32 Modules standards

lidation dfinies par lutilisateur, le traitement conforme POSIX ou conforme au style FSF, les options insensibles la casse et le regroupement traditionnel des options courtes pour ne citer quun chantillon de la corne dabondance de ses fonctionnalits. Si ce module en fait trop, pensez au module plus ordinaire Getopt::Std dcrit plus loin. Si ce module nen fait pas assez, regardez le module de CPAN Getopt::Declare qui offre une syntaxe plus dclarative pour spcifier les options.

Getopt::Std
use Getopt::Std;

Vous pouvez utiliser getopt et getopts avec des variables globales :


out ($opt_o, $opt_i, $opt_f); getopt(oif); # -o, -i et -f prennent tous des arguments. # Positionne les variables globales $opt_*. getopts(oif:); # Maintenant -o et -i sont boolens ; -f prend un arg. # Positionne toujours les variables globales $opt_* # comme effet de bord.

Ou vous pouvez les utiliser avec un hachage priv pour les options :
my %opts; getopt(oif, \%opts); getopts(oif:, \%opts); # # # # Nous placerons les rsultats ici. Tous les trois prennent toujours un argument. Maintenant -o et -i sont des boolens et seul -f prend un argument.

Le module Getopt::Std fournit deux fonctions, getopt et getopts, pour vous aider analyser les arguments de la ligne de commande dans le cas doptions sur un seul caractre. Des deux fonctions, getopts est la plus utile car elle vous laisse spcifier que certaines options prennent un argument ; sinon, on sattend trouver une option boolenne. Le regroupement doptions standards est support. Lordre ne compte pas, ainsi les options ne prenant pas darguments peuvent tre regroupes ensemble. Les options qui prennent un argument doivent tre les dernires dun groupe ou tre spcifie part et leur argument doit venir soit immdiatement aprs loption dans la mme chane, soit comme largument suivant du programme. tant donn lexemple dutilisation de getopts ci-dessus, voici des appels quivalents :
% % % % % prog prog prog prog prog -o -i -f FIC_TEMP autres arguments ici -o -if FIC_TEMP autres arguments ici -io -fFIC_TEMP autres arguments ici -iofFIC_TEMP autres arguments ici -oifFIC_TEMP autres arguments ici

IO::Socket
use IO::Socket;

En tant que client :


$socket = new IO::Socket::INET (PeerAddr => $hote_distant, PeerPort => $port_distant, Proto => "tcp",

customer_8566

IPC::Open2

855

Type => SOCK_STREAM) or die "Connexion impossible vers $hote_distant:port_distant : $!\n"; # Ou utilisez linterface plus simple un seul argument. $socket = IO::Socket::INET->new("$hote_distant:$port_distant,"); # "localhost:80", par exemple. print $socket "donne\n"; $ligne = <$socket>;

En tant que serveur :


$serveur = IO::Socket::INET->new(LocalPort => port_serveur, Type => SOCK_STREAM, Reuse => 1, Listen => 10) # ou SOMAXCONN or die "Impossible dtre un serveur TCP sur le port $port_serveur : $!\n"; while ($client = $serveur->accept()) { # $client est la nouvelle connexion $requete = <$client>; print $client "reponse\n"; close $client; } # Simple fonction de connexion TCP renvoyant un handle de fichier # pour utiliser dans les programmes clients simples. sub connex_tcp { my ($hote, $service) = @_; require IO::Socket; return IO::Socket::INET->new(join ":", $hote, $service); } my $hf = connex_tcp("localhost, "smtp"); # avec un scalaire local *HF = connex_tcp("localhost, "smtp"); # avec un handle

Le module IO::Socket fournit une approche de plus haut niveau pour la gestion des sockets que le module de base Socket. Vous pouvez lutiliser dans un style orient objet, bien que ce ne soit pas obligatoire, car les valeurs renvoyes sont des handles de fichiers rguliers et peuvent tre utilises en tant que telles, comme le montre la fonction connex_tcp dans lexemple ci-dessus. Ce module hrite ses mthodes de IO::Handle et fait lui-mme un require de IO::Socket::INET et IO::Socket::UNIX. Voir la description du module FileHandle pour dautres fonctionnalits intressantes. Voir le chapitre 16 pour une description de lutilisation des sockets.

IPC::Open2
use IPC::Open2; local(*SA_SORTIE, *SON_ENTREE); # Cre les handles locaux si besoin.

customer_8566

856

Chapitre 32 Modules standards

$pid_fils = open2(*SA_SORTIE, *SON_ENTREE, $programme, @args) or die "Impossible douvrir un pipe vers $programme : $!"; print SON_ENTREE "Voici votre entre\n"; $sa_sortie = <SA_SORTIE>; close(SA_SORTIE); close(SON_ENTREE); waitpid($pid_fils, 0);

La seule fonction exporte, open2, du module IPC::Open2 dmarre un autre programme et offre un accs la fois en lecture et en criture cette commande. Les deux premiers arguments doivent tre des handles de fichiers valides (ou alors des variables vides dans lesquelles seront placs les handles de fichiers autognrs). Les arguments restants sont le programme plus ses arguments, qui, sils sont passs sparment, ne seront pas interprts par le shell. Ce module ne rcolte pas le processus fils aprs sa mort. part les programmes courts o il reste acceptable de laisser le systme dexploitation grer cela, vous aurez besoin de le faire vous-mmes. Cela se rsume normalement appeler waitpid $pid, 0 lorsque vous en avez finit avec ce processus fils. Ne pas faire ceci entrane laccumulation de processus dfunts ( zombies ). En pratique, ce module ne fonctionne pas bien avec beaucoup de programmes cause de la manire dont marche le vidage de tampon dans la bibliothque dentres/sorties standard en C. Si vous contrlez le code source des deux programmes, vous pouvez toutefois contourner facilement cette restriction en forant le vidage ( flushing) de vos tampons de sortie plus frquemment que par dfaut. Si ce nest pas le cas, les programmes peuvent tre ennuyeusement avares dans leur accumulation de donnes en sortie. Un autre pige potentiel est le verrou mortel (deadlock) : si les deux processus sont en train de lire au mme moment et quaucun ncrit, alors votre programme se bloquera. Voir le chapitre 16 pour une discussion approfondie.

IPC::Open3
use IPC::Open3; local(*SON_ENTREE, *SA_SORTIE, *SON_ERREUR); $pid_fils = open3(*SON_ENTREE, *SA_SORTIE, *SON_ERREUR, $cmd, @args); print SON_ENTREE "trucs\n"; close(SON_ENTREE); # Donne une fin de fichier au fils. @lignes_sortie = <SA_SORTIE>; # Lit jusqu EOF. @lignes_erreur = <SON_ERREUR>; # XXX : blocage potentiel si norme print "STDOUT:\n", @lignes_sortie, "\n"; print "STDERR:\n", @lignes_erreur, "\n"; close SA_SORTIE; close SON_ERREUR; waitpid($pid_fils, 0); if ($?) { print "Ce fils sest termin avec comme statut dattente $?_n"; }

Le module IPC::Open3 fonctionne comme IPC::Open2 (ce dernier est implment dans

customer_8566

Math::BigInt

857

les termes du premier), except que open3 donne accs aux handles dentre standard, de sortie standard et de sortie derreurs standard du programme que vous lancez. Les mmes prcautions quavec open2 (voir lentre prcdente) sappliquent, plus quelques autres. Au lieu de passer le handle pour la lecture en premier et celui pour lcriture en second, cette fois-ci cest linverse. De plus, avec open3, le danger de verrous mortels (deadlocks) est encore plus grand quavant. Si vous essayez de lire aprs la fin de fichier sur lun des handles de sortie du fils, mais que pendant ce temps il y a beaucoup de trafic en sortie sur lautre handle, le processus pair semble se bloquer. Utilisez soit la forme quatre arguments de select, soit le module IO::Select pour contourner cela. Voir le chapitre 16 pour plus de dtails.

Math::BigInt
use Math::BigInt; $i = Math::BigInt->new($chaine); use Math::BigInt :constant; print 2**200;

Ceci affiche :
+1606938044258990275541962092341162602522202993782792835301376

Le module Math::BigInt fournit des objets qui reprsentent des entiers avec une prcision arbitraire et des oprateurs arithmtiques surchargs. Crez ces objets en utilisant le constructeur new ou, dans une porte lexicale, en important la valeur spciale :constant , aprs laquelle tous les littraux numriques jusqu la fin de cette porte lexicale seront traits comme des objets Math::BigInt. Tous les oprateurs standards sur les entiers sont implments, y compris (depuis la version 5.6 de Perl) les oprateurs logiques de bits. Dans limplmentation actuelle, ce module nest pas ce que vous pouvez appeler dune rapidit fulgurante mais cela pourrait tre le cas dans lavenir. (Nous aimerions voir quelle vitesse vous calculez de tte 2**200.)

Math::Complex
use Math::Complex; $z = Math::Complex->make(5, 6); $z = cplx(5, 6); # idem mais plus court. $t = 4 - 3*i + $z; # effectue des oprations complexes standard print "$t\n"; # affiche 9+3i print sqrt(-9), "\n"; # affiche 3i

Le module Math::Complex fournit des objets reprsentant des nombres complexes avec des oprateurs surchargs. Ce sont des nombres avec une partie relle et une partie imaginaire comme ceux qui satisfont les racines paires de nombres ngatifs, comme montr ci-dessus. ct des oprateurs arithmtiques, nombre de fonctions internes mathmatiques sont galement supplantes par des versions qui connaissent les nombres complexes, incluant abs, log, sqrt, sin, cos et atan2. Dautres fonctions fournies sont Re et Im pour donner les parties relles et imaginaires des arguments complexes, plus une bat-

customer_8566

858

Chapitre 32 Modules standards

terie complte de fonctions trigonomtriques tendues, comme tan, asin, acos, sinh, cosh et tanh. Le module exporte galement la constante i, qui, comme vous pouvez limaginer, contient la valeur de i ; cest--dire, la racine carre de -1.

Math::Trig
use Math::Trig; $x = tan(0.9); $y = acos(3.7); $z = asin(2.4); $pi_sur_deux = pi/2; $rad = deg2rad(120);

Perl ne dfinit lui-mme que trois fonctions trigonomtriques : sin, cos et atan2. Le module Math::Trig les supplante avec des versions plus agrables et fournit toutes les autres fonctions trigos, incluant tan, csc, cosec, sec, cot, cotan, asin, acos, atan, sinh, cosh, tanh et beaucoup dautres. De plus, la constante pi est dfinie, tout comme les fonctions de conversion comme deg2rad et grad2rad. Un support est fourni pour les systmes de coordonnes cartsiennes, cylindriques ou sphriques. Ce module fait un usage implicite de Math::Complex si besoin est (et vice-versa) pour les calculs ncessitant des nombres imaginaires.

Net::hostent
use Socket; use Net::hostent; print inet_ntoa(gethost("www.perl.com")->addr); printf "%vd", gethost("www.perl.com")->addr; print gethost("127.0.0.1")->name; # affiche 208.201.239.50 # idem # affiche localhost

use Net::hostent :FIELDS; if (gethost($nom_ou_nombre)) { print "le nom est $h_name\n"; print "les alias sont $h_aliases\n"; print "les adresses sont ", join ", " => map { inet_ntoa($_) } @h_addr_list; }

Les exportations par dfaut de ce module supplantent les fonctions intrinsques gethostbyname et gethostbyaddr, en les remplaant avec des versions qui renvoient un objet Net::hostent (ou undef en cas dchec). Cet objet possde des mthodes accesseurs dattributs qui renvoient des champs nomms comme ceux de la structure struct hostent de la bibliothque C dfinie dans netdb.h : name, aliases, addrtype, length ou addr_list. Les mthodes aliases et addr_list renvoient des rfrences de tableaux ;

customer_8566

POSIX

859

les autres renvoient des scalaires. La fonction gethost est un frontal qui fait suivre un argument numrique gethostbyaddr par le biais de la fonction Socket::inet_aton et le reste gethostbyname. Comme avec les autres modules semi-pragmatiques qui supplantent des fonctions internes renvoyant des listes, si vous importez le tag :FIELDS , vous pouvez accder des variables de paquetages scalaires ou tabulaires par le mme nom que les appels de mthodes prfixs par h_ . Les fonctions intrinsques sont quand mme supplantes.

POSIX
use POSIX; # Arrondit des nombres virgule flottante lentier suprieur # ou infrieur le plus proche. $n = ceil($n); # arrondi suprieur $n = floor($n); # arrondi infrieur # Produit "20-04-2001" pour aujourdhui. $ch_date = strftime("%d-%m-%Y"), localtime); # Produit "vendredi 04/20/01" pour la mme date. $ch_date = strftime(%A %D"), localtime); # Essaie de nouveaux noms de fichiers temporaires jusqu en trouver un qui # nexiste pas dj; voir galement File::Temp sur CPAN ou dans la v5.6.1. do { $nom = tmpnam(); } until sysopen(HF, $nom, O_CREAT|O_EXCL|O_RDWR, 0666); # Vrifie si le systme a un oprateur chown peu sr le trahissant. if (sysconf(_PC_CHOWN_RESTRICTED)) { print "Hourra -- seul le super-utilisateur peut appeler chown\n"; } # Trouve les informations par uname du systme courant. my ($noyau, $hote, $release, $version, $materiel) = uname(); use POSIX ":queue"; while (($pid_mort = waitpid(-1, &WNOHANG)) > 0) { # Faites quelque chose avec $pid_mort si vous le voulez. } # Devient le leader dune nouvelle session/nouveau groupe de processus # (ncessaire pour crer des dmons non-affects par les signaux # du clavier ou les shells de connexion se terminant). setsid(0) or die "chec de setsid : $!";

Le module POSIX de Perl vous permets daccder tous (ou presque tous) les identificateurs du standard POSIX 1003.1, plus quelques uns du C ANSI que nous ne savions pas

customer_8566

860

Chapitre 32 Modules standards

o mettre. Ce module fournit plus de fonctions quaucun autre. Voir sa documentation en ligne pour une sance de dissection ou le POSIX Programmers Guide de Donald Lewine (OReilly, 1991). Les identificateurs qui sont des #defines sans paramtres en C, comme EINTR ou O_NDELAY sont automatiquement exporter dans votre espace de noms en tant que fonctions constantes. Les fonctions qui ne sont normalement pas disponibles en Perl (comme floor, ceil, strftime, uname, setsid, setlocale et sysconf) sont exports par dfaut. Les fonctions du mme nom que les oprateurs internes de Perl, comme open, ne sont pas exportes moins de le demander explicitement, mais la plupart de gens sont susceptibles de prfrer des noms de fonctions pleinement qualifis pour distinguer POSIX::open de CORE::open. Quelques fonctions ne sont pas implmentes car elles sont spcifiques au C. Si vous tenter de les appelez, elles affichent un messages vous disant quelles ne sont pas implmentes et vous suggrent dutiliser un quivalent Perl sil en existe. Par exemple, une tentative daccder la fonction setjmp affiche le message setjmp() is C-specific: use eval {} instead et tmpfile vous dit Use method IO::File::new_tmp_file() . (Mais depuis la version 5.6.1, vous devriez plutt utilisez File::Temp.) Le module POSIX vous emmne aussi prs du systme dexploitation (ou tout du moins aux parties adresses par le standard POSIX) que ne le ferait nimporte quel programmeur C. Ceci vous donne accs un pouvoir phnomnale et des choses trs utiles, comme bloquer les signaux et contrler les options des entres/sorties du terminal. Toutefois, cela signifie galement que votre code finira par ressembler quasiment du C. Comme dmonstration utile de la manire dviter les vidages de tampons en entre, voici un exemple dun programme complet pour obtenir un seul caractre en entre sans tampon, sur un systme POSIX :
#!/usr/bin/perl -w use strict; $| = 1; for (1..4) { my $lu; print "donnez-moi : "; $lu = lire_un(); print "--> $lu\n"; } exit; BEGIN { use POSIX qw(:termios_h); my ($term, $oterm, $echo, $noecho, $df_entree); $df_entree = fileno(STDIN); $term = POSIX::Termios->new(); $term->getattr($df_entree); $oterm = $term->getlflag(); $echo = ECHO | ECHOK | ICANON; $noecho = $oterm & ~$echo; sub cbreak {

customer_8566

Safe
$term->setlflag($noecho); $term->setcc(VTIME, 1); $term->setattr($df_entree, TCSANOW); } sub cuisine { $term->setflag($oterm); $term->setcc(VTIME, 0); $term->setattr($df_entree, TCSANOW); } sub lire_un { my $clef = ""; cbreak(); sysread(STDIN, $clef, 1); cuisine(); return $clef; } } END { cuisine() }

861

La page de man du module POSIX donne un inventaire complet des fonctions et constantes quil exporte. Il y en a tant que vous finirez souvent par nen importer quun sousensemble, comme :queue , :sys_stat_h ou :termios_h . Un exemple de blocage de signaux avec le module POSIX est donn au chapitre 16.

Safe
use Safe; $mem_proteg = Safe->new(); # espace mmoire protg anonyme $mem_proteg = Safe->new("Nom_Paquetage"); # dans cette table de symboles # Active ou dsactive les codes dopration par groupe ou par nom $mem_proteg->permit(qw(:base_core)); $mem_proteg->permit_only(qw(:base_core :base_loop :base_mem)); $mem_proteg->deny("die"); # comme do() mais dans lespace mmoire protg $ok = $mem_proteg->rdo($fichier); # comme eval() mais dans lespace mmoire protg $ok = $mem_proteg->reval($code); # sans use strict $ok = $mem_proteg->reval($code, 1); # avec use strict

Le module Safe tente de fournir un environnement restreint pour protger le reste du programme des oprations dangereuses. Il utilise deux stratgies diffrentes pour accomplir ceci. Un peu comme lutilisation de chroot(2) par les dmons FTP anonymes altre la vue que lon a de la racine du systme de fichier, la cration dun objet compartiment avec Safe->new("Nom_Paquetage") altre la vue que ce compartiment a de son propre espace de noms. Le compartiment voit maintenant comme sa table de symboles racine (main::), la table de symboles que le reste du programme voit comme

customer_8566

862

Chapitre 32 Modules standards

Nom_Paquetage::. Ce qui ressemble Bidule:: lintrieur du compartiment est en ralit Nom_Paquetage::Bidule:: lextrieur. Si vous ne donnez pas dargument au constructeur, un nouveau nom de paquetage alatoire est slectionn pour vous. Le second et le plus important service fournit par un compartiment Safe est une manire de limiter le code considr comme lgal lintrieur dun eval. Vous pouvez ajuster lensemble des codes doprations (opcodes) autoriss en utilisant des appels de mthodes sur votre objet Safe. Deux mthodes sont disponibles pour compiler du code dans un compartiment Safe : rdo ( restriction du do ) pour les fichiers et reval ( restriction de leval ) pour les chanes. Ils fonctionnent comme do sur un nom de fichier et comme eval sur une chane mais ils sexcutent dans un espace de noms restreint avec des codes doprations limits. Le premier argument est le nom du fichier ou la chane compiler et le second, qui est optionnel, indique si le code doit tre compil sous use strict ou pas. Il est prvu de rcrire ce module (nous avons lintention disoler lespace mmoire protg dans une tche (thread) dinterprteur diffrente pour une scurit supplmentaire), assurez-vous donc de vrifier la page de man de Safe pour les mises niveau. Voir galement le chapitre 23.

Socket
use Socket; $proto = getprotobyname(udp); socket(SOCK , PF_INET, SOCK_DGRAM, $proto) or die "socket : $!"; $iadr = gethostbyname(hishost.com); $port = getservbyname(time, udp); $sin = sockaddr_in($port, $iadr); send(SOCK, 0, 0, $sin) or die "send : $!"; $proto = getprotobyname(tcp); socket(SOCK, PF_INET, SOCK_STREAM, $proto) or die "socket : $!"; $port = getservbyname(smtp, tcp); $sin = sockaddr_in($port, inet_aton("127.1")); $sin = sockaddr_in(7, inet_aton("localhost")); $sin = sockaddr_in(7, INADDR_LOOPBACK); connect(SOCK, $sin) or die "connect : $!"; ($port, $iadr) = sockaddr_in(getpeerbyname(SOCK )); $hote_pair = gethostbyaddr($iadr, AF_INET); $adr_pair = inet_ntoa($iadr); $proto = getprotobyname(tcp); socket(SOCK, PF_UNIX, SOCK_STREAM, $proto) or die "socket : $!";

customer_8566

Symbol
unlink(/tmp/usock); # XXX : lchec est ignor intentionnellement $sun = sockaddr_un(tmp/usock); connect(SOCK, $sun) or die "connect : $!"; use Socket qw(:DEFAULT :crlf); # Maintenant vous pouvez utiliser CR(), LF() et CRLF() ou # $CR, $LF et $CRLF pour les fins de lignes.

863

Le module Socket donne accs aux constantes du fichier #include sys/socket.h de la bibliothque C pour quon les utilise dans les fonctions de bas niveau de Perl concernant les sockets. Il fournit galement deux fonctions, inet_aton et inet_ntoa, pour convertir les adresses IP entres leurs reprsentations ASCII (comme 127.0.0.1 ) et leur empaquetage rseau, ainsi que deux fonctions spciales dempaquetage/dpaquetage, sockaddr_in et sockaddr_un, qui manipulent les adresses de sockets binaires ncessaires aux appels bas niveau. Le tag dimportation :crlf donne des noms symboliques aux conventions diverses de fin de ligne afin que vous nayez pas vous fier aux interprtations natives de \r et \n, qui peuvent varier. La plupart des protocoles de lInternet prfrent CRLF mais tolrent LF. Le module standard IO::Socket fournit une interface de plus haut niveau TCP Voir le chapitre 16. .

Symbol
use Symbol "delete_package"; delete_package("Truc::Bidule"); print "supprim\n" unless exists $Truc::{"Bidule::"}; use Symbol "gensym"; $sym1 = gensym(); $sym2 = gensym(); package Demo; use Symbol "qualify"; $sym = qualify("x"); $sym = qualify("x", "Truc"); $sym = qualify("Bidule::x"); $sym = qualify("Bidule::x", "Truc");

# Renvoie un nouveau typeglob anonyme. # Et encore un autre.

# # # #

"Demo::x" "Truc::x" "Bidule::x" "Bidule::x"

use Symbol "qualify_to_ref"; sub pass_handle(*) { my $hf = qualify_to_ref(shift, caller); ... } # Maintenant vous pouvez appeler pass_handle avec HF, "HF", *HF ou \*HF.

Le module Symbol fournit des fonctions pour faciliter la manipulation des noms globaux : les typeglobs, les noms de formats, les handles de fichiers, les tables de symboles de paquetages et tout autre chose que vous pourriez vouloir nommer via une table de symboles. La fonction delete_package nettoie compltement lespace de nom dun paquetage (en rendant effectivement anonymes toutes rfrences supplmentaires aux r-

customer_8566

864

Chapitre 32 Modules standards

frants de la tables de symboles, y compris les rfrences de code prcompil). La fonction gensym renvoie un typeglob anonyme chaque fois quelle est appele. (Cette fonction nest plus tellement utilise de nos jours, maintenant que les scalaires indfinis sautovivifient avec les handles de fichiers appropris lorsquils sont utiliss comme arguments de open, pipe, socket et leurs semblables.) La fonction qualify prend un nom qui peut tre compltement qualifi avec un paquetage, ou pas, et renvoie un nom qui lest. Si elle a besoin de prfixer le nom du paquetage, elle utilisera le nom spcifi via le second argument (ou sil est omis, votre nom de paquetage courant). La fonction qualify_to_ref fonctionne de la mme manire mais produit une rfrence au typeglob que le symbole reprsenterait. Ceci est important dans les fonctions qui requirent quils soient passs en tant que rfrences. En convertissant cet argument avec qualify_to_ref, vous pouvez maintenant utiliser le handle fourni mme avec strict refs activ. Vous pouvez galement le consacrer avec bless dans une forme objet, puisquil sagit dune rfrence valide.

Sys::Hostname
use Sys::Hostname; $hote = hostname();

Le module Sys::Hostname ne fournit quune seule fonction, hostname, qui compense ce fait en se remuant le derrire pour essayer de deviner comment votre hte courant sappelle. Sur les systmes qui supportent lappel systme standard gethostname(2), celui-ci est utilis, comme il sagit de la mthode la plus efficace.6 Sur les autres systmes, laffichage de lappel standard hostname(1) est employ. Sur dautres encore, on appelle la fonction uname(3) de votre bibliothque C, laquelle est galement accessible par la fonction POSIX::uname de Perl. Si ces stratgies chouent toutes, dautres efforts hroques sont tents. Quelles que soient les opinions de votre systme sur ce qui est sens ou insens, Perl essaie de son mieux pour faire avec. Sur certains systmes, ce nom dhte peut ne pas tre pleinement qualifi avec le nom de domaine ; voir le module Net::Domain de CPAN si vous avez besoin de cela. Il faut galement prendre en considration que hostname ne renvoie quune seule valeur mais que votre systme peut avoir plusieurs interfaces rseaux configures, vous pouvez donc ne pas vous voir renvoyer le nom associ linterface laquelle vous vous intressez si vous prvoyez dutiliser ce module pour certains types de programmation de sockets. Il sagit des cas o vous devrez probablement glaner dans laffichage de la commande ifconfig(8) ou dans lquivalent moral sur votre systme.

Sys::Syslog
use Sys::Syslog; use Sys::Syslog qw(:DEFAULT setlogsock); # Perd setlogsock. # Obtient galement setlogsock.

6. Laquelle est accessible directement par la fonction non-exporte Sys::Hostname::ghname, mais ne dites personne quon vous la dit.

customer_8566

Sys::Syslog
openlog($programme, cons,pid, user); syslog(info, ceci est un autre test); syslog(mail|warning, ceci est un meilleur test : %d, time()); closelog(); syslog(debug, ceci est le dernier test);

865

setlogsock(unix); openlog("$programme $$", ndelay, user); syslog(info, le problme tait %m); # %m = $! pour le journal systme syslog(notice, prog_truc : ceci est vraiment termin); setlogsock(unix); # "inet" ou "unix" openlog("mon_programme", $logopt, $services); syslog($priorite, $format, @args); $ancien_masque = setlogmask($priorite_masque); closelog();

Le module Sys::Syslog se comporte comme la fonction syslog(3) de votre bibliothque C, en envoyant des messages au dmon de votre journal systme, syslogd(8). Il est particulirement utile dans les dmons ou dautres programmes qui ne disposent pas de terminal pour recevoir les affichages de diagnostics ou pour des programmes proccups par la scurit qui veulent produire un enregistrement plus durable de leurs actions (ou des actions de quelquun dautre). Les fonctions supportes sont : openlog IDENT, LISTE_OPT, SERVICES tablit une connexion avec votre amical dmon syslog. IDENT est la chane sous laquelle enregistrer le message (comme $0, le nom de votre programme). LISTE_OPT est une chane avec des options spares par des virgules comme cons , pid et ndelay . SERVICES est quelque chose comme auth , daemon , kern , lpr , mail , news ou user pour les programmes systme et parmi local0 .. local7 pour les programmes locaux. Davantage de messages sont enregistrs en utilisant un service donne et la chane identificatrice. syslog PRIORITE, FORMAT, ARGS Envoie un message au dmon en employant la PRIORITE donne. Le FORMAT est exactement comme printf en comblant les squences dchappement des pourcentages avec les ARGS qui suivent except le fait quen respectant les conventions de la fonction syslog(3) de la bibliothque standard, la squence spciale %m est interpole avec errno (la variable $! de Perl) cet endroit. setlogsock TYPE TYPE doit valoir soit inet , soit unix . Certains dmons de systmes ne font pas attention par dfaut aux messages de syslog provenant du domaine Internet, vous pouvez alors lui affecter unix la place, puisquil ne sagit pas de la valeur par dfaut. closelog Rompt la connexion avec le dmon.

customer_8566

866

Chapitre 32 Modules standards

Pour que ce module fonctionne avec les versions de Perl antrieures la 5.6.0, votre administrateur systme doit lancer h2ph(1) sur votre fichier den-tte sys/syslog.h pour crer un fichier de bibliothque sys/syslog.ph. Toutefois, ceci ntait pas accompli par dfaut linstallation de Perl. Les versions ultrieures utilisent maintenant une interface XS, la prparation de sys/syslog.ph nest donc plus ncessaire.

Term::Cap
use Term::Cap; $ospeed = eval { require POSIX; my $termios = POSIX::Termios->new(); $termios->getattr; $termios->getospeed; } || 9600; $terminal = Term::Cap->Tgetent({ TERM => undef, OSPEED => $ospeed }); $terminal->Tputs(cl, 1, STDOUT); # Efface lcran. $terminal->Tgoto(cm, $col, $lig, STDOUT); # Dplace le curseur.

Le module Term::Cap donne accs aux routines termcap(3) de votre systme. Voir la documentation de votre systme pour plus de dtails. Le systmes qui ne disposent que de terminfo(5) mais pas de termcap(5) choueront. (Beaucoup de systme terminfo peuvent muler termcap.) Toutefois, vous trouverez sur CPAN un module Term::Info ainsi que Term::ReadKey, Term::ANSIColor et divers modules Curses pour vous aider avec les entres caractre par caractre, les affichages en couleur ou la gestions des crans de terminaux un niveau plus lev que Term::Cap ou Term::Info.

Text::Wrap
use Text::Wrap; # Importe wrap(). @lignes = (< <"FIN_G&S" =~ /\\S.*\S/g); Ceci est particulirement rapide, un boniment inintelligible nest gnralement pas entendu, et sil lest, on sen fiche. FIN_G&S $Text::Wrap::columns = 50; print wrap(" " x 8, " " x 3, @lignes), "\n";

Ceci affiche :

customer_8566

Time::Local
Ceci est particulirement rapide, un boniment inintelligible nest gnralement pas entendu, et sil lest, on sen fiche.

867

Le module Text::Wrap implmente un formateur de paragraphes simples. Sa fonction wrap formate un simple paragraphe la fois en coupant les lignes sans le faire au milieu dun mot. Le premier argument est le prfixe ajout au dbut de la premire ligne renvoye. Le second est la chane utilise comme prfixe pour toutes les lignes sauf la premire. Tous les arguments suivants sont joints en utilisant un saut de ligne comme sparateur et ils sont renvoys comme une seule chane de paragraphe reformate. Vous devez apprcier vous-mme la largeur de votre terminal ou au moins spcifier ce que vous dsirez dans $Text::Wrap::columns. Bien que lon puisse utiliser lappel ioctl TIOCWINSZ pour apprcier le nombre de colonnes, il serait plus facile pour ceux qui ne sont pas habitus la programmation en C, dinstaller le module Term::Readkey de CPAN et dutiliser la routine GetTerminalSize de ce module.

Time::Local
use Time::Local; $date = timelocal($sec,$min,$heures,$jour_m,$mois,$annee); $date = timegm($sec,$min,$heures,$jour_m,$mois,$annee); $date = timelocal(50, 45, 3, 18, 0, 73); print "scalar localtime donne : ", scalar(localtime($date)), "\n"; $date += 28 * 365.2425 * 24 * 60 * 60; print "Vingt-huit annes plus tard, il est maintenant\n\t", scalar(localtime($date)), "\n";

Ceci affiche :
scalar localtime donne : Thu Jan 18 03:45:50 1973 Vingt-huit annes plus tard, il est maintenant Wed Jan 17 22:43:26 2001

Le module Time::Local fournit deux fonctions, timelocal et timegm, qui fonctionne exactement linverse des fonctions localtime et gmtime, respectivement. Cest--dire quelles prennent une liste de valeurs numriques pour les divers composants de ce que localtime renvoie dans un contexte de liste et dterminent quel paramtre pass en entre localtime aurait produit ces valeurs. Vous pouvez utiliser ceci si vous voulez comparer ou lancer des calculs sur deux dates diffrentes. Bien que ces fonctions ne soient pas gnriques pour analyser les dates et les heures, si vous pouvez vous arranger pour avoir vos paramtres dans le bon format, elles sont souvent suffisantes. Comme vous pouvez le voir dans lexemple ci-dessus, la date et lheure possdent tout de mme quelque excentricits et mme de simples calculs chouent souvent pour faire ce quon leur demande cause des annes bissextiles, des secondes intercallaires et de la phase de la lune. Deux modules de CPAN, normes mais complets, soccupent de ces problmes et bien plus encore : Date::Calc et Date::Manip.

customer_8566

868

Chapitre 32 Modules standards

Time::localtime
use Time::localtime; print "Lanne est %d\n", localtime->year() +1900; $maintenant = ctime(); use Time::localtime; use File::stat; $date_chaine = ctime(stat($fichier)->mtime);

Ce module supplante la fonction intrinsque localtime en la remplaant avec une version qui renvoie un objet Time::tm (ou undef en cas dchec). Le module Time::gmtime fait de mme, mais il remplace la fonction intrinsque gmtime la place. Lobjet renvoy possde des mthodes qui accdent aux champs nomms comme ceux de la structure struct tm dans time.h de la bibliothque C : sec, min, hour, mday, mon, year, wday, yday et isdst. La fonction ctime donne un moyen dobtenir la fonction originale (dans son sens scalaire) CORE::localtime. Remarquez que les valeurs renvoyes proviennent directement dune structure struct tm, elles se situent donc dans les mmes intervalles, voir lexemple ci-dessus pour la manire correcte de produire une anne sur quatre chiffres. La fonction POSIX::strftime est encore plus utile pour formater les dates et les heures avec une grande varit de styles plus allchants les uns que les autres.

User::grent
use User::grent; $gr = getgrgid(0) or die "Pas de groupe zro"; if ($gr->name eq "audio" && @{$gr->members} > 1) { print "le gid zro sappelle audio et compte dautres membres"; } $gr = getgr($n_importe_qui); # Accepte la fois une chane ou un nombre. use User::grent :FIELDS; $gr = getgrgid(0) or die "Pas de groupe zro"; if ($gr_name eq "audio" && @gr_members > 1) { print "le gid zro sappelle audio et compte dautres membres"; }

Les exportations par dfaut de ce module supplantent les fonctions intrinsques getgrent, getgruid et getgrnam, en les remplaant par des versions qui renvoient un objet User::grent (ou undef en cas dchec). Cet objet possde des mthodes qui accdent aux champs nomms comme ceux de la structure struct group dans grp.h de la bibliothque C : name, passwd, gid et members (et pas mem comme en C !). Les trois premires renvoient des scalaires et la dernire une rfrence de tableau. Vous pouvez galement importer les champs de la structure dans votre propre espace de noms en tant que variables ordinaires en utilisant le tag dimportation :FIELDS , bien que ceci supplante toujours les fonctions intrinsques. Les variables (les trois scalaires et le tableau) sont prfixes par gr_ . La fonction getgr est une simple bascule frontale qui fait suivre tout argument numrique getgrid et tout argument chane getgrnam.

customer_8566

User::pwent

869

User::pwent
# Par dfaut, supplante seulement les fonctions intrinsques. use User::pwent; $pw = getpwnam("daemon") or die "Pas dutilisateur daemon"; if ($pw->uid == 1 && $pw->dir =~ m#^/(bin|tmp)?$# ) { print "uid 1 sur le rpertoire racine"; } $pw = getpw($n_importe_qui); # Accepte la fois une chane ou un nombre. $shell_reel = $pw->shell || /bin/sh; for (($nom_complet, $bureau, $tel_bur, $tel_maison) = split /\s*,\s*/, $pw->gecos) { s/&/ucfirst(lc($pw->name))/ge; } # positionne des variables globales dans le paquetage courant. use User::pwent qw(:FIELDS); $pw = getpwnam("daemon") or die "Pas dutilisateur daemon"; if ($pw_uid == 1 && $pw_dir =~ m#^/(bin|tmp)?$# ) { print "uid 1 sur le rpertoire racine"; } use User::pwent qw/pw_has/; if (pw_has(qw[gecos expire quota])) { ... } if (pw_has("name uid gid passwd")) { ... } printf "Votre struct pwd supporte [%s]\n", scalar pw_has();

Les exportations par dfaut de ce module supplantent les fonctions intrinsques getpwent, getpwuid et getpwnam, en les remplaant par des versions qui renvoient un objet User::pwent (ou undef en cas dchec). Il est souvent prfrable dutiliser ce module plutt que les fonctions intrinsques quil remplace, car les fonctions intrinsques surchargent, voire omettent divers lments dans la liste renvoyer au nom de la compatibilit ascendante. Lobjet renvoy possde des mthodes qui accdent aux champs nomms comme ceux de la structure passwd dans pwd.h de la bibliothque C, avec le prfixe pw_ en moins : name, passwd, uid, gid, change, age, quota, comment, class, gecos, dir, shell et expire. Les champs passwd, gecos et shell sont marqus. Vous pouvez galement importer les champs de la structure dans votre propre espace de noms en tant que variables ordinaires en utilisant le tag dimportation :FIELDS , bien que ceci supplante toujours les fonctions intrinsques. Vous accdez ces champs en tant que variables scalaires nomm avec un prfixe pw_ devant le nom de la mthode. La fonction getpw est une simple bascule frontale qui fait suivre tout argument numrique getpwuid et tout argument chane getpwnam. Perl croit quaucune machine na plus dun champ parmi change, age ou quota dimplment, ni plus dun parmi comment ou class. Certaines machines ne supportent pas expire, gecos, on dit que certaines machines ne supportent mme pas passwd. Vous pouvez appeler ces mthodes quelle que soit la machine sur laquelle vous tes mais elles

customer_8566

870

Chapitre 32 Modules standards

retourneront undef si elles ne sont pas implmentes. Voir passwd(5) et getpwent(3) pour plus de dtails. Vous pouvez dterminer si ces champs sont implments en le demandant la fonction non-portable pw_has. Elle renvoie vrai si tous les paramtres sont des champs supports sur la plate-forme ou faux si au moins un ne lest pas. Elle lve une exception si vous demandez un champ dont le nom nest pas reconnu. Si vous ne passez aucun argument, elle renvoie la liste des champs que votre bibliothque C pense quils sont supports. Linterprtation du champ gecos varie entre les systmes mais il comprend souvent quatre champs spars par des virgules contenant le nom complet de lutilisateur, lemplacement de son bureau, son tlphone professionnel et son tlphone personnel. Un & dans le champ gecos doit tre remplac par le nom de login, name, de lutilisateur avec les majuscules et minuscules correctes. Si le champ shell est vide, on suppose quil vaut /bin/sh, bien que Perl ne le fasse pas pour vous. Le passwd est donne par une fonction de hachage sens unique produisant du charabia au lieu dun texte lisible, et on ne peut inverser la fonction de hachage en essayant brutalement toutes les combinaisons possibles. Les systmes scuriss utilisent souvent une fonction de hachage plus sre que DES. Sur les systmes supportant les mots de passes cachs, Perl renvoie automatiquement lentre du mot de passe sous sa forme cache lorsquun utilisateur suffisamment puissant lappelle, mme si la bibliothque C sous-jacente fournie par votre constructeur avait une vision trop courte pour raliser quil aurait d faire cela.

customer_8566

Messages de diagnostic

33

Ces messages sont classs dans un ordre croissant de dsespoir :


Classe (W) (D) (S) (F) (P) (X) (A) Signification Un avertissement (optionnel). Une obsolescence (optionnelle). Un avertissement srieux (obligatoire). Une erreur fatale (interceptable). Une erreur interne (panique) que vous ne devriez jamais rencontrer (interceptable). Une erreur extrmement fatale (non-interceptable). Une erreur venue de lau-del (non gnre par Perl).

La plupart des messages des trois premires classifications ci-dessus (W, D et S) peuvent tre contrls en utilisant le pragma warnings ou les options -w et -W. Si un message peut tre contrl avec le pragma warnings, la catgorie correspondante de cet avertissement est donne aprs la lettre de classification ; par exemple, (W misc) indique un avertissement de type divers. Le pragma warnings est dcrit au chapitre 31, Modules de pragmas. Les avertissements peuvent tre capturs plutt quaffichs en faisant pointer $SIG{__WARN__} sur une rfrence de routine qui sera appele pour chaque message. Vous pouvez galement en prendre le contrle avant quune erreur interceptable meure en assignant une rfrence de sous-programme $SIG{__DIE__}, mais si vous nappelez pas die lintrieur de ce gestionnaire, lexception sera toujours prsente en revenant. En dautres termes, il nest pas possible de la dfataliser par ce biais. Vous devez utiliser eval cet effet. Les avertissements par dfaut sont toujours activs sauf sils sont explicitement dsactivs avec le pragma warnings ou loption -X.

customer_8566

872

Chapitre 33 Messages de diagnostic

Dans les messages suivants, %sreprsente une chane interpole qui nest dtermine quau moment de la gnration du message. (De mme, %d reprsente un nombre interpol pensez aux formats de printf, mais %d signifie ici un nombre dans nimporte quelle base.) Remarquez que certains messages commencent par %s do une certaine difficult les classer dans lordre alphabtique. Vous pouvez chercher dans ces messages si celui que vous recherchez napparat pas lendroit attendu. Les symboles "%-?@ sont tris avant les caractres alphabtiques, alors que [ et \ le sont aprs. Si vous tes persuad quun bogue provient de Perl et non de vous, essayez de le rduire un cas de test minimal et faites un rapport avec le programme perlbug qui est fourni avec Perl. N.d.T. Les messages sont indiqus ici en anglais tels quils apparaissent lexcution de vos scripts Perl. Toutefois, nous en donnons ici une traduction pour en faciliter la comprhension. "%s" variable %s masks earlier declaration in same %s (La variable "%s" masque une dclaration prcdente dans la mme %s) (W misc) Une variable my ou our a t redclare dans la porte ou dans linstruction courante, liminant effectivement tout accs linstance prcdente. Il sagit presque toujours dune erreur de typographie. Remarquez que la variable dclare plus tt existera toujours jusqu la fin de la porte ou jusqu ce que toutes les fermetures qui sy rfrent soient dtruites. "my sub" not yet implemented ("my sub" nest pas encore implment) (F) Les sous-programmes de porte lexicale ne sont pas encore implments. Nessayez pas encore cela. "my" variable %s cant be in a package (La variable "my" %s ne peut pas se trouver dans un paquetage) (F) Les variables de porte lexicale ne se trouvent pas dans un paquetage, et il ne sert donc rien dessayer den dclarer une, prfixe dun qualificateur de paquetage. Utilisez local si vous dsirez donner une valeur locale une variable de paquetage. "no" not allowed in expression ("no" nest pas autoris dans une expression) (F) Le mot-clef no est reconnu et excut la compilation et il ne renvoie aucune valeur utile. "our" variable %s redeclared (La variable "our" %s est redclare) (W misc) Il semble que vous avez dj dclar la mme variable globale auparavant dans la mme porte lexicale. "use" not allowed in expression ("use" nest pas autoris dans une expression) (F) Le mot-clef use est reconnu et excut la compilation et il ne renvoie aucune valeur utile.

customer_8566

Chapitre 33 Messages de diagnostic


! allowed_only_after types %s (! nest autoris quaprs les types %s) (F) Le ! nest autoris dans pack et unpack quaprs certains types. | and < may not both be specified on command line

873

(| et < ne peuvent pas tre spcifis en mme temps sur la ligne de commande) (F) Il sagit dune erreur spcifique VMS. Perl effectue ses propres redirections dans la ligne de commande. Il se trouve que STDIN tait un pipe et que vous avez essay de rediriger STDIN en utilisant <. Un seul f lux STDIN par personne, sil vous plat. | and > may not both be specified on command line (| et > ne peuvent pas tre spcifis en mme temps sur la ligne de commande) (F) Il sagit dune erreur spcifique VMS. Perl effectue ses propres redirections dans la ligne de commande et pense que vous avez essay de rediriger STDOUT la fois dans un fichier et dans un pipe vers une autre commande. Vous devez choisir lun ou lautre, bien que rien ne vous empche de rediriger dans un pipe vers un programme ou un script Perl qui spare la sortie standard en deux f lux, comme dans :
open(SORTIE,">$ARGV[0]") or die "Impossible dcrire dans $ARGV[0] : $!"; while (<STDIN>) { print; print SORTIE; } close SORTIE;

/ cannot take a count (/ ne peut pas tre li un compteur) (F) Vous aviez un canevas pour unpack indiquant une chane dune longueur sujette un compteur mais vous avez galement spcifi une taille explicite pour cette chane. / must be followed by a, A ou Z (/ doit tre suivi par A, a ou Z) (F) Vous aviez un canevas pour unpack indiquant une chane dune longueur sujette un compteur ; cette chane doit tre suivie dune des lettres a, A ou Z pour indiquer quelle sorte de chane doit tre dpaquete. / must be followed by a*, A* ou Z* (/ doit tre suivi par A*, a* ou Z*) (F) Vous aviez un canevas pour unpack indiquant une chane dune longueur sujette un compteur. Actuellement, les seules choses dont on peut compter la longueur sont a*, A* ou Z*. / must follow a numeric type (/ doit suivre un type numrique) (F) Vous aviez un canevas pour unpack contenant un #, mais celui-ci ne suivait pas lune des spcifications numriques dunpack.

customer_8566

874
% may only be used in unpack

Chapitre 33 Messages de diagnostic

(% ne peut tre utilis que dans unpack) (F) Vous ne pouvez pas empaqueter une chane avec pack en fournissant une somme de contrle car le traitement de cette dernire fait perdre de linformation et vous ne pouvez pas revenir en arrire. Repeat count in pack overflows (Dpassement du compteur de rptitions dans pack) (F) Vous ne pouvez pas spcifier un compteur de rptitions tellement grand quil dpasse la limite pour vos entiers signs. Repeat count in unpack overflows (Dpassement du compteur de rptitions dans unpack) (F) Vous ne pouvez pas spcifier un compteur de rptitions tellement grand quil dpasse la limite pour vos entiers signs. /%s/ Unrecognized escape \\%c passed through (/%s/ : Rencontre dune squence dchappement \\%c inconnue) (W regexp) Vous avez employ une combinaison avec un caractre antislash qui nest pas reconnue par Perl. Cette combinaison apparat dans une variable interpole ou une expression rgulire dlimite par . Le caractre a t interprt littralement. /%s/ Unrecognized escape \\%c in character class passed through (/%s/ : Rencontre dune squence dchappement \\%c inconnue dans une classe de caractres) (W regexp) Vous avez employ une combinaison avec un caractre antislash qui nest pas reconnue par Perl lintrieur dune classe de caractres. Le caractre a t interprt littralement. /%s/ should probably be written as "%s" (/%s/ devrait probablement tre crit "%s") (W syntax) Vous avez employ un motif l o Perl sattendait trouver une chane, comme dans le premier argument de join. Perl utilisera comme chane le rsultat vrai ou faux de la correspondance entre le motif et $_, ce qui nest probablement pas ce que vous aviez en tte. %s(...) interpreted as function (%s(...) interprt comme une fonction) (W syntax) Vous avez drog la rgle qui dit que tout oprateur de liste suivi par des parenthses devient une fonction prenant comme arguments tous les oprateurs de listes trouv entre les parenthses. %s() called too early to check protoype (%s() appele trop tt pour vrifier le prototype) (W prototype) Vous avez appel une fonction possdant un prototype avant que lanalyseur syntaxique ne voie sa dclaration ou sa dfinition et Perl ne peut pas vrifier si lappel se conforme au prototype. Pour obtenir une vrification correcte

customer_8566

Chapitre 33 Messages de diagnostic

875

du prototype, vous devez soit ajouter une dclaration du prototype pour le sousprogramme en question plus haut dans le code, soit dplacer la dfinition du sousprogramme avant lappel. Ou alors, si vous tes certains dappeler la fonction correctement, vous pouvez mettre une esperluette devant le nom pour viter lavertissement. %s argument is not a HASH or ARRAY element (Largument %s nest un lment ni de HACHAGE, ni de TABLEAU) (F) Largument de exists doit tre un lment de hachage ou de tableau, comme :
$truc{$bidule} $ref->{"susie"}[12]

%s argument is not a HASH or ARRAY element or slice (Largument %s nest un lment ni de HACHAGE, ni de TABLEAU, ni une tranche) (F) Largument de delete doit tre soit un lment de hachage ou de tableau, comme :
$truc{$bidule} $ref->{"susie"}[12]

soit une tranche de hachage ou de tableau, comme :


@truc[$bidule, $machin, $chouette] @{$ref->[12]}{"susie", "queue"}

%s argument is not a subroutine name (Largument %s nest pas un nom de sous-programme) (F) Largument de exists pour exists &sub doit tre un nom de sous-programme et non un appel de sous-programme. exists &sub() gnrera cette erreur. %s did not return a true value (%s na pas renvoy une valeur vraie) (F) Un fichier requis par require (ou utilis par use) doit retourner une valeur vraie pour indiquer quil sest compil correctement et que linitialisation de son code sest bien passe. Il est habituel de placer un 1; la fin dun tel fichier, bien quune quelconque valeur fasse laffaire. %s failed--call queue aborted (%s a chou file dappels abandonne) (F) Une exception non capture a t leve pendant lexcution dun sous-programme CHECK, INIT ou END. Le traitement du reste de la file contenant de telles routines sest termin prmaturment. %s found where operator expected (%s trouv l o lon attendait un oprateur) (S) Lanalyseur lexicographique de Perl sait sil attend un terme ou un oprateur. Sil voit ce quil sait tre un terme alors quil sattend un oprateur, il vous donne ce message dalerte. Habituellement, cela indique quun oprateur ou un sparateur a t omis, comme un point virgule.

customer_8566

876
%s had compilation errors

Chapitre 33 Messages de diagnostic

(%s a engendr des erreurs de compilation) (F) Cest le message final lorsquun perl -c choue. %s has too many errors (%s a engendr trop derreurs) (F) Lanalyseur abandonne son analyse du programme aprs 10 erreurs. Les messages suivant ne seraient pas senss. %s matches null string many times (%s correspond trop de fois la chane vide) (W regexp) Le motif que vous avez spcifi rentrerait dans une boucle infinie si le moteur dexpressions rgulires ne contrlait pas cela. %s never introduced (%s na jamais t introduit) (S internal) Le symbole en question a t dclar mais sa porte sest termine avant quil soit possible de sen servir. %s package attribute may clash with future reserved word: %s (Lattribut de paquetage %s risque de rentrer en conf lit avec le mot %s rserv pour une utilisation ultrieure) (W reserved) Un nom dattribut en minuscules gr par un paquetage spcifique a t utilis. Ce mot pourrait avoir un sens pour Perl un jour, mme si ce nest pas encore le cas. Peut-tre devriez-vous employer la place un nom avec des majuscules et des minuscules mlanges. %s syntax OK (%s syntaxe OK) (F) Message final lorsquun perl -c a russi. %s: Command not found (%s: Commande introuvable) (A) Vous avez lanc accidentellement votre script avec csh au lieu de Perl. Vrifiez la ligne avec #! ou lancez vous-mme votre script manuellement dans Perl avec perl nom_script. %s: Expression syntax (%s: Syntaxe dexpression) (A) Vous avez lanc accidentellement votre script avec csh au lieu de Perl. Vrifiez la ligne avec #! ou lancez vous-mme votre script manuellement dans Perl avec perl nom_script. %s: Undefined variable (%s: Variable indfinie) (A) Vous avez lanc accidentellement votre script avec csh au lieu de Perl. Vrifiez la ligne avec #! ou lancez vous-mme votre script manuellement dans Perl avec perl nom_script.

customer_8566

Chapitre 33 Messages de diagnostic


%s: not found

877

(%s: introuvable) (A) Vous avez lanc accidentellement votre script avec le Bourne Shell au lieu de Perl. Vrifiez la ligne avec #! ou lancez vous-mme votre script manuellement dans Perl avec perl nom_script. (in cleanup) %s ((au nettoyage) %s) (W misc) Ce prfixe indique habituellement quune mthode DESTROY a lev lexception indique. Puisque les destructeurs sont appels habituellement par le systme un moment arbitraire durant lexcution, et bien souvent un grand nombre de fois, cet avertissement nest affich quune seule fois pour tous les checs qui sinon auraient caus une rptition du mme message. Les checs des fonctions de rappel (callbacks) dfinies par lutilisateur et propages par lemploi du f lag G_KEEPERR peuvent galement entraner cet avertissement. Voir perlcall(1). (Missing semicolon on previous line?) (Point-virgule manquant sur la ligne prcdente ?) (S) Il sagit dune supposition donne en complment du message %s found where operator expected . Pour autant, najoutez pas systmatiquement un point-virgule simplement parce que vous avez lu ce message -P not allowed for setuid/setgid script (-P nest pas autoris pour un script setuid/setgid) (F) Le prprocesseur C a voulu ouvrir le script en lappelant par son nom, ce qui entrane une situation de concurrence (N.d.T. : race condition) qui casse la scurit. -T and -B not implemented on filehandles (-T et -B ne sont pas implments sur les handles de fichiers) (F) Perl ne peut utiliser le tampon dentre/sortie du handle de fichier quand il ne connat pas votre type dentres/sorties standards. Vous devez utiliser un nom de fichier la place. -p destination: %s (Destination de -p : %s) (F) Une erreur est survenue durant laffichage sur la sortie standard implicite invoque par loption de la ligne de commande -p. (Cette sortie est redirige vers STDOUT moins que vous ne layez redirige avec select.) 500 Server error (Erreur de serveur 500) Voir Server error (Erreur de serveur). ?+* follows nothing in regexp (?+* ne suivent rien dans lexpression rgulire) (F) Vous avez commenc une expression rationnelle avec un quantifiant. Mettez un antislash devant si vous vouliez lemployer au sens littral.

customer_8566

878
@ outside of string

Chapitre 33 Messages de diagnostic

(@ lextrieur de la chane) (F) Vous aviez un canevas empaquet qui spcifiait une position absolue en dehors de la chane dpaqueter. <> should be quotes (<> devraient tre des apostrophes) (F) Vous avez crit require <fichier> alors que vous auriez d crire require fichier. \1 better written as $1 (Il est prfrable dcrire $1 plutt que \1) (W syntax) lextrieur des motifs, les rfrences arrires (backreferences) existent en tant que variables. Lutilisation dantislashs du ct droit dune substitution tait autorise pour nos grands-pres, mais stylistiquement, il mieux vaut adopter la forme des variables attendue par les autres programmeurs Perl. De plus, cela fonctionne mieux sil y a plus de neuf rfrences arrires. accept() on closed socket %s (accept() sur une socket ferme %s) (W closed) Vous avez tent de faire un accept sur une socket ferme. Peut-tre avezvous oubli de vrifier la valeur retourne par lappel de socket ? Allocation too large: %lx (Allocation trop grande : %lx) (X) Vous ne pouvez allouer plus de 64K sur une machine MS-DOS. Applying %s to %s will act on scalar(%s) (Appliquer %s %s fonctionne avec un scalaire (%s)) (W misc) Les oprateurs de recherche de correspondance (//), de substitution (s///) et de translation (tr///) fonctionnent avec des valeurs scalaires. Si vous appliquez lun deux un tableau ou un hachage, il convertit ce dernier en une valeur scalaire la longueur du tableau ou les informations sur le peuplement du hachage puis travaille sur la valeur scalaire. Ce nest probablement pas ce que vous vouliez faire. Arg too short for msgsnd (Argument trop court pour msgsnd) (F) msgsnd ncessite une chane au moins aussi longue que sizeof(long). Ambiguous use of %s resolved as %s (Utilisation ambigu de %s rsolue avec %s) (W ambiguous | S) Vous avez exprim quelque chose qui nest pas interprt comme vous le pensiez. Normalement il est assez facile de clarifier la situation en rajoutant une apostrophe manquante, un oprateur, une paire de parenthses ou une dclaration.

customer_8566

Chapitre 33 Messages de diagnostic


Ambiguous call resolved as CORE::%s(), qualify as such or use &

879

(Appel ambigu rsolu avec CORE::%s, qualifiez le ainsi ou utiliser &) (W ambiguous) Un sous-programme que vous avez dclar a le mme nom quun mot clef de Perl et vous avez utilis ce nom sans le qualifier pour que lon puisse distinguer lun de lautre. Perl dcide dappeler la fonction interne car votre sousprogramme nest pas import. Pour forcer linterprtation sur lappel de votre sous-programme, mettez une esperluette avant le nom ou qualifiez votre sous-programme avec son nom de paquetage. Ou alors, vous pouvez importer le sous-programme (ou prtendre le faire avec le pragma use subs). Pour linterprter en silence comme loprateur Perl, utilisez le prfixe CORE:: sur cet oprateur (ex. CORE::log($x)) ou dclarez le sous-programme en tant que mthode objet. Args must match #! line (Les arguments doivent correspondre la ligne #!) (F) Lmulateur setuid ncessite que les arguments invoqus par Perl correspondent avec ceux utilis sur la ligne #!. Comme certains systmes imposent un unique argument sur la ligne #!, essayez de combiner les options ; par exemple, changez -w -U en -wU. Argument "%s" isnt numeric (Largument "%s" nest pas numrique) (W numeric) La chane indique est utilise comme un argument avec un oprateur qui sattend plutt une valeur numrique. Si vous tes chanceux, le message indique quel oprateur a t si malchanceux. Array @%s missing the @ in argument %d of %s() (D deprecated) Les versions vraiment antrieures de Perl permettaient domettre le @ des tableaux certains endroits. Ceci est maintenant largement obsolte. assertion botched: %s (assertion sabote : %s) (P) Le paquetage malloc fourni avec Perl a subi une erreur interne. Assertion failed: file "%s" (Lassertion a chou : fichier "%s") (P) Une assertion gnrale a chou. Le fichier en question doit tre examin. Assignment to both a list and a scalar (Assignement simultan une liste et un scalaire) (F) Si vous affectez un oprateur conditionnel, les deuxime et troisime arguments doivent soit tre tous les deux des scalaires, soit tous les deux des listes. Autrement Perl ne connat pas le contexte fournir au ct droit. Attempt to free non-arena SV: 0x%lx (Tentative de librer un SV hors dune zone : 0x%lx) (P internal) Tous les objets SV sont supposs tre allous dans une zone qui sera nettoye la sortie du script. Un SV a t dcouvert en dehors dune de ces zones.

customer_8566

880
Attempt to free nonexistent shared string

Chapitre 33 Messages de diagnostic

(Tentative de librer une chane partage inexistante) (P internal) Perl maintient une table interne qui compte les rfrences de chanes pour optimiser le stockage et laccs au clefs de hachages et aux autres chanes. Ce message indique que quelquun a essay de dcrmenter le compteur de rfrences dune chane que lon ne peut plus trouver dans la table. Attempt to free temp prematurely (Tentative prmature de librer une valeur temporaire) (W debugging) Les valeurs lagonie (mortalized) sont supposes tre libres par la routine interne free_tmps. Ce message indique que quelque chose dautre est en train de librer le SV avant que la routine free_tmps ait une chance de le faire, ce qui signifie que la routine free_tmps librera un scalaire non rfrenc au moment o elle tentera de le faire. Attempt to free unreferenced glob pointers (Tentative de librer des pointeurs de glob non rfrencs) (P internal) Le compteur de rfrences a t endommag en ce qui concerne les alias de symboles. Attempt to free unreferenced scalar (Tentative de librer un scalaire non rfrenc) (W internal) Perl allait dcrmenter un compteur de rfrences dun scalaire pour voir sil arrivait 0 et a dcouvert quil tait dj arriv 0 auparavant et quil se pourrait quil ait t libr et, en fait, quil a probablement t libr. Cela peut indiquer que SvREFCNT_dec a t appel trop de fois ou que SvREFCNT_inc na pas t appel assez de fois ou encore que le SV a t achev (mortalized) alors quil naurait pas d ltre ou enfin que la mmoire a t corrompue. Attempt to join self (Tentative de se rejoindre soi-mme) (F) Vous avez essayer de rejoindre avec join une tche (thread) partir delle-mme, ce qui est une opration impossible. Vous pourriez rejoindre la mauvaise tche ou avoir besoin de dplacer le join vers une autre tche. Attempt to pack pointer to temporary value (Tentative dempaqueter un pointeur vers une valeur temporaire) (W pack) Vous avez essay de passer une valeur temporaire (comme le rsultat dune fonction ou une expression calcule) au canevas p de pack. Cela signifie que le rsultat contient un pointeur vers un endroit qui pourrait devenir invalide tout moment, mme avant la fin de linstruction en cours. Utilisez des valeurs littrales ou globales comme arguments du canevas p de pack pour viter cet avertissement. Attempt to use reference as lvalue in substr (Tentative dutiliser une rfrence en tant que lvalue dans substr) (W substr) Vous avez soumis une rfrence utilise en tant que lvalue comme premier argument de substr, ce qui est vraiment trange. Peut-tre avez-vous oubli de la drfrencer en premier lieu.

customer_8566

Chapitre 33 Messages de diagnostic


Bad arg length for %s, is %d, should be %d

881

(Mauvaise longueur dargument pour %s, vaut %d, devrait valoir %d) (F) Vous avez pass un tampon de taille incorrecte msgctl, semctl ou shmctl. En C, les tailles correctes sont respectivement sizeof(struct msqid_ds *), sizeof(struct semid_ds *) et sizeof(struct shmid_ds *). Bad evalled substitution pattern (Mauvaise valuation du motif de substitution) (F) Vous avez utilis loption /e pour valuer lexpression de remplacement pour une substitution mais Perl a trouv une erreur de syntaxe dans le code valuer, trs certainement une parenthse fermante inattendue. Bad filehandle: %s (Mauvais handle de fichier : %s) (F) Un symbole a t pass quelque chose qui sattendait un handle de fichier mais le symbole na aucun handle de fichier qui lui soit associ. Peut-tre avez-vous oubli de faire un open ou dans vous lavez fait dans un autre paquetage. Bad free() ignored (Mauvais free() ignor) (S malloc) Une routine interne a appel free sur quelque chose qui navait jamais t allou avec malloc dans un premier temps. Ce message est obligatoire mais peut tre dsactiv en positionnant la variable denvironnement PERL_BADFREE 1. Ce message peut tre assez frquent avec DB_file sur les systmes avec une dition de liens dynamiques en dur , comme AIX et OS/2. Cest un bug de Berkeley DB. Bad hash (Mauvais hachage) (P) Une des routines internes concernant un hachage a pass un pointeur HV nul. Bad index while coercing array into hash (Mauvais indice lors de la transformation dun tableau en hachage) (F) La recherche dans le hachage, 0me lment dun pseudo-hachage, a dcouvert un indice illgal. La valeurs des indices doit tre suprieure ou gale 1. Bad name after %s:: (Mauvais nom aprs %s::) (F) Vous avez commenc un nom de symbole en utilisant un prfixe de paquetage puis vous navez pas fini le symbole. En particulier, vous ne pouvez pas faire dinterpolation en dehors des guillemets, ainsi :
$var = ma_var; $sym = mon_paquetage::$var;

nest pas identique :


$var = ma_var; $sym = "mon_paquetage::$var";

Bad realloc() ignored (Mauvais realloc() ignor)

customer_8566

882

Chapitre 33 Messages de diagnostic

(S malloc) Une routine interne a appel realloc sur quelque chose qui navait jamais t allou avec malloc dans un premier temps. Ce message est obligatoire mais peut tre dsactiv en positionnant la variable denvironnement PERL_BADFREE 1. Bad symbol for array (Mauvais symbole pour un tableau) (P) Une requte interne a demand ajouter une entre de tableau quelque chose qui nest pas une entre dans la table des symboles. Bad symbol for filehandle (Mauvais symbole pour un handle de fichier) (P) Une requte interne a demand ajouter une entre de handle de fichier quelque chose qui nest pas une entre dans la table des symboles. Bad symbol for hash (Mauvais symbole pour un hachage) (P) Une requte interne a demand ajouter une entre de hachage quelque chose qui nest pas une entre dans la table des symboles. Badly placed ()s (Parenthses mal disposes) (A) Vous avez lanc accidentellement votre script avec csh au lieu de Perl. Vrifiez la ligne avec #! ou lancez vous-mme votre script dans Perl avec perl nom_script. Bareword "%s" not allowed while "strict subs" in use (Mot simple "%s" interdit lorsque "strict subs" est activ) (F) Avec strict subs activ, un mot simple nest autoris que comme identificateur de sous-programme, entre accolades ou la gauche du symbole =>. Peut-tre devriez-vous dclarer au pralable votre sous-programme ? Bareword "%s" refers to nonexistent package (Le mot simple "%s" se rfre un paquetage inexistant) (W bareword) Vous avez utilis un mot simple qualifi de la forme Truc:: mais le compilateur na pas vu dautre utilisation de cet espace de noms avant cet endroit. Peut-tre devriez-vous dclarer au pralable votre paquetage ? Bareword found in conditional (Mot simple dtect dans une condition) (W bareword) Le compilateur a trouv un mot simple l o il attendait une condition, ce qui indique souvent quun || ou un && a t analys comme faisant partie du dernier argument de la construction prcdente, par exemple :
open FOO || die;

Cela peut galement indiqu une constante mal orthographie qui a t interprte en tant que mot simple :
use constant TYPO => 1; if (TYOP) { print "truc" }

Le pragma strict est trs utile pour viter de telles erreurs.

customer_8566

Chapitre 33 Messages de diagnostic


BEGIN failed--compilation aborted

883

(chec de BEGIN compilation abandonne) (F) Une exception non interceptable a t leve pendant lexcution dun sous-programme BEGIN. La compilation sarrte immdiatement et lon quitte linterprteur. BEGIN not safe after errors--compilation aborted (BEGIN non scuris aprs des erreurs compilation abandonne) (F) Perl a trouv un sous-programme BEGIN (ou une directive use, ce qui implique un BEGIN) aprs quune ou plusieurs erreurs de compilation sont dj survenues. Comme lenvironnement du BEGIN ne peut tre garanti ( cause des erreurs) et comme le code qui suit est susceptible de dpendre de son bon fonctionnement, Perl rend la main. Binary number > 0b11111111111111111111111111111111 non-portable (Nombre binaire >0b11111111111111111111111111111111, non portable) (W portable) Le nombre binaire que vous avez spcifi est plus grand que 2**31-1 (4 294 967 295) et nest donc pas portable entre les systmes. bind() on closed socket %s (bind sur une socket ferme %s) (W closed) Vous avez essay de faire un bind sur une socket ferme. Peut-tre avezvous oubli de vrifier la valeur renvoye par lappel de socket ? Bit vector size > 32 non-portable (Taille de vecteur de bits >32, non portable) (W portable) Lutilisation de tailles de vecteurs de bits suprieures 32 nest pas portable. Bizarre copy of %s in %s (Copie trange de %s dans %s) (P) Perl a dtect une tentative de copie dune valeur interne qui nest pas copiable. Buffer overflow in prime_env_iter: %s (Dpassement du tampon dans prime_env_iter : %s) (W internal) Il sagit dun avertissement spcifique VMS. Pendant que Perl se prparait parcourir %ENV il a rencontr un nom logique ou une dfinition de sym, bole qui tait trop long, il la donc tronqu vers la chane indique. Callback called exit (La fonction de rappel a appel exit) (F) Un sous-programme invoqu depuis un paquetage externe via call_sv sest termine en appelant exit. Cant "goto" out of a pseudo block ("goto" impossible vers lextrieur dun pseudo-bloc) (F) Une instruction goto a t excute pour quitter ce qui semblerait tre un bloc, except que ce nest pas un bloc correct. Ceci se produit habituellement si vous

customer_8566

884

Chapitre 33 Messages de diagnostic

essayez de sauter hors dun bloc sort ou dun sous-programme, ce qui na pas de sens. Cant "goto" into the middle of a foreach loop ("goto" impossible vers le milieu dune boucle foreach) (F) Une instruction goto a t excute pour sauter au milieu dune boucle foreach. Vous ne pouvez y aller depuis cet endroit. Cant "last" outside a loop block ("last" impossible vers lextrieur dun bloc de boucle) (F) Une instruction last a t excute pour sortir du bloc courant, except ce lger problme quil nexiste pas de bloc courant. Remarquez que les blocs if ou else ne comptent pas comme des blocs de boucle, tout comme tout comme les blocs passs sort, map ou grep. Vous pouvez habituellement doubler les accolades pour obtenir le mme effet, car les accolades intrieures seront considres comme un bloc qui boucle une seule fois. Cant "next" outside a loop block ("next" impossible vers lextrieur dun bloc de boucle) (F) Une instruction next a t excute pour recommencer le bloc courant mais il nexiste pas de bloc courant. Remarquez que les blocs if ou else ne comptent pas comme des blocs de boucle, tout comme les blocs passs sort, map ou grep. Vous pouvez habituellement doubler les accolades pour obtenir le mme effet, car les accolades intrieures seront considres comme un bloc qui boucle une seule fois. Cant read CRTL environ (Impossible de lire lenvironnement de CRTL) (S) Il sagit dun avertissement spcifique VMS. Perl a essay de lire un lment de %ENV depuis le tableau denvironnement interne de CRTL et a dcouvert que le tableau nexistait pas. Vous devez dterminer o CRTL a incorrectement plac son environnement ou dfinir PERL_ENV_TABLES (voir perlvms(1)) pour que le tableau denvironnement ne soit pas recherch. Cant "redo" outside a loop block ("redo" impossible vers lextrieur dun bloc de boucle) (F) Une instruction redo a t excute pour recommencer le bloc courant mais il nexiste pas de bloc courant. Remarquez que les blocs if ou else ne comptent pas comme des blocs de boucle, tout comme les blocs passs sort, map ou grep. Vous pouvez habituellement doubler les accolades pour obtenir le mme effet, car les accolades intrieures seront considres comme un bloc qui boucle une seule fois. Cant bless non-reference value (Impossible de consacrer avec bless une valeur qui ne soit pas une rfrence) (F) Seules les rfrences en dur peuvent tre consacres avec bless. Cest de cette manire que Perl applique lencapsulation des objets. Cant break at that line (Impossible de sarrter cette ligne) (S internal) Il sagit dun message derreur qui nest affich que lorsque le pro-

customer_8566

Chapitre 33 Messages de diagnostic

885

gramme sexcute avec le dbogueur, indiquant que le numro de ligne spcifi nest pas lemplacement dune instruction laquelle on peut sarrter. Cant call method "%s" in empty package "%s" (Impossible dappeler la mthode "%s" dans le paquetage vide "%s") (F) Vous avez appel une mthode correctement et vous avez indiqu correctement le paquetage pris en tant que classe, mais ce paquetage na rien de dfini et na pas de mthodes. Cant call method "%s" on unblessed reference (Impossible dappeler la mthode "%s" sur une rfrence non consacre avec bless) (F) Un appel de mthode doit connatre depuis quel paquetage elle est suppos tre lance. Il trouve habituellement ceci dans la rfrence de lobjet que vous soumettez mais vous navez pas fourni de rfrence dobjet dans ce cas. Une rfrence nest pas une rfrence dobjet jusqu ce quelle ait t consacre (avec bless). Cant call method "%s" without a package or object reference (Impossible dappeler la mthode "%s" dans un paquetage ou une rfrence dobjet) (F) Vous avez utilis la syntaxe dun appel de mthode mais la place rserve la rfrence dobjet ou au nom du paquetage contient une expression qui retourne une valeur dfinie qui nest ni une rfrence dobjet ni un nom de paquetage. Quelque chose comme ceci reproduira lerreur :
$MAUVAISE_REF = 42; traite $MAUVAISE_REF 1,2,3; $MAUVAISE_REF->traite(1,2,3);

Cant call method "%s" on an undefined value (Impossible dappeler la mthode "%s" sur une valeur indfinie) (F) Vous avez utilis la syntaxe dun appel de mthode, mais la place rserve la rfrence dobjet ou au nom du paquetage contient une une valeur indfinie. Quelque chose comme ceci reproduira lerreur :
$MAUVAISE_REF = undef; traite $MAUVAISE_REF 1,2,3; $MAUVAISE_REF->traite(1,2,3);

Cant chdir to %s (chdir impossible vers %s) (F) Vous avez appel perl -x/truc/bidule, mais /truc/bidule nest pas un rpertoire dans lequel vous pouvez rentrer avec chdir, probablement parce quil nexiste pas. Cant check filesystem of script "% s" for nosuid (Impossible de vrifier le nosuid pour le systme de fichier du script "%s") (P) Pour une raison ou pour une autre, vous ne pouvez pas vrifier le nosuid pour le systme de fichier du script. Cant coerce %s to integer in %s (Impossible de convertir %s vers un entier dans %s) (F) On ne peut pas forcer certain types de SV en particulier les entres de la table ,

customer_8566

886

Chapitre 33 Messages de diagnostic

des symboles (typeglobs) cesser dtre ce quils sont. Donc vous ne pouvez pas faire des choses telles que :
*truc += 1;

Vous pouvez crire :


$truc = *truc; $truc += 1;

mais alors $truc ne contient plus de glob. Cant coerce %s to number in %s (Impossible de convertir %s vers un nombre dans %s) (F) On ne peut pas forcer certain types de SVs, en particulier les entres de la table des symboles (typeglobs) cesser dtre ce quils sont. Cant coerce %s to string in %s (Impossible de convertir %s vers une chane dans %s) (F) On ne peut pas forcer certain types de SVs, en particulier les entres de la table des symboles (typeglobs) cesser dtre ce quils sont. Cant coerce array into hash (Impossible de convertir un tableau vers un hachage) (F) Vous avez utilis un tableau l o un hachage tait attendu, mais le tableau na pas dinformations sur la manire de passer des cls aux indices de tableau. Vous ne pouvez faire cela quavec les tableaux qui ont une rfrence de hachage lindice 0. Cant create pipe mailbox (Impossible de crer un pipe de bote aux lettres) (P) Il sagit dune erreur spcifique VMS. Le processus souffre de quotas dpasss ou dautres problmes de plomberie. Cant declare class for non-scalar %s in "%s" (Impossible de dclarer une classe pour le non-scalaire %s dans "%s") (S) Actuellement, seules les variables scalaires peuvent tre dclare avec un qualificateur de classe spcifique dans une dclaration my ou our. Les smantiques peuvent tre tendues dautres types de variables lavenir. Cant declare %s in "%s" (Impossible de dclarer %s dans "%s") (F) Seuls les scalaires, les tableaux et les hachages peuvent tre dclars comme variables my ou our. Ils doivent avoir un identificateur ordinaire comme nom. Cant do inplace edit on %s: %s (Impossible dditer sur place %s) (S inplace) La cration du nouveau fichier a chou cause de la raison indique. Cant do inplace edit without backup (Impossible dditer sur place sans copie de sauvegarde) (F) Vous tes sur un systme comme MS-DOS qui sembrouille si vous essayez de lire un fichier supprim (mais toujours ouvert). Vous devez crire -i.bak, ou quelque chose comme a.

customer_8566

Chapitre 33 Messages de diagnostic


Cant do inplace edit: %s would not be unique

887

(Impossible dditer sur place : %s ne serait pas unique) (S inplace) Votre systme de fichier ne supporte pas les noms de fichiers plus longs que 14 caractres et Perl na pas pu crer un nom de fichier unique durant ldition sur place avec loption -i. Ce fichier a t ignor. Cant do inplace edit: %s is not a regular file (Impossible dditer sur place : %s nest pas un fichier ordinaire) (S inplace) Vous avez essay dutiliser loption -i sur un fichier spcial, comme un fichier dans /dev ou une FIFO. Le fichier a t ignor. Cant do setegid! (setegid impossible !) (P) Lappel setegid a chou pour une raison ou pour une autre dans lmulateur setuid de suidperl. Cant do seteuid! (seteuid impossible !) (P) Lmulateur setuid de suidperl a chou pour une raison ou pour une autre. Cant do setuid (setuid impossible) (F) Cela veut gnralement dire que le perl ordinaire a essay de faire exec suidperl pour muler le setuid, mais na pas pu faire le exec. Il cherche un nom de la forme sperl5.000 dans le mme rpertoire que celui o rside lexcutable perl sous le nom perl5.000, gnralement /usr/local/bin sur les machines Unix. Si le fichier sy trouve, vrifiez les permissions dexcution. Sil nest pas l, demandez votre administrateur systme pourquoi. Cant do waitpid with flags (waitpid impossible avec les drapeaux) (F) Cette machine na pas ni waitpid ni wait4, ainsi seul waitpid sans aucun drapeau est mul. Cant do {n,m} with n > m (Impossible de faire {n,m} avec n > m) (F) Les minima doivent tre infrieurs ou gaux aux maxima. Si vous voulez vraiment que votre expression rgulire corresponde 0 fois, faites juste {0}. Cant emulate -%s on #! line (Impossible dmuler -%s sur la ligne #!) (F) La ligne #! spcifie une option qui na pas de sens cet endroit. Par exemple, il serait un peu idiot de mettre loption -x sur cette ligne #!. Cant exec "%s": %s (exec de "%s" impossible : %s) (W exec) Lappel system, exec, ou open sur un pipe na pu sexcuter pour la raison indique. Les raisons typiques incluent de mauvaises permissions sur le fichier,

customer_8566

888

Chapitre 33 Messages de diagnostic

que le fichier na pu tre trouv dans $ENV{PATH}, que lexcutable en question a t compil pour une autre architecture ou que la ligne #! pointe vers un interprteur qui ne peux pas tre lanc pour des raisons similaires. (Ou peut-tre votre systme ne supporte pas du tout #!). Cant exec %s (exec %s impossible) (F) Perl a essay dexcuter le programme indiqu pour vous car cest ce qui est spcifi sur la ligne #!. Si ce nest pas ce que vous vouliez, vous devrez mentionner perl quelque part sur la ligne #!. Cant execute %s (Impossible dexcuter %s) (F) Vous avez utilis loption -S, mais les copies du script excuter trouves dans le PATH nont pas les bonnes permissions. Cant find %s on PATH, . not in PATH (Impossible de trouver %s dans le PATH, "." nest pas dans le PATH) (F) Vous avez utilis loption -S, mais le script excuter ne peut tre trouv dans le PATH ou tout au moins avec des permissions incorrectes. Le script existe dans le rpertoire courant, mais le PATH lempche de se lancer. Cant find %s on PATH (Impossible de trouver %s dans le PATH) (F) Vous utilisez loption -S, mais le script excuter ne peut tre trouv dans le PATH. Cant find an opnumber for "%s" (Impossible de trouver un numro dopration pour "%s") (F) Une chane de la forme CORE::mot a t donne prototype mais il nexiste pas de fonction interne nomme mot. Cant find label %s (Impossible de trouver ltiquette %s) (F) Vous avez dit par un goto daller une tiquette qui nest mentionne aucun endroit o il nous est possible daller. Cant find string terminator %s anywhere before EOF (Impossible de trouver la fin de la chane %s quelque part avant EOF) (F) Les chanes de caractres en Perl peuvent stirer sur plusieurs lignes. Ce message signifie que vous avez oubli le dlimitateur fermant. Comme les parenthses protges par des apostrophes comptent pour un niveau, il manque dans lexemple suivant la parenthse finale :
print q(Le caractre ( commence une nouvelle citation.);

Si vous obtenez cette erreur depuis un document ici-mme (N.d.T. : here document), vous devez avoir mis des espaces blancs non visibles avant ou aprs la marque de fermeture. Un bon diteur pour les programmeurs devrait pouvoir vous aider trouver ces caractres.

customer_8566

Chapitre 33 Messages de diagnostic


Cant fork (fork impossible) (F) Une erreur fatale est survenue en essayant de faire un fork. Cant get filespec - stale stat buffer?

889

(Impossible dobtenir la spcification du fichier tampon stat prim ?) (S) Il sagit dun avertissement spcifique VMS. Ceci arrive cause des diffrences entre les contrles daccs sous VMS et sous le modle Unix qui est celui que Perl prsuppose. Sous VMS, les contrles daccs sont fait par le nom de fichier, plutt que par les bits du tampon de stat, ce qui fait que les ACL et les autres protections peuvent tre pris en compte. Malheureusement, Perl prsuppose que le tampon de stat contient toutes les informations ncessaires et le fournit, la place de la spcification du fichier, la fonction de contrle daccs. Il va essayer dobtenir les spcifications du fichier en utilisant le nom du priphrique et le FID prsents dans le tampon de stat, mais si vous avez fait ensuite un appel la fonction stat de CRTL, cela ne fonctionnera pas car le nom du priphrique est cras chaque appel. Si cet avertissement apparat, la recherche de nom a chou et la fonction de contrle daccs a rendu la main en retournant une valeur fausse, histoire dtre un peu conservateur. (Remarque : la fonction de contrle daccs connat loprateur stat de Perl et les tests de fichiers, vous ne devriez donc jamais voir cet avertissement en rponse une commande Perl ; il ne se produit que si du code interne prend les tampons de stat la lgre.) Cant get pipe mailbox device name (Impossible dobtenir le nom de priphrique dun pipe de bote aux lettres) (P) Il sagit dune erreur spcifique VMS. Aprs avoir cr une bote aux lettres se comportant comme un pipe, Perl ne peut obtenir son nom pour un usage ultrieur. Cant get SYSGEN parameter value for MAXBUF (Impossible dobtenir la valeur du paramtre SYSGEN pour MAXBUF) (P) Il sagit dune erreur spcifique VMS. Perl a demande $GETSYI quelle taille vous voulez pour vos tampons de botes aux lettres et il na pas obtenu de rponse. Cant goto subroutine outside a subroutine (goto vers un sous-programme impossible lextrieur dun sous-programme) (F) Lappel hautement magique goto SOUS_PROGRAMME ne peut que remplacer lappel dune fonction par une autre. Il ne peut en fabriquer une brute de fonderie. En gnral, vous ne devriez de toute faon lappeler que depuis une fonction dAUTOLOAD. Cant goto subroutine from an eval-string (goto vers un sous-programme impossible depuis une chane eval) (F) Lappel goto SOUS_PROGRAMME ne peut tre utilis pour sortir dune chane eval. (Vous pouvez lutilisez pour sortir dun eval BLOC mais ce nest probablement pas ce que vous voulez.)

customer_8566

890

Chapitre 33 Messages de diagnostic

Cant ignore signal CHLD, forcing to default (Impossible dignorer le signal CHLD, la valeur par dfaut est force) (W signal) Perl a dtect quil avait t lanc avec le signal SIGCHLD (quelquefois appel SIGCLD) dsactiv. Comme la dsactivation de ce signal va interfrer avec une dtermination correcte du statut de sortie des processus fils, Perl a remis le signal sa valeur par dfaut. Cette situation indique gnralement que le programme pre sous lequel Perl pourrait tourner (exemple : cron) est trs peu prcautionneux. Cant localize through a reference (Impossible de rendre locale via une rfrence) (F) Vous avez crit quelque chose comme local $$ref, ce que Perl ne sait actuellement pas grer car quand il va restaurer lancienne valeur de ce vers quoi $ref pointait aprs que la porte du local est termine, il ne peut tre sr que $ref soit toujours une rfrence. Cant localize lexical variable % s (Impossible de rendre locale la variable %s) (F) Vous avez utilis local sur une variable qui a dj t dclare auparavant comme une variable lexicale laide de my. Ceci nest pas permis. Si vous voulez rendre locale une variable de paquetage du mme nom, qualifiez-la avec le nom du paquetage. Cant localize pseudo-hash element (Impossible de rendre local un lment de pseudo-hachage) (F) Vous avez crit quelque chose comme local $tab->{clef}, o $tab est une rfrence vers un pseudo-hachage. Cela na pas encore t implment mais vous pouvez obtenir un effet similaire en rendant local llment du tableau correspondant directement - local $tab->[$tab->[0]{clef}]. Cant locate auto/%s.al in @INC (Impossible de trouver auto/%s.al dans @INC) (F) Une fonction (ou une mthode) a t appele dans un paquetage qui autorise le chargement automatique mais il nexiste pas de fonction charger automatiquement. Les causes les plus probables sont une faute de frappe dans le nom de la fonction ou de la mthode ou un chec dans lAutoSplit du fichier, disons, lors du make install. Cant locate %s (Impossible de trouver %s) (F) Vous avez crit de faire un do (ou un require ou un use) sur un fichier qui na pu tre trouv. Perl cherche le fichier dans tous les emplacements mentionns dans @INC, moins que le nom du fichier ne prcise son chemin complet. Peut-tre avezvous besoin de positionner la variable denvironnement PERL5LIB ou PERL5OPT pour indiquer o se trouve la bibliothque ou il est possible que le script ait besoin dajouter le nom de la bibliothque @INC. Ou enfin, vous avez peut-tre seulement mal pel le nom du fichier.

customer_8566

Chapitre 33 Messages de diagnostic


Cant locate object method "%s" via package "%s"

891

(Impossible de trouver la mthode objet "%s" via le paquetage %s) (F) Vous avez appel une mthode correctement et vous avez correctement indiqu un paquetage fonctionnant comme une classe mais ce paquetage ne dfinit pas cette mthode-l, ni aucune de ses classes de base. Cant locate package %s for @%s::ISA (Impossible de trouver le paquetage %s pour @%s::ISA) (W syntax) Le tableau @ISA contient le nom dun autre paquetage qui semble ne pas exister. Cant make list assignment to \%ENV on this system (Impossible dassigner une liste \%ENV sur ce systme) (F) Laffectation dune liste %ENV nest pas support sur certains systmes, notamment VMS. Cant modify %s in %s (Impossible de modifier %s dans %s) (F) Vous ntes pas autoris faire daffectation sur llment indiqu, ou essayer de le changer autrement, comme avec une incrmentation automatique. Cant modify non-lvalue subroutine call (Impossible de modifier un appel de sous-programme qui ne soit pas une lvalue) (F) Les sous-programmes destins tre utiliss dans un contexte de lvalue doivent tre dclars en tant que tels. Cant modify nonexistent substring (Impossible de modifier une sous-chane inexistante) (P) La routine interne qui fait laffectation substr a captur un NULL. Cant msgrcv to read-only var (msgrcv dune var en lecture seule impossible) (F) La cible dun msgrcv doit tre modifiable pour tre utilise comme un tampon de rception. Cant open %s: %s (Impossible douvrir %s: %s) (S inplace) Louverture implicite dun fichier via le handle de fichier <>, soit implicitement via les options de la ligne de commande -n ou -p, soit explicitement, a chou cause de la raison indique. Habituellement cest parce que vous navez pas les permissions en lecture sur le fichier que vous avez indiqu sur la ligne de commande. Cant open bidirectional pipe (Impossible douvrir un pipe bidirectionnel) (W pipe) Vous avez essay dcrire open(CMD, "|cmd|"), ce qui nest pas support. Vous pouvez essayer lun des nombreux modules de la bibliothque Perl pour faire cela, comme IPC::Open2. Ou alors, dirigez la sortie du pipe dans un fichier en utilisant > et ensuite lisez-le dans un handle de fichier diffrent.

customer_8566

892
Cant open error file %s as stderr

Chapitre 33 Messages de diagnostic

(Impossible douvrir le fichier derreur %s comme stderr) (F) Il sagit dune erreur spcifique VMS. Perl fait ses propres redirections de la ligne de commande et ne peut ouvrir le fichier spcifi aprs 2> ou 2>> sur la ligne de commande pour y crire. Cant open input file %s as stdin (Impossible douvrir le fichier dentre %s comme stdin) (F) Il sagit dune erreur spcifique VMS. Perl fait ses propres redirections de la ligne de commande et ne peut ouvrir le fichier spcifi aprs < sur la ligne de commande pour y lire. Cant open output file %s as stdout (Impossible douvrir le fichier de sortie %s comme stdout) (F) Il sagit dune erreur spcifique VMS. Perl fait ses propres redirections de la ligne de commande et ne peut ouvrir le fichier spcifi aprs > ou >> sur la ligne de commande pour y crire. Cant open output pipe (name: %s) (Impossible douvrir le pipe de sortie (nom : %s)) (P) Il sagit dune erreur spcifique VMS. Perl fait ses propres redirections de la ligne de commande et ne peut ouvrir le pipe dans lequel envoyer les donnes destines STDOUT. Cant open perl script "%s": %s (Impossible douvrir le script perl "%s" : %s) (F) Le script que vous avez spcifi ne peut tre ouvert pour la raison indique. Cant redefine active sort subroutine %s (Impossible de redfinir le sous-programme de sort actif) (F) Perl optimise la gestion interne des sous-programmes de sort et garde des pointeurs vers ceux-ci. Vous avez essay de redfinir un de ces sous-programmes de sort alors quil tait actuellement actif, ce qui nest pas permis. Si vous voulez vraiment faire cela, vous devez crire sort { &fonc } @x au lieu de sort fonc @x. Cant remove %s: %s, skipping file (Impossible de supprimer %s: %s, fichier pass) (S inplace) Vous avez demand une dition sur place sans crer un fichier de sauvegarde. Perl a t incapable de supprimer le fichier original pour le remplacer avec celui modifi. Le fichier a t laiss inchang. Cant rename %s to %s: %s, skipping file (Impossible de renommer %s en %s: %s, fichier pass) (S inplace) Le renommage effectu par loption -i a chou pour une raison ou pour une autre, probablement parce que vous navez pas le droit dcrire dans le rpertoire.

customer_8566

Chapitre 33 Messages de diagnostic


Cant reopen input pipe (name: %s) in binary mode

893

(Impossible de rouvrir le pipe dentre (nom : %s) en mode binaire) (P) Il sagit dune erreur spcifique VMS. Perl pensait que STDIN tait un pipe et a essay de le rouvrir pour accepter des donnes binaires. Hlas, cela a chou. Cant resolve method "%s" overloading "%s" in paquetage "%s" (Impossible de rsoudre la mthode "%s" surchargeant "%s" dans le paquetage "%s") (F|P) Une erreur sest produite lors de la rsolution de la surcharge spcifie par un nom de mthode ( linverse dune rfrence de sous-programme) : aucune mthode de ce nom ne peut tre appele via ce paquetage. Si le nom de la mthode est ???, il sagit dune erreur interne. Cant reswap uid and euid (Impossible dchanger nouveau luid et leuid) (P) Lappel setreuid a chou pour une raison ou pour une autre dans lmulateur setuid de suidperl. Cant return outside a subroutine (return impossible lextrieur dun sous-programme) (F) Linstruction return a t excute dans le fil principal du code, cest--dire l o il ny a aucun appel de sous-programme dont on peut revenir avec return. Cant return %s from lvalue subroutine (Impossible de renvoyer %s dun sous-programme utilis comme lvalue) (F) Perl a dtect que la valeur renvoye par un sous-programme utilis comme lvalue est illgale (constante ou variable temporaire). Cest interdit. Cant stat script "%s" (stat du script impossible : %s) (P) Pour une raison ou pour une autre, vous ne pouvez faire de fstat sur le script mme si vous lavez dj ouvert. Bizarre. Cant swap uid and euid (Impossible dchanger luid et leuid) (P) Lappel setreuid a chou pour une raison ou pour une autre dans lmulateur setuid de suidperl. Cant take log of %g (Impossible de calculer le log de %g) (F) Pour les nombres rels ordinaires, vous ne pouvez calculer le logarithme dun nombre ngatif ou nul. Il existe toutefois un paquetage Math::Complex livr en standard avec Perl, si cest vraiment ce que vous voulez faire cela avec les nombres ngatifs. Cant take sqrt of %g (Impossible de calculer la racine carre de %g) (F) Pour les nombres rels ordinaires, vous ne pouvez calculer la racine carre dun

customer_8566

894

Chapitre 33 Messages de diagnostic

nombre ngatif. Il existe toutefois le paquetage Math::Complex livr en standard avec Perl, si vous voulez vraiment faire cela. Cant undef active subroutine (undef du sous-programme actif impossible) (F) Vous ne pouvez rendre indfinie une fonction qui est actuellement utilise. Cependant, vous pouvez la redfinir pendant quelle tourne et mme faire un undef sur le sous-programme redfini pendant que lancien tourne. Maintenant, cest vous de voir. Cant unshift (unshift impossible) (F) Vous avez essay de faire un unshift sur un tableau irrel qui ne peut accepter cette opration, comme la pile principale de Perl. Cant upgrade that kind of scalar (Impossible de mettre niveau ce type de scalaire) (P) La routine interne sv_upgrade a ajout des membres un SV ce qui fait , quil se trouve dans une sorte de SV plus spcialise. Les diffrents types les plus levs de SV sont cependant si spcialiss, quils ne peuvent tre converti entre eux. Ce message indique quune telle conversion a t tente. Cant upgrade to undef (Impossible de mettre niveau vers undef) (P) Le SV indfini reprsente le niveau zro de lvolutivit. Lvolution vers undef indique une erreur dans le code appelant sv_upgrade. Cant use %%! because Errno.pm is not available (Impossible dutiliser %%! car Errno.pm nest pas disponible) (F) La premire fois que le hachage %! est utilis, Perl charge automatiquement le module Errno. On attend du module Errno quil se lie avec tie au hachage %! pour fournir des noms symboliques pour les valeurs des numros derreur de $!. Cant use "my %s" in sort comparison (Impossible dutiliser "my %s" dans les comparaisons de sort) (F) Les variables globales $a et $b sont rserves pour les comparaisons de sort. Vous avez mentionn $a ou $b dans la mme ligne que les oprateurs <=> ou cmp et la variable avait t dclare prcdemment en tant que variable lexicale. Soit qualifiez la variable de sort avec le nom de paquetage, soit renommez la variable lexicale. Cant use %s for loop variable (Impossible dutiliser %s comme variable de boucle) (F) Seule une variable scalaire simple peut tre utilise comme variable de boucle dans un foreach. Cant use %s ref as %s ref (Impossible dutiliser la ref %s en tant que ref de %s) (F) Vous avez mlang vos types de rfrences. Vous devez drfrencer la rfrence

customer_8566

Chapitre 33 Messages de diagnostic

895

du type ncessaire. Vous pouvez utilisez la fonction ref pour tester le type de la rfrence, si besoin. Cant use \%c to mean $%c in expression (Impossible dutiliser \%c pour signifier $%c dans une expression) (W syntax) Dans une expression ordinaire, lantislash est un oprateur unaire qui cre une rfrence vers son argument. Lutilisation dun antislash pour indiquer une rfrence arrire vers une sous-chane russissant la correspondance nest valide qu lintrieur du motif de lexpression rgulire. Essayer de faire cela dans un code ordinaire Perl produit une valeur qui saffiche comme SCALAR(0xdecaf). Utilisez la forme $1 la place. Cant use bareword ("%s") as %s ref while "strict refs" in use (Impossible dutiliser un mot simple ("%s") en tant que ref de %s pendant que "strict refs" est actif) (F) Les rfrences en dur sont les seules autorises par strict refs. Les rfrences symboliques sont interdites. Cant use string ("%s") as %s ref while "strict refs" in use (Impossible dutiliser une chane ("%s") en tant que ref de %s pendant que "strict refs" est actif) (F) Les rfrences en dur sont les seules autorises par strict refs. Les rfrences symboliques sont interdites. Cant use an undefined value as %s reference (Impossible dutiliser une valeur indfinie comme rfrence de %s) (F) Une valeur utilise soit comme une rfrence en dur, soit comme une rfrence symbolique doit avoir une valeur dfinie. Cela aide dbloquer certaines erreurs insidieuses. Cant use global %s in "my" (Impossible dutiliser la variable globale %s dans "my") (F) Vous avez essay de dclarer une variable magique en tant que variable lexicale. Cela nest pas permis car la variable magique ne peut tre lie qu un seul endroit (nomm variable globale) et il serait incroyablement confus davoir des variables dans votre programme qui ressemblent des variables magiques mais qui nen sont pas. Cant use subscript on %s (Impossible dutiliser un indice sur %s) (F) Le compilateur a essay dinterprter une expression entre crochets en tant quindice. Mais gauche des crochets, il y avait une expression qui ne ressemblait pas une rfrence de tableau, ni quoi que ce soit que lon puisse indicer. Cant weaken a nonreference (Impossible daffaiblir une non-rfrence) (F) Vous avez tent daffaiblir quelque chose qui ntait pas une rfrence. Seules les rfrences peuvent tre affaiblies.

customer_8566

896
Cant x= to read-only value

Chapitre 33 Messages de diagnostic

(x= impossible sur une valeur en lecture seule) (F) Vous avez essay de rpter une valeur constante (souvent la valeur indfinie) avec un oprateur daffectation, ce qui implique de modifier la valeur elle mme. Peut-tre devriez-vous copier la valeur dans une variable temporaire, et rpter cela. Character class [:%s:] unknown (Classe de caractres [:%s:] inconnue) (F) La classe dans la syntaxe pour une classe de caractres [: :] est inconnue. Character class syntax [%s] belongs inside character classes (La syntaxe [%s] pour une classe de caractres appartient aux classes de caractres) (W unsafe) Les constructions de classes de caractres [: :], [= =] et [. .] se rangent dans les classes de caractres, par exemple : /[012[:alpha:]345]/. Remarquez que les constructions [= =] et [. .] ne sont pas implmentes actuellement ; ce sont juste des places rserves pour de futures extensions. Character class syntax [. .] is reserved for future extensions (Syntaxe [. .] pour une classe de caractre rserve pour de futures extensions) (W regexp) lintrieur des classes de caractres dans les expressions rgulires ([]), la syntaxe commenant par [. et se terminant par .] est rserve pour de futures extensions. Si vous avez besoin de reprsenter de telles squences de caractres lintrieur dune classe de caractres dans une expression rgulire, protgez simplement les crochets avec un anti-slash : \[. et .\]. Character class syntax [= =] is reserved for future extensions (Syntaxe [= =] pour une classe de caractre rserve pour de futures extensions) (W regexp) lintrieur des classes de caractres dans les expressions rgulires ([]), la syntaxe commenant par [= et se terminant par =] est rserve pour de futures extensions. Si vous avez besoin de reprsenter de telles squences de caractres lintrieur dune classe de caractres dans une expression rgulire, protgez simplement les crochets avec un anti-slash : \[. et .\]. chmod() mode argument is missing initial 0 (Il manque le 0 au dbut de largument reprsentant le mode de chmod()) (W chmod) Un utilisateur novice aura tendance crire :
chmod 777, $fichier

en ne ralisant pas que 777 sera interprt comme un nombre dcimal, quivalent 01411. Les constantes octales sont introduites en les faisant dbuter par un 0 en Perl, tout comme en C. Close on unopened file <%s> (Ferme un fichier non ouvert <%s>) (W) Vous avez essay de fermer un descripteur de fichier qui navait jamais t ouvert.

customer_8566

Chapitre 33 Messages de diagnostic


Compilation failed in require

897

(chec de la compilation dans require) (F) Perl na pas pu compiler le fichier spcifi dans une instruction require. Perl utilise ce message gnrique lorsquaucune des erreurs rencontres nest assez grave pour arrter la compilation immdiatement. Complex regular subexpression recursion limit (%d) exceeded (Limite de rcursion pour les expressions rgulires complexes (%d) atteinte) (W regexp) Le moteur dexpressions rgulires utilise la rcursion dans les situations complexes o les retours arrires sont ncessaires. La profondeur de la rcursion est limite 32 766, ou peut-tre moins sur les architectures o la pile ne peut crotre arbitrairement. (Les situations simples et moyennes peuvent tre gres sans rcursion et ne sont pas sujettes une limite.) Essayez de raccourcir la chane examine, faites des boucles dans le code Perl (exemple : avec while) plutt quavec le moteur dexpressions rgulires ou rcrivez lexpression rgulire pour quelle soit plus simple ou quelle contienne moins de retours arrires. connect() on closed socket %s (connect() sur une socket ferme %s) (W closed) Vous avez essay de faire un connect sur une socket ferme. Peut-tre avez-vous oubli de vrifier la valeur retourne par lappel de socket? Constant is not %s reference (La constante nest pas une rfrence de %s) (F) Une valeur constante (dclare peut-tre en utilisant le pragma use constant) est drfrence mais quivaut une rfrence dun mauvais type. Le message indique le type de rfrence qui tait attendu. Ceci indique habituellement une erreur de syntaxe en drfrenant la valeur constante. Constant subroutine %s redefined (Sous-programme constant %s redfini) (S|W redefine) Vous avez redfini un sous-programme qui a t dsign auparavant comme tant en ligne (inlining). Constant subroutine %s undefined (Sous-programme constant %s indfini) (W misc) Vous avez rendu indfini un sous-programme qui a t dsign auparavant comme tant en ligne (inlining). constant(%s): %s (constant(%s) : %s) (F) Lanalyseur syntaxique a trouv des incohrences soit en tentant de dfinir une constante surcharge, soit en essayant de trouver le nom de caractre spcifi dans la squence dchappement \N{...}. Peut-tre avez-vous oubli de charger les pragmas correspondants overload ou charnames. Copy method did not return a reference (La mthode de copie na pas renvoy de rfrence)

customer_8566

898
(F) La mthode qui surcharge = est bogue. CORE::%s is not a keyword

Chapitre 33 Messages de diagnostic

(CORE::%s nest pas un mot clef) (F) Lespace de noms CORE:: est rserv pour les mots clefs de Perl. Corrupt malloc ptr 0x%lx at 0x%lx (Pointeur de malloc 0x%lx corrompu en 0x%lx) (P) Le paquetage malloc distribu avec Perl a eu une erreur interne. corrupted regexp pointers (Pointeurs dexpressions rgulires corrompus) (P) Le moteur dexpressions rgulires est devenu confus parce que le compilateur dexpressions rgulires lui a donn. corrupted regexp program (Programme dexpressions rgulires corrompu) (P) On a pass au moteur dexpressions rgulires un programme dexpression rgulires sans nombre magique valide. Deep recursion on subroutine "%s" (Rcursion profonde pour le sous-programme "%s") (W recursion) Ce sous-programme sest appel lui-mme (directement ou indirectement) 100 fois de plus quil nest revenu. Ceci indique probablement une rcursion infinie, moins que vous ncriviez un trange programme de benchmark, auquel cas cela indique quelque chose dautre. defined(@array) is deprecated (defined(@tableau) est dprci) (D deprecated) defined nest habituellement pas trs utile sur les tableaux car il teste la prsence dune valeur scalaire indfinie. Si vous voulez voir si le tableau est vide, vous navez qu utiliser if (@tableau) { # pas vide }. defined(%hash) is deprecated (defined(%hachage) est dprci) (D deprecated) defined nest habituellement pas trs utile sur les hachages car il teste la prsence dune valeur scalaire indfinie. Si vous voulez voir si le hachage est vide, vous navez qu utiliser if (%hachage) { # pas vide }. Delimiter for here document is too long (Le dlimiteur pour le document ici-mme est trop long) (F) Dans une construction de document ici-mme , comme <<TRUC, ltiquette TRUC est trop longue pour que Perl puisse la grer. Il faut que vous soyez srieusement tordu pour crire un code qui dclenche cette erreur. Did not produce a valid header (Na pas produit un en-tte valide) Voir Server error.

customer_8566

Chapitre 33 Messages de diagnostic


(Did you mean &%s instead?)

899

(Avez-vous plutt voulu dire &%s ?) (W) Vous avez probablement fait rfrence un sous-programme import &TRUC en faisant $TRUC ou quelque chose du genre. (Did you mean "local" instead of "our"?) (Avez-vous voulu dire "local" plutt que "our" ?) (W misc) Souvenez-vous que our ne rend pas locale la variable dclare comme globale. Vous lavez redclare dans la mme porte lexicale, ce qui semble superf lu. (Did you mean $ or @ instead of %?) (Avez-vous voulu dire $ ou @ plutt que % ?) (W) Vous avez probablement crit %hachage{$clef} alors que vous pensiez $hachage{$clef} ou @hachage{@clefs}. Dun autre ct, peut-tre avez-vous juste voulu dire %hachage et vous vous tes laisss emporter. Died (Mort) (F) Vous avez appel die une chane vide (lquivalent de die "") ou vous lavez appel sans arguments et la fois $@ et $_ taient vides. (Do you need to predeclare %s?) (Avez-vous besoin de prdclarer %s) (S) Il sagit dune supposition donne en complment du message %s found where operator expected . Cela veut souvent dire quun nom de sous-programme ou de module a t rfrenc alors quil na pas encore t dfini. Cest peut tre un problme dordre dans votre fichier ou parce quil manque une instruction sub, package, require ou use. Si vous rfrencez quelque chose qui nest pas encore dfini, en fait vous navez pas dfinir le sous-programme ou le paquetage avant cet endroit. Vous pouvez utilisez un sub truc; ou un package TRUC; vide pour entrer une dclaration par avance . Document contains no data (Le document ne contient pas de donnes) Voir Server error. Dont know how to handle magic of type %s (Ne sait pas comment grer la magie du type %s) (P) On a jet un sort sur la gestion interne des variables magiques. do_study: out of memory (do_study : dbordement de mmoire) (P) Ce message aurait plutt d tre captur par safemalloc. Duplicate free() ignored (Duplication de free() ignore) (S malloc) Une routine interne a appel free sur quelque chose qui a dj t libr.

customer_8566

900
elseif should be elsif

Chapitre 33 Messages de diagnostic

(elseif devrait tre elsif) (S) Il ny a pas de mot-clef elseif en Perl car Larry pense que cest trs laid. Votre code sera interprt comme une tentative dappel la mthode nomme elseif pour la classe renvoye par le bloc qui suit. Ce nest srement pas ce que vous voulez. entering effective %s failed (Lentre dans %s effectif a chou) (F) Alors que le pragma use filetest tait actif, lchange entre les UID ou les GID rels et effectifs a chou. Error converting file specification %s (Erreur en convertissant la spcification de fichier %s) (F) Il sagit dune erreur spcifique VMS. Comme Perl doit grer des spcifications de fichiers dans les syntaxes VMS ou Unix, il convertit celles-ci dans un format unique lorsquil doit les traiter directement. Soit vous avez pass des spcifications de fichier invalides, soit vous avez trouv un cas que les routines de conversion ne grent pas. Zut ! %s: Eval-group in insecure regular expression (%s : Groupe eval dans une expression rgulire non scurise) (F) Perl a dtect une donne marque en essayant de compiler une expression rgulire qui contient lassertion de longueur zro (?{ ... }) , ce qui nest pas scuris. %s: Eval-group not allowed, use re eval (%s : Groupe eval interdit, utilisez use re eval) (F) Une expression rgulire contenait lassertion de longueur nulle (?{ ... }), mais cette construction est seulement permise quand le pragma use re eval est actif. %s: Eval-group not allowed at run time (%s : Groupe eval interdit lexcution) (F) Perl a essay de compiler une expression rgulire contenant lassertion de longueur nulle (?{ ... }) lexcution, comme il le ferait si le motif contenait des valeurs interpoles. Comme cest un risque de scurit, cela nest pas permis. Si vous insistez, vous pouvez toujours le faire en construisant explicitement votre motif depuis une chane interpole lexcution et lutiliser dans un eval. Excessively long <> operator (Oprateur <> excessivement long) (F) Le contenu dun oprateur <> ne doit pas excder la taille maximum dun identificateur Perl. Si vous essayez seulement dobtenir les extensions dune longue liste de fichiers, essayez dutiliser loprateur glob ou mettez les noms de fichiers dans une variable et faites un glob dessus.

customer_8566

Chapitre 33 Messages de diagnostic


Execution of %s aborted due to compilation errors (Excution de %s abandonne cause derreurs de compilation) (F) Le message de rsum final lorsquune compilation Perl choue. Exiting eval via %s

901

(Sortie dun eval via %s) (W exiting) Vous tes sorti dun eval dune faon non conventionnelle, comme un goto ou une instruction de contrle de boucle. Exiting format via %s (Sortie dun format via %s) (W exiting) Vous tes sorti dun format dune faon non conventionnelle, comme un goto ou une instruction de contrle de boucle. Exiting pseudoblock via %s (Sortie dun pseudo-bloc via %s) (W exiting) Vous tes sorti dune construction tout fait spciale de bloc (comme un bloc ou un sous-programme de sort) dune faon non conventionnelle, comme un goto, ou une instruction de contrle de boucle. Exiting subroutine via %s (Sortie dun sous-programme via %s) (W exiting) Vous tes sorti dun sous-programme dune faon non conventionnelle, comme un goto ou une instruction de contrle de boucle. Exiting substitution via %s (Sortie dune substitution via %s) (W exiting) Vous tes sorti dune substitution dune faon non conventionnelle, comme un goto ou une instruction de contrle de boucle. Explicit blessing to (assuming package main) (Conscration par bless explicite vers (paquetage principal main adopt)) (W misc) Vous avez consacr par bless une rfrence une chane de longueur nulle. Cela a pour effet de consacrer la rfrence dans le paquetage principal main. Ce nest pas habituellement ce que vous voulez. Pensez fournir un paquetage cible par dfaut, comme dans bless($ref, $p || Mon_Paquetage); false [] range "%s" in regexp (Faux intervalle [] "%s" dans lexpression rgulire) (W regexp) Un intervalle de classe de caractres doit dbuter et finir par un caractre littral et non par une autre classe de caractres comme \d ou [:alpha:]. Le dans votre faux intervalle est interprt comme un - littral. Pensez protger le comme cela : \-. Fatal VMS error at %s, line %d (Erreur VMS fatale dans %s, ligne %d) (P) Il sagit dune erreur spcifique VMS. Il sest pass quelque chose de fcheux dans un service du systme VMS ou dans une routine CRTL ; le statut de sortie de

customer_8566

902

Chapitre 33 Messages de diagnostic

Perl devrait fournir plus de dtails. Le nom de fichier dans at %s et le numro de ligne dans line %d vous indiquent quelle section du code source Perl a t affecte. fcntl is not implemented (fcntl non implment) (F) Votre machine nimplmente apparemment pas fcntl. Quest-ce que cest que a, un PDP-11 ou quelque chose de similaire ? Filehandle %s never opened (Handle de fichier %s jamais ouvert) (W unopened) Une opration dentre/sortie a t tente sur un handle de fichier qui na jamais t initialis. Vous devez faire un appel open ou socket ou appeler un constructeur du module FileHandle. Filehandle %s opened only for input (Handle de fichier %s ouvert seulement pour les entres) (W io) Vous avez tent dcrire dans un handle de fichier ouvert en lecture seule. Si vous vouliez que ce soit un handle de fichier ouvert en lecture-criture, vous deviez louvrir avec +<, +> ou +>> au lieu de < ou rien du tout. Si vous dsiriez uniquement crire dans le fichier, utilisez > ou >>. Filehandle %s opened only for output (Handle de fichier %s ouvert seulement pour les sorties) (W io) Vous avez tent de lire dans un handle de fichier ouvert en criture seule. Si vous vouliez que ce soit un handle de fichier ouvert en lecture-criture, vous deviez louvrir avec +<, +> ou +>> au lieu de < ou rien du tout. Si vous dsiriez uniquement lire dans le fichier, utilisez <. Final $ should be \$ or $name ($ final devrait tre \$ ou $nom) (F) Vous devez maintenant dcider si le $ final dans une chane devait tre interprt comme le signe dollar littral ou sil tait l pour introduire un nom de variable savrant manquer. Vous devez donc ajouter soit lantislash, soit le nom. Final @ should be \@ or @name (@ final devrait tre \@ ou @nom) (F) Vous devez maintenant dcider si le @ final dans une chane devait tre interprt comme le signe arobase littral ou sil tait l pour introduire un nom de variable savrant manquer. Vous devez donc ajouter soit lantislash, soit le nom. flock() on close filehandle %s (flock() sur un handle de fichier ferm %s) (W closed) Le handle de fichier sur lequel vous avez essay de faire flock a t luimme ferm quelque temps auparavant. Vrifiez le f lux logique de votre programme. flock agit sur des handles de fichiers. Avez-vous tent dappeler flock sur un handle de rpertoire du mme nom ? Format %s redefined (Format %s redfini)

customer_8566

Chapitre 33 Messages de diagnostic

903

(W redefine) Vous avez redfini un format. Pour supprimer cet avertissement, crivez
{ no warnings; eval "format NAME =..."; }

Format not terminated (Format inachev) (F) Un format doit tre termin par une ligne contenant uniquement un point. Perl est arriv en fin de fichier sans trouver une telle ligne. Found = in conditional, should be == (= trouv dans une condition, devrait tre ==) (W syntax) Vous avez crit :
if ($truc = 123)

alors que vous vouliez dire :


if ($truc == 123)

(ou quelque chose de similaire). gdbm store returned %d, errno %d, key "%s" (Le stockage gdbm a renvoy %d, numro derreur %d, clef "%s") (S) Un avertissement de lextension GDBM_File indique quun stockage a chou. gethostent not implemented (gethostent non implment) (F) Votre bibliothque C nimplmente apparemment pas gethostent, probablement parce que si elle le faisait, elle se sentirait moralement oblige de renvoyer chaque nom dhte existant sur Internet. get%sname() on closed socket %s (get%sname() sur une socket ferme %s) (W closed) Vous avez essay dobtenir une socket ou une socket parente dune socket ferme. Peut-tre avez-vous oubli de vrifier la valeur renvoye par lappel socket ? getpwnam returned invalid UIC %#o for user "%s" (getpwname a renvoy lUIC %#0 invalide pour lutilisateur "%s") (S) Il sagit dun avertissement spcifique VMS. Lappel sys$getuai, sous-jacent de loprateur getpwnam, a retourn une UIC invalide. glob failed (%s) (chec du glob) (W glob) Quelque chose sest mal pass avec le(s) programme(s) externe(s) utilis(s) par glob et <*.c>. Habituellement, cela signifie que vous avez fourni un motif de glob qui a entran lchec du programme externe qui sest termin avec un statut diffrent de zro. Si le message indique que la sortie anormale a engendr une copie du cur du programme (core dump), ceci peut galement vouloir dire que

customer_8566

904

Chapitre 33 Messages de diagnostic

votre csh (C shell) est corrompu. Si cest le cas, vous devriez changer toutes les variables se rapportant csh dans config.sh. Si vous utilisez tcsh, changez les variables qui sy rfrent comme si ctait csh. (ex. full_csh=/usr/bin/tcsh) ; sinon, videz-les toutes (sauf d_csh qui devrait valoir undef) pour que Perl croit quil manque csh. Dans tous les cas, une fois config.sh mis jour, lancez ./Configure -S et reconstruisez Perl. Glob not terminated (Glob non termin) (F) Lanalyseur lexical a vu un signe infrieur un endroit o il sattendait trouver un terme, il recherche donc le signe suprieur correspondant et ne le trouve pas. Il y a des chances que vous ayez oubli des parenthses ncessaires auparavant dans la ligne et que vous avez rellement voulu dire le symbole <. Global symbol "%s" requires explicit package name (Le symbole global "%s" exige un nom de paquetage explicite) (F) Vous avez crit use strict vars, ce qui indique que toutes les variables doivent soit avoir une porte lexicale (en utilisant my), soit tre dclars au pralable en utilisant our, soit tre explicitement qualifies pour dire quel paquetage la variable globale appartient (en utilisant ::). Got an error from DosAllocMem (Erreur rencontre depuis DosAllocMem) (P) Il sagit dune erreur spcifique OS/2. Le plus probable est que vous employez une version obsolte de Perl, cette erreur ne devrait donc jamais se produire de toute faon. goto must have label (goto doit avoir une tiquette) (F) Au contraire de next et de last, vous ntes pas autoriss faire un goto vers une destination non spcifie. Had to create %s unexpectedly (A d crer %s de manire inattendue) (S internal) Une routine a demand un symbole dans une table des symboles qui aurait d dj exister mais pour une raison ou pour une autre ce ntait pas le cas elle a t cre en urgence pour viter une copie du cur du programme (core dump). Hash %%s missing the % in argument %d of %s() (Il manque le % du hachage %%s dans largument %d de %s()) (D deprecated) Seules les versions de Perl vraiment anciennes vous permettaient domettre le % dans les noms de hachage certains endroits. Cest maintenant largement obsolte. Hexadecimal number > 0xffffffff non-portable (Nombre hexadcimal > 0xffffffff, non portable) (W portable) Le nombre hexadcimal que vous avez spcifi est plus grand que 2**32-1 (4 294 967 295) et nest donc pas portable dun systme lautre.

customer_8566

Chapitre 33 Messages de diagnostic


Identifier too long

905

(Identificateur trop long) (F) Perl limite la taille des identificateurs (noms des variables, fonctions, etc.) 250 caractres environ pour les noms simples et un peu plus pour les noms composs (comme $A::B). Vous avez dpass les limites de Perl. Les futures versions de Perl seront susceptibles dliminer ces limitations arbitraires. Ill-formed CRTL environ value "%s" (Valeur denvironnement de CRTL "%s" mal forme) (W internal) Il sagit dun avertissement spcifique VMS. Perl a essay de lire le tableau denvironnement interne de CRTL et a rencontr un lment sans le sparateur = utilis pour sparer les clefs des valeurs. Llment est ignor. Ill-formed message in prime_env_iter: |%s| (Message mal form dans prime_env_iter : |%s|) (W internal) Il sagit dun avertissement spcifique VMS. Perl a essay de lire un nom logique ou une dfinition de symbole CLI en se prparant parcourir %ENV et il na pas vu le sparateur attendu entre les clefs et les valeurs, la ligne a donc t ignore. Illegal character %s (carriage return) (Caractre illgal %s (retour chariot)) (F) Dordinaire, Perl traite les retours chariots dans le texte du programme au mme titre que nimporte quel autre caractre despacement, ce qui signifie que vous ne devriez jamais voir cette erreur lorsque Perl a t construit en utilisant les options standards. Pour une raison ou pour une autre, votre version de Perl semble avoir t construite sans ce support. Parlez-en votre administrateur Perl. Illegal division by zero (Division par zro illgale) (F) Vous avez essay de diviser un nombre par 0. Soit quelque chose clochait dans votre logique, soit vous devez placer une condition pour vous prserver de cette entre dnue de sens. Illegal modulus zero (Modulo zro illgal) (F) Vous avez essay de diviser un nombre par 0 pour obtenir le reste. La plupart des nombres ne peuvent faire cela gentiment. Illegal binary digit (Chiffre binaire illgal) (F) Vous avez utilis un chiffre autre que 0 ou 1 dans un nombre binaire. Illegal octal digit (Chiffre octal illgal) (F) Vous avez utilis un 8 ou un 9 dans un nombre octal.

customer_8566

906
Illegal binary digit %s ignored

Chapitre 33 Messages de diagnostic

(Chiffre binaire illgal %s, ignor) (W digit) Vous avez essay dutiliser un chiffre autre que 0 ou 1 dans un nombre binaire. Linterprtation du nombre binaire sest arrte avant le chiffre en cause. Illegal octal digit %s ignored (Chiffre octal illgal %s, ignor) (W digit) Vous avez peut-tre essay dutiliser un 8 ou un 9 dans un nombre octal. Linterprtation du nombre octal sest arrte avant le 8 ou le 9. Illegal hexadecimal digit %s ignored (Chiffre hexadcimal illgal %s, ignor) (W digit) Vous avez essay dutiliser un caractre autre qui nest ni entre 0 et 9, ni entre A et F, ni entre a et f dans un nombre hexadcimal. Linterprtation du nombre hexadcimal sest arrte avant le caractre illgal. Illegal number of bits in vec (Nombre de bits illgal dans vec) (F) Le nombre de bits dans vec (le troisime argument) doit tre une puissance de deux de 1 32 (ou 64 si votre plate-forme le supporte). Illegal switch in PERL5OPT: %s (Option illgale dans PERL5OPT : %s) (X) La variable denvironnement PERL5OPT ne peut tre utilise que pour positionner les options suivantes : -[DIMUdmw]. In string, @%s now must be written as \@%s (Dans une chane, @%s doit maintenant scrire \@%s) (F) Perl essayait auparavant de deviner si vous vouliez un tableau interpol ou un @ littral. Il faisait ceci lorsque la chane tait utilise la premire fois pendant lexcution. Les chanes sont maintenant analyses la compilation et les instances ambigus de @ doivent tre claircies, soit en prfixant par un antislash pour indiquer quil sagit dun littral, soit en dclarant (ou en utilisant) le tableau dans le programme avant la chane (lexicalement). (Un jour un @ sans antislash sera simplement interprt comme une interpolation dun tableau.) Insecure dependency in %s (Dpendance non scurise dans %s) (F) Vous avez essay de faire quelque chose que le mcanisme de marquage des variables na pas apprci. Ce mcanisme de marquage est activ quand vous excutez un script setuid ou setgid, ou lorsque vous spcifiez -T pour lactiver explicitement. Le mcanisme de marquage tiquette toutes les donnes drives directement ou indirectement de lutilisateur, qui est considr indigne de votre confiance. Si lune de ces donnes est utilise dans une opration dangereuse , vous obtenez cette erreur. Insecure directory in %s (Rpertoire non scuris dans %s)

customer_8566

Chapitre 33 Messages de diagnostic

907

(F) Vous ne pouvez utilisez system, exec ou un pipe ouvert vers un script setuid ou setgid si $ENV{PATH} contient un rpertoire qui a les droits en criture pour tout le monde. Insecure $ENV{%s} while running %s ($ENV{%s} non scuris alors que %s est en train de tourner) (F) Vous ne pouvez utilisez system, exec ou un pipe ouvert vers un script setuid ou setgid si $ENV{PATH}, $ENV{IFS}, $ENV{CDPATH}, $ENV{ENV} ou $ENV{BASH_ENV} sont drivs de donnes fournies (ou potentiellement fournies) par lutilisateur. Le script doit positionner le chemin une valeur connue, en utilisant une donne digne de confiance. Integer overflow in %s number (Dpassement dentier dans le nombre %s) (W overf low) Le nombre hexadcimal, octal ou binaire que vous avez spcifi soit comme littral, soit comme argument de hex ou oct est trop grand pour votre architecture. Sur les machines 32-bits ,les plus grands nombres hexadcimaux, octaux ou binaires reprsentables sans dpassement sont 0xFFFFFFFF, 037777777777 et 0b11111111111111111111111111111111, respectivement. Remarquez que Perl lve de manire transparente tous les nombres vers une reprsentation interne en virgule f lottante sujette des erreurs de perte de prcision dans les opration ultrieures. Internal inconsistency in tracking vforks (Incohrence interne dans la recherche des vforks) (S) Il sagit dun avertissement spcifique VMS. Perl garde une trace du nombre de fois o vous avez appel fork et exec, pour dterminer si lappel courant exec devrait affecter le script en cours ou un sous-processus (Voir exec LIST dans perlvms(1)). De toute faon, ce compte est devenu perturb, Perl fait donc une supposition et traite ce exec comme une requte pour terminer le script Perl et excuter la commande spcifie. internal disaster in regexp (dsastre interne dans une expression rgulire) (P) Quelque chose sest trs mal pass dans lanalyseur dexpressions rgulires. internal urp in regexp at /%s/ (gloups interne dans une expression rgulire) (P) Quelque chose a trs mal tourn dans lanalyseur dexpressions rgulires. Invalid %s attribute: %s (Attribut %s invalide : %s) (F) Lattribut indiqu pour un sous-programme ou une variable na pas t reconnu par Perl ou par un gestionnaire fourni par lutilisateur. Invalid %s attributes: %s (Attributs %s invalides : %s) (F) Les attributs indiqus pour un sous-programme ou une variable nont pas t reconnus par Perl ou par un gestionnaire fourni par lutilisateur.

customer_8566

908
invalid [] range "%s" in regexp

Chapitre 33 Messages de diagnostic

(Intervalle [] "%s" invalide dans lexpression rgulire) (F) Lintervalle spcifi dans une classe de caractres a un caractre de dbut suprieur au caractre de fin. Invalid conversion in %s: "%s" (Conversion invalide dans %s : "%s") (W printf) Perl ne comprend pas le format de conversion donn. Invalid separator character %s in attribute list (Caractre de sparation %s invalide dans la liste dattributs) (F) Quelque chose dautre quun deux-points ou quun espacement a t dtect entre les lments dune liste dattributs. Si lattribut prcdent avait une liste de paramtres entre parenthses, peut-tre que cette liste sest termine trop tt. Invalid type in pack: %s (Type invalide dans pack : %s) (F) Le caractre donn nest pas un type dempaquetage valide. (W pack) Le caractre donn nest pas un type dempaquetage valide mais lhabitude tait de lignorer silencieusement. Invalid type in unpack: %s (Type invalide dans unpack : %s) (F) Le caractre donn nest pas un type de dpaquetage valide. (W unpack) Le caractre donn nest pas un type de dpaquetage valide mais lhabitude tait de lignorer silencieusement. ioctl is not implemented (F) Votre machine nimplmente apparemment pas ioctl, ce qui est quelque peu surprenant de la part dune machine qui supporte le C. junk on end of regexp (Dchets la fin de lexpression rgulire) (P) Lanalyseur dexpressions rgulires sest embrouill. Label not found for "last %s" (tiquette introuvable pour "last %s") (F) Vous avez nomm une boucle pour en sortir mais vous ntes pas actuellement dans une boucle de ce nom, mme si vous comptez do vous avez t appel. Label not found for "next %s" (tiquette introuvable pour "next %s") (F) Vous avez nomm une boucle pour effectuer litration suivante mais vous ntes pas actuellement dans une boucle de ce nom, mme si vous comptez do vous avez t appel. Label not found for "redo %s" (tiquette introuvable pour "redo %s")

customer_8566

Chapitre 33 Messages de diagnostic

909

(F) Vous avez nomm une boucle pour recommencer litration en cours mais vous ntes pas actuellement dans une boucle de ce nom, mme si vous comptez do vous avez t appel. leaving effective %s failed (la sortie de %s effectif a chou) (F) Alors que le pragma use filetest tait actif, lchange entre les UID ou les GID rels et effectifs a chou. listen() on closed socket %s (listen() sur une socket ferme %s) (W closed) Vous avez essay de faire un listen sur une socket ferme. Peut-tre avez-vous oubli de vrifier la valeur renvoye par votre appel socket ? Lvalue subs returning %s not implemented yet (Sous-programmes en tant que lvalue retournant %s pas encore implments) (F) cause de limitations dans limplmentation actuelle, les valeurs de tableaux et de hachages ne peuvent pas tre renvoyes dans un contexte de lvalue. Malformed PERLLIB_PREFIX (PERLLIB_PREFIX malforme) (F) Il sagit dune erreur spcifique OS/2. PERLLIB_PREFIX doit tre de la forme :
prefixe1 ;prefixe2

ou :
prefixe1 prefixe2

avec prefixe1 et prefixe2 non vides. Si prefixe1 est en fait un prfixe dun chemin de recherche de bibliothque interne, on lui substitue prefixe2. Lerreur peut survenir si les composants ne sont pas trouvs ou sils sont trop longs. Voir PERLLIB_PREFIX dans le fichier README.os2 inclus dans la distribution de Perl. Method for operation %s not found in package %s during blessing (La mthode pour lopration %s na pas t trouve dans le paquetage %s durant la conscration avec bless) (F) Une tentative a t effectue pour spcifier une entre dans une table de surcharge qui ne peut tre rsolue par un sous-programme valide. Method %s not permitted (Mthode %s interdite) Voir Server error. Might be a runaway multi-line %s string starting on line %d (%s pourrait tre une chane galopant sur plusieurs lignes, dbutant la ligne %d) (S) Une suggestion indiquant que lerreur prcdente peut avoir t cause par un sparateur manquant dans une chane ou un motif car la chane se finissait ventuellement plus tt sur la ligne courante. Misplaced _ in number (_ mal plac dans un nombre)

customer_8566

910

Chapitre 33 Messages de diagnostic

(W syntax) Un caractre soulign dans une constante dcimale ntait pas sur une limite de 3 chiffres. Missing $ on loop variable ($ manquant dans un variable de boucle) (F) Apparemment, vous avez programm en csh un peu trop longtemps. Les variables en Perl sont toujours prcdes du $, au contraire des shells, ou cela peut varier dune ligne lautre. Missing %sbrace%s on \N{} (%saccolades%s manquantes sur \N{}) (F) Vous avez employ la mauvaise syntaxe de nom de caractre littral \N{nom_caractere} lintrieur dun contexte de guillemets. Missing comma after first argument to %s function (Virgule manquante aprs le premier argument de la fonction %s) (F) Alors que certaines fonctions vous permettent de spcifier un handle de fichier ou un objet indirect avant la liste darguments, celle-ci nen fait pas partie. Missing command in piped open (Commande manquante dans un open avec un pipe) (W pipe) Vous avez utilis la construction open(HF, "| commande") ou open(HF, "commande |") mais il manquait la commande ou alors elle tait vide. Missing name in "my sub" (Nom manquant dans "my sub") (F) La syntaxe rserve pour les sous-programmes de porte lexicale exige quils aient un nom par lequel on puisse les trouver. (Missing operator before %s?) (Oprateur manquant avant %s ?) (S) Il sagit dune supposition donne en complment du message %s found where operator expected . Souvent loprateur manquant est une virgule. Missing right curly or square bracket (Accolade fermante ou crochet fermant manquant) (F) Lanalyseur lexical a compt plus daccolades ouvrantes ou de crochets ouvrants que daccolades fermantes ou de crochets fermants. En rgle gnrale, vous trouverez le signe manquant ct de lendroit o vous venez dditer. Modification of a read-only value attempted (Tentative de modification dune valeur en lecture seule) (F) Vous avez essay, directement ou indirectement, de changer la valeur dune constante. Vous ne pouvez pas, bien entendu, essayer de faire 2 = 1 car le compilateur intercepte ceci. Mais une autre faon simple de faire la mme chose est :
sub mod { $_[0] = 1 } mod(2);

Un autre moyen serait daffecter substr ce qui se trouve au-del de la fin de la chane.

customer_8566

Chapitre 33 Messages de diagnostic


Modification of non-creatable array value attempted, subscript %d

911

(Tentative de modification dune valeur de impossible crer, indice %d) (F) Vous avez essay de faire natre une valeur de tableau et lindice tait probablement ngatif, mme en comptant rebours depuis de la fin du tableau. Modification of non-creatable hash value attempted, subscript "%s" (Tentative de modification dune valeur de hachage impossible crer, indice "%s") (P) Vous avez essay de faire natre une valeur de hachage et elle na pu tre cre pour une raison particulire. Module name must be constant (Le nom de module doit tre constant) (F) Seul un nom de module brut est permis comme premier argument dun use. msg%s not implemented (msg%s non implment) (F) Vous navez pas dimplmentation de messages des IPC System V sur votre systme. Multidimensional syntax %s not supported (Syntaxe multidimensionnelle %s non supporte) (W syntax) Les tableaux multidimensionnels ne scrivent pas $truc[1,2,3]. Ils scrivent $truc[1][2][3], tout comme en C. Name "%s::%s" used only once: possible typo (Nom %s::%s" utilis une seule fois : faute de frappe possible) (W once) Les fautes de frappe apparaissent frquemment sous la forme de noms de variable uniques. Si vous avez une bonne raison pour cela, vous navez qu mentionner la variable nouveau pour supprimer ce message. La dclaration our est destine cela. Negative length (Longueur ngative) (F) Vous avez essay de faire une opration read/write/send/recv avec un tampon de longueur plus petite que 0. Cest difficile imaginer. nested *?+ in regexp (*?+ imbriqu dans lexpression rgulire) (F) Vous ne pouvez quantifier un quantifiant sans faire intervenir de parenthses. Donc les choses comme **, +* ou ?* sont illgales. Remarquez cependant que les quantifiants de recherche de correspondance minimum, *?, +?, et ?? ressemblent des des quantifiants imbriqus mais ne le sont pas. No #! line (Pas de ligne #!) (F) Lmulateur setuid exige que le script possde une ligne valide de la forme #! mme sur les machines ne supportant pas la construction #!.

customer_8566

912
No %s allowed while running setuid

Chapitre 33 Messages de diagnostic

(Pas de %s autoris alors que lon tourne avec setuid) (F) Pour des questions de scurit, certaines oprations sont trop dangereuses pour tre excutes, voire tentes, dans un script setuid ou setgid. Gnralement, il y existera bien un autre moyen pour faire ce que vous voulez, cest--dire que si ce moyen nest pas scuris, il est au moins scurisable. No -e allowed in setuid scripts (pas de -e autoris dans les scripts setuid) (F) Un script setuid ne peut tre spcifi par lutilisateur. No %s specified for -%c (Pas de %s spcifi pour -%c) (F) Loption de la ligne de commande indique ncessite un argument obligatoire mais vous nen avez pas spcifi. No comma allowed after %s (Pas de virgule autorise aprs %s) (F) Lorsquun oprateur de liste a un handle de fichier ou un object indirect , il ne doit pas y avoir une virgule ce premier argument et les arguments suivants. Sinon, il serait juste interprt comme tout autre un argument. Une situation tnbreuse dans laquelle ce message se produit est lorsque vous vous attendez importer une constante dans votre espace de noms avec use ou import mais quune telle importation ne sest pas produite. Vous auriez d utiliser une liste dimportation explicite des constantes que vous vous attendiez voir. Une liste dimportation explicite aurait probablement intercept cette erreur plus tt. Ou peut-tre sagit-il seulement dune erreur de frappe dans le nom de la constante. No command into which to pipe on command line (Pas de commande dans laquelle envoyer un pipe sur la ligne de commande) (F) Il sagit dune erreur spcifique VMS. Perl effectue ses propres redirections dans la ligne de commande et a trouv un | la fin de la ligne de commande, il ne sait donc pas vers o vous voulez rediriger avec un pipe la sortie de cette commande. No DB::DB routine defined (Pas de routine DB::DB de dfinie) (F) Le code en train dtre excut a t compil avec loption -d mais pour une raison ou pour une autre le fichier perl5db.pl (ou alors un fac-simil) na pas dfini de routine appeler au dbut de chaque instruction. Ce qui est trange car le fichier aurait d tre charg automatiquement et na pas pu tre analys correctement. No dbm on this machine (Pas de dbm sur cette machine) (P) Ceci est compt comme une erreur interne ; chaque machine doit fournir dbm de nos jours car Perl est livr avec SDBM.

customer_8566

Chapitre 33 Messages de diagnostic


No DBsub routine

913

(Pas de routine DBsub) (F) Le code en train de sexcuter a t compil avec loption -d mais pour une raison ou pour une autre le fichier perl5db.pl (ou alors un fac-simil) na pas dfini de routine DB::sub appeler au dbut de chaque appel de sous-programme ordinaire. No error file after 2> or 2>> on command line (Pas de fichier derreur aprs 2> ou 2>> sur la ligne de commande) (F) Il sagit dune erreur spcifique VMS. Perl effectue ses propres redirections dans la ligne de commande et y a trouv un 2> ou un 2>> mais sans trouver le nom du fichier dans lequel crire les donnes destines STDERR. No input file after < on command line (Pas de fichier dentre aprs < sur la ligne de commande) (F) Il sagit dune erreur spcifique VMS. Perl effectue ses propres redirections dans la ligne de commande et y a trouv un < mais sans trouver le nom du fichier depuis lequel lire les donnes de STDIN. No output file after > on command line (Pas de fichier de sortie aprs 2> ou 2>> sur la ligne de commande) (F) Il sagit dune erreur spcifique VMS. Perl effectue ses propres redirections dans la ligne de commande et a trouv un > isol la fin de la ligne de commande mais sans savoir o vous vouliez redirigez STDOUT. No output file after > or >> on command line (Pas de fichier de sortie aprs > ou >> sur la ligne de commande) (F) Il sagit dune erreur spcifique VMS. Perl effectue ses propres redirection dans la ligne de commande et y a trouv un > ou un >> mais sans trouver le nom du fichier dans lequel crire les donnes destines STDOUT. No package name allowed for variable %s in "our" (Pas de nom de paquetage autoris pour la variable %s dans "our") (F) Les noms de variable pleinement qualifis ne sont pas autoriss dans les dclarations our car cela naurait pas beaucoup de sens avec les smantiques existantes. Une telle syntaxe est rserve pour de futures extensions. No Perl script found in input (Pas de script Perl trouv en entre) (F) Vous avez appel perl -x mais aucune ligne nest trouve dans le fichier commenant par #! et contenant le mot perl . No setregid available (Pas de setregid de disponible) (F) Configure na rien trouv qui ressemble lappel setregid pour votre systme. No setreuid available (Pas de setreuid de disponible) (F) Configure na rien trouv qui ressemble lappel setreuid pour votre systme.

customer_8566

914
No space allowed after -%c

Chapitre 33 Messages de diagnostic

(Pas despace autoris aprs -%c ) (F) Largument de loption de la ligne de commande indique doit suivre immdiatement loption, sans quaucun espace nintervienne. No such pseudohash field "%s" (Aucun champ de pseudo-hachage "%s") (F) Vous avez essay daccder un tableau en tant que hachage mais le nom de champ utilis nest pas dfini. Le hachage lindice 0 doit faire correspondre tous les noms de champs valides aux indices du tableau pour que cela fonctionne. No such pseudohash field "%s" in variable %s of type %s (Aucun champ de pseudo-hachage "%s" dans la variable %s de type %s) (F) Vous avez essay daccder un champ dune variable type mais le type ignore le nom du champ. Les noms de champ sont recherchs dans le hachage %FIELDS dans le paquetage du type la compilation. Le hachage %FIELDS est gnralement initialis avec le pragma fields. No such pipe open (Aucun pipe ouvert) (P) Il sagit dune erreur spcifique VMS. La routine interne my_pclose a essay de fermer un pipe qui navait pas t ouvert. Ceci aurait d tre captur plus tt comme une tentative de fermeture dun handle de fichier non ouvert. No such signal: SIG%s (Aucun signal: SIG%s) (W signal) Le nom de signal que vous avez spcifi comme indice de %SIG na pas t reconnu. Faites kill -l dans votre shell pour voir les noms de signaux valides sur votre systme. No UTC offset information; assuming local time is UTC (Pas dinformation sur le dcalage UTC ; adopte UTC comme heure locale) (S) Il sagit dun avertissement spcifique VMS. Perl a t incapable de trouver le dcalage horaire pour lheure locale, il a donc suppos que lheure locale du systme et UTC taient quivalentes. SI ce nest pas le cas, dfinissez le nom logique SYS$TIMEZONE_DIFFERENTIAL pour quil traduise le nombre de secondes ajouter UTC afin dobtenir lheure locale. Not a CODE reference (Non une rfrence de CODE) (F) Perl a essay dvaluer une rfrence vers une valeur de code (cest--dire un sous-programme) mais a trouv une rfrence vers quelque chose dautre la place. Vous pouvez utiliser la fonction ref pour trouver de quelle sorte de rfrence il sagissait exactement. Not a format reference (Non une rfrence de format) (F) Nous ne sommes pas srs de la manire dont vous vous arrangez pour gnrer

customer_8566

Chapitre 33 Messages de diagnostic

915

une rfrence vers un format anonyme, mais ce message indique que vous lavez fait et que cela nexiste pas. Not a GLOB reference (Non une rfrence de GLOB) (F) Perl a essay dvaluer une rfrence vers un typeglob (cest--dire une entre dans la table des symboles ressemblant *truc) mais a trouv une rfrence vers quelque chose dautre la place. Vous pouvez utiliser la fonction ref pour trouver de quelle sorte de rfrence il sagissait exactement. Not a HASH reference (Non une rfrence de HACHAGE) (F) Perl a essay dvaluer une rfrence vers une valeur de hachage mais a trouv une rfrence vers quelque chose dautre la place. Vous pouvez utiliser la fonction ref pour trouver de quelle sorte de rfrence il sagissait exactement. Not a perl script (Non un script perl) (F) Lmulateur setuid exige que le script possde une ligne valide de la forme #! mme sur les machines ne supportant pas la construction #!. La ligne doit mentionner perl . Not a SCALAR reference (Non une rfrence de SCALAIRE) (F) Perl a essay dvaluer une rfrence vers une valeur scalaire mais a trouv une rfrence vers quelque chose dautre la place. Vous pouvez utiliser la fonction ref pour trouver de quelle sorte de rfrence il sagissait exactement. Not a subroutine reference (Non une rfrence de sous-programme) (F) Perl a essay dvaluer une rfrence vers une valeur de code (cest--dire un sous-programme) mais a trouv une rfrence vers quelque chose dautre la place. Vous pouvez utiliser la fonction ref pour trouver de quelle sorte de rfrence il sagissait exactement. Not a subroutine reference in overload table (Non une rfrence de sous-programme dans la table de surcharge) (F) Une tentative a t faite pour spcifier une entre dans une table de surcharge qui ne pointe pas dune faon ou dune autre vers un sous-programme valide. Not an ARRAY reference (Non une rfrence de TABLEAU) (F) Perl a essay dvaluer une rfrence vers une valeur de tableau mais a trouv une rfrence vers quelque chose dautre la place. Vous pouvez utiliser la fonction ref pour trouver de quelle sorte de rfrence il sagissait exactement. Not enough arguments for %s (Pas assez darguments pour %s) (F) La fonction exige plus darguments que vous nen avez spcifis.

customer_8566

916
Not enough format arguments

Chapitre 33 Messages de diagnostic

(Pas assez darguments de format) (W syntax) Un format spcifiait plus de champs dimages que la ligne suivante ne lui en a fournis. Null filename used (Nom de fichier vide utilis) (F) Vous ne pouvez exiger un nom de fichier vide, notamment car sur beaucoup de machines ceci signifie le rpertoire courant ! Null picture in formline (Image vide dans formline) (F) Le premier argument de formline doit tre une spcification de format dimage valide. On a trouv que cet argument tait vide, ce qui signifie probablement que vous lui avez fourni une valeur non initialise. NULL OP IN RUN (OP NUL DANS RUN) (P debugging) Une routine interne a appel run avec un pointer de code dopration (opcode) nul. Null realloc (rallocation nulle) (P) Une tentative a eu lieu pour rallouer le pointeur NULL. NULL regexp argument (argument NUL dans lexpression rgulire) (P) Les routines internes de recherche de motifs ont tout explos. NULL regexp parameter (paramtre NUL dans lexpression rgulire) (P) Les routines internes de recherche de motifs ont perdu la tte. Number too long (Nombre trop long) (F) Perl limite la reprsentation des nombres dcimaux dans les programmes environ 250 caractres. Vous avez dpass cette longueur. Les futures versions de Perl sont susceptibles dliminer cette limitation arbitraire. En attendant, essayez dutiliser la notation scientifique (ex. 1e6 au lieu de 1_000_000). Octal number > 037777777777 non portable (Nombre octal >037777777777, non portable) (W portable) Le nombre octal que vous avez spcifi est plus grand que 2**32-1 (4 294 967 295) et nest donc pas portable dun systme lautre. Octal number in vector unsupported (Nombre octal dans un vecteur non support) (F) Les nombres commenant par un 0 ne sont actuellement pas autoriss dans les

customer_8566

Chapitre 33 Messages de diagnostic

917

vecteurs. Linterprtation en octal de tels nombres sera peut-tre supporte dans une future version. Odd number of elements in hash assignment (Nombre impair dlment dans une affectation de hachage) (W misc) Vous avez spcifi un nombre impair dlments pour initialiser un hachage, ce qui est un impair la rgle car un hachage va avec des paires cl/valeur. Offset outside string (Dcalage en dehors de la chane) (F) Vous avez essay de faire une opration read/write/send/recv avec un dcalage pointant en dehors du tampon. Ceci est difficile imaginer. La seule exception cette rgle est que faire un sysread aprs un tampon tendra ce tampon et remplira de zros la nouvelle zone. oops: oopsAV (gloups : gloupsAV) (S internal) Il sagit dun avertissement interne comme quoi la grammaire est abme. oops: oopsHV (gloups gloupsHV) (S internal) Il sagit dun avertissement interne indiquant que la grammaire est abme. Operation "%s": no method found, %s (Opration "%s" : aucune mthode trouve, %s) (F) Une tentative a t faite pour effectuer une opration de surcharge pour laquelle aucun gestionnaire na t dfini. Alors que certains gestionnaires peuvent tre autognrs en termes dautres gestionnaires, il nexiste pas de gestionnaire par dfaut pour quelque opration que ce soit, moins que la cl de surcharge fallback soit spcifie comme tant vraie. Operator or semicolon missing before %s (Oprateur ou point-virgule manquant avant %s) (S ambiguous) Vous avez utilis une variable ou un appel de sous-programme l o lanalyseur syntaxique sattendait trouver un oprateur. Lanalyseur a considr que vous pensiez vraiment utiliser un oprateur mais cela est fortement susceptible de savrer incorrect. Par exemple, si vous crivez accidentellement *truc *truc, cela sera interprt comme si vous aviez crit *truc * truc. Out of memory! (Dpassement de mmoire !) (X) La fonction interne de Perl malloc a renvoy 0, ce qui indique que la mmoire restante (ou la mmoire virtuelle) na pas suffit satisfaire la requte. Perl na pas dautre option que de sortir immdiatement. Out of memory for yacc stack (Dpassement de mmoire pour la pile de yacc)

customer_8566

918

Chapitre 33 Messages de diagnostic

(F) Lanalyseur syntaxique yacc a voulu agrandir sa pile pour quil puisse continuer son analyse mais realloc na pas voulu lui donner plus de mmoire, virtuelle ou autre. Out of memory during request for %s (Dpassement de mmoire pendant une requte pour %s) (X|F) La fonction malloc a renvoy 0, ce qui indique que la mmoire restante (ou la mmoire virtuelle) na pas suffit satisfaire la requte. La requte a t juge faible, la possibilit de la capturer est donc dpendante de la faon dont Perl a t compil. Par dfaut, elle ne peut tre capture. Cependant, sil a t compil cet effet, Perl peut utiliser le contenu de $^M comme une zone durgence aprs tre sorti par die avec ce message. Dans ce cas lerreur peut-tre capture une seule fois. Out of memory during "large" request for %s (Dpassement de mmoire pendant une requte "large" pour %s) (F) La fonction malloc a renvoy 0, ce qui indique que la mmoire restante (ou la mmoire virtuelle) na pas suffit satisfaire la requte. Cependant, la requte a t juge assez large (par dfaut 64K la compilation), la possibilit de sortir en capturant cette erreur est donc permise. Out of memory during ridiculously large request (Dpassement de mmoire pendant un requte ridiculement large) (F) Vous ne pouvez allouer plus de 2**31+ epsilon octets. Cette erreur est gnralement cause par une faute de frappe dans le programme Perl (ex. $tab[time] au lieu de $tab[$time]). page overflow (dpassement de page mmoire) (W io) Un seul appel write a produit plus de lignes que ne peut en contenir une page. panic: ck_grep (panique : ck_grep) (P) Le programme a chou sur un test de cohrence interne en essayant de compiler un grep. panic: ck_split (panique : ck_split) (P) Le programme a chou sur un test de cohrence interne en essayant de compiler un split. panic: corrupt saved stack index (panique : index de la pile de sauvegarde corrompu) (P) On a demand la pile de sauvegarde de restaurer plus de valeurs localises quil nen existe. panic: del_backref (panique : rfrence arrire supprime)

customer_8566

Chapitre 33 Messages de diagnostic

919

(P) Le programme a chou sur un test de cohrence interne en essayant de rinitialiser une rfrence lche (weak reference). panic: die %s (panique : die %s) (P) Nous avons pass llment du dessus de la pile de contexte un contexte deval pour dcouvrir alors que lon ntait pas dans un contexte deval. panic: do_match (panique : do_match) (P) La routine interne pp_match a t appele avec des donnes oprationnelles invalides. panic: do_split (panique : do_split) (P) Quelque chose de terrible sest mal pass lors de la prparation pour un split. panic: do_subst (panique : do_subst) (P) La routine interne pp_subst a t appele avec des donnes oprationnelles invalides. panic: do_trans (panique : do_trans) (P) La routine interne do_trans a t appele avec des donnes oprationnelles invalides. panic: frexp (panique : frexp) (P) La fonction de la bibliothque frexp a chou, rendant le printf("%f") impossible. panic: goto (panique : goto) (P) Nous avons pass llment du dessus de la pile un contexte avec ltiquette spcifie et dcouvert ensuite quil ne sagissait pas dun contexte que nous savions joindre par un goto. panic: INTERPCASEMOD (panique : INTERPCASEMOD) (P) Lanalyseur lexical sest retrouv dans un mauvais tat un modificateur de casse (majuscule/minuscule). panic: INTERPCONCAT (panique : INTERPCONCAT) (P) Lanalyseur lexical sest retrouv dans un mauvais tat en analysant une chane de caractres avec des parenthses.

customer_8566

920
panic: kid popen errno read

Chapitre 33 Messages de diagnostic

(panique : lecture du numro derreur dans le popen dun fils) (F) Un fils issu dun fork a renvoy un message incomprhensible propose de son numro derreur. panic: last (panique : last) (P) Nous avons pass llment du dessus de la pile un contexte de bloc et dcouvert par la suite que ce ntait pas un contexte de bloc. panic: leave_scope clearsv (panique : clearsv dans la sortie de la porte) (P) Une variable lexicale modifiable est maintenant en lecture seule dans le bloc pour une raison ou pour une autre. panic: leave_scope inconsistency (panique : sortie de la porte incohrente) (P) La pile de sauvegarde nest srement plus synchronise. Du moins, il y avait un type enum invalide son sommet. panic: malloc (panique : malloc) (P) Quelque chose a demand un nombre ngatif doctets malloc. panic: magic_killbackrefs (panique : suppression magique de toutes les rfrences arrires) (P) Le programme a chou sur un test de cohrence interne en essayant de rinitialiser toutes les rfrences lches vers un objet. panic: mapstart (panique : mapstart) (P) Le compilateur sest embrouill avec la fonction map. panic: null array (panique : tableau nul) (P) On a pass lune des routines interne pour les tableaux un pointeur dAV nul. panic: pad_alloc (panique : pad_alloc) (P) Le compilateur ne sait plus quelle mmoire de travail (scratchpad) il allouait et librait les valeurs temporaires et lexicales. panic: pad_free curpad (panique : pad_free curpad) (P) Le compilateur ne sait plus quelle mmoire de travail (scratchpad) il allouait et librait les valeurs temporaires et lexicales. panic: pad_free po (panique : pad_free po)

customer_8566

Chapitre 33 Messages de diagnostic

921

(P) Un dcalage incorrect dans la mmoire de travail (scratchpad) a t dtect en interne. panic: pad_reset curpad (panique : pad_reset curpad) (P) Le compilateur ne sait plus quelle mmoire de travail (scratchpad) il allouait et librait les valeurs temporaires et lexicales. panic: pad_sv po (panique : pad_sv po) (P) Un dcalage incorrect dans la mmoire de travail (scratchpad) a t dtect en interne. panic: pad_swipe curpad (panique : pad_swipe curpad) (P) Le compilateur ne sait plus quelle mmoire de travail (scratchpad) il allouait et librait les valeurs temporaires et lexicales. panic: pad_swipe po (panique : pad_swipe po) (P) Un dcalage incorrect dans la mmoire de travail (scratchpad) a t dtect en interne. panic: pp_iter (panique : pp_iter) (P) Litrateur de foreach a t appel dans un contexte qui ntait pas un contexte de boucle. panic: realloc (panique : realloc) (P) Quelque chose a demand un nombre ngatif doctets realloc. panic: restartop (panique restartop) (P) Une routine interne a demand un goto (ou quelque chose de semblable) mais na pas fourni de destination. panic: return (panique : return) (P) Nous avons pass llment du dessus de la pile de contexte un sous-programme ou un contexte deval pour dcouvrir alors que lon ntait ni dans un sous-programme, ni dans un contexte deval. panic: scan_num (panique : scan_num) (P) La fonction interne de Perl scan_num a t appele sur quelque chose qui ntait pas un nombre.

customer_8566

922
panic: sv_insert

Chapitre 33 Messages de diagnostic

(panique : sv_insert) (P) On a demand la routine sv_insert denlever plus de chanes quil en existe. panic: top_env (panique : top_env) (P) Le compilateur a tent de faire un goto ou quelque chose daussi bizarre. panic: yylex (panique : yylex) (P) Lanalyseur lexical sest retrouv dans un mauvais tat en traitant un modificateur de casse (majuscule/minuscule). panic: %s (panique : %s) (P) Une erreur interne. Parentheses missing around "%s" list (Parenthses manquantes autour de la liste "%s") (W parenthesis) Vous avez crit quelque chose comme :
my $truc, $machin = @_;

alors que vous vouliez dire :


my ($truc, $machin) = @_;

Souvenez-vous que my, our et local regroupent plus fortement que la virgule. Perl %3.3f required--this is only version %s, stopped (Perl %3.3f requis il ne sagit que de la version %s, arrt) (F) Le module en question utilise des fonctionnalits offertes par une version plus rcente que celle excute actuellement. Depuis combien de temps navez-vous pas fait de remise niveau ? PERL_SH_DIR too long (PERL_SH_DIR trop long) (F) Il sagit dune erreur spcifique OS/2. PERL_SH_DIR est le rpertoire o se trouve le shell sh. Voir PERL_SH_DIR dans le fichier README.os2 compris dans la distribution de Perl. Permission denied (Permission refuse) (F) Lmulateur setuid de suidperl a dcid que vous ntiez pas quelquun de bon. pid %x not a child (le pid %x nest pas un fils) (W exec) Il sagit dune alerte spcifique VMS ; on a demand waitpid dattendre un processus qui nest pas un sous-processus du processus courant. Mme si cela est correct dans la perspective de VMS, cela nest probablement pas ce que vous vouliez.

customer_8566

Chapitre 33 Messages de diagnostic


POSIX getpgrp cant take an argument

923

(getpgrp POSIX ne prend pas dargument) (F) Votre systme dispose de la fonction POSIX getpgrp, qui ne prend pas dargument, au contraire de la version BSD, qui prend un PID. Possible Y2K bug: %s (Bogue possible de lan 2000) (W y2k) Vous tre en train de concatner le nombre 19 avec un autre nombre, ce qui pourrait tre un problme potentiel pour lan 2000. Possible attempt to put comments in qw() list (Tentative possible de mettre des commentaires dans une liste qw()) (W qw) Les listes qw contiennent des lments spars par des espacements ; comme avec les chanes littrales, les caractres de commentaires ne sont pas ignors, mais au lieu de a traits comme des donnes littrales. (Vous auriez pu utiliser des dlimiteurs diffrents des parenthses indiques ici ; les accolades sont galement frquemment utilises.) Vous avez probablement crit quelque chose comme ceci :
@liste = qw( a # un commentaire b # un autre commentaire );

alors que vous auriez d crire cela :


@liste = qw( a b );

Si vous voulez vraiment des commentaires, construisez votre liste lancienne, avec des apostrophes et des virgules :
@liste = ( a, # un commentaire b, # un autre commentaire );

Possible attempt to separate words with commas (Tentative possible de sparer les mots avec des virgules) (W qw) Les listes qw contiennent des lments spars par des espacements ; les virgules ne sont donc pas ncessaires pour sparer les lments. (Vous auriez pu utiliser des dlimiteurs diffrents des parenthses indiques ici ; les accolades sont galement frquemment utilises.) Vous avez probablement crit quelque chose comme ceci :
qw( a, b, c );

ce qui place les caractres virgules parmis certains lments de la liste. crivez-le sans virgules si vous ne voulez pas les voir apparatre dans vos donnes :
qw( a b c );

customer_8566

924

Chapitre 33 Messages de diagnostic

Possible memory corruption: %s overflowed 3rd argument (Corruption possible de la mmoire : le 3e argument de %s a dbord) (F) Un ioctl ou un fcntl a renvoy plus que ce Perl demandait. Perl anticipe un tampon de taille raisonnable mais place un octet de sentinelle la fin du tampon au cas o. On a cras cet octet de sentinelle et Perl suppose que la mmoire est maintenant corrompue. pragma "attrs" is deprecated, use "sub NAME : ATTRS" instead (le pragma "attrs" est dprci, utilisez la place "sub NOM : ATTRS") (W deprecated) Vous avez crit quelque chose comme ceci :
sub fait { use attrs qw(locked) }

Vous auriez d utiliser la place la nouvelle syntaxe de dclaration :


sub fait : locked { ...

Le pragma use attrs est maintenant obsolte et nest fourni que pour assurer une compatibilit antrieure. Precedence problem: open %s should be open(%s) (Problme de prcdence : open %s devrait tre open(%s)) (S precedence) Lancienne construction irrgulire :
open TRUC || die;

est maintenant mal interprte en :


open(TRUC || die);

cause la stricte rgularisation de la grammaire de Perl 5 en oprateurs unaires et oprateur de listes. (Lancien open tait un peu des deux.) Vous devez mettre des parenthses autour du handle de fichier ou utiliser le nouvel oprateur or la place de ||. Premature end of script headers (Fin prmature des en-ttes du script) Voir Server error. print() on closed filehandle %s (print() sur le handle de fichier ferm %s) (W closed) Le handle de fichier dans lequel vous imprimez sest retrouv ferm un moment auparavant. Vrifier le f lux logique de votre programme. printf() on closed filehandle %s (printf() sur le handle de fichier ferm %s) (W closed) Le handle de fichier dans lequel vous crivez sest retrouv ferm un moment auparavant. Vrifier le f lux logique de votre programme. Process terminated by SIG%s (Processus termin par SIG%s)

customer_8566

Chapitre 33 Messages de diagnostic

925

(W) Il sagit dun message standard formul par les applications OS/2, alors que les applications Unix meurent en silence. Cest considr comme une caractristique du portage sous OS/2. Cet avertissement peut facilement tre dsactiv en positionnant les gestionnaires de signaux appropris. Voir galement Process terminated by SIGTERM/SIGINT (N.d.T. : Processus termin par SIGTERM/SIGINT) dans le fichier README.os2 livr avec la distribution de Perl. Prototype mismatch: %s vs %s (Non correspondance de prototypes : %s contre %s) (S) La sous-fonction qui est en train dtre dclare ou dfinie a t prcdemment dclare ou dfinie avec un prototype diffrent. Range iterator outside integer range (Itrateur dintervalle en dehors dun intervalle) (F) Lun (ou les deux) des arguments numriques de loprateur dintervalle .. est en dehors de lintervalle qui peut tre reprsent en interne par des entiers. Contourner cela est en forant Perl utiliser des incrments de chanes magiques en ajoutant 0 au dbut de vos nombres. readline() on closed filehandle %s (readline() sur un handle de fichier ferm %s) (W closed) Le handle de fichier dans lequel vous tes en train de lire sest retrouv ferm un moment auparavant. Vrifier le f lux logique de votre programme. realloc() of freed memory ignored (realloc() sur de la mmoire libre, ignor) (S malloc) Une routine interne a appel realloc sur quelque chose qui avait dj t libr. Reallocation too large: %lx (Rallocation trop grande : %lx) (F) Vous ne pouvez allouez plus de 64K sur une machine MS-DOS. Recompile perl with -DDEBUGGING to use -D switch (Recompilez Perl avec -DDEBUGGING pour utiliser loption -D) (F debugging) Vous ne pouvez utiliser loption -D que si Perl a t compil avec le code qui produit la sortie dsire ; comme cela implique une certaine surcharge, cela na pas t inclus dans votre instalaltion de Perl. Recursive inheritance detected in package %s (Hritage rcursif dtect dans le paquetage %s) (F) Plus de 100 niveaux dhritage ont t utiliss. Ceci indique probablement une boucle accidentelle dans votre hirarchie de classes. Recursive inheritance detected while looking for method %s in package %s (Hritage rcursif dtect en recherchant la mthode %s dans le paquetage %s) (F) Plus de 100 niveaux dhritages ont t utiliss. Ceci indique probablement une boucle accidentelle dans votre hirarchie de classes.

customer_8566

926

Chapitre 33 Messages de diagnostic

Reference found where even-sized list expected (Rfrence trouve o une liste de taille paire tait attendue) (W misc) Vous avez donn une seule rfrence l o Perl sattendait avoir une liste avec un nombre pair dlments (pour affection un hachage). Cela veut habituellement dire que vous avez utilis le constructeur de hachage anonyme alors que vous vouliez utiliser des parenthses. Dans tous les cas, un hachage exige des paires clef/valeur.
%hachage %hachage %hachage %hachage = = = = { un => 1, deux => 2, }; [ qw( un tableau anonyme /)]; ( un => 1, deux => 2, ); qw( un 1 deux 2 ); # # # # MAUVAIS MAUVAIS juste galement correct

Reference is already weak (La rfrence est dj lche) (W misc) Vous avez tent de relcher une rfrence qui tait dj lche. Ceci na aucun effet. Reference miscount in sv_replace() (Mauvais compte de rfrences dans sv_replace()) (W internal) On a pass la fonction interne sv_replace un nouvel SV avec un nombre de rfrences diffrent de 1. regexp *+ operand could be empty (Loprande *+ de lexpression rgulire pourrait tre vide) (F) La partie dune expression rgulire sujette au quantifiant * ou + pourrait correspondre une chane vide. regexp memory corruption (Corruption de la mmoire de lexpression rgulire) (P) Le moteur dexpressions rgulires sest tromp avec ce que lexpression rgulire lui a donn. regexp out of space (Plus despace pour lexpression rgulire) (P) Il sagit dune erreur qui ne peut pas arriver car safemalloc aurait d la capturer plus tt. Reversed %s= operator (Oprateur %s= invers) (W syntax) Vous avez crit votre oprateur daffectation lenvers. Le = doit toujours arriver en dernier, pour viter lambigut avec les oprateurs unaires suivants. Runaway format (Format schappant) (F) Votre format contenait la squence de rptition jusqu un caractre blanc ~~ mais il a produit 200 lignes dun coup et la 200e ligne ressemblait exactement la 199me. Apparemment vous ne vous tes pas arrang pour que les arguments soit

customer_8566

Chapitre 33 Messages de diagnostic

927

consomms, soit en utilisant ^ au lieu de @ (pour les variables scalaires), soit en faisant un shift ou un pop (pour les variables de tableaux). Scalar value @%s[%s] better written as $%s[%s] (Valeur scalaire @%s[%s] mieux crite avec $%s[%s]) (W syntax) Vous avez utilis une tranche de tableau (indiqu par @) pour slectionner un seul lment dun tableau. Gnralement il vaut mieux demander une valeur scalaire (indique par $). La diffrence est que $truc[&machin] se comporte toujours comme un scalaire, la fois lors de son affectation et lors de lvaluation de son argument, alors que @truc[&machin] se comporte comme une liste lorsque vous y affectez quelque chose en fournissant un contexte de liste son indice, ce qui peut donner des choses tranges si vous vous attendez un seul indice. Dun autre ct, si vous espriez vraiment traiter llment du tableau comme une liste, vous devez regarder comment fonctionnent les rfrences car Perl ne va pas par magie faire la conversion entre les scalaires et les listes votre place. Scalar value @%s{%s} better written as $%s{%s} (Valeur scalaire @%s{%s} mieux crite avec $%s{%s}) (W syntax) Vous avez utilis une tranche de hachage (indique par @) pour slectionner un seul lment dun hachage. Gnralement il vaut mieux demander une valeur scalaire (indique par $). La diffrence est que $truc{&machin} se comporte toujours comme un scalaire, la fois lors de son affectation et lors de lvaluation de son argument, alors que @truc{&machin} se comporte comme une liste lorsque vous y affectez quelque chose en fournissant un contexte de liste son indice, ce qui peut donner des choses tranges si vous vous attendez un seul indice. Dun autre ct, si vous espriez vraiment traiter llment du hachage comme une liste, vous devez regarder comment fonctionnent les rfrences car Perl ne va pas par magie faire la conversion entre les scalaires et les listes votre place. Script is not setuid/setgid in suidperl (Le script nest pas en setuid/setgid dans suidperl) (F) Curieusement, le programme suidperl a t invoqu sur un script qui na pas de bit setuid ou setgid bit positionn. Cela na vraiment aucun sens. Search pattern not terminated (Motif de recherche non termin) (F) Lanalyseur lexical na pas pu trouver le dlimiteur final dune construction // ou m{}. Souvenez-vous que les dlimiteurs fonctionnant par paires ouvrant/fermant (tels que les parenthses, les crochets, les accolades ou les signes infrieur/suprieur) comptent les niveaux imbriqus. Omettre le $ au dbut dune variable $m peut causer cette erreur. %sseek() on unopened file (%sseek() sur un fichier non ouvert) (W unopened) Vous avez essay dutiliser la fonction seek ou sysseek sur un handle de fichier qui soit na jamais t ouvert, soit a t ferm depuis.

customer_8566

928
select not implemented

Chapitre 33 Messages de diagnostic

(select non implment) (F) Cette machine nimplmente pas lappel systme select. sem%s not implemented (sem%s non implment) (F) Vous navez pas dimplmentation des smaphores des IPC System V sur votre systme. semi-panic: attempt to dup freed string (Demi-panique : tentative de dupliquer une chane libre) (S internal) La routine interne newSVsv a t appele pour dupliquer un scalaire qui avait t marqu auparavant comme tant libre. Semicolon seems to be missing (Il semble manquer un point-virgule) (W semicolon) Une quasi-erreur de syntaxe a probablement t cause par un point-virgule manquant ou un autre oprateur manquant peut-tre, comme une virgule. send() on closed socket (send() sur une socket ferme) (W closed) La socket dans laquelle vous envoyer des donnes sest retrouve ferme un moment auparavant. Vrifiez le f lux logique de votre programme. Sequence (? incomplete (Squence (? incomplte) (F) Une expression rgulire finissait par une extension incomplte (?. Sequence (?#... not terminated (Squence (?... non termine) (F) Un commentaire dune expression rgulire doit se terminer par une parenthse ferme. Les parenthses imbriques ne sont pas autorises. Sequence (?%s...) not implemented (Squence (?%s...) non implmente) (F) Une proposition dextension des expressions rgulires a rserv le caractre mais na pas encore t crite. Sequence (?%s...) not recognized (Squence (?%s...) non reconnue) (F) Vous avez utilis une expression rgulire qui na aucun sens. Server error (Erreur du serveur) Il sagit du message derreur gnralement vu dans une fentre de navigateur lorsque vous essayez de lancer un programme CGI (y compris SSI) sur le Web. Le vritable texte derreur varie largement dun serveur lautre. Les variantes les plus

customer_8566

Chapitre 33 Messages de diagnostic

929

frquemment vues sont 500 Server error , Method (something) not permitted , Document contains no data , Premature end of script headers et Did not produce a valid header ( Erreur de serveur 500 , Mthode (quelque_chose) non permise , Le document ne contient aucune donne , Fin prmature des en-ttes de script et Na pas produit den-tte valide ). Il sagit dune erreur CGI, non dune erreur Perl. Vous devez vous assurer que votre script soit excutable, accessible par lutilisateur sous lequel le script CGI tourne (qui nest probablement pas le compte utilisateur sous lequel vous avez fait vos tests), quil ne repose sur aucune variable denvironnement (telle que PATH) que lutilisateur ne va pas avoir et quil ne se trouve pas un emplacement inatteignables pour le serveur CGI. Pour plus dinformations, merci de voir les liens suivants : http://www.perl.com/CPAN/doc/FAQs/cgi/idiots-guide.html http://www.perl.com/CPAN/doc/FAQs/cgi/perl-cgi-faq.html ftp://rtfm.mit.edu/pub/usenet/news.answers/www/cgi-faq http://hoohoo.ncsa.uiuc.edu/cgi/interface.html http://www-genome.wi.mit.edu/WWW/faqs/www-security-faq.html

Vous devriez galement regarder la FAQ Perl. setegid() not implemented (setegid() non implment) (F) Vous avez essay daffecter $) mais votre systme dexploitation ne supporte pas lappel systme setegid (ou un quivalent) ou du moins cest ce que pense Configure. seteuid() not implemented (seteuid() non implment) (F) Vous avez essay daffecter $> mais votre systme dexploitation ne supporte pas lappel systme seteuid (ou un quivalent) ou du moins cest ce que pense Configure. setpgrp cant take arguments (setpgrp ne peut pas prendre darguments) (F) Votre systme dispose de la fonction setpgrp de BSD 4.2, qui ne prend pas dargument, au contraire de setpgid POSIX, qui prend un ID de processus et un ID de groupe de processus. setrgid() not implemented (setrgid() non implment) (F) Vous avez essay daffecter $( mais votre systme dexploitation ne supporte pas lappel systme setrgid (ou un quivalent) ou du moins cest ce que pense Configure. setruid() not implemented (setruid() non implment)

customer_8566

930

Chapitre 33 Messages de diagnostic

(F) Vous avez essay daffecter $< mais votre systme dexploitation ne supporte pas lappel systme setruid (ou un quivalent) ou du moins cest ce que pense Configure. setsockopt() on closed socket %s (setsockopt() sur une socket ferme %s) (W closed) Vous avez essay de positionner des options sur une socket ferme. Peuttre avez-vous oubli de vrifier la valeur renvoye par votre appel socket ? Setuid/gid script is writable by world (Script setuid/setgid modifiable par le monde entier) (F) Lmulateur setuid ne lancera pas un script modifiable par le monde entier car le monde entier peut trs bien dj lavoir modifi. shm%s not implemented (shm%s non implment) (F) Vous navez pas dimplmentation de la mmoire partage des IPC System V sur votre systme. shutdown() on closed socket %s (shutdown() sur une socket ferme %s) (W closed) Vous avez essay de faire un shutdown sur socket ferme. Cela semble quelque peu superf lu. SIG%s handler "%s" not defined (Gestionnaire "%s" pour SIG%s non dfini) (W signal) Le gestionnaire pour le signal nomm dans %SIG nexiste en fait pas. Peut-tre lavez-vous mis dans le mauvais paquetage ? sort is now a reserved word (sort est maintenant un mot rserv) (F) Il sagit dun ancien message derreur que pratiquement personne ne rencontrera plus. Mais avant que sort soit un mot-clef, les gens lutilisaient parfois comme un handle de fichier. Sort subroutine didnt return a numeric value (Le sous-programme de sort na pas renvoy de valeur numrique) (F) Une routine de comparaison pour sort doit retourner un nombre. Vous lavez probablement foutu en lair en nutilisant pas <=> ou cmp, ou en ne les utilisant pas correctement. Sort subroutine didnt return single value (Le sous-programme de sort na pas renvoy une valeur unique) (F) Une routine de comparaison pour sort ne peut pas renvoyer une valeur de liste avec plus ou moins dun lment. Split loop (Boucle dans un split) (P) Le split bouclait sans fin. (videmment, un split ne devrait boucler plus de fois quil ny a de caractres en entre, ce qui sest pass.)

customer_8566

Chapitre 33 Messages de diagnostic


Stat on unopened file <%s>

931

(stat sur un fichier non ouvert <%s>) (W unopened) Vous avez essay dutiliser la fonction stat (ou un test de fichier quivalent) sur un handle de fichier qui na jamais t ouvert ou qui a t ferm depuis. Statement unlikely to be reached (Instruction peu susceptible dtre atteinte) (W exec) Vous avez fait un exec avec des instructions le suivant autres quun die. Il sagit presque toujours dune erreur car exec ne revient jamais moins quil ny ait une erreur. Vous vouliez probablement utiliser system la place, qui lui revient. Pour supprimer cet avertissement, mettez le exec dans un bloc tout seul. Strange *+?{} on zero-length expression (*+?{} trange sur une expression de longueur nulle) (W regexp) Vous avez appliqu un quantifiant dexpression rgulire un endroit o cela na aucun sens, comme dans une assertion de longueur nulle. Essayez de plutt mettre le quantifiant lintrieur de lassertion. Par exemple, le moyen de russir la correspondance avec abc, si cest suivi par trois rptitions de xyz est /abc(?=(?:xyz){3})/, et non /abc(?=xyz){3}/. Stub found while resolving method %s overloading %s in package %s (Souche trouve lors de la rsolution de la mthode %s surchargeant %s dans le paquetage %s) (P) La rsolution de la surcharge dans larbre @ISA a peut tre t rompue par des souches (stubs) dimportation. Les souches ne devraient jamais tre implicitement cres mais les appels explicites can peuvent rompre cela. Subroutine %s redefined (Sous-programme %s redfini) (W redefine) Vous avez redfini un sous-programme. Pour supprimer cet avertissement, crivez :
{ no warnings; eval "sub name { ... }"; }

Substitution loop (Boucle dans une substitution) (P) La substitution boucle sans fin. (videmment, une substitution ne devrait boucler plus de fois quil ny a de caractres en entre, ce qui sest pass.) Substitution pattern not terminated (Motif pour la substitution non termin) (F) Lanalyseur lexical ne peut trouver le dlimiteur intrieur dune construction s/// ou s{}{}. Souvenez-vous que les dlimiteurs fonctionnant par paires ouvrant/fermant (tels que les parenthses, les crochets, les accolades ou les signes infrieur/suprieur) comptent les niveaux imbriqus. Omettre le $ au dbut dune variable $s peut causer cette erreur.

customer_8566

932
Substitution replacement not terminated

Chapitre 33 Messages de diagnostic

(Remplacement pour la substitution non termin) (F) Lanalyseur lexical ne peut trouver le dlimiteur final dune construction s/// ou s{}{}. Souvenez-vous que les dlimiteurs fonctionnant par paires ouvrant/fermant (tels que les parenthses, les crochets, les accolades ou les signes infrieur/suprieur) comptent les niveaux imbriqus. Omettre le $ au dbut dune variable $s peut causer cette erreur. substr outside of string (substr lextrieur dune chane) (W substr|F) Vous avez essay de rfrencer un substr qui pointait en dehors dune chane. Cest--dire que la valeur absolue du dcalage est plus grande que la longueur de la chane. Cet avertissement est fatal si substr est utilis dans un contexte de lvalue (par exemple comme oprateur du ct gauche dune affectation ou comme argument dun sous-programme). suidperl is no longer needed since %s (suidperl nest plus ncessaire depuis %s) (F) Votre Perl a t compil avec -DSETUID_SCRIPTS_ARE_SECURE_NOW mais une version de lmulateur setuid est tout de mme arriv se lancer dune manire ou dune autre. switching effective %s is not implemented (lchange de %s effectif nest pas implment) (F) Avec le pragma use filetest actif, nous ne pouvons pas changer les UID ou les GID rels et effectifs. syntax error (erreur de syntaxe) (F) Ce message veut probablement dire que vous avez eu une erreur de syntaxe. Les raisons habituelles incluent : un mot clef est mal orthographi ; il manque un point-virgule ; il manque une virgule ; il manque une parenthse ouvrante ou fermante ; il manque un crochet ouvrant ou fermant ; il manque une apostrophe ou un guillemet fermant.

Souvent un autre message sera associ avec lerreur de syntaxe donnant plus dinformations. (Parfois, cela aide dactiver -w.) Le message derreur en lui-mme dit souvent quel endroit de la ligne Perl a dcider de sarrter. Parfois la vritable erreur se trouve quelque tokens avant car Perl est dou pour comprendre ce que lon entre alatoirement. Occasionnellement, le numro de ligne peut tre inexact et la seule manire de savoir ce qui ce passe est dappeler de faon rptitive, une fois tous les 36 du mois, perl -c en liminant chaque fois la moiti du programme pour voir o lerreur disparat. Il sagit dune sorte de version cyberntique du jeu des 20 questions.

customer_8566

Chapitre 33 Messages de diagnostic


syntax error at line %d: %s unexpected

933

(erreur de syntaxe la ligne %d : %s inattendu) (A) Vous avez accidentellement lanc votre script via le Bourne shell au lieu de Perl. Vrifier la ligne #! ou lancez vous-mme votre script manuellement dans Perl avec perl nom_script. System V %s is not implemented on this machine (%s de System V nest pas implment sur cette machine) (F) Vous avez essay de faire quelque chose avec une fonction commenant par sem, shm ou msg mais cet IPC System V nest pas implment sur votre machine. (Sur certaines machines, la fonctionnalit peut exister mais peut ne pas tre configure.) syswrite() on closed filehandle (syswrite() sur un handle de fichier ferm) (W closed) Le handle de fichier dans lequel vous crivez sest retrouv ferm un moment auparavant. Vrifiez le f lux logique de votre programme. Target of goto is too deeply nested (La cible du goto est trop profondment imbrique) (F) Vous avez essay dutiliser goto pour atteindre une tiquette qui tait trop profondment imbrique pour que Perl puisse latteindre. Perl vous fait une faveur en vous le refusant. tell() on unopened file (tell() sur un fichier non ouvert) (W unopened) Vous avez essay dutiliser la fonction tell() sur un handle de fichier qui na jamais t ouvert ou qui a t ferm depuis. Test on unopened file %s (Test sur un fichier non ouvert %s) (W unopened) Vous avez essay dinvoquer un oprateur de test de fichier sur un handle de fichier qui nest pas ouvert. Vrifiez votre logique. That use of $[ is unsupported (Cette utilisation de $[ nest pas supporte) (F) Laffectation de $[ est maintenant strictement circonscrite et interprte comme une directive de compilation. Vous devez maintenant crire une seule possibilit parmi celles-ci :
$[ = 0; $[ = 1; ... local $[ = 0; local $[ = 1; ...

Ceci est impos pour prvenir le problme dun module changeant la base des tableaux depuis un autre module par inadvertance.

customer_8566

934
The %s function is unimplemented

Chapitre 33 Messages de diagnostic

(La fonction %s nest pas implmente) La fonction indique nest pas implmente sur cette architecture, selon les tests de Configure. The crypt() function is unimplemented due to excessive paranoia (La fonction crypt() nest pas implmente cause dune paranoa excessive) (F) Configure na pas pu trouver la fonction crypt sur votre machine, probablement parce que votre vendeur ne la pas fournie, probablement parce quil pense que le gouvernement des tats-Unis pense que cest un secret ou du moins continue prtendre que cen est un. The stat preceding -l _ wasnt an lstat (Le stat prcdant -l _ ntait pas un lstat) (F) Cela na pas de sens de vrifier si le tampon courant de stat est un lien symbolique si le dernier stat que vous avez crit dans le tampon a dj pass le lien symbolique pour obtenir le fichier rel. Utilisez un vritable nom de fichier la place. This Perl cant reset CRTL environ elements (%s) (Cette copie de Perl ne peut pas rinitialiser les lments de lenvironnement de CRTL (%s)) This Perl cant set CRTL environ elements (%s = %s) (Cette copie de Perl ne peut pas positionner les lments de lenvironnement de CRTL (%s = %s)) (W internal) Il sagit davertissements spcifiques VMS. Vous avez essay de modifier ou de supprimer un lment du tableau denvironnement interne de CRTL mais votre copie de Perl na pas t compile avec un CRTL contenant la fonction interne setenv. Vous devrez recompiler Perl avec un CRTL qui le contienne ou redfinir PERL_ENV_TABLES (voir perlvms(1)) pour que le tableau denvironnement ne soit pas la cible de la modification de %ENV qui a produit cet avertissement. times not implemented (times non implment) (F) Votre version de la bibliothque C ne fait apparemment pas de times. Je suspecte que vous ntes pas sous Unix. Too few args to syscall (Trop peu darguments pour syscall) (F) Il doit y avoir au moins un argument syscall pour spcifier lappel systme appeler, pauvre tourdi ! Too late for "-T" option (Trop tard pour loption "-T") (X) La ligne #! (ou son quivalent local) dans un script Perl contient loption -T mais Perl na pas t invoqu avec -T sur la ligne de commande. Il sagit dune erreur car le temps que Perl dcouvre un -T dans un script, il est trop tard pour marquer proprement lintgralit de lenvironnement. Donc Perl abandonne.

customer_8566

Chapitre 33 Messages de diagnostic

935

Si le script Perl a t excut en tant que commande en utilisant le mcanisme #! (ou son quivalent local), cette erreur peut habituellement tre corrige en ditant la ligne #! pour que loption -T fasse partie du premier argument de Perl : ex. changer perl -n -T en perl -T -n. Si le script Perl a t excut en tant que perl nom_script alors loption -T doit apparatre sur la ligne de commande : perl -T nom_script. Too late for "-%s" option (Trop tard pour loption "-%s") (X) La ligne #! (ou son quivalent local) dans un script Perl contient loption -M ou -m. Il sagit d une erreur car les options -M et -m ne sont pas prvues pour tre utilises lintrieur des scripts. Utilisez use la place. Too late to run %s bloc (Trop tard pour lancer le bloc %s) (W void) Un bloc CHECK ou INIT a t dfini lexcution, lorsque lopportunit de le lancer est dj passe. Vous chargez peut-tre un fichier avec require ou do alors que vous devriez utiliser use la place. Ou vous devriez peut-tre mettre le require ou le do lintrieur dun bloc BEGIN. Too many (s (Trop de ( ) Too many )s (trop de ) ) (A) Vous avez lanc accidentellement votre script via csh au lieu de Perl. Vrifiez la ligne #! ou lancez vous-mme votre script manuellement dans Perl avec perl nom_script. Too many args to syscall (Trop dargument pour syscall) (F) Perl supporte un maximum de 14 arguments seulement pour syscall. Too many arguments for %s (Trop dargument pour %s) (F) La fonction demande moins darguments que vous en avez spcifis. trailing \ in regexp (\ la fin de lexpression rgulire) (F) Lexpression rgulire se termine par un antislash qui nest pas protg par un antislash. Faites-le. Transliteration pattern not terminated (Motif pour la traduction non termin) (F) Lanalyseur lexical na pas pu trouver le dlimiteur intrieur dune construction tr///, tr[][], y/// ou y[][]. Omettre le $ au dbut des variables $tr ou $y peut causer cette erreur.

customer_8566

936
Transliteration replacement not terminated

Chapitre 33 Messages de diagnostic

(Remplacement pour la traduction non termin) (F) Lanalyseur lexical na pas pu trouver le dlimiteur final dune construction tr/// ou tr[][]. truncate not implemented (truncate non implment) (F) Votre machine nimplmente pas de mcanisme de troncation de fichier que Configure puisse reconnatre. Type of arg %d to %s must be %s (not %s) (Le type de largument %d de %s doit tre %s (pas %s)) (F) Cette fonction exige que largument cette position soit dun certain type. Les tableaux doivent tre @NOM ou @{EXPR}. Les hachages doivent tre %NOM ou %{EXPR}. Aucun drfrencement implicite nest permis utilisez la forme {EXPR} en tant que drfrencement explicite. umask: argument is missing initial 0 (umask : il manque 0 au dbut de largument) (W umask) Un umask de 222 est incorrect. Il devrait tre 0222 car les littraux octaux commencent toujours par 0 en Perl, tout comme en C. umask not implemented (umask non implment) (F) Votre machine nimplmente pas la fonction umask et vous avez essay de lutiliser pour restreindre les permissions pour vous-mme. (EXPR & 0700). Unable to create sub named "%s" (Incapable de crer le sous-programme nomm "% ") (F) Vous avez tent de crer ou daccder un sous-programme avec un nom illgal. Unbalanced context: %d more PUSHes than POPs (Contexte dsquilibr : %d PUSH de plus que de POP) (W internal) Le code de sortie a dtect une incohrence interne entre le nombre de contextes dexcution dans lesquels on est entr et depuis lesquels on est sorti. Unbalanced saves: %d more saves than restores (Sauvegardes dsquilibres : %d sauvegardes de plus que de restaurations) (W internal) Le code de sortie a dtect une incohrence interne entre le nombre de variables qui ont t sauvegardes par local. Unbalanced scopes: %d more ENTERs than LEAVEs (Portes dsquilibres : %d ENTER de plus que de LEAVE) (W internal) Le code de sortie a dtect une incohrence interne entre le nombre de blocs dans lequel on est rentr et depuis lesquels on est sorti. Unbalanced tmps: %d more allocs than frees (Valeurs temporaires dsquilibrs : %d alloues de plus que de libres)

customer_8566

Chapitre 33 Messages de diagnostic

937

(W internal) Le code de sortie a dtect une incohrence interne entre le nombre de scalaires mortels qui ont t allous et librs. Undefined format "%s" called (Format indfini "%s" appel) (F) Le format indiqu ne semble pas exister. Peut-tre est-il rellement dans un autre paquetage ? Undefined sort subroutine "%s" called (Sous-programme de sort indfini "%s" appel) (F) La routine de comparaison de sort spcifie ne semble pas exister. Peut-tre estelle dans un autre paquetage? Undefined subroutine &%s called (Sous-programme indfini &%s appel) (F) Le sous-programme indiqu na pas t dfini ou sil la t, il a t indfini depuis. Undefined subroutine called (Sous-programme indfini appel) (F) Le sous-programme anonyme que vous essayez dappeler na pas t dfini ou sil la t, il a t indfini depuis. Undefined subroutine in sort (Sous-programme indfini dans sort) (F) La routine de comparaison de sort spcifie est dclare mais ne semble pas avoir t dfinie pour le moment. Undefined top format "%s" called (Format den-tte indfini "%s" appel) (F) Le format indiqu ne semble pas exister. Peut-tre est-il en ralit dans un autre paquetage? Undefined value assigned to typeglob (Valeur indfinie affecte un typeglob) (W misc) Une valeur indfinie a t affecte un typeglob, comme *truc = undef. Ceci na aucun effet. Il est possible que vous vouliez dire en ralit undef *truc. unexec of %s into %s failed! (chec de lunexec de %s dans %s !) (F) La routine unexec a chou pour une raison ou pour une autre. Voir votre reprsentant local FSF (Free Software Fondation), qui la probablement mis l en premier lieu. Unknown BYTEORDER (BYTEORDER inconnu) (F) Il ny a aucune fonction dchange doctets pour une machine fonctionnant avec cet ordre doctets.

customer_8566

938
Unknown open() mode %s

Chapitre 33 Messages de diagnostic

(Mode dopen() %s inconnu) (F) Le deuxime argument dun open trois arguments nest pas dans la liste des modes valides : <, >, > >, +<, +>, +> >, -|, |-. Unknown process %x sent message to prime_env_iter: %s (Le processus inconnu %x a envoy un message au prime_env_iter : %s) (P) Il sagit dune erreur spcifique VMS. Perl lisait des valeurs pour %ENV avant de le parcourir et quelquun dautre a coll un message dans le f lux de donnes que Perl attendait. Quelquun de trs perturb ou peut-tre essayant de subvertir le contenu de %ENV pour Perl dans un but nfaste. unmatched () in regexp (() sans correspondance dans lexpression rgulire) (F) Les parenthses non protges par un anti-slash doivent toujours tre quilibres dans les expressions rgulires. Si vous tes utilisateur de vi, la touche % est parfaitement adapte pour trouver la parenthse correspondante. Unmatched right %s bracket (Signe %s fermant sans correspondance) (F) Lanalyseur lexical a compt plus daccolades ou de crochets fermants que douvrants, vous avez donc probablement oubli de mettre un signe ouvrant correspondant. En rgle gnrale, vous trouverez le signe manquant (si lon peut sexprimer ainsi) prs de lendroit o vous tiez en train dditer en dernier. unmatched [] in regexp ([] sans correspondance dans lexpression rgulire) (F) Les crochets autour dune classe de caractres doivent se correspondre. Si vous voulez inclure un crochet fermant dans une classe de caractres, protgez le avec un antislash ou mettez le en premier. Unquoted string "%s" may clash with future reserved word (Chane sans guillemets ni apostrophes "%s" susceptible dtre en conf lit avec un mot rserv dans le futur) (W reserved) Vous utilisez un mot simple qui pourrait tre un jour proclam comme tant un mot rserv. Le mieux est de mettre un tel mot entre guillemets ou entre apostrophes ou en lettres capitales ou dinsrer un soulign dans son nom. Vous pouvez galement le dclarer en tant que sous-programme. Unrecognized character %s (Caractre %s non reconnu) (F) Lanalyseur syntaxique de Perl ne sait absolument pas quoi faire avec le caractre spcifi dans votre script Perl (ou dans un eval). Peut-tre avez-vous essay de lancer un script compress, un programme binaire ou un rpertoire en tant que programme Perl. Unrecognized escape \\%c passed through (Rencontre dune squence dchappement \\%c non reconnu)

customer_8566

Chapitre 33 Messages de diagnostic

939

(W misc) Vous avez employ une combinaison avec un caractre antislash qui nest pas reconnue. Unrecognized signal name "%s" (Nom de signal "%s" non reconnu) (F) Vous avez spcifi un nom de signal la fonction kill qui nest pas reconnue. Faites kill -l dans votre shell pour voir les noms de signaux valides sur votre systme. Unrecognized switch: -%s (-h will show valid options) (Option on reconnue : -%s (-h donne les options valides)) (F) Vous avez spcifi une option illgale pour Perl. Ne faites pas cela. (Si vous pensez ne pas lavoir fait, vrifiez la ligne #! pour voir si elle ne spcifie pas la mauvaise option dans votre dos.) Unsuccessful %s on filename containing newline (chec de %s sur un nom de fichier contenant un saut de ligne) (W newline) Une opration de fichier a t tente sur un nom de fichier et cette opration a chou, probablement parce que le nom de fichier contenait un caractre de saut de ligne, probablement parce que vous avez oubli de le faire sauter par un chop ou un chomp. Unsupported directory function "%s" called (Fonction "%s" sur les rpertoires non supporte appele) (F) Votre machine ne supporte pas opendir et readdir. Unsupported function fork (Fonction fork non supporte) (F) Votre version dexcutable ne supporte pas le fork. Remarquez que sur certains systmes, comme OS/2, il peut y avoir diffrentes versions dexcutables Perl, certaines dentre elles supportent fork, dautres non. Essayez de changer le nom que vous utilisez pour appelez Perl en perl_, perl__ et ainsi de suite. Unsupported function %s (Fonction %s non supporte) (F) Cette machine nimplmente apparemment pas la fonction indique ou du moins cest ce que pense Configure. Unsupported socket function "%s" called (Fonction "%s" sur les sockets non supporte appele) (F) Votre machine ne supporte pas le mcanisme des sockets Berkeley ou du moins cest ce que pense Configure. Unterminated <> operator (Oprateur <> non termin) (F) Lanalyseur lexical a vu un signe infrieur un endroit o il sattendait un terme, il recherche donc le signe suprieur correspondant et ne le trouve pas. Il y a des chances que vous ayez oubli des parenthses obligatoires plus tt dans la mme ligne et vous que pensiez vraiment un < signifiant infrieur .

customer_8566

940

Chapitre 33 Messages de diagnostic

Unterminated attribute parameter in attribute list (Paramtre dattribut non termin dans une liste dattributs) (F) Lanalyseur lexical a vu une parenthse ouvrante lorsquil analysait une liste dattributs mais na pas trouv la parenthse fermante correspondante. Vous devez ajouter (ou enlever) un caractre antislash pour quilibrer vos parenthses. Unterminated attribute list (Liste dattributs non termine) (F) Lanalyseur lexical a trouv quelque chose dautre quun identificateur simple au dbut dun attribut et ce ntait pas un point-virgule ni le dbut dun bloc. Peuttre avez-vous termin trop tt la liste de paramtres de lattribut prcdent. Use of $# is deprecated (Lutilisation de $# est dprcie) (D deprecated) Il sagissait dune tentative mal avise dmuler une fonctionnalit de awk mal dfinie. Utilisez plutt un printf ou sprintf explicite. Use of $* is deprecated (Lutilisation de $* est dprcie) (D deprecated) Cette variable activait comme par magie la recherche de motifs en multilignes, la fois pour vous et pour les sous-programmes malchanceux que vous seriez amen appeler. Maintenant, vous devriez utiliser les modificateurs //m et //s pour faire cela sans les effets dangereux daction distance de $*. Use of %s in printf format not supported (Utilisation de %s non supporte dans un format de printf) (F) Vous avez essay dutiliser une fonctionnalit de printf qui est accessible en C. Cela veut habituellement dire quil existe une meilleure manire de faire cela en Perl. Use of bare << to mean <<"" is deprecated (Lutilisation dun << brut signifiant <<"" est dprcie) (D deprecated) Vous tes maintenant encourag utiliser la forme explicite avec des guillemets ou des apostrophes si vous dsirez utiliser une ligne vide comme dlimiteur final dun document ici-mme (here document). Use of implicit split to @_ is deprecated (Lutilisation dun split implicite sur @_ est dprcie) (D deprecated) Vous donnez beaucoup de travail au compilateur lorsque vous crasez la liste darguments dun sous-programme, il vaut donc mieux affecter explicitement les rsultats dun split un tableau (ou une liste). Use of inherited AUTOLOAD for non-method %s() is deprecated (Lutilisation de lhritage par AUTOLOAD pour la non-mthode %s() est dprcie) (D deprecated) Comme fonctionnalit (hum) accidentelle, les sous-programmes AUTOLOAD taient recherchs de la mme faon que les mthodes (en utilisant la hirarchie de @ISA) mme lorsque les sous-programmes autocharger taient appels en tant que fonctions brutes (ex. : Truc::bidule()) et pas en tant que mthodes (par exemple, Truc->bidule() ou $obj->bidule()).

customer_8566

Chapitre 33 Messages de diagnostic

941

Ce bogue a t rectifi dans Perl 5.005, qui utilisait la recherche de mthodes seulement pour lAUTOLOAD de mthodes. Cependant, il y a une base significative de code existant susceptible dutiliser lancien comportement. Ainsi, en tant qutape intermdiaire, Perl 5.004 mettait cet avertissement optionnel quand des non-mthodes utilisaient des AUTOLOAD hrites. La rgle simple est la suivante : lhritage ne fonctionnera pas quand il y a autochargement de non-mthodes. La simple correction pour de lancien code est : dans tout module qui avait lhabitude de dpendre de lhritage dAUTOLOAD pour les non-mthodes dune classe de base nomme Classe_Base, excutez *AUTOLOAD = &Classe_Base::AUTOLOAD au dmarrage. Dans le code qui actuellement fait use AutoLoader; @ISA = qw(AutoLoader);, vous pouvez supprimer AutoLoader de @ISA et changer use AutoLoader; en use AutoLoader AUTOLOAD;. Use of reserved word "%s" is deprecated (Lutilisation du mot rserv "%s" est dprcie) (D deprecated) Le mot simple indiqu est un mot rserv. Les futures versions de Perl peuvent lutiliser en tant que mot-clef, vous feriez donc mieux de mettre explicitement le mot entre guillemets ou entre apostrophes dune manire approprie son contexte dutilisation ou dutiliser de surcrot un nom diffrent. Lavertissement peut tre supprim pour les noms de sous-programmes en ajoutant un prfixe & ou en qualifiant la variable avec le paquetage, comme &local(), ou Truc::local(). Use of %s is deprecated (Lutilisation de %s est dprcie) (D deprecated) La construction indique nest plus recommande, gnralement parce quil y a une meilleure faon de faire et galement parce que lancienne mthode a de mauvais effets de bord. Use of uninitialized value %s (Utilisation dune valeur non initialise %s) (W uninitialized) Une valeur indfinie a t utilise comme si elle avait dj t dfinie. Elle a t interprte comme un "" ou un 0 mais peut-tre est-ce une erreur. Pour supprimer cet avertissement, affectez une valeur dfinie vos variables. Useless use of "re" pragma (Utilisation inutile du pragma "re") (W) Vous avez fait un use re sans aucun argument. Ceci nest vraiment pas trs utile. Useless use of %s in void context (Utilisation inutile de %s dans un contexte vide) (W void) Vous avez fait quelque chose sans effet de bord dans un contexte qui ne fait rien de la valeur de retour, comme une instruction ne renvoyant pas de valeur depuis un bloc ou le ct gauche dun oprateur scalaire virgule. Par exemple, vous obtiendrez ceci si vous confondez les prcdences en C avec les prcdences en

customer_8566

942
Python en crivant :
$un, $deux = 1, 2;

Chapitre 33 Messages de diagnostic

alors que vous vouliez dire :


($un, $deux) = (1, 2);

Une autre erreur courante est lutilisation de parenthses ordinaires pour construire une liste de rfrences alors vous devriez utiliser des accolades ou des crochets, par exemple, si vous crivez :
$tableau = (1,2);

alors que vous vouliez dire :


$tableau = [1,2];

Les crochets transforment explicitement une valeur de liste en une valeur scalaire tandis que les parenthses ne le font pas. Donc, lorsquune liste entre parenthses est value dans un contexte scalaire, la virgule est traite comme loprateur virgule du C, qui rejette largument de gauche, ce qui nest pas ce que vous voulez. untie attempted while %d inner references still exist (untie tent alors que %d rfrences intrieures existent toujours) (W untie) Une copie de lobjet renvoy par tie (ou par tied) tait toujours valide lorsquuntie a t appel. Value of %s can be "0"; test with defined() (La valeur de %s peut valoir "0" ; testez avec defined()) (W misc) Dans une expression conditionnelle, vous avez utilis <HANDLE>, <*> (glob), each ou readdir en tant que valeur boolenne. Chacune de ces constructions peut renvoyer une valeur de "0" ; cela rendrait fausse lexpression conditionnelle, ce qui nest probablement pas ce que vous dsiriez. Quand vous utilisez ces constructions dans des expressions conditionnelles, testez leur valeur avec loprateur defined. Value of CLI symbol "%s" too long (Valeur du symbole de CLI "%s" trop longue) (W misc) Il sagit dun avertissement spcifique VMS. Perl a essay de lire la valeur dun lment de %ENV depuis la table de symboles de CLI et a trouv une chane rsultante plus longue que 1 024 caractres. La valeur de retour a t tronque 1 024 caractres. Variable "%s" is not imported %s (La variable "%s" nest pas importe de %s) (F) Alors que use strict est activ, vous vous tes rfrs une variable globale quapparemment vous pensiez avoir importe depuis un autre module car quelque chose dautre ayant le mme nom (habituellement un sous-programme) est export par ce module. Cela veut habituellement dire que vous vous tes tromp de drle de caractre ($, @, % ou &) devant votre variable. Variable "%s" may be unavailable (La variable "%s" peut tre inaccessible) (W closure) Un sous-programme anonyme intrieur (imbriqu) se trouve dans un sous-programme nomm et encore lextrieur se trouve un autre sous-programme ;

customer_8566

Chapitre 33 Messages de diagnostic

943

et le sous-programme anonyme (le plus lintrieur) fait rfrence une variable lexicale dfinie dans le sous-programme le plus lextrieur. Par exemple :
sub le_plus_exterieur { my $a; sub au_milieu { sub { $a } } }

Si le sous-programme anonyme est appel ou rfrenc (directement ou indirectement) depuis le sous-programme le plus lextrieur, il va partager la variable comme vous pouviez vous y attendre. Mais si le sous-programme anonyme est appel ou rfrenc lorsque le sous-programme le plus lextrieur est inactif, il verra la valeur de la variable partage telle quelle tait avant et pendant le premier appel au sous-programme le plus lextrieur, ce qui nest probablement pas ce que vous voulez. Dans ces circonstances, il vaut habituellement mieux rendre anonyme le sous-programme du milieu anonyme, en utilisant la syntaxe sub {}. Perl possde un support spcifique pour les variables partages dans les sous-programmes anonymes imbriqus ; un sous-programme nomm entre les deux interfre avec cette fonctionnalit. Variable "%s" will not stay shared (La variable "%s" ne restera pas partage) (W closure) Un sous-programme nomm intrieur (imbriqu) fait rfrence une variable lexicale dfinie dans un sous-programme extrieur. Lorsque le sous-programme intrieur est appel, il verra probablement la valeur de la variable du sous-programme extrieur telle quelle tait avant et pendant le premier appel au sous-programme extrieur ; dans ce cas, aprs que le premier appel au sous-programme extrieur est termin, les sous-programmes intrieur et extrieur ne partageront plus de valeur commune pour la variable. En dautres termes, la variable ne sera plus partage. De plus, si le sous-programme extrieur est anonyme et fait rfrence une variable lexicale en dehors de lui-mme, alors les sous-programmes intrieur et extrieur ne partageront jamais la variable donne. Le problme peut habituellement tre rsolu en rendant anonyme le sous-programme intrieur, en utilisant la syntaxe sub {}. Lorsque des sous-programmes anonymes intrieurs, faisant rfrence des variables dans des sous-programmes extrieurs, sont appels ou rfrencs, ils sont automatiquement relis la valeur courante de ces variables. Variable syntax (Syntaxe de variable) (A) Vous avez lanc accidentellement votre script via csh au lieu de Perl. Vrifiez la ligne #! ou lancez vous-mme votre script manuellement dans Perl avec perl nom_script. Version number must be a constant number (Le numro de version doit tre un nombre constant) (P) La tentative de conversion dune instruction use Module n.n LISTE vers le bloc BEGIN quivalent a trouv une incohrence interne dans le numro de version. perl: warning: Setting locale failed. (perl : avertissement : chec avec la configuration des locales)

customer_8566

944

Chapitre 33 Messages de diagnostic

(S) Le message davertissement complet ressemblera quelque peu :


perl: warning: Setting locale failed. perl: warning: Please check that your locale settings: LC_ALL = "Fr_FR", LANG = (unset) are supported and installed on your system. perl: warning: Falling back to the standard locale ("C").1

(La configuration des locales qui a chou variera.) Cette erreur indique que Perl a dtect que vous ou votre administrateur systme avez configur les variables du systme ainsi nommes mais Perl na pas pu utiliser cette configuration. Ce nest pas mortel, heureusement : il existe une locale par dfaut appele C que Perl peut et va utiliser pour le script puisse ainsi fonctionner. Mais avant que vous rsolviez vraiment ce problme, vous allez toutefois avoir le mme message derreur chaque fois que vous lancerez Perl. La manire de vraiment rsoudre le problme peut tre trouve dans perllocale(1), la section Locale Problems . Warning: somethings wrong (Avertissement : quelque chose sest mal pass) (W) Vous avez pass warn une chane vide (lquivalent dun warn "") ou vous lavez appel sans arguments et $_ tait vide. Warning: unable to close filehandle %s properly (Avertissement : incapable de fermer proprement le handle de fichier %s) (S) Le close implicite effectu par un open a reu une indication derreur sur le close. Cela indique habituellement que votre systme de fichier a puis lespace disque disponible. Warning: Use of "%s" without parentheses is ambiguous (Avertissement : Lutilisation de "%s" sans parenthses est ambigu) (S ambiguous) Vous avez crit un oprateur unaire suivi par quelque chose ressemblant un oprateur binaire mais pouvant galement tre interprt comme un terme ou un oprateur unaire. Par exemple, si vous savez que la fonction rand a un argument par dfaut valant 1.0 et que vous crivez :
rand + 5;

vous pouvez pensez que vous avez crit la mme chose que :
rand() + 5;

alors quen fait vous avez obtenu :


rand(+5);
1. N.d.T. : perl : avertissement : chec avec la configuration des locales. perl : avertissement : Merci de vrifier que votre configuration des locales : LC_ALL = "Fr_FR", LANG = (non configur) soit supporte et installe sur votre systme. perl : avertissement : Retour aux locales standards ("C").

customer_8566

Chapitre 33 Messages de diagnostic


Donc mettez des parenthses pour dire ce que vous voulez vraiment dire. write() on closed filehandle

945

(write() sur un handle de fichier ferm) (W closed) Le handle de fichier dans lequel vous crivez sest retrouv ferm un moment auparavant. Vrifiez le f lux logique de votre programme. X outside of string (X en dehors dune chane) (F) Vous aviez un canevas pour pack spcifiant une position relative avant le dbut de la chane en train dtre dpaquet. x outside of string (x en dehors dune chane) (F) Vous aviez un canevas pour pack spcifiant une position relative aprs la fin de la chane en train dtre dpaquet. Xsub "%s" called in sort (Xsub "%s" appel dans un sort) (F) Lutilisation dun sous-programme externe pour la comparaison dun sort nest pas encore supporte. Xsub called in sort (Xsub "%s" appel dans un sort) (F) Lutilisation dun sous-programme externe pour la comparaison dun sort nest pas encore supporte. You cant use -l on a filehandle (Vous ne pouvez pas utiliser -l sur un handle de fichier) (F) Un handle de fichier reprsente un fichier ouvert et lorsque vous avez ouvert le fichier, il avait dj pass tous les liens symboliques que vous essayez vraisemblablement de rechercher. Utilisez plutt un nom de fichier. YOU HAVENT DISABLED SET-ID SCRIPTS IN THE KERNEL YET! (VOUS NAVEZ TOUJOURS PAS DSACTIV LES SCRIPTS SET-ID DANS LE NOYAU !) (F) Et vous ne le ferez probablement jamais car vous navez pas les sources du noyau et probablement que votre fabriquant se moque perdument de ce que vous voulez. La meilleure solution est de mettre une surcouche setuid en C autour de votre script en utilisant le script wrapsuid situ dans le rpertoire eg de la distribution Perl. You need to quote "%s" (Vous devez protger "%s" avec des guillemets ou des apostrophes) (W syntax) Vous avez affect un mot simple comme nom dun gestionnaire de signaux. Malheureusement, vous avez dj un sous-programme avec ce nom, ce qui veut dire que Perl 5 essayera dappeler ce sous-programme lorsque laffectation sera excute, ce qui nest probablement pas ce que vous voulez. (Si cest bien ce que vous voulez, mettez une & devant.)

customer_8566

customer_8566

Glossaire

Un mot rfrenc ailleurs dans le glossaire est prsent en italique la manire dun hyperlien. addresse rseau Lattribut le plus important dune socket, comme le numro de votre tlphone. Typiquement une adresse IP Voir aussi . port. affectation Un oprateur dont la fonction est de modifier la valeur dune variable. algorithme Squence dinstructions clairement dfinie dans le langage de la machine (virtuelle). alias Surnom dune variable qui se comporte comme le nom original. Par exemple, un alias temporaire est cr implicitement pour la variable de boucle dans linstruction foreach, avec les oprateurs map et grep dans la variable $_, dans les variables $a et $b lors de lappel de la fonction de comparaison sort ou bien pour les paramtres rels dun appel de fonction dans la variable @_. Des alias permanents sont crs explicitement dans les paquetages par limportation des symboles ou par affectation dans les typeglobs. Des alias porte lexicale dans les paquetages sont crs avec la dclaration our.

alternatives Une liste de choix possibles parmi lesquels on ne peut en slectionner quun, comme dans : Prfrez-vous la porte A, B ou C ? Les termes des alternatives dans les expressions rgulires sont spars par une barre verticale : |. Les termes des alternatives dans les expressions Perl normales sont spars par deux barres verticales : ||. On peut parler dune alternative dalternatives. Ou non. vous de choisir. Les alternatives logiques dans les expressions boolennes sont spares par || ou bien or. analyse lexicale Terme amusant pour dire tokeniseur. analyse syntaxique Lart subtil et parfois brutal pour tenter de tranformer votre programme avec ses erreurs potentielles en arbre syntaxique. anonyme Qualifie un rfrent qui ne peut tre accd par une variable, mais indirectement par une rfrence dure, qui disparat aprs utilisation. appel par rfrence Un mcanisme de passage darguments par lequel les arguments formels se rfrent directement aux arguments rels, le sousprogramme pouvant modifier les arguments rels en changeant les arguments

customer_8566

948
formels. Les arguments formels sont des alias pour les arguments rels. Voir aussi appel par valeur. appel par valeur Un mcanisme de passage darguments par lequel les arguments formels se rfrent une copie des arguments rels, le sous-programme ne pouvant modifier les arguments rels par les arguments formels. Voir aussi appel par rfrence. appel systme Un appel direct de sous-programme au systme dexploitation. Nombre des fonctions et des sous-programmes utiliss ne sont pas des appels systmes directs, mais constituent des surcouches au-dessus du niveau de lappel systme. En gnral, les utilisateurs de Perl nont pas se soucier de la distinction. Nanmoins, si vous connaissez les fonctions Perl qui font des appels systmes, vous savez celles qui affecteront la variable $! ($ERRNO) lors dun chec. Malheureusement, les programmeurs Perl emploient souvent le terme appel systme lorsquils utilisent la fonction system, laquelle met en jeu beaucoup dappels systmes. Pour viter tout confusion, nous utilisons presque toujours le terme appel systme pour dsigner lappel indirect laide de la fonction Perl syscall, mais jamais pour indiquer un appel de la fonction Perl system. appelant Lagent responsable de lappel dune mthode. Dans une mthode de classe, lappelant est un nom de paquetage. Dans une mthode dinstance lappelant est une rfrence dobjet. approche bote outils La notion selon laquelle, avec un ensemble complet doutils simples qui fonctionnent bien les uns avec les autres, il est possible de raliser ce que lon veut. Ce qui convient si lon assemble un tricycle, mais dans le cas dun microsthseur rhombodal double inversion de f lux, il faut absolument quun atelier construise les outils adapts. Perl est une sorte datelier. arbre danalyse Voir arbre syntaxique.

Glossaire

arbre syntaxique Une reprsentation interne de votre programme dans laquelle les constructions de bas-niveau sont incluses dans les blocs contenant. architecture Le type dordinateur sur lequel on travaille, type signifiant que les ordinateurs en faisant partie peuvent faire tourner le mme programme binaire. Puisque les scripts Perl sont des fichiers texte et non binaires, un script Perl est beaucoup moins sensible larchitecture sur laquelle il tourne que les programmes dautres langages (comme C) qui sont compils en code machine. Voir aussi systme dexploitation. argument Des donnes fournies en entre dun programme, dun sous-programme, dune fonction ou dune mthode servant lui dire quoi faire. galement appel paramtre . arguments de la ligne de commande Les valeurs fournies comme paramtres dun programme dont lexcution est demande au shell. Ces valeurs sont accessibles en Perl par lintermdiaire du tableau @ARGV. arguments formels Nom gnrique des arguments dun sousprogramme. En Perl, les arguments formels dun programme sont dans un tableau : $ARGV[0], $ARGV[1], ainsi de suite. Ceux dun sous-programme sont $_[0], $_[1], etc, arguments quon peut tranformer localement en noms par laffectation une liste my. Voir aussi arguments rels. arguments rels Les valeurs scalaires que lon fournit une fonction ou un sous-programme que lon appelle. Par exemple, quand on appelle jeton("bingo"), la chane "bingo" est largument rel. Voir galement argument et arguments formels.

customer_8566

Glossaire
ARGV Nom du tableau qui contient le vecteur dargument de la ligne de commande. Avec loprateur <>, ARGV est la fois le nom du filehandle qui utilisera les arguments et le scalaire contenant le nom du fichier en entre. ASCII American Standard Code for Information Interchange (un ensemble de caractre efficace pour la reprsentation imparfaite des textes anglais). Utilis aussi pour dsigner les 128 premires valeurs des codages ISO-8859-X, un groupe de codes 8 bits incompatibles entre eux. assertion Composant dune expression rgulire qui doit tre vraie pour le motif recherch, mais qui ne correspond pas forcment avec un caractre. Souvent utilis pour dsigner une assertion de longueur nulle, cest--dire value sur une chane nulle. associativit Dtermine lequel des oprateurs de droite ou de gauche est excut en premier, quand on a A oprateur B oprateur C , si les deux oprateurs ont la mme prcdence. Les oprateurs comme + sont associatifs gauche, alors que les oprateurs comme ** sont associatifs droite. Le chapitre 3, Oprateurs unaires et binaires, donne la liste des associativits. asynchrone vnements ou activits dont loccurrence relative est indtermine, car trop nombreux se produire dans la mme unit temporelle. On peut dire que cest un vnement qui arrivera limproviste. atome Composant dune expression rgulire qui peut correspondre une sous-chane qui contient un ou plusieurs caractres et qui est traite comme une unit syntaxique par tout quantificateur qui la suit. comparer avec lassertion qui svalue sur une chane de longueur nulle et ne peut tre quantifie.

949
attribut Nouvelle fonctionnalit qui permet dajouter des modificateurs des dclarations de variable ou fonction avec modificateurs comme dans sub foo : locked method. Cest aussi lautre nom dune variable dinstance dun objet. autognration Fonctionnalit de loprateur de surcharge des objets, o le comportement de certains oprateurs peut tre driv des oprateurs fondamentaux. Cela suppose bien entendu que les oprateurs surchargs ont les mmes relations que les oprateurs ordinaires. Voir le chapitre 13, Surcharge. auto-incrmentation Ajouter automatiquement un quelque chose. Gnralement employ pour dcrire loprateur ++. Lopration inverse, soustraire 1, est appel autodcrmentation . autochargement Chargement la demande (galement appel chargement paresseux ), prcisment appel dune fonction AUTOLOAD en lieu et place dun routine indfinie. autosplit Dcoupage automatique dune chane la manire du slecteur -a utilis avec -p ou n pour muler la commande awk. Voir aussi le module AutoSplit (qui na rien voir avec lautosplit, mais beaucoup voir avec lautochargement). autovivification Terme dorigine grco-latine signifiant litralement se donner la vie . En Perl, les places mmoires (ou lvalues) se crent suivant le besoin, y compris la cration des rfrences dures ncessaires pour adresser le niveau suivant de stockage. Laffectation $a[5][5][5][5][5] = "quintet" cre cinq scalaires, plus quatre rfrences (dans les quatre premiers scalaires) pointant sur quatre tableaux anonymes. Mais ici le point important est que nous navons pas nous en soucier.

customer_8566

950
AV Abrviation de array value , qui se rfre lun des types de donnes interne de Perl. Une AV est une sorte de SV . avertissement Un message affich sur le f lux STDERR indiquant que quelque chose ne va pas mais que ce nest pas une raison pour tout casser. Voir warn dans le chapitre 29, Fonctions, ainsi que le pragma use warnings dans le chapitre 31, Modules de pragmas. avide Un sous-motif dont le quantificateur cherche effectuer une correspondance avec le maximum de choses. awk Abrviation du mot trange . Aussi un vnrable langage de traitement de textes auquel Perl a emprunt quelques ides de haut niveau. backtracking En thorie cela revient dire si ctait refaire, je le referais autrement , et en pratique avec Perl cest le refaire vraiment. Mathmatiquement parlant, il sagit du retour dune rcursion ayant chou sur une arborescence de possibilits. Le backtracking, ou retour arrire, se produit en Perl quand il tente de comparer des motifs avec une expression rgulire, et que ses premiers essais ne correspondent pas. Voir Le petit Moteur qui /(ne )?pouvait( pas)?/ au chapitre 5, Recherche de motif. bibliothque Une collection de procdures. Aux temps hroques, se rfrait une collection de sous-programmes dans un fichier .pl. Actuellement, se rfre souvent lintgralit des modules Perl dun systme. binaire Ayant voir avec les nombres reprsents en base deux. Cela veut dire quil existe deux nombres, zro et un. Dsigne galement un fichier non-texte , dont le codage a t effectu avec les 8 bits de loctet. Avec larrive dUNICODE, cette distinction perd toute signification.

Glossaire
bit Entier dans lintervalle 0-1, bornes comprises. La plus petite unit de stockage dinformation. Un huitime doctet ou de dollar. (Lexpression Pieces of eight, pices de huit, vient de la possibilit de diviser les vieux dollars espagnols en 8 bits, chacun restant de largent valable. Cest l do vient lexpression twobits pour une pice de 25 cents. bits dautorisation Les bits utiliss par le propritaire dun fichier pour limiter les accs celui-ci. Ces bits font partie du mot mode retourn par la fonction stat prdfinie lorsque vous demandez ltat dun fichier. Sur les systmes Unix, vous pouvez regarder la page de manuel ls(1) pour plus dinformation. bit dexcution La marque spciale qui indique au systme dexploitation quil peut lancer ce programme. Il existe en fait trois bits dexcution sous UNIX, et le bit utilis dpend de ce que lon possde le fichier individuellement, collectivement, ou pas du tout. bloc Un gros morceau de donnes, dune taille que le systme dexploitation apprcie (dhabitude une puissance de 2 comme 512 ou 8192). Cela dsigne habituellement un morceau de donnes venant dun fichier ou y allant. BLOCK Une construction syntaxique compose dune squence dinstructions Perl dlimites par des accolades. Nous parlons parfois de bloc pour une squence dinstructions qui agissent comme un BLOC, mme non dlimite par des accolades. bloqu tat dun processus qui attend une ressource : ce processus est bloqu car il attend une ressource du disque . Boolen Valeur vraie ou fausse.

customer_8566

Glossaire
boucle Une construction qui effectue quelque chose de faon rpte, comme un surfeur sur des rouleaux. brouillon Cest une zone mmoire temporaire dans laquelle un sous-programme ou un fichier place temporairement ses valeurs et aussi toute variable porte lexicale. BSD Une drogue psychotrope, populaire dans les annes 80, probablement dveloppe lU.C. Berkeley ou ses environs. Similaire par de nombreux points la mdication appele System V , mais infiniment plus utile (ou du moins, plus amusante). Le nom chimique complet est Berkeley Standard Distribution . bucket Espace dans une table de hachage contenant plusieurs entres dont les cls ont une valeur de hachage identique. (Cette notion est interne la gestion des tableaux faite par Perl et ne vous concerne pas, en rgle gnrale.) bytecode Un baragouin employ par les androdes quand ils ne veulent pas rvler leur orientation (voir boutismes). Ainsi dnomm daprs certains langages similaires parls (pour des raisons similaires) entre les compilateurs et les interprteurs la fin du vingtime sicle. Ces langages sont caractriss par leur faon de reprsenter par une squence doctets indpendante de larchitecture. C Un langage chri par de nombreuses personnes pour ses dfinitions de types inverses, ses rgles de prcdence impntrables et une surcharge importante de ses mcanismes dappel de fonctions. (En fait, les gens sont dabord passs au C parce quils trouvaient les identificateurs en minuscules plus faciles lire que ceux en majuscules.) Linterprteur Perl est crit en C, et il nest donc pas surprenant que Perl lui ait emprunt quelques ides.

951
canal de sortie actuellement slectionn Le dernier handle de fichier ayant t dsign par select (FILEHANDLE) ; STDOUT par dfaut, si aucun handle na t slectionn. canonique Rduction dans une forme standard qui facilite la comparaison. capture Lutilisation de parenthses autour dun sous-motif dans une expression rgulire pour mmoriser la sous-chane correspondante comme rfrence arrire. (Les chanes captures peuvent aussi tre retournes dans un contexte de liste.) caractre Un petit entier qui code une unit dcriture. Historiquement, les caractres sont encods dans un entier de longueur fixe (typiquement un octet, voir deux selon le type coder), mais avec lapparition du codage UTF-8, ils sont cods sur une longueur variable. Perl gre ceci dune manire transparente, en gnral. caractre espace Un caractre qui dplace le curseur mais naffiche rien lcran. Se rfre typiquement aux caractres suivants : blanc, tabulation, retour chariot, saut de ligne, saut de page. caractre nul Un caractre ASCII de valeur zro. Il est utilis par C et certains appels systme UNIX pour terminer les chanes, alors que Perl autorise les chanes contenir un nul. chane Une squence de caractres telle que il dit !@#*&%@#*?! . Une chane nest pas obligatoirement imprimable. chane binaire Squence de bits interprte comme un squence de bits. chane nulle Une chane ne contenant aucun caractre, ne pas confondre avec une chane contenant un caractre nul, qui a une longueur positive et une valeur vraie.

customer_8566

952
champ Un bout simple de donnes faisant partie dune chane, dun enregistrement ou dune ligne. Les champs de longueur variable sont gnralement spars par des dlimiteurs (on utilise split pour extraire les champs) alors que les champs de longueur fixe se trouvent des positions constantes (on utilise unpack). Les variables dinstances sont aussi appeles champs . chemin Un nom de fichier entirement qualifi tel /usr/bin/perl. Parfois confondu avec PATH. classe Un type prdfini par lutilisateur implment en Perl par la dclaration package, paquetage qui fournit (directement ou par hritage) les mthodes (cest--dire les sousroutines) pour grer les instances de la classe (ses objets). Voir aussi lhritage. classe de base Type dobjet gnrique dont la classe trs abstraite peut tre drive par hritage vers des classes plus spcialises. Aussi appel superclasse dans la tradition de nos anctres. classe de caractres Une liste de caractres entre crochets employe dans une expression rgulire pour indiquer que tout caractre de lensemble peut se trouver cet endroit. Aussi tout ensemble de caractres prdfinis. classe drive Une classe qui dfinit certaines de ses mthodes dans les termes dune classe plus gnrique, appele classe de base. Remarquez que les classes ne sont par classifies exclusivement en classes de base ou classes drives ; une classe peut simultanment fonctionner des deux manires, ce qui est typique. classe parent Voir classe de base. clef Lindex de type chane dun hachage, utilis

Glossaire
pour chercher une valeur associe une certaine clef. client Dans un contexte de rseau, un processus qui prend contact avec un processus serveur pour changer des donnes et ventuellement recevoir un service. cloisonneur Un cluster utilis pour restreindre la porte dun modificateur dexpression rationnelle. cluster Un sous-motif entre parenthses utilis pour grouper les parties dune expression rationnelle dans un seul atome. CODE Mot retourn par la fonction ref applique la rfrence dune sous-routine. Voir aussi CV . commande En programmation shell, la combinaison syntaxique dun nom de programme avec ses arguments. Plus gnralement, tout ce que lon entre dans un shell (un interprteur de commandes) qui fait quelque chose. En programmation Perl, une instruction, qui peut dmarrer par une tiquette et se termine typiquement par un point-virgule. commentaire Une remarque qui naffecte pas la signification du programme. En Perl, un commentaire commence par un caractre # et continue jusqu la fin de la ligne. compatibilit ascendante Possibilit de faire tourner ses anciens fichiers sources sur les nouvelles versions de linterprteur, car nous navons cass ni les fonctionalits, ni les bugs sur lesquels reposent les anciens programmes. compilateur Au sens strict, un programme qui en absorbe un autre et recrache un troisime fichier contenant ce programme sous une forme plus excutable, contenant typiquement des instructions en langage machine

customer_8566

Glossaire
natif. Le programme perl nest pas un compilateur selon cette dfinition, mais il en contient un qui prend un programme et le mtamorphose sous une forme plus excutable (arbres syntaxiques) lintrieur du processus perl lui-mme, que linterprteur interprte ensuite. Il existe nanmoins des modules dextension qui permettent Perl dagir plus comme un vrai compilateur. Voir le chapitre 18, Compilation. compilation Le moment o Perl essaye de comprendre ce que signifie le programme, par opposition celui o, croyant savoir ce quil signifie, il essaye de faire ce que le programme lui dit de faire. Voir excution. compositeur Un constructeur pour un rfrent qui nest pas vraiment un objet, comme un tableau ou un hachage. Par exemple, une paire daccolades agissent comme compositeur de hachage, et une paire de crochets agissent comme compositeur de tableau. Voir Cration de rfrences au chapitre 8, Rfrences. concatnation Coller le museau dun chat la queue dun autre. On peut remplacer chat par chane . condition Avec des si . Voir contexte boolen. connexion En tlphonie, le circuit lectrique temporaire entre les tlphones de lappelant et de lappel. En rseau, le mme genre de circuit temporaire entre un client et un serveur. consacrer Perl va classer un rfrent pour quil fonctionne comme un objet. Voir la fonction bless dans le chapitre 29. constructeur Toute mthode de classe, mthode dinstance ou sous-programme qui cre, initialise, consacre et retourne un objet. Le terme est quelquefois utilis pour dsigner un compositeur.

953
construction Un ensemble syntaxique compos dlments plus petits. galement laction de crer un objet grce un constructeur. construire Crer un objet avec un constructeur. contexte Lenvironnement. Le contexte donn par le code environnant dtermine le genre de donnes quune expression doit renvoyer. Les trois contextes primordiaux sont le contexte de liste, le contexte scalaire et le contexte peu importe. Le contexte scalaire est parfois subdivis en contexte boolen, contexte numrique et contexte de chane. Il existe aussi un contexte peu importe (qui est trait au chapitre 2, Composants de Perl, si cela vous importe). contexte boolen Un contexte scalaire particulier utilis dans les conditions pour valuer une valeur scalaire vrai ou faux. comparer lvaluation dune chane ou dun nombre. Voir contexte. contexte de chane La situation dans laquelle lenvironnement (le code appelant) attend dune expression quelle renvoie une chane. Voir aussi contexte et contexte numrique. contexte de liste La situation dans laquelle un environnement (le code appelant) attend dune expression quelle renvoie une liste de valeurs au lieu dune valeur unique. Les fonctions qui dsirent une LIST darguments indiquent ses arguments quils doivent produire une liste de valeurs. Voir galement contexte. contexte de tableau Ancienne expression pour dire contexte de liste. contexte numrique La situation dans laquelle lenvironnement (le code appelant) attend dune expression quelle renvoie un nombre. Voir aussi contexte et contexte de chane.

customer_8566

954
contexte scalaire La situation dans laquelle lenvironnement (le code appelant) attend dune expression quelle renvoie une valeur unique au lieu dune liste. Voir galement contexte et contexte de liste. Un contexte scalaire impose parfois des contraintes supplmentaires sur la valeur de retour, voir contexte de chane et contexte numrique. Nous parlons parfois dun contexte boolen dans les conditions, mais cela nimplique aucune contrainte supplmentaire puisque toute valeur scalaire, quelle soit numrique ou chane, est dj vraie ou fausse. contexte vide Une forme de contexte scalaire dans lequel une expression ne retourne aucune valeur et qui nest utile que pour ses propres effets de bord. continuation Le traitement de plusieurs lignes physiques comme une seule ligne logique. Les lignes de Makefile sont continues en mettant un antislash avant le saut de ligne. Les en-ttes de messages Internet sont continus en mettant un espace ou une tabulation aprs le saut de ligne. Les lignes Perl nont pas besoin dun quelconque forme de marque de continuation, car les espaces (y compris les sauts de ligne) sont joyeusement ignors. En gnral. Le cadavre dun processus, sous la forme dun fichier laiss dans le rpertoire de travail du processus, gnralement rsultant de certaines formes derreur fatale. conversion en chane La production dune chane pour reprsenter un objet. correspondance Voir recherche de correspondance. CPAN Comprehensive Perl Archive Network ou Rseau dtaill des Archives de Perl. Voir la prface et le chapitre 22, CPAN, pour les dtails. cracker Une personne qui viole la scurit des systmes dexploitation. Un cracker peut-tre

Glossaire
un vrai hacker ou simplement un script kiddie. CV Une dfinition de type de valeur de code (code value). Un CV est une sorte de SV . datagramme Un paquet de donnes, tel un message UDP qui est transmis indpendament de , la couche applicative sur le rseau (ce sont de paquets IP encapsuls dans un protocole TCP et donc invisible depuis votre programme.) DBM Signifie Data Base Management , un ensemble de routines qui mulent un tableau associatif avec des fichiers sur disque. Les routines emploient un systme de hachage dynamique pour localiser nimporte quelle entre en seulement deux accs disque. Les fichiers DBM permettent un script Perl de conserver un hachage entre plusieurs invocations. Il est possible de lier par tie les variables hachage diverses implmentations DBM ; voir AnyDBM_File(3) et lentre DB_File au chapitre 32, Modules standards. dbogueur symbolique Un programme permettant lexcution pas pas dun programme, en arrtant pour afficher des choses ici et l pour voir si quelque chose a mal tourn. Ladjectif symbolique signifie que lon peut discuter avec le dbogueur en employant les mmes symboles que ceux qui ont t utiliss pour crire le programme. dcalage Dcalage droite ou gauche dans un mot de la mmoire, dont leffet est de multiplier ou de diviser par une puissance de 2. dcalage droite Un dcalage de bit qui divise un nombre par une puissance de 2. dcalage gauche Un dcalage de bits qui multiplie un nombre par une puissance de deux.

customer_8566

Glossaire
dclaration Une assertion de lexistence de quelque chose, et ventuellement de ce quoi cela ressemble, sans prsumer de ce qui va lui arriver, ni de quelle faon. Une dclaration ressemble la partie dune recette numrant : deux tasses de farine, un uf, quatre ou cinq beaux ttards... Voir son oppos instruction. Remarquez que certaines dclarations fonctionnent galement comme des instructions. Les dclarations de sous-routines forment aussi une dfinition si le corps est fourni. dclencheur Un vnement qui dclenche un handler. dcrmenter Soustraire une valeur dune variable comme dans decrement $x qui soustrait 1 ou dcrmenter $x de 3 . dfaut (par) Une valeur qui est choisie pour vous si vous nen fournissez pas une vous-mme. dfini Possdant une signification. Perl pense que certaines des choses que les gens font nont aucune signification : en particulier lutilisation dune variable qui na jamais t attribue de valeur, et effectuer des oprations sur des donnes qui nexistent pas. Par exemple, si lon essaye de lire des donnes aprs la fin dun fichier, Perl renvoie une valeur indfinie. Voir galement faux et loprateur defined au chapitre 29. dlimiter Un caractre ou une chane qui dlimite un objet textuel de taille indfinie que lon ne doit pas confondre avec le sparateur ou terminateur. Dlimiter veut simplement dire entourer ou clturer (comme ces parenthses le font). dplacement Ou offset : le nombre dlments sauter aprs le dbut dune chane ou dun tableau pour arriver une position spcifique. Loffset minimal est donc zro et non un, car il ny rien sauter pour arriver au premier lment.

955
drfrencer Un joli terme informatique signifiant suivre une rfrence vers ce sur quoi elle pointe . Le prfixe d indique quil sagit denlever un niveau dindirection. descripteur Voir descripteur de fichier. descripteur de fichier Le petit numro quutilise le systme dexploitation pour garder la trace du fichier ouvert dont on soccupe. Perl dissimule le descripteur de fichier dans un f lux dE/S standard, puis attache le f lux un handle de fichier. destruction globale Le ramasse-miettes des globales (et laction de ces destructeurs) qui se produit quand linterprteur Perl est arrt. destructeur Une mthode spciale qui est appele quand un objet le demande. La mthode DESTROY neffectue pas la destruction proprement parler. Elle donne loccasion la classe de faire un peu de mnage. dtruire Dsallouer la mmoire dun rfrent (mais en appelant dabord sa mthode DESTROY, si elle existe.) diffuser Envoyer un datagramme plusieurs destinataires simultanment. directive Une directive pod. POD. Voir le chapitre 26,

distribuer Envoyer une chose sa destination correcte. Mtaphore utilise pour dsigner le transfert dun programme vers un autre par slection dans une table de fonction de rfrences ou bien comme dans le cas des mthodes dobjets, par le parcours dun arbre dhritage de classes. distribution Une version stable dun systme ou dun logiciel. Par dfaut, le code source est

customer_8566

956
inclus. Dans le cas inverse, elle est dite binary-only . document ici-mme Ainsi appel en raison dune construction similaire des shells qui prtendent que les lignes suivant ici mme la commande sont un fichier spar donner la commande, jusqu une chane servant de dlimiteur de fin. En Perl, il ne sagit que dune forme labore de protection. domaine public Qui nest possd par personne. Perl fait lobjet dun copyright, et nest donc pas dans le domaine public ; il nest que librement disponible et librement redistribuable. drapeau Nous vitons lutilisation de ce terme qui veut tout dire : un slecteur de la ligne de commande qui ne prend pas dargument (tels -n et -p), un simple bit indicateur (tels O_CREAT et O_EXCL utiliss dans sysopen). drle de caractre Quelquun comme Larry, ou les types qui lui servent damis. Ou bien, lun de ces tranges prfixes devant les noms de variables en Perl. dweomer Un enchantement, une illusion, un phantasme, ou une acrobatie. Se dit dun programme Perl qui ne fait pas ce que vous attendez de lui, mais plutt quelque chose de lordre de la sorcellerie. dwimmer DWIN est un acronyme pour Do What I Mean , principe selon lequel une instruction devrait faire ce que vous dsirez, sans faire de chichis. Un morceau de code qui fait du dwimming est un dwimmer . Dwimming ncessite souvent beaucoup de travail en arrire plan et si a se voit a devient du dweomer. clectique Driv de nombreuses sources. Certains diraient trop nombreuses.

Glossaire
dition de lien Rsolution de noms dans un fichier partiellement compil afin de produire une image (presque) excutable. Ldition de liens est statique ou dynamique ( ne pas confondre avec la porte statique ou dynamique). effets de bord Un effet secondaire qui se produit lors de lvaluation dune expression. Par exemple lvaluation dune simple affectation a pour effet de bord daffecter une valeur une variable (ce qui tait bien votre intention premire!). De mme, laffectation dune valeur la variable spciale $| ($AUTOFLUSH) a pour effet de bord de forcer un vidage aprs chaque write ou chaque print sur le handle de fichier courant. lment Une brique de base. Quand on parle dun tableau, lun des items qui le composent. emplacement dobjet indirect Position syntaxique entre lappel dune mthode et ses arguments quand la notation indirecte est invoque. La position se distingue des arguments par labsence de virgule entre elle et largument suivant. STDERR est dans un emplacement indirect ici :
print STDERR "Debout! Rveillez-vous! Peur, Feu, Folie! Debout!\n";

en passant Quand on change la valeur dun objet au moment de sa copie (de lexpression, prise du pion en passant aux checs). encapsulation La couche abstraite qui spare linterface de limplmentation, et qui impose que tout accs ltat dun objet soit effectu au travers de mthodes exclusivement. enregistrement Ensemble de donnes relies entre elles dasn un fichier ou un f lux, souvent associes avec une clef unique. Sous Unix, elles sont souvent rassembles sur une ligne ou un dans un paragraphe (suite de lignes

customer_8566

Glossaire
termine par une ligne vide). Chaque ligne du fichier /etc/passwd est un enregistrement dont la clef est le login, et qui contient linformation de lutilisateur. enrobage Un programme qui en lance un autre votre place, en modifiant certaines des entres ou des sorties pour mieux vous convenir. entier Un nombre sans partie fractionnaire. Un nombre pour dnombrer comme 1, 2, 3..., en incluant 0 et les nombres ngatifs. entre standard Le f lux dentre par dfaut dun programme, qui doit si possible ne pas soccuper du lieu de provenance des donnes. Reprsent dans un programme Perl par le handle de fichier STDIN. environnement Lensemble des variables denvironnement que le processus hrite de son parent. Accessible via %ENV. EOF Fin de fichier. Mtaphore pour dsigner la chane indiquant la fin dun fichier icimme erreur Voir exception ou erreur fatale. erreur fatale Une exception non traite, qui provoque la fin du processus aprs impression dun message sur la console derreur standard. Les erreurs dans un bloc eval ne sont pas fatales : le bloc se termine aprs avoir plac le message dexception dans la variable $@ ($EVAL_ERROR). On peut lever explicitement une exception avec loprateur die qui peut tre traite dynamiquement par le bloc eval. Sil ne lest pas, cela provoque une erreur fatale. erreur standard Le f lux de sortie par dfaut qui sert faire des remarques dsobligeantes qui ne sont pas destines la sortie standard. Reprsent en Perl par le handle de fichier

957
STDERR. Ce f lux peut tre utilis explicitement, mais les oprateurs die et warn le font automatiquement. errno Le numro de lerreur renvoy par un appel systme UNIX quand il choue. Perl se rfre lerreur par le nom $! (ou $OS_ERROR si lon utilise le module English). E/S standard Une bibliothque standard du C ( standard I/O ) servant aux entres et aux sorties i vers le systme dexploitation (le standard des E/S standard na quun rapport marginal avec le standard des entres et sorties standard). En gnral, Perl se base sur limplmentation propre chaque systme dexploitation, et les caractristiques de tamponnage peuvent donc ne pas exactement correspondre dune machine lautre. Cela ninf luence normalement que lefficacit et non la portabilit. Si les fonctions dE/S standard tamponnent par bloc et quil serait souhaitable de vider les tampons plus souvent, il suffit de mettre la variable $| une valeur vraie. espace de noms Un domaine de noms. Il ny a pas besoin de se soucier de savoir si les noms dun tel domaine ont t utiliss dans dautres. Voir paquetage. est une sorte de Relation entre deux objets dans laquelle lun est considr comme une version plus spcifique de lautre objet gnrique : Un chameau est un mammifre . Lobjet gnrique tant une abstraction au sens platonique, on parle plutt de relation entre une classe de base et une classe spcifique dite classe drive. trangement, les classes abstraites platoniques nont pas toujours des relations platoniques voir la notion dhritage. tiquette Nom donn une instruction pour pouvoir y accder partout ailleurs dans le programme.

customer_8566

958
tiquette de boucle Un genre de clef ou de nom rattach une boucle pour que les instructions de contrle de boucle puissent savoir quelle boucle elles doivent contrler. exception Un joli nom pour une erreur. Voir erreur fatale. exec Stopper le programme du processus en cours pour le remplacer par un autre, tout en gardant les ressources en cours dans le processus (sauf son image mmoire). excuter Excution dun programme ou sous-programme. (Rien voir avec la fonction tuer kill, sauf si vous mettez en uvre un handler de signal.) excution Le laps de temps pendant lequel Perl essaye de faire ce que le script lui ordonne, par opposition la priode prcdente pendant laquelle Perl essayait de savoir si le script avait un sens quelconque lexcution. Voir galement compilation. exporter Rendre les symboles dun module disponibles depuis un autre par la directive import. expression Tout assemblage de littraux, variables, oprateurs, fonctions ou sous-programmes, effectu suivant les rgles, quand on a besoin dune valeur. expression alerte Une expression qui provoque un arrt lorsque sa valeur change, ce qui permet de dboguer. expression rgulire Une entit unique avec diverses interprtations, comme un lphant. Pour un informaticien, il sagit de la grammaire dun petit langage dans lequel certaines chanes sont lgales et dautres non. Pour les gens normaux, cest un motif que lon

Glossaire
peut utiliser pour trouver ce dont on a besoin quand la cible varie selon les cas. Les expressions rgulires en Perl sont loin dtre rgulires au sens mathmatique du terme, mais fonctionnent plutt bien lorquon les utilise correctement. Exemple dune expression rgulire : /Oh, m.*d../. Ce motif correspond des chanes comme Oh, mais vous tiez dans le train allant Lourdes et Oh, ma foi, il se fait tard ! . Voir le chapitre 5. extension Un module Perl qui comporte du code C ou C++ compil. Ou plus gnralement, une option exprimentale qui peut tre compile et intgre dans Perl, comme le multithreading. false En Perl, toute valeur qui ressemble "" ou "0" dans un contexte de chane. Tout valeur indfinie est donc faussse, car value "", mais toute valeur fausse nest pas forcment indfinie. FAQ Questions frquemment poses (Frequently Asked Questions, ou Foire aux Questions) (mme les rponses ny sont pas forcment, surtout dans les FAQ de la version courante qui peuvent dater). fermeture Un sous-programme anonyme qui, gnr lexcution, garde trace des identits des variables lexicales visibles de lextrieur mme aprs que ces variables lexicales sont devenues hors de porte. Elles sont appeles fermetures parce que ce genre de comportement donne aux mathmaticiens un sentiment disolement. fichier Une collection de donnes nomme, gnralement stocke sur disque dans un rpertoire lui-mme dans un systme de fichiers. Ressemblant vaguement un document, si on apprcie les mtaphores dordre bureautique. Sous quelques systmes dexploitation comme UNIX, un mme fichier peut en fait rpondre plusieurs noms. Certains fichiers sont spciaux

customer_8566

Glossaire
comme les rpertoires et les priphriques. fichiers den tte Un fichier contenant certaines dfinitions requises qui doivent tre incluses entte pour pratiquer certaines oprations obscures. Un fichier den-tte C possde une extension .h. Un fichier den-tte Perl possde une extension .ph. Voir loprateur require au chapitre 29. (Les fichiers den-tte ont t supplants par le mcanisme de module.) fichier excutable Un fichier marqu, reconnu par le systme dexploitation comme excutable. Simplement appel excutable . fichier normal Un fichier qui nest pas un rpertoire, un priphrique, un tube nomm, une socket ou un lien symbolique. Perl utilise loprateur de test de fichier -f pour identifier les fichiers normaux . FIFO Premier entr, premier sorti, file dattente. Voir aussi LIFO. Aussi lautre nom pour un tube nomm. fileglob Une correspondance par joker sur des noms de fichier. Voir la fonction glob. filtre Transforme un f lux dentre en f lux de sortie. filtre source Un module spcial qui opre un prtraitement sur votre script juste avant lanalyseur lexical. f lux Un f lux continu de donnes de type caractres ou octets entrant ou sortant dun processus sans donner limpression darriver paquet par paquet. Cest une sorte dinterface limplmentation sousjacente est invisible, et peut fort bien grouper les donnes par paquets.

959
FMTEYEWTK Plus que vous navez jamais espr savoir. Trait exhaustif sur un sujet pointu, quelque chose comme une super FAQ. Voir Tom pour en savoir beaucoup plus. fonction Mathmatiquement, une relation faisant correspondre un ensemble de valeurs de dpart vers un ensemble de valeurs darrive. Dans le langage des ordinateurs, se rfre un sous-programme ou un oprateur, avec ou sans valeurs dentre (appeles arguments) qui retourne une valeur. fonction de rappel Un handler dclar dans une autre partie du programme et qui peut tre dclench par un code diffrent lorsquun vnement se produit. fork Crer un processus fils identique au processus pre, du moins jusqu ce quil se fasse ses propres ides. Un thread avec sa mmoire locale. format Spcification indiquant combien despaces, de chiffres et de choses diverses il faut pour que tout ce que vous imprimez donne un rsultat agrable regarder. freeware Logiciel mis libre disposition, parfois avec son code source. On lappelle maintenant plutt logiciel source ouvert. Rcemment, une tendance est apparue qui oppose les freewares aux logiciels source ouvert, et qui rserve le terme freeware aux logiciels diffuss sous la licence GPL de la Free Software Foundation . gnrateur de code Systme qui produit du code machine tel le code final dun compilateur. Voir gnrateur de programme. gnrateur de programme Un systme qui crit du code pour vous dans un langage de haut niveau. Voir aussi gnrateur de code.

customer_8566

960
gestionnaire de signal Un sous-programme qui, au lieu de se contenter dtre appel de faon normale, attend dans son coin quun clair se produise soudainement avant de daigner sexcuter. En Perl, ces clairs sont appels des signaux, et elles sont distribues avec la fonction prdfinie kill. Voir le hachage %SIG dans le chapitre 28, Noms spciaux, et la section Signaux dans le chapitre 16, Communication interprocessus. GID Group ID, identifiant de groupe ; sous UNIX, le numro de groupe que le systme dexploitation utilise pour vous identifier, ainsi que tous les utilisateurs de votre groupe. glob Au sens strict, le caractre * du shell, qui recherche une correspondance avec un glob (une palanque) de caractres quand on essaye de gnrer une liste de noms de fichiers. Plus gnralement, le fait dutiliser des globs et des symboles similaires afin deffectuer des recherches de correspondances. Voir aussi fileglob et typeglob. global Ce que lon peut voir de partout, concernant en gnral les variables et les sous-programmes visibles de partout dans le programme. En Perl, seules certaines variables sont vraiment globales ; la plupart des variables (comme tous les sousprogrammes) sont locales au paquetage courant. Les variables globales peuvent tre dclares avec our. Voir Dclarations globales dans le chapitre 4, Instructions et dclarations. granularit La taille des objets avec lesquels vous travaillez. grep Vient de la vieille commande UNIX Recherche globale dun expression rgulire et impression ( Global search for a Regular Expression and Print ), utilis maintenant pour tout type de recherches

Glossaire
textuelles. Perl possde une fonction grep prdfinie qui cherche dans une liste la correspondance suivant certains critres, alors que le programme grep(1) cherche les lignes qui correspondent une expression rgulire dans un ou plusieurs fichiers. gros-boutiste Dcrit les ordinateurs qui rangent loctet du poids le plus fort dun mot une adresse plus basse que loctet du poids le plus faible, souvent considrs comme suprieurs aux ordinateurs petit-boutiste. Daprs Swift : quelquun qui mange les ufs la coque par le grand bout. Voir aussi petit-boutiste. groupe Un ensemble dutilisateurs dont on fait partie. Sous certains systmes dexploitation (comme UNIX), il est possible de donner certaines permissions daccs fichier aux autres membres de son groupe. groupe de slecteurs La combinaison de plusieurs slecteurs dune commande (i.e -a -b -c) en un seul (i.e -abc). Un slecteur avec argument doit tre plac en dernier. GV Une valeur glob (glob value), signifiant un typeglob. Un GV est une sorte de SV . hachage Une liste nomme de paires clef/valeur, arrange de telle manire quil soit facile dutiliser une clef pour trouver sa valeur associe ; une relation binaire, pour les utilisateurs de bases de donnes. Ce glossaire ressemble un hachage, o le mot dfinir est la clef et la dfinition est la valeur. Un hachage est parfois galement appel un tableau associatif en six syllabes (ce qui est une bonne raison pour lappeler un hachage). hacker Personne pugnace rsoudre les problmes techniques, quel que soit le sujet quil sagisse de jouer au golf, de combattre des orques ou de programmer. Hacker est un terme neutre, moralement parlant. Les

customer_8566

Glossaire
bons hackers ne doivent pas tre confondus avec les crackers fous ou les script kiddies incomptents. Si vous les confondez, nous vous considrons comme fou ou incomptent. handle de fichier Ce avec quoi on slectionne un fichier. Ou bien, un nom (qui nest pas ncessairement le vrai nom du fichier) qui reprsente une instance donne douverture dun fichier jusqu ce quil soit ferm. Si lon doit ouvrir et fermer plusieurs fichiers la suite, il est possible douvrir chacun dentre eux avec le mme handle, ce qui fait que lon na pas rcrire du code pour traiter chacun dentre eux. handle de fichier indirect Une expression dont la valeur est un handle de fichier : une chane (nom de handle de fichier), un typeglob, une rfrence de typeglob, ou un objet de bas niveau du module IO. handle de rpertoire Un nom reprsentant une instance donne de rpertoire ouvert, jusqu ce quil soit ferm. Voir la fonction opendir. handler Un sous-programme ou mthode appel par Perl quand votre programme doit rpondre un vnement interne tel un signal, ou bien la rencontre avec un oprateur de surcharge. Voir aussi fonction de rappel. hritage Ce que nous laissent nos anctres, en termes gntiques ou autres. Si vous tes une classe, vos anctres sont appels classes de base et vos descendants classes drives. Voir aussi lhritage simple et hritage multiple. hritage multiple Les caractristiques de votre mre et de votre pre, mlanges de faon imprvisible (voir hritage et hritage simple). Dans les langages informatiques (y compris Perl), la notion selon laquelle une classe donne peut avoir plusieurs anctres directs ou classes de base.

961
hritage simple Les caractristiques hrites de votre mre, si elle vous a racont que vous naviez pas de pre (voir galement hritage et hritage multiple). Dans les langages informatiques, la reproduction des classes est asexue, et une classe donne ne peut avoir quun seul anctre direct ou classe de base. Perl ne connat pas ces restrictions, mme si cest possible de faire de cette manire. hexadcimal Un nombre en base seize, parfois raccourci en hexa . Les chiffres allant de dix quinze sont conventionnellement reprsents par les lettres allant de a f. Les constantes hexadcimales commencent par 0 en Perl. Voir aussi la fonction hex au chapitre 29. hte Lordinateur sur lequel rside un programme ou des donnes. HV Abrviation de hash value (valeur de hachage), qui se rfre lun des types de donnes internes de Perl. Un HV est une sorte de SV . identificateur Un nom lgalement form pour tout ce qui peut intresser un programme informatique. De nombreux langage (y compris Perl) autorisent les identificateurs commenant par une lettre et contenant des lettres et des chiffres. Perl considre galement le caractre soulign comme une lettre valide. (Perl dispose aussi dune notation complexe avec les noms qualifis.) impatience La colre qui vous saisit quand lordinateur paresse. Vous tes alors pouss crire des programmes qui ne se contentent pas de rpondre vos besoins, mais aussi les anticiper. Idalement. En consquence, la deuxime grande vertu du programmeur. Voir galement paresse et orgueil. implmentation La manire dont un morceau de code fait

customer_8566

962
rellement son travail. Les utilisateurs nont pas soccupper des dtails de limplmentation moins quelle ne soit disponible travers son interface. importer Avoir accs des symboles qui sont exports depuis un autre module. Voir loprateur use au chapitre 29. incrmentation magique Un oprateur dincrmentation qui sait comment ajouter 1 tant une chane alphanumrique qu un nombre. incrmenter Augmenter une valeur dune unit (ou de tout autre nombre, si spcifi). indexation lorigine, rechercher une clef dans un index (comme un annuaire), mais de nos jours, il sagit surtout dutiliser une clef ou une position pour trouver la valeur correspondante, mme alors quaucun index nentre en jeu. La situation a tellement dgnr que la fonction index de Perl se contente de localiser la position dune chane dans une autre. indice Une valeur indiquant la position dun lment dun tableau. indirection Quelque chose qui indique o se trouve la valeur cherche. Ce qui peut se faire avec des rfrences symboliques ou des rfrences dures. infixe Un oprateur qui se place entre ses oprandes, tel la multiplication dans 24 * 7. insr Quand une chose est contenue dans une autre, mme si cest parfois surprenant : Jai insr un interprteur Perl dans mon diteur ! . instance Raccourci pour instance de classe qui signifie un objet de cette classe.

Glossaire
instruction Une commande lordinateur concernant ce quil faut faire ensuite, comme une tape dans une recette : Ajouter du rhum la pte et mlanger . ne pas confondre avec une dclaration, qui ne dit pas lordinateur de faire quoi que ce soit, mais dapprendre quelque chose. instruction de contrle de boucle Une instruction dans le corps de la boucle qui peut arrter le bouclage ou sauter une itration. Voir la phrase du milieu de lentre prcdente. Nessayez pas cela sur un vrai rouleau sans parachute. instruction pendante Une instruction simple, sans aucune accolade, aprs une condition if ou while. Le langage C les autorise mais pas Perl. instruction switch Une construction de programmation qui permet dvaluer une expression et, daprs la valeur de lexpression, deffectuer un dbranchement choix multiple vers le code appropri pour cette valeur. galement appel une structure case daprs la construction Pascal similaire. La plupart des instructions switch en Perl sont des numrations for. Voir Structures de cas dans le chapitre 4. interface Les services quun morceau de code promet de fournir, en constraste de son implmentation, quil peut modifier son gr. interpolation Linsertion dun scalaire ou dune liste au milieu dune autre valeur, sans que cela se voit. En Perl, linterpolation de variable se produit dans les chanes entre guillemets doubles et dans les motifs, et linterpolation de liste se produit dans la construction dune liste passer en paramtre un oprateur de liste ou tout autre construction qui prend une LIST. interpolation de variable Linterpolation dune scalaire ou dun tableau en une chane.

customer_8566

Glossaire
interprteur Au sens strict, un programme qui lit un second programme et fait ce que ce dernier lui dit sans dabord le transformer sous une forme diffrente, ce qui est le comportement des compilateurs. Perl nest pas un interprteur selon cette dfinition, car il contient un compilateur qui prend un programme et en produit un (arbre syntaxique), dans le processus Perl lui-mme, quinterprte ensuite la machine virtuelle Perl temps-rel. invocation Le fait dappeler une divinit, un dmon, un programme, un sous-programme ou une fonction pour quil fasse ce quil a faire. Les fonctions ou sous-programmes sont usuellement appels alors que les mthodes sont invoques , a sonne mieux. I/O Entre depuis, ou sortie vers un fichier ou priphrique. IO Un objet I/O interne. Peut aussi vouloir dire objet indirect. IP Protocole Internet, ou proprit intellectuelle. IPC Interprocess Communication , communication interprocessus. itration Faire une chose rptition. itrateur Un machin de programmation spcial qui garde tout seul la trace de litration lendroit o lon se trouve. La boucle Perl foreach contient un itrateur ; ainsi que le hachage, ce qui permet de lui appliquer loprateur each pour le parcourir. IV IV veut dire la Valeur interne Entire quun type scalaire peut porter, ne pas confondre avec NV .

963
JAPH Just Another Perl Hacker , un bout de code trappu, mais illisible, qui lorsquexcut svalue cette chane. Souvent utilis pour illustrer certaine particularits de Perl, et dans les concours de Perl obscurci. langage rassembleur Un langage, tel Perl, bon pour rassembler des choses diffrentes entre elles, qui ntaient pas prvues pour sassembler. le plus gauche, le plus long Priorit dune expression rgulire pour tablir la correspondance sur le motif le plus gauche, et partir de cette position dessayer la plus longue (en supposant lusage dun quantificateur avide). Voir le chapitre 5 pour en savoir beaucoup plus sur le sujet. lexme Terme amusant pour dire token. lexeur Terme amusant pour dire analyseur lexical. lexicale type Une variable lexicale dclare avec un type classe : my Poney $bill. librement diffusable Signifie que lon ne risque rien en donner des copies pirates des amis, mme si cela se sait. Nhsitez pas le faire pour Perl. librement disponible Signifie quil nest pas besoin de payer pour lobtenir, mais le copyright peut toujours rester proprit de quelquun dautre (comme Larry). lien Utilis comme nom, un rpertoire reprsentant un fichier. Un fichier donn peut avoir plusieurs liens, comme quand plusieurs noms de lannuaire se rapportent au mme numro de tlphone. lien symbolique Un nom de fichier supplmentaire qui pointe sur le vrai nom de fichier, lequel son tour pointe sur le fichier. Quand le sys-

customer_8566

964
tme dexploitation essaye danalyser un nom de chemin contenant un lien symbolique, il se contente de substituer le vrai nom et continue lanalyse. lier Associer une adresse rseau une socket. LIFO Dernier arriv, premier sorti. Voir aussi FIFO. Une LIFO est plutt appel une pile. ligne Sous UNIX, une squence de zro, un ou plusieurs caractres autres que le saut de ligne, termine par un caractre saut de ligne. Sur les machines non UNIX, ce concept est mul mme si le systme dexploitation sous-jacent a sa propre ide sur la question. lisible 1) Fichier dont le bit dautorisation adquat est 1, ce qui permet laccs en lecture. 2) Programme informatique assez bien crit pour que quelquun dautre puisse revenir plus tard en ayant une chance de comprendre ce quil fait. LIST Une construction syntaxique reprsentant une liste dexpressions spares par des virgules, dont lvaluation produit une liste de valeurs. Chaque expression dans une LIST est value dans un contexte de liste et interpole en une liste de valeurs. liste Une liste ordonne de valeurs. liste nulle Une valeur de liste de zro lments, reprsents en Perl par (). littral Un token tel un nombre ou une chane qui vous donne une valeur effective au lieu de simplement contenir une valeur, ce que fait une variable. littral scalaire Un nombre ou une chane entre apostrophes ; une vraie valeur dans le texte du programme, par opposition avec une variable.

Glossaire
local Ne signifiant pas la mme chose partout. Une variable globale Perl peut tre rendue locale une porte dynamique par loprateur local. Voir porte dynamique. logiciel source ouvert Programmes dont le code source est librement disponible et que lon peut redistribuer sans droit commerciaux attach. Pour une dfinition plus dtaille, voir http://www.opensource.org/osd.html. longueur zro Une assertion qui correspond une chane nulle entre deux caractres. lvalue Terme utilis par les puristes des langages informatiques (et abhorr par les puristes des langages humains) concernant un endroit auquel une nouvelle valeur peut tre assigne, comme une variable ou un lment de tableau. Le l signifie left , pour le ct gauche dune assignation, un endroit typique pour une lvalue. Une fonction ou expression normale laquelle on peut affecter une valeur comme dans pos($x) = 10. magique Smantique attache aux variables telles que $!, $0, %ENV, %SIG, ou tout autre variable lie. Des choses magiques se produisent lors de lutilisation de ces variables. Makefile Un fichier qui contrle la compilation dun programme. Les programmes Perl nen ont pas besoin en gnral, car le compilateur a beaucoup de self-control. man Le programme Unix qui affiche la documentation en ligne (pages de manuel). marqu Caractristique de donnes pouvant provenir des doigts malodorants dun utilisateur, et donc dangereux du point de vue dun programme scuris. Perl effectue des vrifications dentachement ( taint checks ) si on lance un programme setuid (ou setgid) ou si lon active loption -T.

customer_8566

Glossaire
membre Voir variable dinstance. mmoire Concerne toujours la mmoire principale, jamais le disque. La mmoire virtuelle laisse croire que la mmoire est plus importante, mais on ne peut la substituer la mmoire physique. La seule diffrence en cas de limite mmoire atteinte, est que le systme mettra plus de temps crasher, alors quavec la mmoire physique il sarrtera tout de suite. mmoire partage Un morceau de mmoire accessible par deux processus diffrents qui autrement ne pourraient voir la mmoire de lautre. mtacaractre Un caractre qui nest pas cens tre trait normalement. Le choix des caractres traiter de manire spciale comme mtacaractres varie grandement avec le contexte. Le shell peut en accepter certains, les chanes Perl protges par des apostrophes doubles en ont dautres, et les motifs dexpression rgulire connaissent ces derniers plus dautres encore. mtasymbole Une squence de caractres dont le premier est un mtacaractre. mthode Laction que fait un objet quand on lui demande. Voir le chapitre 12, Objets. mthode daccs Une mthode permettant de lire ou de modifier une variable dinstance dun objet. mthode de classe Une mthode dont linvocant est le nom dun paquetage et non une rfrence dobjet. Cette mthode sapplique la classe entire. mthode statique Ne se dit pas. Voir mthode de classe minimalisme La croyance selon laquelle moins cest mieux . Paradoxalement, lorsque lon dit

965
quelque chose dans un petit langage, on obtient un grand discours, et lorsque lon dit la mme chose dans un grand langage on obtient un petit discours. Allez savoir. mode Dans le contexte de lappel systme stat(2), se rfre au mot contenant les permissions et le type du fichier. modificateur Voir modificateur dinstruction, modificateur dexpression rgulire, et modificateur de lvalue. modificateur de lvalue Pseudo-fonction adjective qui qualifie la porte dune dclaration de variable. Il y a actuellement 3 modificateurs de lvalue : my, our, et local. modificateur dexpression rgulire Une option sur un motif ou une substitution telle que /i pour rendre le motif insensible la casse. Voir aussi cloisonneur. modificateur dinstruction Une condition ou une boucle que vous mettez aprs une instruction au lieu de la mettre devant, si vous voyez ce que je veux dire. module Un fichier qui dfinit un paquetage (presque) du mme nom, qui peut aussi bien exporter des symboles que fonctionner comme une classe dobjet. (Le fichier principal .pm dun module peut aussi inclure dautres fichiers). Voir loprateur use. modulo Un entier, quand on est plus intress par le reste que par le quotient. mongueur Raccourci pour Perl mongueur, un fournisseur de Perl. mortel Une valeur temporaire prvue pour durer le temps dune instruction. mot En informaticianais , le bout de donnes de la taille la plus efficace pour un

customer_8566

966
ordinateur, typiquement 32 bits quelques puissances de deux prs. Dans la culture Perl, se rfre souvent un identificateur (avec ou sans caractre alphanumrique), ou une chane de caractres sans espaces dlimite par des espaces ou des limite de chane. mot-cl Voir mots rservs. mot simple Un mot suffisamment ambigu pour que Perl lestime illgal, lorsque la directive use strict subs est en vigueur. Sans cette directive, ce mot isol est trait comme avec des guillemets. motif Modle utilis en reconnaissance de correspondance. motif lexcution Un motif qui contient une ou plusieurs variables interpoler avant que ce motif soit analys comme une expression rgulire, et qui ne peut donc pas tre analys la compilation, mais doit tre reanalys chaque fois que loprateur de recherche de correspondance est valu. Les motifs dexcution sont utiles mais coteux. mots rservs Un mot-clef possdant une signification interne spcifique pour un compilateur, comme if ou delete. En de nombreux langages (pas en Perl), il est illgal dutiliser des mots rservs pour nommer quoi que ce soit dautre (cest dailleurs pourquoi ils sont rservs, aprs tout). En Perl, il est simplement interdit de les utiliser pour nommer les tiquettes et les handles de fichiers. Aussi appels mot-cl. nettoyer Dernire opration effectue par un processus parent lors de la terminaison dun processus fils de telle sorte quil ne reste pas en mmoire. Voir les appels des fonctions wait et wait. NFS Systme de fichiers en rseau qui permet de monter un systme de fichier distant comme sil tait local.

Glossaire
nom de commande Le nom du programme en cours dexcution, tel quil a t entr sur la ligne de commande. En C, le nom de la commande est pass au programme comme premier argument. En Perl, il est connu sous le nom de $0, et spar des arguments. nom de fichier Le nom donn un fichier. Ce nom est list dans un rpertoire, et on peut lutiliser dans une instruction open pour indiquer au systme dexploitation quel fichier ouvrir exactement, et lassocier un handle de fichier qui servira didentit pour les accs suivants dans votre programme jusqu sa fermeture. nombre en virgule f lottante Cest la notation scientique qui permet de reprsenter les nombres avec une prcision indpendante de lordre de grandeur (le point dcimal f lotte). Perl effectue les calculs numriques avec des nombres virgule f lottante (parfois appels des f lottants ) lorsque les entiers ne suffisent plus. Ce sont des approxiations des nombres rels. normale Qui peut servir de lvalue. numro de ligne Le nombre de lignes avant celle-ci, plus 1. Perl conserve un numro de ligne spar pour chaque script ou fichier dentre quil ouvre. Le numro de ligne du script courant est reprsent par __LINE__. Le numro de ligne dentre courant (du fichier qui a t le plus rcemment ouvert par <FH>) est reprsent par la variable $. ($INPUT_LINE_NUMBER). De nombreux messages derreur renvoient les deux valeurs, si elles sont disponibles. NV Valeur numrique interne du type virgule f lottante quun scalaire peut reprsenter, ne pas confondre avec IV . objet Une instance de classe. Quelque chose qui sait quoi il ressemble, et ce quil peut faire car il connat sa classe. Le programme peut demander un objet de faire des cho-

customer_8566

Glossaire
ses, mais cest lobjet qui dcide sil veut le faire ou non. Certains sont plus accomodants que dautres. objet indirect Terme grammatical indiquant le complment dobjet indirect bnficiaire ou rcepteur de laction. En Perl, linstruction print STDOUT "$foo\n"; peut tre interprte grammaticalement comme verbe objet-indirect objet o STDOUT est le rcepteur de laction print, et "$foo" est lobjet imprim. De la mme manire, quand on invoque une mthode on place linvocant entre la mthode et les arguments :
$golem = newCreature::Pathetique"Smeagol"; donner $gollum "Poisson!"; donner $gollum "Tressor!";

967
oprateur binaire Un oprateur qui prend deux oprandes. oprateur circonfixe Un oprateur qui entoure ses oprandes, commme loprateur dangle ou les parenthses, ou une embrassade. oprateur dadressage Certains langages travaillent directement avec les valeurs des adresses mmoire, ce qui peut tre dangereux. Perl fournit des gants isolants pour ce genre dopration. Loprateur le plus proche en Perl est le backslash qui svalue une rfrence dure beaucoup plus sre quune adresse mmoire. oprateur daffectation Soit une affectation rgulire, soit un oprateur compos, form par lassociation dune affectation ordinaire avec un autre oprateur qui modifie la valeur dune variable en place, cest--dire relativement son ancienne valeur. Par exemple, $a += 2 ajoute 2 $a. oprateur de liste Un oprateur comme join ou grepqui agit sur une liste de valeurs. Habituellement utilis pour dsigner des oprateurs prdfinis (tels print, unlink, et system qui ne ncessitent pas de parenthses autour de leurs liste darguments. oprateur de test de fichier Un oprateur interne de Perl qui permet de dterminer si quelque chose est vrai concernant un fichier, tel le test -o $filename qui retourne vrai si vous tes propritaire du fichier. oprateur logique Symboles reprsentant les concepts et , ou , ou exclusif et non . oprateur relationnel Un oprateur qui indique si une relation dordre donne est vraie concernant une paire doprandes. Perl possde des oprateurs relationnels sur les chanes et sur les nombres. Voir squence de tri. oprateur unaire Un oprateur avec un seul oprande,

octal Un nombre en base huit. Seuls les chiffres allant de zro sept sont autoriss. Les constantes octales commencent par un zro en Perl, comme pour 013. Voir aussi la fonction oct. octet Un bout de donnes long de huit bits la plupart du temps. one-liner Un programme entier concentr sur une ligne de texte. oprande Une expression qui donne une valeur sur laquelle un oprateur agit. Voir aussi prcdence. oprateur Une fonction, gnralement intgre au langage, souvent avec une syntaxe ou un symbole spcial, qui transforme des entres en sorties. Un oprateur donn peut attendre des types de donnes spcifiques en tant quarguments (oprandes), ainsi quen tant que rsultat. oprateur arithmtique Un symbole tel que + ou ** qui indique Perl deffectuer un calcul arithmtique, tel un de ceux appris lcole. Voir galement oprateur.

customer_8566

968
comme ! ou chdir. Ce sont en gnral des oprateurs prfixs, ils prcdent leurs oprandes. Les oprateurs ++ et -- sont prfixs ou postfixs. (Leur position modifie leur sens.) opration atomique Lorsque Dmocrite inventa le mot atome pour dsigner la plus petite quantit de matire, il voulait dire litralement inscable a- (privatif) suivi de tomos (scable) : inscable. Une opration atomique est une action qui ne peut tre interrompue. options Voir slecteurs ou modificateur dexpression rationnelle. orgueil Fiert excessive, le genre de chose qui attire les foudres de Jupiter. Mais aussi une qualit qui fait crire (et maintenir) des programmes dont les autres ne voudront pas dire de mal. En consquence, la troisime grande vertu du programmeur. Voir galement paresse et impatience. pad Contraction brouillon. de scratchpad , voir

Glossaire
paquetage Un espace de noms pour les variables globales, les sous-programmes et autres, qui les distinguent de ceux de mme noms dans un autre espace. En un sens, seul un paqueage est global puisque on accde un symbole de sa table en nommant ce paquetage. Mais dans un autre sens, tous les symboles des packages sont globaux, mais organiss comme il faut. paquetage courant Le paquetage dans lequel le code en cours est compil. Parcourez votre code en arrire dans la porte lexicale courante et les portes englobantes. La premire dclaration package que vous trouvez est le paquetage courant. paramtre Voir argument. paresse La qualit qui vous pousse fournir des efforts surhumains dans le but de rduire le travail total. Vous tes ainsi conduit crire des programmes qui, au total, conomisent un dur labeur et que dautres trouvent utiles, et documenter ce que vous avez crit pour ne pas devoir rpondre sans arrt aux mmes questions. En consquence, la premire grande vertu du programmeur. Voir aussi impatience et orgueil. patch Dans le monde des hackers, une liste des diffrences entre deux versions dun programme que lon peut appliquer avec le programme patch(1) pour la mise jour ou la correction dun bogue. PATH La liste de rpertoires quexamine le systme pour trouver un programme excuter. La liste est stocke dans une variable denvironnement, accessible en Perl par $ENV{PATH}. priphrique Un super matriel de la mort (comme un disque, une unit bande, un modem ou un joystick) rattach lordinateur que le systme dexploitation essaye de faire ressem-

page de manuel Une page des manuels UNIX ( manpage ), laquelle on accde typiquement par la commande man(1). Une page de manuel contient un synopsis, une description, une liste de bogues, etc., et est gnralement plus longue quune page. Il existe des pages de manuel documentant les commandes, les appels systmes, les fonctions de bibliothque, les priphriques, les protocoles, les fichiers, et ainsi de suite. Dans ce livre, toute partie de la docmentation Perl standard telle perlop ou perldelta, est appele page de manuel indpendamment du format utilis par votre systme. paquet Groupe de modules communs sur CPAN. (Dnomme parfois aussi un groupe doptions de la ligne de commande rassembls en une groupe doptions.)

customer_8566

Glossaire
bler un fichier (ou un groupe de fichiers). Sous UNIX, ces faux fichiers tendent rsider dans le rpertoire /dev. petit-boutiste Dcrit les ordinateurs qui rangent loctet du poids le plus fort dun mot une adresse plus haute que loctet du poids le plus faible, souvent considrs comme suprieurs aux ordinateurs gros-boutiste, daprs Swift : quelquun qui mange les ufs la coque par le petit bout. phase de compilation Phase avant lexcution. Voir aussi phase dexcution. Elle effectue surtout de la compilation, mais elle peut galement effectuer un peu dexcution dans lvaluation des blocs BEGIN, des dclarations use ou des sous-expressions constantes. Le code de dmarrage et dimportation des dclarations use est aussi excut dans cette phase. phase dexcution Ds que Perl commence excuter votre programme. Voir aussi phase de compilation. La phase dexcution effectue surtout de lexcution, mais elle peut effectuer de la compilation lorsquelle excute les oprateurs require, do FILE, or eval STRING, ou lorsquune substitution utilise le modificateur /ee. pile Un dispositif qui permet dempiler des objets dessus et plus tard de les rcuprer dans lordre inverse. Voir LIFO. pipeline Une srie de processus en ligne, relis par des tubes, o chacun passe sa sortie au suivant. plateforme Le contexte hardware et software dans lequel un programme tourne. Un programme crit dans un langage qui dpend dune plate-forme peut crasher si vous changez lune des choses suivantes : la machine, le systme dexploitation, les bibliothques, le compilateur ou la configuration du systme. Linterprteur perl doit tre recompil chaque portage car il

969
est crit en C, mais les programmes crits en Perl sont dans une large mesure indpendants de la plateforme. pod Les balises pour inclure la documentation dans votre code. Voir chapitre 26, POD. point darrts Une ligne marque dans le source o le dboggueur stoppe lexcution, afin de pouvoir jeter un coup dil et voir si quelque chose a commenc mal fonctionner. pointeur Une variable dans un langage comme C qui contient lemplacement exact dun autre lment. Perl gre les pointeurs en interne et lon na pas besoin de sen soucier. On utilise des pointeurs symboliques sous la forme de clefs et de noms de variables, ou de rfrences en dur, qui ne sont pas des pointeurs (mais agissent comme tels et, en fait, contiennent des pointeurs). polymorphisme Le fait de pouvoir dire un objet de faire quelque chose de gnrique, et lobjet linterprtera de diverses faons, en fonction de sa forme (vient du Grec, formes nombreuses). port La partie de ladresse dune socket TCP ou UDP qui dirige les paquets vers le processus correct aprs avoir trouv la bonne machine, un peu comme le numro de poste de quelquun qui lon veut tlphoner au bureau. portable Il y a longtemps, du code compilable la fois sur BSD et SysV En gnral, du code . qui est relativement facile convertir pour fonctionner sur une autre plateforme. On peut considrer que tout code est portable, il suffit dy mettre du sien. portage Se dit aussi de la conversion du code machine vers une autre machine. porte Distance laquelle une variable reste visible, du point de vue dune autre variable.

customer_8566

970
Perl comprend deux mcanismes de visibilit : la porte dynamique dune variable locale, ce qui veut dire que le reste du bloc et tous les sous-programmes appels dans le reste du bloc peuvent voir les variables locales au bloc ; et la porte lexicale des variables my, ce qui signifie que le reste du bloc peut voir les variables, mais ce nest pas le cas pour les autres sous-programmes appels par le bloc. porte dynamique Les variables porte dynamique sont visibles dans tout le reste du bloc dans lesquelles elles ont t dabord utilises, ainsi que dans les sous-programmes appels par le reste du bloc. Les variables porte dynamique peuvent voir leur valeur temporairement modifies (et restaures implicitement plus tard) par une instruction local. Comparer avec porte lexicale. Employ plus gnralement pour dcrire la faon dont un sous-programme en train den appeler un autre contient ce sousprogramme lexcution. porte lexicale La zone dinf luence du Dictionnaire de lAcadmie Franaise (connue galement sous le nom de porte statique, vu la priode de renouvellement du dictionnaire en question). De mme, la proprit de variables ranges dans un dictionnaire propre chaque bloc (espace de nom), qui ne sont visibles que du point de leur dclaration la fin du bloc dans lequel elles ont t dclares. Syn. porte statique. Ant. porte dynamique. porte statique Ne se dit pas. Voir porte lexicale. porteur Une personne qui porte le logiciel dune plate-forme vers une autre. Le portage de programmes crits en C peut tre un travail difficile, mais celui dun interprteur Perl est trs complexe, mais la rcompense est en proportion. POSIX La spcification des systmes dexploitation portables.

Glossaire
postcurseur Une assertion qui cherche la chane droite de la correspondance courante. postfixe Un oprateur qui suit son oprande comme dans $x++. pp Une abrviation pour le code pushpop qui implmente en C la machine pile de Perl. pragma Un module de bibliothque dont les suggestions et les conseils pratiques sont reus (et parfois ignors) par le compilateur. Les pragmas ont des noms en caractres minuscules. prcdence Les rgles de conduite qui, en labsence dautres directives, dterminent ce qui doit se produire en premier. Par exemple, en labsence de parenthses, la multiplication se produit toujours avant laddition. prcurseur Une assertion qui cherche la chane gauche de la correspondance courante. prdfini Une fonction prdfinie du langage. Mme si elle est surcharge, on peut toujours y accder en qualifiant son nom avec le pseudo-paquetage CORE::. prfixe Un oprateur qui prcde son oprande, comme dans ++$x. prprocesseur Un processus daide pour prparer des donnes pour le processus courant. Souvent effectu laide dun tube. Voir aussi prprocesseur. prprocesseur C La premire passe typique du compilateur C, qui traite les lignes qui commencent par un # pour compiler de manire conditionnelle et dfinir les macros, et qui effectue diverses manipulations du texte du programme en se basant sur les dfini-

customer_8566

Glossaire
tions courantes. galement connu sous le nom de cpp(1). procdure Un sous-programme. processus Une instance dun programme en train de tourner. Sous des systmes multitches comme UNIX, plusieurs processus peuvent faire tourner le mme programme de faon indpendante en mme temps ; en fait, la fonction fork est conue pour en arriver cet heureux tat de fait. Sous dautres systmes dexploitation, les processus sont parfois appels tches ou jobs souvent avec de faibles nuances de signification. propritaire Lutilisateur unique (le super-utilisateur mis part) qui exerce un contrle absolu sur un fichier. Un fichier peut galement appartenir un groupe dutilisateurs qui en partagent la proprit si le propritaire rel le permet. Voir bits dautorisation. proprit Voir variable dinstance ou proprit de caractre. proprit de caractre Une classe de caractre prdfinie retourne par le mtasymbole \p. La plupart de ces proprits sont dfinies pour Unicode. protocole En rseau, une manire convenue denvoyer et de recevoir des messages qui permet aux deux correspondants de ne pas trop se mlanger les pinceaux. prototype Partie optionnelle dune dclaration de sous-programme indiquant au compilateur Perl le type et le nombre de ses paramtres rels, qui rend les sous-programmes semblables des fonctions prdfinies. pseudofonction Une construction qui ressemble une fonction mais qui nen est pas une. Utilis pour les modificateurs de lvalue comme my, pour les modificateurs de contexte

971
comme scalar, et pour les constructions comme q//, qq//, qx//, qw//, qr//, m//, s///, y/// et tr///. pseudohachage Une rfrence un tableau dont le premier lment contient une rfrence un hachage. Un pseudohachage peut tre considr comme une rfrence un tableau ou une rfrence un hachage. pseudo littral Un oprateur qui ressemble un littral, comme loprateur dabsorption de sortie, commande. pumpkin Un hypothtique sceptre qui se transmet dune personne lautre dans la communaut Perl pour savoir qui gouverne tel ou tel domaine de dveloppement. PV Abrviation de pointer value , qui signifie char* en Jargon Interne Perl. qualifi Nom dfini compltement dfini. Le symbole $Foo::bar est qualifi ; $bar ne lest pas. Un nom de fichier qualifi est le chemin complet depuis la racine des rpertoires. quantificateur Composant dune expression rgulire spcifiant le nombre doccurrence dun atome. quartet La moiti dun octet, quivalent un chiffre hexadcimal, et qui vaut quatre bits. ramasse-miettes Une fonctionnalit de certains langages de programmation, qui devrait plutt sappeler Maman va ranger la chambre . Ce nest pas exactement ce que fait Perl, mais il se fie un mcanisme de comptage de rfrences pour laisser les lieux aussi propres en sortant quen entrant. Cependant, si a peut vous rassurer quand linterprteur sort, un vrai ramasse-miettes est lanc pour sassurer que des rfrences circulaires (entre autres) ne tranent pas dans les coins.

customer_8566

972
recherche de correspondance Prendre un motif, exprim par une expression rgulire, et lessayer de diverses manires sur une chane pour voir sil y a moyen de le faire correspondre. Souvent utilis pour extraire des informations intressantes dun fichier. reconnaissance de motif progressive Une reconnaissance de motif qui reprend partir de l o il sest arrt . rcursion Lart de dfinir un chose (au moins partiellement) en fonction delle-mme, ce qui dans un dictionnaire est absolument exclu, mais qui dans un programme dordinateur quivaut une boucle infinie avec une condition darrt exceptionnelle, en faisant attention datteindre un jour cette condition. rfrence Un endroit o lon trouve un pointeur vers des informations stockes ailleurs (voir indirection). Les rfrences existent sous deux formes, rfrences symboliques et rfrences en dur. rfrence arrire Une sous-chane capture par un motif partiel entre parenthses simples, lintrieur dune regex. Les termes (\1, \2, etc.) mmorisent une rfrence pour les occurrences correspondantes des sous-motifs. Hors du motif, les variables nombres $1, $2, etc.) rfrencent les mmes valeurs, tant que le champ dynamique du motif est valable. rfrence en dur Une valeur scalaire contenant ladresse relle dun rfrent, telle que la renvoie le compteur de rfrences. (Certaines rfrences en dur sont contenues en interne, comme la rfrence implicite de lun des emplacements de variable dun typeglob son rfrent correspondant). Une rfrence en dur est diffrente dune rfrence symbolique. rfrence soft Voir rfrence symbolique.

Glossaire
rfrence symbolique Une variable dont la valeur est le nom dune autre variable ou dun sous-programme. Drfrencer la premire variable permet dobtenir la seconde. Les rfrences symboliques sont interdites avec le pragma use strict refs. rfrent Ce quoi rfre une rfrence, qui na pas forcment un nom. Les types de rfrent communs sont les scalaires, le tableaux, le hachages et les sous-programmes. regex Voir expression rgulire. remplacement Dissimuler ou invalider une autre dfinition du mme nom ( ne pas confondre avec la surcharge, qui se contente dajouter des dfinitions lesquelles sont distingues par un autre moyen). Comme si ce ntait pas suffisant, nous employons ce mot avec deux dfinitions surcharges : pour dcrire comment il est possible de dfinir un sous-programme personnel cachant une fonction interne du mme nom (voir Supplanter des fonctions internes dans le chapitre 11, Modules) et pour dcrire comment dfinir une mthode de remplacement dans une classe drive cachant la mthode dune classe de base du mme nom (voir le chapitre 12). rpertoire Un endroit o rsident les fichiers et ventuellement dautres rpertoires. Certains systmes dexploitation peuvent le nommer dossier , drawer (tiroir) ou catalogue . galement appel directory dans certains langages humanodes. rpertoire courant Voir rpertoire de travail. rpertoire de base Le rpertoire dans lequel on se trouve quand on sest identifi sur le systme. Sur un systme UNIX, le nom est souvent plac dans $ENV{HOME} ou $ENV{LOGDIR} par le programme de login, mais on peut galement le trouver avec getp-

customer_8566

Glossaire
wuid($<)[7]. (Certains systmes dpourvus de cette notion.) sont

973
systme dcriture pour un langage particulier tel le Grec, le Bengali ou le Klingon. script kiddie Un cracker qui nest pas un hacker, mais en connat juste assez pour excuter des scripts tout faits. En gnral, les programmes quil crit sont de simples imitations de programmes existants. sed Un vnrable diteur duquel Perl drive certaines ides. slecteur Une option de la ligne de commande qui modifie le comportement dun programme, habituellement note avec le signe moins. smaphore Jolie sorte de signaux mutuels qui empchent les threads ou les processus dutiliser les mmes ressources simultanment. sparateur Un caractre ou une chane qui spare deux chanes entre elles. La fonction split fonctionne sur les sparateurs. ne pas confondre avec les dlimiteurs ou les terminateurs. Le ou de la premire phrase spare deux alternatives. squence dchappement Voir mtasymbole. squence de tri Lordre dans lequel les caractres sont tris. Utilis par les routines de comparaison de chanes pour dcider, par exemple, o mettre dans le glossaire squence de tri . srialisation Mettre une structure de donnes en ordre linaire de faon pouvoir la stocker comme une chane sur un fichier disque ou dans une base de donnes ou bien lenvoyer dans un tube. serveur En rseau, un processus qui peut publier un service ou se contenter dattendre un endroit donn que des clients ayant besoin dun service se manifestent.

rpertoire de travail Votre rpertoire courant partir duquel les noms de fichiers relatifs sont calculs. Le systme dexploitation le connat par la fonction chdir ou parce que votre processus parent a dmarr cet endroit. RFC Request For Comment , appel commentaires, qui sont des sries de documents standards importants, contrairement ce que laisse supposer leur dnomination timide. root Le super-utilisateur (UID == 0). Cest aussi le rpertoire racine du systme de fichier. RTFM Sigle anglophone pour vous suggrer de bien vouloir lire le superbe manuel. RV Une Rfrence de Valeur interne du type de celle quun scalaire reprsente. Voir aussi IV et NV . rvalue Une valeur que lon peut trouver du ct droit dune assignation. Voir galement lvalue. saut de ligne Un caractre unique reprsentant la fin dune ligne, dune valeur de 012 octal sous UNIX (mais 015 sur un Mac), et reprsent par \n dans les chanes Perl. Pour les machines sous Windows et certains priphriques physiques comme les terminaux, il est traduit automatiquement par votre bibliothque C en saut de ligne et retour chariot, mais normalement aucune traduction nest effectue. scalaire Une valeur simple, comme un nombre, une chane ou une rfrence. script Un fichier texte qui est un programme excuter directement au lieu davoir le compiler sous une autre forme avant lexcution. Aussi, dans le contexte Unicode, un

customer_8566

974
service Quelque chose que lon fait une personne pour lui faire plaisir, comme lui indiquer lheure. Sur certaines machines, les services les plus connus sont lists par la fonction getserver. setgid Comme setuid, mais concernant les privilges des groupes. setuid Un programme tournant avec les privilges de son propritaire au lieu des privilges de lutilisateur (ce qui est en gnral le cas). Dcrit aussi le bit du mot mode (f lags de permissions) qui implmente cette fonctionnalit. Ce bit doit tre explicitement activ par le propritaire, et le programme doit tre crit de faon ne pas donner plus de privilges que ncessaire. shebang En Perl cest la squence #! qui indique au systme o trouver linterprteur. Le terme vient de la construction du mot anglais sharp dsignant # et de bang pour !. shell Un interprteur de ligne de commande. Le programme qui donne une invite interactive, accepte une ou plusieurs lignes dentre et excute les programmes mentionns, leur fournissant leurs arguments et leurs donnes dentre. Les shells peuvent galement excuter des scripts contenant ces commandes. Sous le systme dexploitation UNIX, les shells habituels sont le Bourne shell (/bin/sh), le C shell (/bin/csh) et le Korn shell (/bin/ksh). Perl nest pas strictement un shell car il nest pas interactif (bien que des programmes Perl puissent tre interactifs). signal Un clair soudain ; ou plutt un vnement dclench par le systme dexploitation, nimporte quel moment, de prfrence au moment o vous ne vous y attendez pas. slurp Lire un fichier en entier dans une chane en une opration.

Glossaire
socket Un point de communication rseau entre deux processus, qui fonctionne comme un tlphone ou une bote lettres. La chose la plus importante concernant une socket est son adresse rseau (comme un numro de tlphone). Des types diffrents de sockets ont des types dadresse diffrents ; certains ressemblent des noms de fichiers, dautres non. sortie standard Le f lux de sortie par dfaut dun programme, qui ne doit pas se proccuper de la destination des donnes. Reprsent dans un programme Perl par le handle de fichier STDOUT. sous-chane Une partie dune chane, commenant partir dune certaine position de caractre (dplacement), et courant sur un certain nombre de caractres. sous-classe Voir classe drive. sous-motif Composant un motif dune expression rationnelle sous-motif de code Sous-motif dune expression rationnelle dont la fonction est dexcuter du code Perl, par exemple les sous-motifs (?{...}) et (??{...}). sous-programme Une partie nomme dun programme qui peut tre invoque dun autre endroit du programme pour atteindre un but secondaire du programme. Un sous-programme est souvent paramtr pour accomplir des tches diffrentes mais en rapport selon les arguments fournis en entre. Si la valeur que le programme retourne a une signification. standard Inclus dans la distribution officielle de Perl comme module standard, outil standard ou bien page de manuel standard. statique Variant lentement, compar autre chose.

customer_8566

Glossaire
(Malheureusement, tout est relativement stable compar autre chose, part certaines particules lmentaires, et encore). Dans les ordinateurs, o les choses sont censes varier rapidement, statique a une connotation pjorative, indiquant une variable, une mthode ou un sous-programme lgrement dfectueux. Dans la culture Perl, nous vitons dutiliser ce mot. statut La valeur renvoye au processus pre quand lun de ses processus fils meurt. Cette valeur est place dans la variable spciale $?. Ses huit bits de poids fort sont le statut de sortie du processus dfunt, et ses huit bits de poids faible identifient le signal (sil y a lieu) dont est mort le processus. Sur les systmes UNIX, cette valeur de statut est la mme que le mot qui est renvoy par wait(2). Voir system dans le chapitre 29. statut de sortie Voir statut. STDERR Voir erreur standard. STDIN Voir entre standard. STDIO Voir E/S standard. STDOUT Voir sortie standard. struct Un mot-clef C prsentant une dfinition ou un nom de structure. structure Voir structure de donnes. structure de donne La faon dont les donnes sarticulent entre elles et la forme quelles constituent ensemble, comme par exemple un arbre de forme triangulaire ou une table rectangulaire.

975
structure stat Un endroit spcial dans lequel Perl garde linformation sur le dernier fichier consult. substitution Pour changer des parties de chane avec loprateur s///. Ne pas confondre avec linterpolation de variable. sucre syntaxique Faon diffrente dcrire quelque chose : raccourci. superclasse Voir classe de base. super-utilisateur La personne qui le systme dexploitation laisse faire presque tout ce quil veut. Typiquement, ladministrateur systme, ou quelquun prtendant ltre. Sur un systme UNIX, lutilisateur root. Sur les systmes Windows cest ladministrateur. surcharge Donner une nouvelle signification un symbole ou une construction. En fait, tous les langages pratiquent la surcharge un degr ou un autre, car les gens savent distinguer les significations daprs le contexte. surcharge doprateur Un type de surcharge que lon peut effectuer sur les oprateurs internes pour les faire fonctionner (de manire syntaxique) sur des objets comme sil sagissait des valeurs scalaires ordinaires, mais les rgles smantiques tant fournies par la classe. Ceci est activ par le pragma de surcharge-voir le chapitre 13. SV Abrviation de scalar value . Mais dans linterprteur Perl, tout rfrent est trait comme une sorte de SV dune certaine , manire oriente objet. Toute valeur dans Perl est passe en tant que pointeur SV* en C. La struct SV connat son propre type de rfrent, et le code est assez intelligent (esprons-le) pour ne pas essayer dappeler une fonction de hachage sur un sous-programme.

customer_8566

976
symbole En gnral, un token ou un mtasymbole. Souvent utilis pour dsigner les noms que lon trouve dans une table de symboles. synchrone Squence dvnnements dont lordre darrive est dtermin. syntaxe Du grec avec-arrangement . Comment des lments (en particulier des symboles) sont assembls entre eux. systme dexploitation Un programme spcial qui tourne sur la machine elle-mme et cache les dtails bas niveau de gestion des processus et des priphriques. galement utilis dans un sens plus gnral pour indiquer une culture de programmation particulire. Le sens gnral peut tre employ divers degrs de spcificit. un extrme, on peut dire que toutes les versions dUNIX et de ses clones sont le mme systme dexploitation (ce qui nerve beaucoup de gens, surtout les avocats). lautre extrme, une version donne du systme dexploitation dun fournisseur donn diffre de nimporte quelle autre version de ce fournisseur ou dun autre. Perl est beaucoup plus portable entre les systmes dexploitation que de nombreux autres langages. Voir galement architecture et plateforme. systme de fichiers Un ensemble de rpertoires et de fichiers rsidant sur une partie du disque. Aussi appel partition . Vous pouvez changer le nom dun fichier ou bien le dplacer dans larborescence du systme sans dplacer le fichier lui-mme, du moins sur le systme UNIX. table de hachage Une mthode utilise en interne par Perl pour implmenter les tableaux associatifs (hachages) de manire efficace. table de symboles L o un compilateur conserve ses symboles. Un programme comme Perl doit, dune manire ou dune autre, se souvenir de tous les noms de variables, de handles de

Glossaire
fichiers et de sous-programmes quil a utilis. Il place cet effet les noms dans une table de symboles, qui est implmente en Perl par une table de hachage. Il existe une table de symboles spare pour chaque paquetage, qui donne chaque paquetage son propre espace de noms. tableau Squence de valeurs ordonnes de faon pouvoir y accder par indice entier qui indique la valeur du dplacement. tableau associatif Voir hash, svp. tableau multidimensionnel Un tableau avec plusieurs indices pour trouver un lment donn. Perl utilise des rfrences cet effet ; voir le chapitre 9, Structures de donnes. tampon Un lieu de stockage temporaire des donnes. Le tamponnage par bloc signifie que les donnes sont passes leur destination quand le tampon est plein. Le tamponnage par ligne signifie quelles sont passes chaque fois quune ligne complte est reue. Le tamponnage de commandes signifie quelles sont passes aprs chaque commande print (ou quivalente). Si la sortie nest pas bufferise, le systme procde octet par octet sans utilisation dune zone temporaire, ce qui est moins efficace. tampon par bloc Une mthode efficiente de tamponnage dentres/sorties qui utilise un bloc de donnes dun coup. Perl lutlise par dfaut pour laccs au fichiers sur le disque. Voir tampon et tampon de commande. tampon par commande Un mcanisme en Perl qui vous permet de stocker la sortie dune commande, et la vide immdiatement dans la mme requte au systme dexploitation. Il est activ en positionnant la variable $| ($AUTOFLUSH) une valeur vraie. Cest utilis lorsque vous ne souhaitez pas que vos donnes soient l sans rien faire attendre lordre du dpart, ce qui peut se produire car, par dfaut, un fichier ou un tube utilisent un tampon par bloc.

customer_8566

Glossaire
tamponnage de ligne Utilis par un f lux dE/S standard de sortie qui vide (f lush) ses tampons (buffers) aprs chaque saut de ligne. De nombreuses bibliothques dE/S standard activent ainsi automatiquement la sortie allant au terminal. TCP Abrviation de Transmission Control Protocol . Un protocole au-dessus de IP , faisant apparatre un mcanisme de transmission de paquets non fiable comme un f lux doctets fiable (enfin, en thorie). terme Court-circuit pour terminal cest--dire la feuille dun arbre syntaxique, et qui a le rle dun oprande pour les oprateurs de lexpression. terminateur Un caractre ou une chane qui indique la fin dune autre chane. La variable $/ contient la chane qui termine lopration readline, ce que la fonction chomp enlve de la fin. ne pas confondre avec les dlimiteurs ou les sparateurs. Le point la fin de cette phrase est un terminateur. ternaire Un oprateur prenant trois oprandes. test de la sous-classe vide Le fait quune classe drive vide doit se comporter exactement comme sa classe de base. texte Normalement, une chane ou un fichier contenant des caractres imprimables. thread Comme un processus ddoubl, mais sans la protection mmoire de linstruction fork. Un thread est plus lger, au sens que les threads peuvent tre excuts ensemble lintrieur du mme processus en se disputant la mme mmoire, moins de prendre des prcautions pour les isoler les uns des autres. Voir le chapitre 17, Threads. tie Le lien entre une variable magique et sa classe dimplmentation. Voir la fonction

977
tie au chapitre 29 et au chapitre 14, Variables lies. TMTOWTDI Theres More Than One Way To Do It , la devise Perl. Lide quil peut y avoir plusieurs faons de procder pour rsoudre un problme de programmation. (Cela ne veut pas dire que le fait davoir plusieurs possibilits est toujours une bonne chose, ouque toutes les possibilits sont aussi bonnes les unes que les autres. Cela veut juste dire quil ny a pas de vrit unique. token Un morphme en langage de programmation : la plus petite unit de texte qui possde un sens. tokenisation clater un programme en mots et en symboles spars, chacun tant appel un token (symbole). galement appel lexicaliser , auquel cas lon obtient des lexmes . tokeniseur Un module qui spare le programme en squences de tokens pour lanalyseur syntaxique. traitement dexception La manire dont un programme ragit une erreur. Le mcanisme de traitement dexception de Perl est la construction eval. tranche Une partie des lments dune liste, dun tableau ou dun hachage. translittration Transformation dune chane vers une autre par correspondance de chaque caractre vers un autre avec une fonction. Voir loprateur tr/// dans le chapitre 5. transtypage Conversion explicite de donnes dun type lautre. C autorise ceci. Perl nen a pas besoin. Et nen veut pas. troff Un langage de mise en forme duquel Perl drive sa variable $% secrtement utilis

customer_8566

978
dans la production des livres de la srie du Chameau. tronquer Vider un fichier de son contenu, soit automatiquement en louvrant pour criture ou explicitement par la fonction truncate. true Toute valeur scalaire qui ne vaut pas pas 0 ou "" svalue true dans un contexte boolen. tube Une connexion directe entre lentre dun processus et la sortie dun autre sans fichier intermdiaire. Une fois quil est initialis, les deux processus concerns peuvent lire et crire dessus comme si ctait un fichier banal, avec quelques prcautions. tube nomm Un tube avec un nom encapsul dans le systme de fichiers de faon pouvoir tre utilis comme un fichier par le processus lecteur, ce qui rend la programmation indpendante des donnes sources car il suffit de considrer la source comme un fichier. type Voir type de donnes et classe. type de donnes Un ensemble de valeurs possibles, avec toutes les oprations qui savent les grer. Par exemple, un type de donnes numrique comprend un certain ensemble de valeurs sur lesquelles il est possible de travailler, ainsi que diverses oprations mathmatiques associes qui nauraient que peu de sens sur, par exemple, une chane comme argh . Les chanes ont leurs oprations propres, comme la concatnation. Les types composs dun certain nombre dlments plus petits ont gnralement des oprations permettant de les composer et de les dcomposer, et peuttre de les rarranger. Les objets qui modlisent les choses du monde rel ont souvent des oprations qui correspondent des activits relles. Par exemple, si lon modlise un ascenseur, lobjet en question peut avoir une mthode ouvrir_porte().

Glossaire
typedef La dfinition dun type en langage C. typeglob Emploi dun identificateur unique (par exemple *nom) pour dsigner $nom, @nom, %nom, &nom ou simplement nom. Son mode dutilisation dtermine sil est interprt comme tous ces derniers, ou comme un seul dentre eux. Voir Typeglobs et handles de fichiers dans le chapitre 2. typemap Dans un module extension crit en XS dcrit comment transformer un type C vers un type Perl ou rciproquement. UDP User Datagram Protocol , la faon typique denvoyer des datagrammes sur internet. UID Un identifiant dutilisateur. Souvent employ dans le contexte de la proprit dun fichier ou dun processus. umask Le masque de bits dautorisation pour crer des fichiers ou des rpertoires pour dterminer qui vous en refusez laccs. Voir la fonction umask. Unicode Un ensemble de caractres qui contient tous les caractres du monde, plus ou moins. Voir http://www.unicode.org. unit de compilation Le fichier (ou la chane dans le cas dun eval) dans le processus de compilation courant. Unix Un grand langage en constante volution avec plusieurs syntaxes largement incompatibles, avec lequel nimporte qui peut dfinir nimporte quoi nimporte comment, ce dont peu se privent. Les UNIXophones le croient facile apprendre car on peut facilement le tordre sa convenance, mais les diffrences entre les dialectes rendent les communications intertribales quasiment impossibles, et les voyageurs en

customer_8566

Glossaire
sont souvent rduits utiliser une version petit-ngre du langage. Pour tre universellement compris, un programmeur shell UNIX doit tudier son art pendant des annes. Nombreux sont ceux qui ont abandonn cette discipline et communiquent prsent via une sorte despranto appel Perl. Dans les temps anciens, UNIX reprsentait galement du code que quelques personnes des Bell Labs avaient crit pour utiliser un ordinateur PDP-7 qui ne faisait rien dautre ce moment-l. v-chane Une chane vecteur ou version spcifie avec v suivie par une srie dentiers dcimaux en notation pointe, par exemple, v1.20.300.4000. Chaque nombre devient un caractre avec sa valeur ordinale. (Le v est optionel quand il y a au moins trois caractres.) valeur Une donne relle, par constraste avec les variables, rfrences, clefs, index, oprateurs ou toute chose pour accder une valeur. valeur de liste Une liste sans nom de valeurs scalaires temporaires qui peuvent tre passes dans un programme par une fonction renvoyant une liste une expression qui fournit un contexte de liste. valeur de retour La valeur produite par un sous-programme ou une expression lvaluation. En Perl, une valeur de retour doit tre soit une liste, soit un scalaire. valeur scalaire Une valeur qui se trouve tre scalaire par opposition une liste. variable Un emplacement de mmoire qui porte un nom et qui peut contenir diverses valeurs, quand votre programme en ressent le besoin. variable denvironnement Mcanisme par lequel un agent de haut niveau, tel un utilisateur, peut transmettre

979
ltat de ses variables de travail un processus fils. Chaque variable denvironnement a la forme dune paire clef/valeur comme dans un hachage. variable dinstance Lattribut dun objet ; donne mmorise par linstance de lobjet et non par la classe entire. variable lexicale Une variable ayant une porte lexicale, dclare par my. Souvent juste appel une lexicale . (La dclaration our dclare un nom porte lexicale pour une variable globale, qui nest pas une variable lexicale.) variable scalaire Une variable prfixe par un $, contenant une valeur unique. variables magiques Variables spciales donnant des effets secondaires quand on y accde en lecture ou en criture. Par exemple, en Perl, la modification des lments du hachage %ENV modifie galement les variables denvironnement correspondantes que les sous-processus utilisent. La lecture de la variable $! donne le numro ou le message derreur UNIX courant. variable statique Rien de tel. Utilisez plutt une variable lexicale pour une porte plus grande que votre sous-programme. variadique Se dit dune fonction qui reoit avec bonheur un nombre indtermin darguments rels. vecteur Jargon mathmatique pour dsigner une liste de valeurs scalaires. vidage Le vidage dun tampon, souvent avant quil ne soit rempli. virtuel Ce qui donne lillusion de quelque chose qui na pas dexistence relle comme par

customer_8566

980
exemple la mmoire virtuelle qui simule la mmoire relle (voir aussi mmoire). Le mot inverse est transparent qui donne une existence relle quelque chose qui napparat pas comme la faon dont Perl gre lencodage variable UTF-8. WYSIWYG What You See Is What You Get (Vous obtenez ce que vous voulez). Utilis pour indiquer quelque chose qui saffiche comme il est crit, comme par exemple les dclarations Perl format. Cest aussi le contraire de la magie parce que chaque chose apparat comme elle est rellement, comme dans la fonction open 3 arguments. XS eXternal Subroutine, extraordinairement exporte, expditivement excellente, expressment excute en C ou C++ existant, ou dans un nouveau et excitant langage dextension appel (de faon

Glossaire
exasprante) XS. Examinez le chapitre 21, Mcanismes internes et accs externes, pour une explication exacte. XSUB Un sous-programme externe dfini dans XS. yacc Yet Another Compiler Compiler . Un gnrateur danalyseur syntaxique sans lequel Perl naurait pas exist. Voir le fichier perly.y dans le source de la distribution Perl. zombie Un processus qui est mort mais dont le pre na pas t inform par la fonction wait ou waitpid. Si vous utilisez fork, vous devez ensuite nettoyer la mmoire avant de sortir sinon la table des processus va se remplir et risque de dborder ce qui risque de fcher ladministrateur systme.

customer_8566

Index

Symboles
! (point dexclamation) ! (ngation logique), oprateur 80 surcharge 324 !!, commande du dbogueur 484 != (diffrent de), oprateur 88, 554 !~, oprateur de lien 81 utilisation avec les oprateurs de recherche de motif 127 dans les commandes du dbogueur 484 oprateur (diffrent de) != 24 utilisation pour complmenter les jeux de caractres 156 " (doubles apostrophes) 51, 127, 242 chanes, utilisation dans 7 dans la chane de remplacement 135 dans les arguments de formline 680 interpolation des variables 6 oprateur de conversion en chane 323 traitement des squences dchappement de conversion 173 voir aussi qq// et la fonction print # (dise) #! (shebang), notation 16, 456 problmes de scurit causs par 537 simuler sur les systmes non-Unix 458 dans les formats 214 les caractres protgs, lespace et 55 pour les commentaires 43 utilisation avec le modificateur de motif /x 131 $ (dollar) 11 $! ($ERRNO, $OS_ERROR) 24, 591, 635 $" ($LIST_SEPARATOR) 634

$# prfixe pour obtenir le dernier index 65 variable obsolte pour limpression des nombres 623 $$ ($PROCESS_ID) 47, 638 $% ($FORMAT_PAGE_NUMBER) 216, 630 $& ($MATCH) 129, 130, 166, 561, 635 $( ($REAL_GROUP_ID) 638 $) ($EFFECTIVE_GROUP_ID) 626, 638 $* 623 $+ ($LAST_PAREN_MATCH) 166, 634 $, ($OUTPUT_FIELD_SEPARATOR) 636 $- ($FORMAT_LINES_LEFT) 216, 218, 629 $. ($INPUT_LINE_NUMBER) 90, 631 remise zro avec la fonction close 658 $/ ($INPUT_RECORD_SEPARATOR) 460, 632 $: ($FORMAT_LINE_BREAK_CHARACT ERS) 214, 629 $; ($SUBSCRIPT_SEPARATOR) 67, 640 $< ($REAL_USER_ID) 638 $= ($FORMAT_LINES_PER_PAGE) 216, 629 $> ($EFFECTIVE_USER_ID) 627 $? ($CHILD_ERROR) 47, 625 fonction close et 658 oprateur backtick et 68 $@ ($EVAL_ERROR) 627 $[ (index du premier lment dun tableau) 623 $[, variable 623 $\ ($OUTPUT_RECORD_SEPARATOR) 465, 636

customer_8566

982
$] ($OLD_PERL_VERSION) 635 $^ ($FORMAT_TOP_NAME) 216, 218, 555, 630 $^A ($ACCUMULATOR) 219, 624 formline, sortie 680 $^C ($COMPILING) 626 $^D ($DEBUGGING) 462, 626 $^E ($EXTENDED_OS_ERROR) 629 $^F ($SYSTEM_FD_MAX) 395, 641, 677 $^H (indication pour le parser Perl) 630 $^I ($INPLACE_EDIT) 631 $^L ($FORMAT_FORMFEED) 216, 629 $^M (espace mmoire) 634 $^O ($OSNAME) 587, 635 $^P ($PERLDB) 637 $^S ($EXCEPTIONS_BEING_CAUGHT) 6 28 $^T ($BASETIME) 87, 625 $^V ($PERL_VERSION) 637 $^W ($WARNING) 121, 641 $^X ($EXECUTABLE_NAME) 628 $_ ($ARG), variable 624 grep, fonction et 692 instructions foreach et 103 map, fonction et 702 $` ($PREMATCH) 129, 166 ${^ (noms de variables internes) 47 ${^WARNING_BITS} 641 ${^WIDE_SYSTEM_CALLS} 375, 641 $| ($OUTPUT_AUTOFLUSH) 216, 555, 636 $~ ($FORMAT_NAME) 216, 555, 630 $ ($PREMATCH) 561 $ ($POSTMATCH) 129, 130, 166, 561, 637 $ ($PREMATCH) 637 $0 ($PROGRAM_NAME) 638 $1 et cie. 623 $a et $b (variables de sort) 624 $line 28 caractre de prototype 206 dans le dbogueur 477 dans les noms de variables scalaires 45 dans les recherches, assertion de fin de ligne 134, 161 drfrencement avec 230 interpolation des variables scalaires 53 mtacaractre 125, 141 oprateur $_ ($ARG) oprateur dangle 69 pour les noms de variables scalaires 5, 9 variable $_ ($ARG) 32, 34 fonction glob avec 72 % (pourcent) 84 %=, oprateur affectation de modulo 93 caractre de prototype 206

Index
dans les noms de hachage 9 oprateur modulo 82 pour les sommes de contrle 777 typage des variables 6 & (esperluette) 84 &&, oprateur et logique 23, 89, 289 &&=, oprateur logique et affectation 93 &, oprateur et sur les bits 88 &=, oprateur sur les bits et affectation 93 adresse-de, oprateur (en C) 96 caractre de prototype 206 dans les noms de fichiers 712 Perl version 5, changement dans lutilisation 14 pour les noms de sous-programme 6, 46, 47, 112, 198 dans les prototypes 205 () (parenthses) 11, 77, 555, 571 (...) groupement 142 comme caractres de protection 63 dans les appels de sous-programme 198, 211 dans les fonctions 643 quilibrage 193 insrer automatiquement avec Deparse 450 listes nulles, representation 63 mtacaractre 125, 141 notation (?:PATTERN), regroupement sans capture 167 pour la capture dans des motifs 126, 129, 135 pour les rfrences arrires 36, 164, 166 pour les valeurs de listes 62 regroupement, oprateur de 181 utilisation avec loprateur conditionnel 92 * (astrisque) 84 **, oprateur dexponentiation 80 **=, oprateur dexponentiation et daffectation 93 *=, oprateur de multiplication et daffectation 93 *? quantificateur 142 caractre de prototype 206 mtacaractre 125, 141 oprateur de drfrencement (en C) 96 oprateur multiplicatif 78, 82 pour les noms de typeglobs 6, 47, 67 quantificateur 34, 142, 159 + (signe plus) 84 ++, oprateur dauto-incrmentation 22, 79 +, oprateur unaire 77, 81 +=, oprateur daddition et daffectation 93 +?, quantificateur 142 dans les noms de fichiers 709 mtacaractre 125, 141 oprateur additif 83

customer_8566

Index
qualificateurs 32 quantificateur 142, 159 , (virgule) $, variable 636 dans les rapports avec print 636 erreur dans les instructions print 554 grands nombres et 51 oprateur 94 contexte scalaire 560 voir aussi => operator paires clef/valeur et 11 paires clefs/valeurs et 65 prcdence 78, 115 sparateur 11 sparation des valeurs dune liste 62, 63 utilisation dans les dclarations de boucle 102 - (tiret) 84, 181 -*- pour emacs 457 --, oprateur dautodcrmentation 22, 79 --, option de la ligne de commande 460 -=, oprateur de soustraction et affectation 93 ->, oprateur flche 79, 231 appels de mthode et 287 drfrencement de rfrences avec 79 dans les commandes du dbogueur 482 dans les intervalles de caractres 148 oprateur arithmtique de ngation 80 oprateur de soustraction 83 soustraction de jeu de caractres 156 . (point) 84 .., oprateur dintervalle 90 ..., oprateur dintervalle 90 .=, oprateur de concatnation et affectation 93 caractre joker 131, 147 caractres spciaux 33 dans @INC 805 dans des motifs 181 dans les classes de caractres 157 glober des fichiers et 689 mtacaractre 125, 141 oprateur (concatnation) 20 oprateur de concatnation 83, 565 autognration par le handler de conversion en chane 324 quantificateurs, utilisation dans les 33 sparation des entiers avec les v-chanes 58 vecteurs (adresses IP) 683 / (slash) 84 //, voir m//, oprateur /=, oprateur de division et affectation 93 commande du dbogueur 483 dlimiteurs, remplacement comme 54

983
oprateur de division 82 rpertoire racine 657 : (deux-points) :: dans les noms absolus 47 :: dans les noms de module, traduction en sparateurs de rpertoire 276 :: pour identifier un paquetage 56, 267, 558 dans les dclarations de sousprogramme 210, 211 dans les tiquettes 101 dans les groupes de motif 168 dans les listes dimportation dun module 628 dans les XSUB 502 sauts de lignes dans les formats avec $: 629 ; (point-virgule) dans les commandes du dbogueur 478 dans les noms de fichiers, risques de scurit des 534 erreurs, oublier la fin 554 fin des instructions simples 43, 97 < (infrieur) <, oprateur (infrieur) 18, 24, 87 <<, oprateur de dcalage gauche 83, 954 <<, oprateur de lecture de ligne voir oprateur angle <<, pour documents ici-mme 56 <<=, oprateur de dcalage et affectation 93 <=, oprateur (infrieur ou gal ) 24, 87 <=>, oprateur de comparaison 24, 88, 747 <>, oprateur de lecture de ligne voir oprateur angle dans les commandes du dbogueur 484 dans les noms de fichiers 709 pour globaliser les noms de fichiers avec <> 71 pour la justification gauche 217 <> dans un contexte de liste 70 = (gal) ==, oprateur gal 21, 24, 88, 554 ==>, marqueur de ligne courante 477 => (associatif) oprateur 11 =>, oprateur de correspondance 66, 95 paramtres nomms et 66 =~, oprateur de liaison de motif 32, 81 utilisation avec les oprateurs de recherche de motif 127 commande du dbogueur 485 dans les directives pod 596 oprateur daffectation 6 > (suprieur) <> oprateur lecture de ligne voir oprateur lecture de ligne >, oprateur (suprieur) 18, 24, 87

customer_8566

984
>=, oprateur suprieur ou gal 24, 87 >>, oprateur de dcalage droite 83 >>=, oprateur de dcalage et affectation 93 dans les commandes du dbogueur 484 dans les noms de fichiers 709 pour globaliser les noms de fichiers 71 pour la justification droite 217 ? (point dinterrogation) 84 ?, quantificateur 34, 142, 166 ?:, oprateur conditionnel 91, 110 ??, quantificateur 142, 166 mtacaractre 125, 141 ? (point dinterrogation) extensions de regex (?!) 183 (?<!) 184 (?<=) 184 (?=) 183 (?>) 185 @ (arobase) @+ (@LAST_MATCH_END) tableau de positions finales 166 @+ (@LAST_MATCH_END) tableau des positions des fins 633 @- (@LAST_MATCH_START) tableau de positions initiales 166 @- (@LAST_MATCH_START) tableau des positions des dbuts 633 @_ (@ARG), tableau 199, 625 lintrieur des chanes, chappement et caractre antislash 53 caractre de prototype 206 dans le dbogueur 477 dans les lignes images 214 modifications entre les versions de Perl 558 pour les noms de tableaux 5, 45 [] (crochets) [, mtacaractre 125, 141 \C pour de lUnicode et 378 composeur de tableaux 224 et \p, \P pour de lUnicode 378 et \X pour de lUnicode et 378 pour dtecter des caractres 181 pour les classes de caractres 32, 142, 145, 148 prcdence 77 tableaux et 9, 11 \ (antislash) 51, 728 \\ doubles guillemets, interprtation avec 6 chanes protges, viter la surcharge dans les 54 comme caractre dchappement 52 en tant que sparateur de rpertoires sur MSSDOS 848 entrer des commandes continues dans le dbogueur 478

Index
interprtation par lanalyseur de regex 172 la notation \Q pour prfixer tous les caractres non alphanumriques 53 oprateur de rfrence 81, 223, 235 pour des commandes du dbogueur multilignes 476 pour faire des mtasquences de caractres simples 124 pour les mtacaractres 125, 142 pour protger des caractres 124, 141 rfrences arrires et 36 \d (pour digit, chiffre) 32 ^ (chapeau) ^=, oprateur xor sur les bits et affectation 93 assertion de dbut de ligne 34, 35, 161 comportement spcifique, lviter dans un motif 148 dans la dtection 181 assertion de fin de ligne 134 inversion de classe de caractre 148 mtacaractre 125, 141 oprateur ou-exclusif sur les bits 88 pour le texte inclus dans les formats 214 _ (soulign) dans les identificateurs 42, 47 dans les noms de variable 268, 572 doubl 59 fields, pragma, utilisation dans 801 grands nombres et 51 handle de fichier global 623 marquage et 530 modifications entre les versions de Perl 558 {} (accolades) 242, 554, 570 {, mtacaractre 125, 141 blocs simples, crer avec des 108 composeur de hachages 225 dans les chanes 268 dans les commandes du dbogueur 484 dans les formats 214 flches et 232 hachage vs. tableaux 11 identificateurs dans les 53 identificateurs entre 53 indiquer une clef entre 11 motifs de recherche, claircir lutilisation 56 pour les blocs dinstructions 27, 43, 99 pour Unicode 147, 377 prcdence 77 quantificateur 33, 142 | (barre verticale) ...|... alternative 126, 142, 168 |- recevoir/envoyer une pseudo-commande via un pipe 400 |=, oprateur ou sur les bits 93

customer_8566

Index
||, commande du dbogueur 484 ||, oprateur ou logique 89, 170, 289 prcdence face chdir 78 ||=, oprateur logique et daffectation 93 commande du dbogueur 484 dans les noms de fichiers 709 mtacaractre 125, 141 oprateur ou sur les bits 88 pour le centrage 217 ~ (tilde) expansion du rpertoire maison 689 oprateur de ngation sur les bits 80 pour supprimer les lignes blanches 215 (apostrophe inverse) 51, 54, 399 contexte vide et 571 excution de commande 68 exemple dutilisation 7 inhiber linterpolation des variables 6 oprateur 61, 558, 571 portabilit de 592 scurit et 535 supprimer linterpolation des variables 54 (apostrophe) inhiber le traitement des squences dchappement de conversion 173 qx et 728

985
signaux et 388 utilisation avec connect 659 utilisation avec le module FileHandle 767 accs date pour un fichier 758, 780 lments de tableaux lis 345 enregistrements de structures de donnes labores 260 hachages de tableaux 253 hachages multidimensionnels 257 mthodes supplantes 297 tableau de hachages 255 tableaux multidimensionnels 248 tranches de tableaux multidimensionnels 248 accs aux donnes, threads 425433 deadlock 427 dverrouiller 427 variables de condition 430 verrou mortel 427 verrouiller des mthodes 429 verrouiller des sous-programmes 428 accolades ({}) voir accolades dans les symboles $ACCUMULATOR 624 actions (dbogueur) excution de commandes, spcifier depuis le dbogueur 483 lister toutes 481 ActiveState, distribution de Perl installer sur les systmes Windows 458 Microsoft, modules uniquement pour 830 PPM (Perl Package Manager) 520 addition 20 oprateur plus (+) surcharg 321 adressage de tableau ngatif 44 adresse-de, oprateur (en C) 96 adresses empaquetes de sockets 689 en langage C ou en Perl 557 noms de sockets comme 650 obtenir depuis des noms dhtes 685 rseau, convertir en noms 682, 683, 684 rutilises, afficher le contenu des 490 affectation loprateur conditionnel ?: 93 aux listes 64 de variables lies 341 lment de tableau li 346 lments de tableaux deux dimensions 247 affectation, oprateurs d 93 prcdence des, modifications entre les versions de Perl 559

Nombres
0 but true 676 exemption de -w 675 0+ (numification) oprateur 323 -0, option de la ligne de commande 456, 460 32-bits, systmes 589 64-bits, systmes 589

A
\a (alerte ou bip) 52 -a (autosplit), option de la ligne de commande 461, 629 -A (date daccs) oprateur de test de fichier 86, 87, 625 \A (limite de chane) 161 abbrviations, texte 820 abs (valeur absolue), fonction 648 complexes, nombres et 857 surcharge 326 abstraction 265 en programmation oriente objet 285 accent grave voir apostrophe inverse dans les symboles accept, fonction dans les serveurs prforks 393 defined 648 exemple dutilisation 412, 413, 855 portabilit de 588

customer_8566

986
surcharge 325 voir aussi constructeur de copie affichage hachages de tableaux 253 hachages multidimensionnels 257, 260 tableaux de hachages 255 tableaux multidimensionnels 248, 252, 255 afficher typeglob, contenu dun 490 affirmative de prvision, assertion 180, 183 AFN (automate fini non dterministe) 178 ajouter des chanes des chanes avec .= 93 des lments des tableaux 247, 777 des membres un hachage existant 255 lments des tableaux 727 .al, fichiers se terminant avec 274 alarm, fonction 649 associer avec sleep 746 dlai limite pour les correspondances de motifs 551 portabilit de 588 alatoires, nombres 728, 757 algorithmes 947 modules Perl pour les 517 alias 947 commande du dbogueur pour les 485 dune table de symbole 68 dans la table des symboles 48 dans les boucles for/foreach 104 rechercher et remplacer des lments dans des tableaux 137 en affectant un typeglob 270 pour des caractres 146 ALRM, signal dfini 389 exemple dutilisation 384 alternance 947 alternatives 126 classes de caractres et 149 dans des motifs 168 dtecte lun ou lautre (...|...) 142 interne, limitation de la porte de 167 prcdence, recherche de motif 179 American Standard Code for Information Interchange voir ASCII amorcer (bootstrapping) des modules 503, 828 analyse interpolation en guillemets doubles et expressions rationnelles 127 analyse de texte modules Perl pour l 518 analyse lexicale 947 analyse syntaxique 500 dans le compilateur Perl 438

Index
ancres 35, 161 and (&&), oprateur logique 572 angle voir oprateur dangle anonyme 947 composeur de hachages 225 composeur de sous-programme 226 composeur de tableaux 224 hachages ajout des hachages multidimensionnels 256 structure de donnes pour objets 291 tableau de, cration 254 pipes 398399 rfrents 222 sous-programmes 197 donner un nom lexcution 271 tableaux cration dun hachage de 252 tranche de tableau deux dimensions 249 AnyDBM_File, module 824 Apache, serveur web 507 CGI::Apache, module 824 mod_perl, extension 445 modules Perl pour 519 apostrophe inverse () voir apostrophe inverse dans les symboles apostrophes () comme dlimiteurs de paquetage 268 appelant 948 appels indirects de sous-programme 198 par rfrence 199, 203, 947 par valeur 200, 948 appels bloquants, verrous dans les threads 426 appels systme 763, 948 en Perl ou en langage C 557 interruption de signaux dans les 388 relancer 389 arbres syntaxiques 436, 439 interne, garder en 446 originaux, reconstruire et intgrer dans larbre syntaxique actuel 448 reconstruction des 437 arc tangente, fonction voir atan2 architecture 948 $ARG ($_ avec use English) 624 $ARG (terme pour $_) 69 arguments 948 formels 625, 948 rels 948 voir aussi paramtres arguments de la ligne de commande 948 arguments de programmes, en shell ou en Perl 558

customer_8566

Index
ARGV, handle de fichier 621, 625 @ARGV, tableau 625, 669 -s, option et 467 exemple dutilisation 107, 140, 188, 406, 760 marquage et 527 pop et 724 shift et 744 $ARGV, variable 625, 948, 949 en langage C ou en Perl 557 ARGVOUT, handle de fichier 621, 625 arit 75 liste de la plus haute la plus basse 76 arrondir des nombres avec la fonction sprintf 694 ASCII 41, 949 convertir en caractres 657 convertir vers de lUnicode 377 valeurs pour les caractres 716 voir chr voir ord ASP modules Perl pour 519 assertion \b (limite de mot) 35 assertions (dans des motifs) 125, 142, 949 assertions priphriques 183 classes de caractres et 149 de position 161164 \A et ^, assertions de limite de chane 161 \b et \B, assertions (limite de mot) 162 \G, assertion 134 \z, \Z et $, assertions 161 dfinir vos propres 194 prcdence, recherche de motif 180 assertions de largeur nulle 125, 142, 161 quantificateurs 126 associatifs, tableaux voir hachages associativit des oprateurs 75, 88, 949 astronomie modules Perl pour l 520 async, fonction (dans le module Thread) 421 atan2 (arc tangente), fonction complexes, nombres et 857 pour calculer pi 649 atomes 180, 949 dans les recherches de motifs 181 atomique, opration 540 attributes, pragma 210, 792 attributs 949 attributes, pragma 825 classe stocker ltat de 315 de classe 706

987
de fichiers, oprateurs de test pour 25 en programmation oriente objet 293 interpolation de variables et 716 locked et method, utilisation avec les threads 315 locked, sous-programmes 429 lvalue, sous-programmes 314 objets, hachage d 12 sous-classe, surcharge de surclasse 306 sous-programmes 210212 syntaxe des noms 211 attrs, module (obsolte) 825 audio modules Perl pour l 520 authentification modules Perl pour l 518, 825 auto-incrmentation (++), oprateur 22, 79, 326, 949 magique 80 autochargement 949 gnration daccesseurs par 309 mthodes 301 autodcrmentation (--), oprateur 22, 79 magique 325 autodtection, de caractres 181 autognration, surcharge 324, 949 empcher 330 AUTOLOAD, sous-programme 112, 273274, 301 utilisation avec goto 692 AutoLoader, module 274, 827 autorisation modules Perl pour l 518 autosplit, mode (avec loption -a) 461 AutoSplit, module 274, 827 portabilit de 591 autouse, pragma 793, 827 autovivification 79, 674, 949 de handles de fichiers 708, 851 de typeglobs 228, 356 defined 232 AV (valeur tableau interne) 500, 950 avertissements 950 ${^WARNING_BITS} 641 au sujet des valeurs indfinies 97 dsactiver de manire permanente 471 modules pour les 827 sur les rfrences aux objets lis 367 verbosit, forcer dans les 826 avertissements lexicaux 827 voir aussi warnings pragma avertissements, messages 470, 783, 871945 awk 30, 950 conversion en Perl 67

customer_8566

988

Index
bases de donnes relationnelles lier un hachage (Tie::DBI) 368 lier un hachage (Tie::RDBM) 369 voir aussi bases de donnes $BASETIME 625 basetime ($^T) 625 BEGIN, blocs 436, 500 altrer lanalyse du fichier par le compilateur 452 dfinition de @INC 276 initialisation de variables avant lappel de sous-programme 203 ordre dexcution 451 Benchmark, module 829 comparer des temps dexcution de versions diffrentes de code 831833 bibliothques 788, 950 bibliothque mathmatique C 506 C/C++, charger en tant quextensions Perl 828, 829 extensions non-installes depuis MakeMaker 828 ExtUtils::Liblist, module 828 fichier de bibliothque Perl, rechercher 472 Perl, installer des modules dans 521 bidirectionnelle, communication avec des pipes 402404 big-endian voir gros-boutiste /bin/sh voir sh binaire 950 mode des handles de fichiers 650 oprateur de rptition (x) 20 pack, fonction 718722 binaires, fichiers 714 dcompiler avec le module B::Deparse 450 bind, fonction 650, 743 exemple dutilisation 412 portabilit de 588 binmode, fonction 650, 714 avec seek et tell sur MS-DOS 588 portabilit de 588 pour les handles de fichier lis 359 sysopen et 765 biologie modules Perl pour la 520 bits 950 bits dexcution 950 bits, oprateurs sur les 88, 95 et (~), oprateur, exemple dutilisation 860 ngation (~), oprateur 860 oprateur de ngation (~) 80 surcharge 325

B
-B (binaire), test de fichier 86 \b (espace arrire, backspace), caractre 144 dans les classes de caractre de regex 149, 162, 181 \B (non limite de mot), assertion 144, 162 -b (spcial de type bloc), test de fichier 85 \b, assertion de limite de mot 125, 162 pour backspace (espace arrire) 149, 181 B, module 829 B::Asmdata, module 829 B::Assembler, module 829 B::Bblock, module 829 B::Bytecode, module 447, 829 B::C et B::CC, modules 448 B::C, module 829 B::CC, module 829 B::Debug, module 829 B::Deparse, module 450, 829 B::Disassembler, module 829 B::Lint, module 449, 829 B::Showlex, module 829 B::Stash, module 829 B::Terse, module 829 B::Xref, module 449, 829 backends voir sorties backends (sorties), compilateur 830 backslash (\) voir antislash dans les symboles backtick () voir backtick dans les symboles backtracking 950 bang (!) voir point dexclamation dans les symboles barewords 966 barre verticale (|) voir barre verticale dans les symboles basculer lactivation du mode trace (dbogueur) 481 base de registres (Microsoft Windows) manipuler 335 base, classes de 826 pour les filtres et les traducteurs de pod 827 UNIVERSAL, module, fournir toutes les classes 826 base, pragma 297, 794, 795 implmentations par pseudo-hachage, ncessaire avec 308 bases de donnes connexions de Perl aux 123 liaison de variables de hachage aux 335 modules Perl pour exploiter les 518 voir DBD ; DBI

customer_8566

Index
blancs caractres dans les formats 214 modificateur /x dans la recherche de motif 131 normalisation dans une variable 137 bless, fonction 226, 236, 291, 651, 953 constructeurs, utilisation avec 291 drfrencement implicite et 223 exemple dutilisation 573, 651, 730 liaison ou 336 typeglobs et 227 blib, pragma 828 blib, rpertoire 505 blocs 27, 43, 97, 99, 231 boucles et 697 continue, bloc 101 dclarations de paquetage, porte de 267 simples 108111 faire des structures case avec 109 vidage du tampon par 636 blocs de bits 156 blocs, et stat 758 bloquer des signaux 389 bloquer, verrous partags 391 bloqus 950 bogues dans Perl, rapporter 872 Boolen 950 contexte 60 bool, oprateur de conversion 323 oprateur m// (match) en 133 dfinition de la vrit 26 boolen contexte 953 oprateurs boolens 25 bootstrapping (amorcer) des modules 828 boucle tiquettes pour 962 boucle foreach 29 boucle while 24, 28 affectation de liste dans les 65 contexte boolen, fournir un 61 oprateur angle et $_ 69 boucles 28, 101108, 555, 571, 951 commentaires et lignes blanches, rejet avant traitement 171 dextraction de tranches de tableaux multidimensionnels 248 tiquettes pour 105 eval, fonction dans les 562 for, boucle 29, 102 foreach, boucle 29 infinies 103 instruction de contrle dans les 962 itration 963 itration sur 102

989
last, oprateur et 30, 103, 697 next, oprateur et 30, 706 oprateur s/// (substitution), utilisation sur des tableaux 137 oprateurs de contrle pour instructions contre 107 redo, oprateur et 731 reset, fonction et 734 until, boucle 101 utilisation dans lassertion \G lintrieur de 164 utilisation dans les substitutions globales 138 while, boucle 28, 101 boucles infinies voir infinies, boucles break, commande (en C) 557 break, instruction voir last, oprateur BSD (Berkeley Standard Distribution) 951 BSD::Ressource, module limites des ressources par processus, configurer des 551 buckets 951 buffering 976 bundles 516 bytecode 436, 499, 951 ByteLoader, module 448, 830 bytes, pragma 376, 795, 822

C
-C (caractres larges natifs), option de la ligne de commande 375 -c (contrle de la syntaxe), option de la ligne de commande 461, 500, 626 compilateur, Perl 439 C (correspondant un seul octet en langage C), mtasymbole joker 378 -C (date de modification dinode), test de fichier 87, 88, 625 -c (spcial de type caractre), test de fichier 85 -C (wide-characters natif), option de la ligne de commande 461, 641 C, langage 951 accder Perl depuis une infrastructure lentourant 446 bibliothque, signaux provoquant des core dumps dans la 385 C, pile, stocker les variables C dans la 445 correspondre un char 378 fcntl.h, dfinitions, charger en tant que constantes Perl 823 fichiers den-tte 959 fonctions de la bibliothque 644 gnrateurs de code C 448

customer_8566

990
oprateurs manquant en Perl 96 oprateurs logiques 89 relations de prcdence 77 Perl, tendre avec 499, 501507 bibliothque C externe, utiliser des fonctions venant 506 crer des extensions 503505 envelopper autour de fonctions Perl 502 XSUB et langage XS 501 Perl, utiliser depuis 507 ajouter un interprteur Perl 508 compiler des programmes Perl insrs 508 instruction Perl, valuer 510 pile de Perl, manipuler 511 sous-programme Perl, appeler depuis 509 XSUB, entres et sorties 506 programmer en, diffrences avec Perl 556 programmes denrobage 538 scurit par rapport Perl 527 structs 721 syslog, fonctions, utilisation en Perl 823 typedefs 500 variables statiques 202 \C, mtacaractre joker (correspondant un octet simple en C) 144, 147 /c, modificateur de motif 139 continuer la recherche malgr les checs 163 cache 244 avec stat 623 dobjets en mmoire 315 de classes de caractres 156 de fichiers 822 de fichiers systme 565, 682 de recherches de mthode 296 exemple dutilisation 352, 574, 575 modules fournissant un cache 368 web 519 callbacks (fonctions de rappel) 761, 959 voir aussi fonctions de rappel caller, fonction 652 dbogueur de Perl et 492 et la pile de contexte 444 exemple dutilisation 206, 313, 351, 608, 863 modifications entre les versions de Perl 559 utilisation avec goto 112, 692 can, mthode (paquetage UNIVERSAL) 300 canevas, chanes 718722 caractres pour pack/unpack 718 canonisation des caractres, informations sur la 378

Index
capitales initiales voir majuscules capitalisation 47 caractres dchappement 52 capture dans des motifs 164167, 951 mots alphanumriques 134 suppression dans les regroupements 167 capture la plus gauche la plus longue 160 capturer exceptions 669 capturer la sortie dune commande externe 768 de fonctions 401 caractre alerte (bip) 52 caractre de mot (\w) 32 caractre ESC 52 caractre espace 32, 951 caractres protgs, utilisation en 55 caractre sparateur de ligne 43 caractre sparateur de paragraphe 43 caractre, smantique de consquences de la 376 octet, smantique d, ou 376 caractres 41, 951 alias pour 146 casse des voir majuscules convertir entre une taille fixe de 8 bits et une taille variable UTF-8 375 dans des motifs 124126 dans les formats 718 dcomposition de 152 drles de caractres devant les noms de variable 335, 956 entre dun seul caractre 681 hexadcimal voir hexadcimal jokers pour 147 longueur en 698 mtacaractres 124 obtenir depuis des valeurs ASCII 657 obtenir depuis des valeurs Unicode 657 obtenir la valeur ASCII des 716 octal voir nombres octaux octets ou 373, 645 proprits 971 dfinir vos propres 155 voir aussi under Unicode prototype 206 remplacer dans les chanes 139 spcial 181 supprimer 655 voir aussi classes de caractres ; motifs caractres de contrle 51 non-ASCII sur Macintosh 459

customer_8566

Index
caractres spciaux 181 Carp, module 339, 827, 833 voir die, fonction voir warn, fonction cartes de crdit modules Perl pour les 520 casse conversion de chanes en casse de titre 140 mots simples, problmes avec 55 oprateurs de traduction, utiliser des tables Unicode 379 squences dchappement pour les traiter, passe dinterpolation de variables 145 supprimer la dtection sensible la casse 130, 131, 134, 136, 174 voir aussi capitalization casse de titre fonctions \u et ucfirst, utilisation dans des conversions 140 cat, commande (Unix) 352 catgories de caractres 151 de fonctions 646647 cbreak, option 681 centrer 217 csures dans du texte module Perl pour les 518 /cg, modificateur de motif 134 CGI CGI.pm, module 834 compartiments scuriss pour 544, 547 groupes dutilisateurs pour xxiv mod_Perl et xxiii modules Perl pour 519, 824 ncessit dactiver le mode de marquage pour 527 performances sous mod_perl 445 scripts semblant bloquer 679 scurit des scripts 414 voir HTML CGI::Apache, module 824 CGI::Carp, module 824, 834 CGI::Cookie 824 CGI::Fast, module 824 CGI::Pretty, module 824 CGI::Push, module 824 chane entre guillemets, interpolation et concatnation 20 chane litrale v-chane (vecteur ou version) 58 chane, conversion en 323 dobjets 236 de rfrences 236, 243, 248, 249 de structures de donnes 262 surcharge 360

991
chanes 5 affichage de valeurs dans 237 affichage, changer dans le dbogueur 490 afficher 725 apostrophes interpolation des caractres dans 52 assertions de limite 35, 161 binaires 707 comme units de compilation 48 comparaison 88 concatnation 83, 565 avec la fonction join 695 contexte de 60, 953 conversion en nombres 50 prfixes 0x, 0b, et 0, gestion des 51 convertir en valeurs de liste 776 dtection sur des chanes contenant des sauts de ligne 131 clater en sous-chanes 752 entre apostrophes modifications entre les versions de Perl 560 eval, fonction et 561 extraire des sous-chanes 762 formats pour les 754757 hexadcimales voir nombres hexadcimaux index, fonction et 693 interpole 7 joindre 695 minuscules, mise en 697 modification 137 octales voir octaux, nombres oprateur dintervalle, travailler avec 91 oprateurs 20, 554 oprateurs de comparaison 24 oprateurs sur les bits, travailler avec 89 premier caractre dune 623 rechercher et remplacer des sous-chanes (oprateur s///) 135 rfrences et 243 rindex, fonction et 736 saut voir dollar, $: dans les symboles study, fonction et 759 valeur boolennes des 26 valeurs de listes, convertir vers des 718722 vec, fonction et 781 voir aussi texte chanes en tant que 781 chanes littrales 51 sauts de ligne dans les 53 chameaux rose et bleu 613

customer_8566

992
sanglant 57 vs. chevaux 4 champ, spcifier un sparateur diffrent 461 changements denvironnement, pile de 444 chapeau (^) voir chapeau dans les symboles chargement dune structure de donnes depuis le disque 261 charnames, pragma 377, 795, 822 chdir, fonction 653 avec le module Cwd 837 comportement sans argument 471 exemple dutilisation 100, 535, 590, 665 exemple de surcharge 281 prcdence et 78 CHECK, blocs 436, 500 ordre dexcution 451 chemin pour les recherches de bibliothque 630 chemin, modules installs sur un systme Windows 276 chercher des sous-chanes 736 chiffrement 660 chiffres dans les noms 47 chiffres (digit) 32 $CHILD_ERROR 625 chimie modules Perl pour la 520 chmod, fonction 16, 653 exemple dutilisation 72, 644, 777 portabilit de 588 chomp, fonction 19, 655 $/ et 632 $\ et 465 chop ou 655 exemple dutilisation 558, 577, 660, 754 longeur de chane et 379 chop, fonction 19, 655 efficacit de 562 exemple dutilisation 22, 832 longeur de chane et 379 voir chomp, fonction chown, fonction 656 portabilit de 588 sur les systmes POSIX 859 chr, fonction 657 CRLF et 414 exemple dutilisation 58, 326, 702 Unicode et 147, 154, 379 voir ord chroot, fonction 544, 657 portabilit de 588 circuits virtuels (en tant que flux TCP) 409 citation paquetages 290

Index
Class::Contract, module 314 Class::Multimethods, module 299 Class::Struct, module 820, 835 classe, mthodes Thread, classe 421 classes 266, 283, 952 de base voir classes de base drives voir classes drives donnes de, gestion 315318 stockage de rfrences aux donnes de classe dans lobjet lui-mme 317 fonctions pour 647 gnration avec le module Class::Struct 309 hritage 295303 autochargement de mthodes 301 classe UNIVERSAL et 299301 mthodes prives, viter avec 302 mthodes supplantes, accs aux 297 hritage parmi les base, pragma 825 implmentant les hachages lis 349 implmentant les handles de fichier lis 355 implmentant tie 336 implmentation avec un pseudohachage 705 liant des scalaires 338342 modules orients objet comme dfinitions de 275 modules ou 266 notation de paquetage explicite 290 numro de version, retournant un 300 objets, cration de 291 paquetage 79, 770, 778 paquetages comme 285 Perl 148 tableau @ISA, inclusion avec le pragma base 297 classes conteneur avec pointeurs sur des structures de donnes autorfrentielles 304 classes de base 284, 952 constructeurs et 294 invoquer toutes les mthodes supplantes 300 supplanter les mthodes de 297 classes de caractres 32, 148158, 181, 952 classiques Perl 156 confusion avec les index de tableau 56 correspondre avec des proprits de caractres en Unicode 378 inversion ou ngation 148 mtasymboles jokers et 147 mtasymboles utiliss lintrieur 145, 149 personnalises 148

customer_8566

Index
POSIX, style 157158 prdfinies, disponibilit de 378 proprits Unicode 150157 raccourcis Perl pour 149 classes drives 284, 952 mthodes servant demballage de mthodes de classe de base 298 test de la sous-classe vide 977 classes parent 284 clefs de correspondance, pseudo-hachages 307 cls, hachage voir hachage, cls clients 952 obtenir le nom de 413 TCP 411 UDP 415 cloisters 952 clotres 168 close, fonction 399, 658 exemple dutilisation 18, 100, 263, 393 exemple dutilisation avec des pipes 398, 399, 711 numros de lignes et 631 portabilit de 591 verrouillage de fichier et 392 close-on-exec, flag 543, 641, 649 fcntl et 396, 714 socket et 747 socketpair et 747 closedir, fonction 659 portabilit de 591 voir opendir closures 958 clusters dans les motifs 952 cmp, fonction (dans File::Compare) 844 cmp, oprateur 24, 88, 747 surcharge 326 code efficacit du 567 extraire et afficher avec les dbogueurs 482 mlanger une smantique de caractre avec une smantique doctet 376 non sr 543 compartiments de scurit pour 544 dguiser du code en donnes 548 exemples scuriss 547 rutiliser 573 code retour (exit status) 625 code source CPAN, pour la distribution Perl 516 fentre autour dun point darrt, examiner 477 filtres pour le 448, 517, 585 outils de dveloppement pour le 449 code, gnration 829

993
code, sous-motifs dans des expressions rationnelles 190 coderef voir sous-programmes, rfrences de codes dopration 439, 443, 500 combinaison de caractres, correspondance de \X avec 148 commandes accder avec des privilges restreints 534 dans pod 598 dbogueur 478486 actions et 483 affichage de structures de donnes 481 documentation, consulter 486 historique 476 localisation de code 482 options, manipuler 486 pas pas et lancement 479 points darrt 480 quitter le dbogueur 485 redmarrer le dbogueur 485 traage 481 hachages de fonctions, stocker dans 259 noms de 14 pour le contrle de boucle 106 rappeler, option du dbogueur 488 tampon 976 traiter des 455471 emplacement de Perl 460 voir interprteurs; Perl, interprteur vidage du tampon de 636 commentaires 952 dfinition 43 en Perl ou en C, syntaxe pour les 557 tendre avec le modificateur de motif /x 131 jeter avant le traitement 171 multilignes 596 Common Gateway Interface voir CGI communication interprocessus voir IPC ; IPC::*, modules comp.lang.Perl newsgroups xxiv comparaison chanes 88 comparaison, oprateurs de 88 sort, fonction et 747 surcharge 326 comparer chanes 554 fichiers 821 temps dexcution de versions de code diffrentes 829 compartiments scuriss pour le code non sr 544 compatibilit ascendante 952

customer_8566

994
compatibilit des caractres, dcomposition de 152 compilateurs 952 compilateur de regex 176 dclarations globales et 112 compilateurs, Perl 626 indications pour 630 interprteur, interactions avec 450454 modules en rapport avec les 517, 829 sorties (backends) pour les 446 compilation 953 contrler le dbogueur durant 478 compilation, phase 500 ou compilation 438 compiler 435454, 499 cycle de vie des programmes Perl 436 compilation, phase de 436 gnration de code, phase de 436 reconstruction de larbre syntaxique, phase de 437 du code 437443 ordre 454 insr, programme Perl (dans du C) 508 $COMPILING 626 composites, proprits Unicode 151 Comprehensive Perl Archive Network voir CPAN compression modules Perl pour la 519 compteurs, variables compteurs magiques 342 COMSPEC, variable denvironnement 472 concatnation (.), oprateur de 20, 83 autognration par loprateur de conversion en chane 324 chanes constantes, surcharge 331 efficacit de 563, 565 exemple dutilisation 83 concatner des chanes 953 avec .= 22 avec join 695 optimiser dans le compilateur 441 condition, variables de 430 conditionnel (?:), oprateur 91, 110 conditionnelles, instructions criture sans accolades 99 expressions dans des boucles 102 interpolations dans des motifs 194 voir aussi instruction if; instruction unless Config, module 588, 828 %Config, hachage 508 correspondance du systme dexploitation entre les noms et les numros de signaux 386 configuration modules Perl pour la 518

Index
connect, fonction 659 exemple dutilisation 411 portabilit de 588 Socket, module et 863 utiliser le module IO::Socket au lieu de 411 connexions 953 arrter 745 constant, pragma 271, 797 constantes 271 IPC Sytem V, dfinir pour les 824 mise en ligne des fonctions constantes 208 Perl, charger les dfinitions de fcntl.h en tant que 823 surcharge 330 constructeur de copie 328 constructeurs 226, 283, 291295, 953 fonction bless et 291 hritables 292 import, mthode 706 initialisation 293 nommage 293 noms de classe ou objets, fonctionnement avec 292 variables de classe lies 336 vrifications daccs, spcification dans les 313 construire des modules de CPAN 521 contexte 5962, 953 boolen 60 conditionnel voir contexte boolen de guillemets doubles tendre dans les variables scalaires 135 de liste 3638, 59, 953 affectation de liste en 94 appel et valuation de sous-programmes en 199 expressions en, voir LIST hachage dans un 11 instruction foreach, dans un 29 lvalues en 115 m//g, lister toutes les occurrences en 133 oprateur angle dans le 70 oprateur antislash le fournissant 236 oprateur conditionnel en 92 oprateur dintervalle (..) en 90 oprateur m// (match) en 133 oprateur virgule en 94 variables de hachage, utilisation dans les 66 de tableau voir contexte de liste entre guillemets 61 interpolatif 61 interpolatif (entre guillemets) 61

customer_8566

Index
numrique 60, 953 scalaire 59 affectation de liste dans un 64, 94 appel et valuation de sous-programmes en 199 contexte vide 61 expressions en, voir EXPR lvalues en 115 oprateur conditionnel en 92 oprateur dintervalle (..) en 90 oprateur m// (match) en 133 oprateur virgule en 94 types drivs 60 utilisation dans le modificateur de motif /g 134 valeurs boolennes et 61, 953 variables de hachage, valuation dans un 66 scalaire et liste 59 vide 61, 64, 783, 953 void 23 voir aussi contexte de liste ; contexte scalaire contextes, pile de 444 continuation lines 954 continue, bloc 101, 105, 106 voir aussi boucles continue, commande (en C) 557 contractions dans les mots, viter la confusion avec les guillemets simples 184 contrat entre le module et lutilisateur 278 contrle, caractres de 157 mtasymboles dans des motifs 146 contrle, variables de 103 conversion, oprateurs contexte boolen, interprtation dun objet en 323 conversion en chane 323 numification (conversion de non-nombre en nombre) 323 convertir date et heure 690, 700 des caractres vers des valeurs ASCII 716 des chanes en valeurs de liste 752, 776 des langages entre eux 585 des nombres hexadcimaux en dcimaux 692 des nombres octaux en dcimaux 707 des valeurs de liste en chanes 695, 718 entre des entiers et des caractres UTF-8 379 formats de fichiers modules Perl pour 519 nombres vers/depuis de lhexadcimal 136 une valeur ASCII en caractre 657 une valeur Unicode en caractre 657

995
cookies (HTTP), lire et crire 824 copie lors dcritures, smantique 418 copier des fichiers ou des handles de fichiers 821 copy-on-write, smantique voir copie lors dcritures core dump (copie du cur du programme) dump, fonction pour 667 problme de saturation des serveurs avec les correspondances de motifs 551 provoqus par des signaux dans la bibliothque C 385 Thread::Signal, module, empcher avec 433 core, fichiers 469 CORE, pseudo-paquetage 282, 298 CORE::GLOBAL pseudo-paquetage 282 correspondance (??), oprateur voir m?? correspondance (m//), oprateur voir m// correspondance avide 34, 950 correspondance la plus gauche, la plus longue 963 correspondance large symboles 43 correspondance minimale 34 correspondance minimale ou maximale, indiquer 33 correspondances possibles, spcifier lensemble des 168 cos (cosinus), fonction 659 complexes, nombres et 857 exemple dutilisation 443, 650 Math::Trig et 858 CPAN (Comprehensive Perl Archive Network) xviii, 13, 266, 275, 515, 954 modules 828, 836 catgories de modules 517 construire 521 crer 522 dcompresser et dpaqueter 520 installer dans la bibliothque Perl 521 installer des modules avec 520 installer et construire 520 portabilit des 592 rpertoire 516 modules de liaison 368369 sous-rpertoires 515 CPU accder dans un environnement multitches 536 temps pour les processus 772 threads cdant la priorit 424 variables de condition permettant aux threads dabandonner 430

customer_8566

996
cracker 954 CRLF dans les programmes Internet 414 voir sauts de ligne crochets ([]) voir crochets devant Symbols crypt, fonction 660 exemple dutilisation 65 portabilit de 588 cryptage modules Perl pour le 518 cryptographie 757 Ctrl-A 135 Ctrl-C 52 signaux, gestionnaire pour les 385 Ctrl-C et Ctrl-Z, gnrer des signaux avec 384 Ctrl-D pour eof (fin de fichier) 59, 584 Ctrl-Z pour eof (fin de fichier) 59, 584 Curses modules Perl pour 518 CV (internal code value) 954 Cwd, module 821 rpertoire de travail courant pour le processus, dterminer le 837 cycle de vie des programmes Perl 436 compilation, phase de 436 excution, phase d 437 gnration de code, phase de 436 reconstruction de larbre syntaxique, phase de 437

Index
modules Perl pour 517 portabilit 593 date daccs, et stat 758 date de cration, et stat 758 date de modification, et stat 758 date et heure 772 accs/modification de fichiers 780 Greenwich Mean Time(GMT) 690 pour le mridien local 700 Time::Local, module 820 UPD, programme pour obtenir depuis dautres machines 415 date, fonction voir localtime, fonction DB, module 825 caller, fonction 653 DB_File, module 824 Data::Dumper, utiliser avec le module 838 DBD (Database drivers) modules Perl pour 518 DBI (Database Interface) modules Perl pour 518 DBM, fichiers 954 dbmclose et dbmopen, fonctions 661 modules pour les 824 portabilit des 592 supprimer dans 663 valeurs de donnes complexes, stocker dans des 838 verrouiller 393 dbmclose, fonction 335 portabilit de 588 dbmopen, fonction 335 DBMs et 337 portabilit de 588 verouillage et 393 deadlock dans les threads 427 dbogage 461, 475498 arguments 626 bogues de scurit dUnix 537 code du dbogueur, commande pour charger 472 commandes du dbogueur Perl 478486 contrler depuis les programmes 478 DB module 825 dbogueur, excution autonome 490 dclencher dans un handle de fichier li 362 destruction globale dobjets et dautres rfrences, contrler 472 Devel::Peek, module pour les programmes XS 826 erreurs courantes des dbutants 553560 implmentation du debogueur, Perl 492 modules de sorties (backends) pour 446 niveau de dbogage, spcification par la classe ou les instances 316

D
^D (Ctrl-D) pour eof 584 -D (dbogage), option de la ligne de commande 462 -d (dbogage), option de la ligne de commande 461, 475, 494 -d (rpertoire), test 25 -d (rpertoire), test de fichier 85 /d, modificateur de motif 139, 140 dangereuses, oprations 469 dans les scripts 746 data types 978 DATA, handle de fichier 626 Data::Dumper, module 262, 825, 838 __DATA__, symbole 59 __DATA__, token 626 databases Data Base Management voir DBM, fichiers datagrammes 954, 955 voir aussi paquets date fichier, accs/modification 758 fonctions Perl pour 647

customer_8566

Index
Perl, utilisation de loption -DDEBUGGING du compilateur C 296 personnalisation du dbogueur 487490 pour les programmeurs crbraux du C 556 pour les programmeurs pnitents de Perl 4 558 pour les programmeurs shrifs du shell 557 rapports de bogues xxv surcharge 333 symbolique 954 tableaux multidimensionnels 249 voir marquage, vrification dbogueur, ligne de commande 489 $DEBUGGING 626 dbutants, erreurs courantes des 553560 dbuts de chanes, dtection 161 dcalage pour les russites de m// 725 read, fonction et 729 seek, fonction 738, 739 dcalage droite (>>), oprateur voir suprieur dans les symboles dcalage gauche (<<), oprateur voir infrieur dans les symboles dcalage binaire (<<, >>) 954 dcalage de bits (<<, >>), oprateurs 83, 93 voir aussi suprieur et infrieur dans les symboles dcalage, oprateurs de 83 dchiffrement voir chiffrement dclaration local 115, 116 utilisation sur des variables globales 119 dclaration our rgles de contexte et 60 dclarations 3, 97122, 680, 955 champs (avec le pragma use fields) 306 formats 213 mthodes, indication de retour de lvalue 314 paquetage 12, 114, 267, 722 porte 114 sous-programme 112, 197, 761 anonyme 197 struct 309 variables 97, 114 variables globales 112 porte lexicale 118 dclarative, approche de la programmation des expressions rationnelles 187 dcomposer les caractres en caractres plus simples 152 dcomposition normalise de caractres 152 dcompresser des modules de CPAN 520

997
dcrmentation des variables 22 DEFAULT, pseudo-signal 386 defined, fonction 662 exemple dutilisation 270, 394, 396, 654, 661, 712 sous-programmes et 198 voir undef, fonction wantarray et 201 defined, fonction, ou exists ou vrai 673 dfinitions 955 classes (modules orients objet comme) 275 sous-programmes 199 chargement avec AUTOLOAD 273 chargement depuis dautres fichiers 113 dclaration contre 112 DEL en hexadcimal 52 delete, fonction 663 exemple dutilisation 234 pseudo-hachages et 234 tableaux lis, ne renvoyant pas les valeurs dtruites pour 560 undef ou 775 dlimiteurs 955 oprateurs de dtection de motifs et 129 Dmocrite 540 dmons marquage, importance dactiver le mode de 527 modules Perl pour les 519 denial-of-service voir saturation des serveurs dpannage voir dbogage dpaqueter des modules de CPAN 520 dequeue, mthode (Thread::Queue, module) 431 drfrence, surcharge des oprateurs 327 drfrencement 955 drfrencement dadresse (*), oprateur de C 96 drfrencement infixe, oprateur voir flche (->), oprateur drfrencement symbolique vrification avec le pragma strict 122 drfrencer 223, 229, 230, 231 lments de tableaux 248 oprateur voir flche (->), oprateur typeglobs 270 valeurs de hachages en tant que fonctions 259 voir aussi rfrences droulement voir excution

customer_8566

998
dsallocation mmoire 244 descripteurs de fichiers 676, 740, 955 handles de fichiers, passer avec des 395 passer via une variable denvironnement ou une option de la ligne de commande 396 destructeurs 303, 955 contrler 472 mmoire partage et smaphore 408 ramasse-miettes et 304 detach, mthode 423 dtecter valeurs dfinies 662 dtection de motifs voir patterns dtection squentielle 179 dtruire voir supprimer dtruire des threads detach, mthode 423 join, mthode 422 Devel::DProf, module 825 profiler lexcution de sous-programmes avec 494497 Devel::Peek, module 826 Devel::SmallProf, module 497 dveloppement, modules pour le support du 517 devices (hardware) 968 diagnostic, messages de voir erreurs, messages d diagnostics, pragma 798, 826 diagrammes, gnration 213 die, fonction 665 alarm et 389 dans les gestionnaires de signaux 385 des erreurs fatales, provoquer 957 END, blocs et 452 eval et 670 exemple dutilisation 78, 90, 100, 570 gestionnaires de signaux et 385386 mettre la valeur de retour pour 635 sigtrap, pragma et 809 voir __DIE__ voir Carp, module warn ou 783 __DIE__, routine 639640 exemple dutilisation 784 dieLevel, option du dbogueur 488 diffrent voir galit, oprateurs d ; relation, oprateurs de) diffrent de (!=), oprateur 88 voir aussi point dexclamation dans les symboles

Index
diffusion 955 directives (pod) 598, 955 disciplines 714 handles de fichiers, dfinir avec 650 division voir multiplicatifs oprateurs DNS (serveur de noms de domaine) 409 do 78 BLOC 98 itrer 108 terminaison 109 bloc 666 contrles de boucle 98, 108, 555 FICHIER 666 require ou 666 SOUS-PROGRAMME 667 SUBROUTINE 98 doc, rpertoire (CPAN), pages de manuel officielles de Perl 515 documentation de modules standard 275 fonctions de la bibliothque 644 insre dans des programmes Perl 595 livres sur Perl xxii modules pour la 827 pages du manuel xix rapports de bogues xxv visionneuse par dfaut du systme, appeler 486 documents ici-mme 56, 956 fin de fichier 957 indentation dun 57 dollar ($) voir dollar dans les symboles donnes de longueur fixe, fonctions pour 646 non sres 526 accs aux commandes et aux fichiers avec des privilges restreints 534 dguiser du code en donnes 548 dtecter et blanchir des donnes marques 529 environnement, nettoyer 533 orientes octet ou orientes caractre 373 vidage lcran 826 donnes dinstance 293, 304315, 979 criture de fonctions diffrentes pour chaque 305 gnration daccesseurs par autochargement 309 gnration daccesseurs par fermetures 311 gnration de classes avec Class::Struct 309 nouvelles fonctionnalits, Perl 5.6 314 utilisation de fermetures pour objets privs 312314

customer_8566

Index
donnes membres 293 donnes, types de modules pour les 820 dosish.h, fichier 458 down, mthode (Thread::Semaphore, module) 432 DProf voir Devel::DProf, module dprofpp, programme 495497 drapeaux 956 voir aussi modificateurs ; slecteurs voir options, ligne de commande voir modifiers drles de caractres 335, 956 dump, fonction 667 portabilit de 588 Dumpvalue, module 826 dupliqus, liminer les caractres remplacs 142 dure dexcution dun script 87 dweomer 956 dwimmer 956 DynaLoader, module 274, 503, 828 dynamique, dition de liens 502 C, code source depuis Perl 501

999
diteur de texte comptage des lignes, diffrences avec Perl 43 diteur vi expressions rgulires, utilisation des 30 diteurs de texte criture de scripts dans les 16 diteurs, implmentation du dbogage pour les 487 dition sur place ($^I, $INPLACE_EDIT) 463, 631 effacer caractres trouvs mais non remplacs 139 voir supprimer $EFFECTIVE_GROUP_ID 626 $EFFECTIVE_USER_ID 627 efficacit dans les programmes Perl 561569 profiler 494 programmer en Perl avec 568 gal (==), oprateur 88 galit, oprateurs d 88 lments de hachage 663 lments de tableaux 8, 956 else, instruction 27 emacs -*-, squences 457 expressions rgulires, utilisation des 30 implmentation pour le dbogueur 487 email voir mail embotements destruction 303 listes 245 sous-programmes 240 tableaux 245252 empaquetage sockaddr 685 en-tte de formulaire, traitement 785 en-tte, traitement 739 en-ttes, noms de format 218 encapsulation 12, 233, 284, 956 base sur les espaces de noms 369 objets dans les fermetures 312 encryptage modules Perl pour l 825 END, blocs 436 court-circuiter 452 ordre dexcution 451 valeur de sortie dun programme, modifier 453 __END__, token 59, 566, 584, 626 endgrent, fonction 681 portabilit de 588 endhostent, fonction 684 portabilit de 588

E
/e (valuation dexpression), modificateur de motif 139, 189 -e (excuter), option de la ligne de commande 456, 463 -e (existe), test de fichier 85 -e (fichier existe), test 25 each, fonction 258, 668 efficacit de 566 exemple dutilisation 770 hachages lis et 349, 354 keys et 695 voir keys voir values, fonction chappement pour les caractres de contrle, squence de 173 chappements dans les chanes littrales, squences d 822 checs, continuer la recherche malgr 163 craser des fichiers existants, situations de concurrence et 539 crire dans des fichiers, mode douverture et 710 dans des segments de mmoire partage 745 des donnes via des appels systme de bas niveau 725, 726, 769, 784 des scripts voir scripts

customer_8566

1000
endnetent, fonction 647 portabilit de 588 endprotoent, fonction 687 portabilit de 588 endpwent, fonction 687 portabilit de 588 endservent, fonction 689 portabilit de 588 English, module 217, 826 enqueue, mthode (Thread::Queue, module) 431 enregistrements de diverses structures de donnes 259262 composition, accs et affichage 260 gnration dun hachage de 261 fonctions pour 646 longueur variable 215 mode par 632 sparateur en entre voir dollar, $/ dans les symboles sparateur en sortie voir dollar, $\ dans les symboles enrobage C, autours des scripts set-id 538 enrobage de texte module Perl pour l 518 ensembles, intersection 204 entiers 693, 720, 957 chanes en tant que vecteurs d 781 convertir vers des caractres UTF-8 379 dans les options de la ligne de commande 853 empaquets et compresss dans des chanes 718, 781 en C 43 exponentiation 511 formats 51, 720, 755, 756 IV (valeur entire interne) 963 typedef en C 500 module Math::BigInt 319 modules standards pour de larithmtique avec des 820 motifs, exemples dutilisation avec 171 oprateurs sur les bits avec 89 stockage compact des 566 surcharge 330 voir integer, pragma voir Math::BigFloat, module voir Math::BigInt, module entrailles 499 entre dbogueur, slectionner 491 des pipes 397405 bidirectionnels 402 pipelines sur plusieurs niveaux 399 tridirectionnels 402

Index
handles de fichier 17 voir aussi tableau @ARGV ; handle STDIN oprateurs 68 sparateur denregistrements en voir dollar, $/ dans les symboles STDIN, handle de fichier 677 un seul caractre, avec et sans tampon 681 vrifier les descripteurs de fichiers pour la 740 entre dans le fichier passw 687 entre standard voir STDIN entres fichiers, dtecter la fin avec eof 465 fichiers, mode douverture pour les 710 fonctions pour 646 utiliser ioctl pour les 694 XSUB 506 %ENV, hachage 627 portabilit de 591 supprimer dans 663 Env, module 826 env, programme, commencer perl avec 457 envelopper du texte 820 environnement 957 nettoyer 533 environnement, variables 471473, 627 en shell ou en Perl 558 Env, module 826 marquage,vrification 527 portabilit des 591 EOF (fin de fichier) 957 eof, fonction 28, 565, 668 exemple dutilisation 91, 107, 606 handle de fichier li, utilisation avec 359 sysread et 767 eq, oprateur 24, 88, 554 exemple dutilisation 27, 30 equal, mthode (Thread, module) 424 quilibrage de texte 219 erreur standard voir STDERR erreurs $?, variable pour 625 $@, variable pour 627 (out-of-memory) erreurs de dpassements en mmoire 634 Carp, module 833 CGI::Carp, module, manipuler 834 donnes non sres 528 chec dexportation de symbole 280 numro (errno) 957 sous-programmes 201 STDERR, handle de fichier 677 variable $! pour 635

customer_8566

Index
warn, fonction produisant des messages derreur 783 erreurs de dpendance non sre 528 erreurs fatales 957, 958 erreurs, messages d 573, 871945 efficacit pour lutilisateur, amliorer 569 errno 957 voir aussi dollar, signe $! parmi les symboles ; $OS_ERROR %ERRNO, hachage voir %OS_ERROR, hachage Errno, module 826 espace 42, 570, 643 comme nom de variable ou dlimiteur dans les constructions protges, modification pour 559 devant, supprimer documents icimme 57 espace arrire \b dans les classes de caractres 144, 149, 162, 181 espace de nommage 46 des paquetages 13 espace de noms 957 accs, restreindre avec le module Safe 544 encapsulation partir de 369 modules et 278 voir aussi paquetages espaces finaux dans les comparaisons de chanes 88 est une sorte de 957 et (&&), oprateur logique 89, 95 prcdence de and par rapport && 23, 289 et (&), oprateur sur les bits 88 et logique (&&), oprateur 23 tat hritage avec mthodes accesseurs de classe 318 objets de classe et 315 /etc/group, fichier 565, 681 /etc/hosts, fichier 684 /etc/networks, fichier 685 /etc/passwd, fichier 565, 687 /etc/protocoles, fichier 687 /etc/services, fichier 689 /etc/utmp, fichier 684 tendre la longueur 65 tendre Perl 501507 extensions, crer des 503505, 825, 958 utiliser des fonctions venant dune bibliothque C externe 506 XSUB et langage XS, envelopper du Perl dans 501 XSUB, entres et sorties 506 tiquettes 99, 106, 957 boucles et 101, 105, 571, 908, 962

1001
ensembles de symboles, Exporter 281 goto et 111, 691, 888 HTML et XML, transformer du texte en 194 noms pour les 47 paquetages et 267 toile voir astrisque eval (Safe, module) 545 eval exec, bidouille 17, 457, 468, 583 eval, fonction 48, 78, 221, 561, 669 AUTOLOAD, utilisation dans 273 boucles et 106, 108, 562 caller et 653 chanes et 117 code interpol et 550 die, fonction et 585, 665 do et 666 donnes marques, utiliser pour 529, 547 erreurs 627 exceptions dans les threads, utilisation avec 424 exceptions et 640, 647 excution et 438 exemple dutilisation 207 lucarne, optimisation et 441 paquetages et 269 pendant la compilation 436 qr et 760 reconstituer des structures de donnes avec 262, 838 retour, valeur de 579 return et 735 s///ee et 137, 187 surcharge, modification lexcution 333 traduire avec les variables 140 utilisation dans les formats 217 eval, mthode dans les threads 423 $EVAL_ERROR 627 eval_sv et eval_pv, fonctions 510 vnements asynchrones 949 exceptions 958 capturer 669 threads 423 dans les threads fils dtachs 424 des erreurs fatales, provoquer 957 die et 665 donnes non sres 528 fonctions levant 648 intercepter 639 lever lors dun chec 826 lever pour indiquer une erreur dans un sousprogramme 201 modules pour les 827 $EXCEPTIONS_BEING_CAUGHT 628 exclusifs, verrous de fichier 391 obtenir 392

customer_8566

1002
exec, fonction 671, 768, 958 END, blocs et 437, 452 exemple dutilisation 528, 535 fork et 673 forme avec un argument de liste, viter le shell avec la 549 handles de fichiers, laissez ouverts entre les appels 395, 641, 714 portabilit de 588, 592 supplanter, lever une exception lorsque 842 voir system excutable, fichier dimage 436 $EXECUTABLE_NAME 628 excuter autonome (parcours des options) 490 dautres programmes depuis Perl 768 des programmes Perl 16, 437, 455 du code 443446 conditionnel 24 ordre 454 mthodes 285291 excution conditionnelle de code 24 excution, phase ou excution 438 execv, fonction (en C) 672 execvp, fonction (en C) 671 existence dun processus vrifier 387 exists, fonction 575, 673 delete et 663 exemple dutilisation 310, 313, 473 hachages lis et 347 invocation sur un hachage 354 pseudo-hachages et 234 exit, fonction 3, 457, 674, 679 END, blocs et 453 exemple dutilisation 394 threads et 422, 424 traitement en batch, utilisation pour le 569 exp, fonction 675 exemple dutilisation 14 expansion, nom de fichier 689 expat, analyseur XML 580 Expect, module 403, 519 exponentiation (**), oprateur 80 exponentiation dentiers 511 @EXPORT, tableau 628 export_fail, mthode 280 @EXPORT_OK, tableau 628 %EXPORT_TAGS, hachage 628 export_to_level, mthode 280 exportation de symboles 275, 277, 278, 958 sans utiliser la mthode import de Exporter 280 Exporter, module 503, 828 espace priv de module et 278281

Index
expressions 958 boucles et 102 EXPR et LIST 99 goto et 111 s///e et 187 expressions alertes 958 expressions rgulires voir motifs $EXTENDED_OS_ERROR 629 extensions de langage modules Perl pour 517 externes, portabilit des sous-programmes 592 extraire des sous-chanes 762 ExtUtils::Command, module 828 ExtUtils::Embed, module 508, 828 ExtUtils::Install, module 828 ExtUtils::Installed, module 828 ExtUtils::Liblist, module 828 ExtUtils::MakeMaker, module 522, 828 voir MakeMaker ExtUtils::Manifest, module 828 ExtUtils::Mkbootstrap, module 828 ExtUtils::Mksymlists, module 828 ExtUtils::MM_Cygwin, module 828 ExtUtils::MM_OS2, module 828 ExtUtils::MM_Unix, module 828 ExtUtils::MM_VMS, module 828 ExtUtils::MM_Win32, module 828 ExtUtils::Packlist, module 828 ExtUtils::testlib, module 828

F
-f (fichier normal), test de fichier 85 -f (fichier rgulier), test 25 -F (motif pour clater), option de la ligne de commande 461, 463 @F, tableau 629 fallback, clef de surcharge 329 FAQ de Perl en ligne 553 Fast CGI, protocole 824 Fatal, module 826 fcntl, fonction 675 close-on-exec, flag, manipuler 396, 543 Fcntl, module et 842 flag close-on-exec, manipuler 714 flock et 677 h2ph et 790 ou FileHandle, module 852 portabilit de 588 risques de scurit associs 543 valeur de retour 694 Fcntl, module 823, 842 fermetures 117, 237241, 761 affectation glob pour dfinir un sousprogramme 273 comme patrons de fonctions 239

customer_8566

Index
cration 198 dans les threads 421 exemple dutilisation 303 gnration de mthodes accesseurs par 311 handles de fichier lis 358 objets privs, utilisation pour 312314 serveurs, les connexions (demifermeture) 412 sous-programmes imbriqus, mulation avec 240 fichier rgulier, test de 25 fichier texte (oprateur de test) -T 25 fichier, descripteurs de retour pour les handles de fichier lis 360 fichier, tronquer 773 fichiers 958 accder avec des privilges restreints 534 ges des 87 changer le nom de 733 composants de chemin, sparateurs pour les 590 core 469 dans les communications interprocessus 390397 passer des handles de fichiers 394397 verrouillage, mcanismes de 390 date daccs et de modification 758, 780 de modules, autochargement 274 descripteurs voir descripteurs de fichiers distinction texte/binaire 714 do FICHIER, oprateur 666 crire via des appels systme de bas niveau 769 end-of-file (EOF : fin de fichier) 668 excutable 959 fermer 658 fin de fichier (EOF) 957 fonctions pour 646 handles de voir handles de fichier lier symboliquement 763 lire via des appels systme de bas niveau 767 mode binaire 650 module Perl, stockage dans un seul 266 modules Perl pour les 518, 519 modules pour les conversions de formats 519 obtenir les statistiques de 758 open, fonction 707 oprateurs de test voir tests de fichier ouvrir via des appels systme de bas niveau 765 permissions 766, 774 portabilit pour ouvrir des 591

1003
portes 117 renommer, programme pour 670 renvoyer la position actuelle dans les 770 supprimer 775 temporaires 850 utilisateur et groupe propritaires, changer 656 variables scopes et 49 Win32API::File, module 831 fichiers binaires rguliers 25 fichiers den-tte 959 voir aussi modules fichiers DBM stockage de donnes complexes dans 368 voir DBM, fichiers fichiers excutables 959 fichiers irrguliers 25 fichiers point, manipulation avec hachages lis 350 %FIELDS, hachage 629 fields, pragma 297, 306309, 800, 826 dclarations de champ avec 306309 FIFO 404 FIFOs 959 File::Basename, module 590, 821 File::CheckTree, module 821 File::chmod, module 654 File::Compare, module 821 File::Copy, module 821 File::DosGlob, module 821 File::Find, module 821 File::Glob, module 821 File::Path, module 821 File::Spec, module 590, 821 File::Spec::Functions, module 821 File::Spec::Mac, module 821 File::Spec::OS2, module 821 File::Spec::Unix, module 821 File::Spec::VMS, module 821 File::Spec::Win32, module 821 File::stat, module 821 exemple dutilisation 849 voir stat, fonction File::Temp, module situations de concurrence, potentiel pour des 542 __FILE__, token 59, 584 FileHandle, module 217, 219, 822 fileno, fonction 676 portabilit de 588 voir aussi fichier, descripteurs de files 245 files dattente Thread::Queue, module 431 filetest, pragma 86, 803

customer_8566

1004
fils, processus 398 accessibles en lecture, dmarrer 398 voir processus filtrer la sortie avec un open sur un fork 400 filtres 959 code source 37, 585 fin (quit), gestionnaire pour le signal de 385 fin de chane, dtecter 161 find, fonction 32 parcourir des arborescences de fichiers comme 821 FindBin, module 828 findstr, fonction 30, 32 finir voir terminer fins de ligne dans les programmes Internet 414 fins de ligne, traitement automatique 465 fixe, taille de caractre sur 8 bits 375 flags (drapeaux) voir options, ligne de commande flche (->), oprateur pour drfrencer des rfrences 231 voir aussi hyphen under Symbols flock, fonction 340, 677 alarmes et 389 portabilit de 588 flux des programmes, fonctions pour le contrle 646 fmt (utilitaire Unix) 218 FMTEYEWTK (Far More Than Everything You Ever Wanted to Know) 959 fonction dfinie 955 oprateur entre de ligne et 69 tableaux et 61 fonctions 14, 643785, 959 arguments par dfaut, viter les erreurs avec les 556 autochargement 273274, 301 bibliothque C 644 dans un contexte scalaire ou de liste 645 dbogueur, appeler les fonctions internes 488 enrobages orients octet pour les 377 gnration 238 hachages de 259 internes, lister par type 827 interpolation 348 inventaire par catgorie 646647 modles pour voir fermetures modules, exportation vers des programmes 278 noms de 572 oprateurs de retour 106 oprateurs et 75

Index
oprateurs unaires nomms 83 Perl, envelopper autour de C 502 Perl, variant entre les plates-formes 588 personnalisation du dbogueur 494 pour grer des signaux 384 publiques de surcharge 332 rfrences comme entre et sortie 204 retournant une donne marque 648 sockets, relatives aux 409 supplanter 281282 temporaires, gnrer des noms de fichiers 541 Thread, module 421 voir sous le nom spcifique de la fonction voir aussi sous-programmes fonctions de rappel (callbacks) 238, 761 dans Pod::Parser 607 dans XML::Parser 580 fonctions dfinies par lutilisateur voir sous-programmes fonctions diverses 646 fonctions systmes appels systme vs. xxii fonctions, appels de 78 pipe, de bas niveau pour les communication bidirectionnelles 403 fontes modules Perl pour les 518 for 29, 98, 102 comme alias de foreach 103 rechercher et remplacer des lments dans des tableaux 137 foreach, boucles 98, 103, 561 $_ et 110 modifications entre les versions de Perl 560 rechercher et remplacer des lments dans des tableaux 137 variable de boucle, programmer en shell ou en Perl 557 fork, fonction 399, 678, 959 $$ et 638 clner des interprteurs sur Windows 418, 445 double sens, communication avec 403 exec et 673 exemple dutilisation 395 fork-open 399, 712 hriter des handles de fichiers du pre 397 open sur un pipe, viter le shell dans un 535 ou modle de thread 419 perlfork, documentation 384 pipes et 398, 724 portabilit de 588, 592 processus fils, hriter des handles de fichiers du pre 394 serveurs, clns avec 413

customer_8566

Index
shutdown et 745 socketpair et 747 traitement en batch, utilisation pour le 569 verrous, hritage travers les appels 678 wait et 782 zombies, processus et 387 format, dclaration voir write, fonction $FORMAT_FORMFEED 629 $FORMAT_LINE_BREAK_CHARACTERS 629 $FORMAT_LINES_LEFT 629 $FORMAT_LINES_PER_PAGE 629 $FORMAT_NAME 630 $FORMAT_PAGE_NUMBER 630 $FORMAT_TOP_NAME 630 formatage de prsentation (marshalling), modules de 838 formats 213219, 959 accs aux 219 accumulateur de sortie 680 B::Xref, module, rfrences croises avec du C 449 dclaration 213 dclarer 680 entiers 720 fmt (utilitaire Unix) 218 listes darguments pour les, valuer en contexte de liste 559 numros de page 630 pack/unpack 718722 pieds de page 218 pour les chanes 754757 traitement du haut de page 215 variables 216 variables lexicales dans 216 formels (arguments) 625 formline, fonction 219, 680 $^A et 624 Fortran 42 fossoyer les processus zombies 387 serveurs 414 freeware 959

1005
gnrateurs de Perl 582586 autres langages en Perl 583 dans dautres langages 584 filtres de code source 585 gnration de code 436 gestionnaires de signaux 384 getc, fonction 563, 681 et les handles de fichier lis 357 getenv voir environnement, variables getgrent, fonction 681 portabilit de 588 supplanter 868 getgrgid, fonction portabilit de 588 getgrid, fonction 682 getgrnam, fonction 682 portabilit de 588 gethost*, fonctions internes, supplanter les 824 gethostbyaddr, fonction 682 cache, mettre les valeurs de retour dans un 565 exemple dutilisation 413, 415 getpeername et 685 portabilit de 588 reconvertir des caractres en octets 375 Socket, module et 863 supplanter 858 gethostbyadr, fonction exemple dutilisation 689 gethostbyname, fonction 683 exemple dutilisation 413 portabilit de 588 Socket, module et 863 supplanter 858 gethostent, fonction 684 portabilit de 588, 684 getlogin, fonction 684 portabilit de 588 getnet*, fonctions internes, supplanter les 824 getnetbyaddr, fonction 684 portabilit de 588 getnetbyname, fonction 685 portabilit de 588 getnetent, fonction 685 Getopt::*, modules 107 Getopt::Long, module 821 Getopt::Std, module 821 getpeername, fonction 413, 685 exemple dutilisation 863 getpgrp, fonction 685 portabilit de 588 getppid, fonction 686 exemple dutilisation 696 portabilit de 588

G
/g (global), modificateur de motif 134, 136 -g (setgid), test de fichier 85 \G, assertion de position 134, 163 GDBM (GNU DBM) verrouiller des fichiers sous 394 GDBM (GNU DBM) GDBM_File, module 825 ge, oprateur 24 voir aussi angle droit dans les symboles gnrateurs de code 446, 447449, 959 bytecode, gnrateur de 447 C, gnrateur de code 448

customer_8566

1006
getpriority, fonction 686 portabilit de 588 setpriority, exemple dutilisation avec 743 getproto*, fonctions internes, supplanter les 824 getprotobyname, fonction 686 exemple dutilisation 415 portabilit de 588 Socket, module et 863 getprotobynumber, fonction 686 portabilit de 588 getprotoent, fonction 687 portabilit de 588 getpwent, fonction 687 exemple dutilisation 65, 663 portabilit de 588 supplanter 869 getpwnam, fonction 687 exemple dutilisation 351, 656 portabilit de 588 supplanter 869 getpwuid, fonction 684, 688 dterminer le nom et les infos dun utilisateur 797 dterminer le rpertoire personnel avec 90 exemple dutilisation 351, 422, 660 portabilit de 588 supplanter 869 getserv*, fonctions internes, supplanter les 824 getservbyname, fonction 688 exemple dutilisation 415 portabilit de 588 Socket, module et 863 getservbyport, fonction 688 portabilit de 588 getservent, fonction 689 portabilit de 588 getsockname, fonction 689 portabilit de 588 getsockopt, fonction 689 portabilit de 588 GID (groupe ID) 656, 960 effectif ($EFFECTIVE_GROUP_ID) 626, 638 voir dollar, $) dans les symboles rechercher des fichiers par 682 rel ($REAL_GROUP_ID) 638 voir dollar, $( dans les symboles voir dollar, $( et $) dans les symboles gid, et stat 758 GIF modules Perl pour 519 Gimp modules Perl pour 519 glob, fonction 71, 72, 689 et <> 327

Index
exemple dutilisation 690 portabilit de 588 surcharge 282 global (variables) 960 globales, variables 114 contrle de leur utilisation avec le pragma strict 121 dclaration 112, 118, 716 local, utilisation sur 119 prdclarer avec le pragma vars 826 rendre locales 699 threads, accder aux 425 variables de paquetage comme 267 globalisation des noms de fichier 71 globbing filenames 960 globs de noms de fichiers portabilit de 591 gmtime, fonction 690, 820 exemple dutilisation 722 inverser 867 supplanter 823, 868 time, fonction et la fonction time 772 utime et 780 voir localtime voir time Gnome modules Perl pour 518 gober des fichiers 461 goto, fonction 111, 273, 561, 691 blocs optimiss laisss de ct, utilisation avec des 443 blocs optimiss, utiliser avec les 559 dump et 667 modifications entre les versions de Perl 559 gourmande, recherche 160, 180 graine, nombre alatoire 757 graphiques modules Perl pour les 519 Greenwich Mean Time (GMT) 690 grep, fonction 571, 692 $_ et 575 contexte vide et 571 crire le vtre 207 exemple dutilisation 204, 282, 351, 363, 399, 413, 654 rpertoire, exemple dutilisation avec 729 voir map, fonction grep, utilitaire 174 gros-boutiste 589, 960 ordonner avec vec 781 trier avec pack 718 groupes ID voir GID

customer_8566

Index
nom pour les 682 processus 386, 685, 743 fonctions pour 647 renvoyer la priorit de 686 tuer 696 utilisateurs 960 fonctions pour 647 membres, nom de login 681 nom de groupe 682 voir Usenet gt, oprateur 24 voir aussi angle droit dans les symboles Gtk modules Perl pour 518 GUI voir interfaces graphiques guillemets doubles 127 voir aussi apostrophes simples et doubles dans les symboles guillemets simples () #index# (irrelevant) 184 recompilation de motif et 131 suppression de linterpolation de variable et du traitement des squences de traduction 173 voir aussi apostrophes dans les symboles GV (valeur glob interne) 500, 960

1007
denregistrements complexes 261 de tableaux 252254 accs et affichage 253 gnration 252 lments, donner des valeurs temporaires aux 699 exists, fonction et 673 HV (valeur hachage), typedef en C 500 initialisation avec loprateur x 83 inverser 735 liaison 349355 mthodes de 350355 lier des fichiers DBM avec 661 marqu 527 multidimensionnel 255259 accs et affichage 257 gnration 256 noms de 45 organisation des donnes de Perl lintrieur de 251 paires cl/valeur 9, 44, 65 capture partir dune chane avec loprateur m//g 134 renvoyer avec la fonction each 668 passage par rfrence en entre ou sortie de fonction 204 rfrences 223 rfrences comme cls 243 renvoyer des valeurs de 780 restreint, implmentation 314 style de sortie, changer dans le dbogueur 490 supprimer des valeurs dans 663 tableaux de 254255 gnration 254 tables de recherche plat, donnant accs 245 tables de symboles 269273 paires cl/valeur dans les 270 typeglobs dans les 270 traitement, fonctions pour 646 hacker 960 handle STDERR 18 handle STDIN 18 handle STDOUT 18, 19, 951 handlers 961 overload 320 handler comme_chaine 323 manquant 329 handlers de signal, dfinir avec des chanes 269 handles 5 rfrences 227 rpertoires 822, 961 handles de fichier 17, 961 anonyme 228 cration 18

H
-h (aide), option de la ligne de commande 463 %^H, hachage 630 h2xs, utilitaire 502, 503, 522 hachage 5, 8, 9, 44, 6567, 960 %SIG, rfrences des gestionnaires de signaux 384 affiche en ordre 104 anonyme comme structures de donnes dobjet 291, 305 rfrences 225 au lieu de conditions en cascade, utiliser 110 au lieu de recherches linaires 561 buckets 951 cl 9, 44, 952 accolades ({}), indiquer entre 11 chemins de module (dans le hachage %INC) 276 fournir des rfrences en tant que 826 organiser accder aux valeurs dans 251 renvoye par chaque fonction 646 renvoyer avec la fonction each 668 renvoyer des listes de 695 suppression 349 table de symboles 270 trouver le nombre de 67

customer_8566

1008
dupliquer, raisons pour 713 finissant par _TOP 215, 630 fonctions pour 646 formats associs, noms par dfaut 213 indirects 658, 961 lecture des donnes 69 liaison 355366 handles de fichiers originaux 362 mthodes de 356366 lire des octets de donnes depuis 729 localiser 67 mthodes objets pour les 822 noms pour les 47 open, fonction 707 oprateur angle 69 passage 206 passer via des IPC 394397 via les handles de fichiers standard 395 pips, fermeture explicite 711 positionner un pointeur de fichier pour les 738 pour typeglobs 67 rfrencement implicite dans 223 rfrences 227 rendre locaux 700 scurit des, ou noms de fichiers 540 slectionner pour la sortie 739 SelectSaver, module 822 syslog, lier la sortie un 369 verrous de fichiers sur les 392 hardware devices 968 haut de page, traitement 215 hritage 284, 961 accs restreint et 314 accesseurs de classe 317 classe 266, 295303 simple ou multiple 295 classes de base, tablir la compilation 825 constructeurs 292 implmentation en pseudo-hachage et 308 modules, de la classe Exporter 278 par le tableau @ISA 296 surcharge et 332 hritage multiple 295, 961 mthodes, invocation de toutes les classes de base supplantes 300 pseudo-paquetage SUPER, fonctionner avec 298 sous-programme AUTOLOAD et 302 hritage simple 295 heure fonctions Perl pour 647 modules Perl pour 517 hex, fonction 692 voir oct voir sprintf

Index
hexadcimal 51, 961 convertir des nombres en 136 spcifier les nombres en 147 hexadcimaux 692 histoire de Perl 611 historique des commandes du dbogueur 476 home directory (rpertoire de base) 653 HOME, variable denvironnement 471 hosts, fichier voir /etc/hosts htes 961 htes (distants), test de la joignabilit 824 htes, noms convertir en adresses 683 obtenir depuis des adresses rseau 682 Sys::Hostname, module 823 HTML (Hypertext Markup Language) code, produire dans un format agrable 824 gnration avec le module CGI 824 modules Perl pour 519 pod, convertir en fichier 827 voir CGI HTTP (Hypertext Transfer Protocol) cookies, lire et crire 824 liens, recherche de 31 modules Perl pour 519 HV (valeur de hachage interne) 961 HV (valeur hachage interne) 500 hypothques modules Perl pour les 520

I
-I (chemin dinclusion), option de la ligne de commande 456, 465 -i (diter sur place), option de la ligne de commande 463 /i (insensibilit la casse), modificateur de motif 131, 134, 136 I/O (input/output) 963 I18N::Collate, module 822 ICP::Open2, module 507 identifiants 961 GID (groupe ID) 960 PID (processus ID) 386, 714 deviner 541 threads, ID de 424 UID et GID effectifs rels ou 526 se protger contre les 534 identificateurs 42, 47 apostrophe simple () dans les 52 commenant par un soulign (_), modifications entre les versions de Perl 558 entre accolades 53

customer_8566

Index
modules Perl 276 mots simples et 56 noms vs. 47 paquetage 267 dans la table de symboles dun paquetage 268 segment de mmoire partage 745 smaphores 742 Unicode, contenant des caractres alphanumriques 377 voir aussi GID, PID, UID identificateurs simples 56 idogrammes 33 correspondre avec \w 378 idographiques, oprateurs unaires 80 idiomes, en Perl 573582 if, instruction 24, 27 oprateurs logiques et 23 if, instructions 98, 100 C, langage, diffrences avec Perl 556 dans des structures case 109 IGNORE, pseudo-signal 386 image dun processus 954 imbriques structures de donnes 11, 481 impatience 961 impratif, style de programmation 186 import, mthode 275, 280, 693, 706 surcharge de constantes 330 importer 113, 276 des smantiques dans des paquetages 778 des symboles dun paquetage vers un autre 271 sous-programmes dun autre module 198 voir aussi Exporter, module; exportation de symboles imprimer des structures de donnes imbriques 481 %INC, hachage 276, 630 @INC, tableau 276, 630, 828 ajouter des rpertoires au dbut de 465 lib, pragma et 804 inclure du Perl 828 incrmentation des variables 22 index, fonction 693, 962 $[ et 623 exemple dutilisation 408 longeur de chane et 379 indexer des tableaux 8, 253 indications, compilateur 630 indicer 561, 962 indices de tableau ngatifs 44, 560 indirection 49, 221, 962 entre lutilisation dune classe et son implmentation 285

1009
voir aussi rfrences dures ; rfrences symboliques indirects, handles de fichiers 708 ingalit voir galit, oprateurs d ; relation, oprateurs de inet_ntoa, fonction (Soket, module) 683 infrieur (<), oprateur 87 infrieur ou gal (<=), oprateur 87 infinies, boucles 103 INIT, blocs 436 initialisation de variables avant lappel de sous-programme 203 ordre dexcution 451, 454 init, programme 686 initiale majuscule ucfirst, traduire en 379 initialisation de variables avant dappeler des sousprogrammes 203 dbogueur, personnaliser avec des fichiers dinitialisation 487 expressions 102 objets 293 tranches de tableaux et de hachages 83 variables de hachage 66 inode, et stat 758 $INPLACE_EDIT 631 $INPUT_LINE_NUMBER 631 $INPUT_RECORD_SEPARATOR 460, 632 insrer Perl 499, 507512, 962 ajouter un interprteur Perl un programme C 508 compiler des programmes insrs 508 valuer une instruction Perl depuis C 510 pile de Perl, manipuler depuis C 511 installation modules supportant l 827 modules, de CPAN 520 dans la bibliothque Perl 521 installs, inventaire des modules 828 instances 283, 962 instruction unless 27 instructions 97122 boucles voir boucles composes 99 dclarations globales et 112 tiquettes pour voir tiquettes if et unless 100 oprateurs de contrle de boucle contre 107 pendant 962 Perl, valuer depuis C 510 simple 97

customer_8566

1010
instructions itratives 28 boucle for 29 boucle while 28 instruction foreach 29 instruction until 28 instructions pendantes 962 int, fonction 693 exemple dutilisation 728 integer, pragma 82, 803 exemple dutilisation 791 intercepter des signaux 385 erreurs de dpassement en mmoire (out-ofmemory) 634 intercepter des signaux, gestionnaire pour 385 interfaces 284, 962 smantique doctet ou de caractre dans les 375 interfaces graphiques modules Perl pour les 518 Perl/Tk en utilisant Perl/Tk 568 interfaces utilisateurs, modules fournissant des 825 internationalisation 41, 593 donnes textuelles avec Unicode 373 modules Perl pour l 518, 822 internes appel de mthodes surcharges 298 fonctions lister par type 827 prototyper les sous-programmes pour muler 205 smantique de caractres, manipuler la 376 surcharge 281282 types de donnes 4345 Internet clients/serveurs TCP 411 Internet, modules CPAN pour les services 410 interpolation de conditions dans des motifs 194 de motifs lors de la recherche 193 interpolation de variable 6, 53, 962 contrle de dtection de motif avec 172176 dans des guillemets doubles 127 dans les chanes entre guillemets 20, 53 en utilisant loprateur de globalisation 73 fonctions et 348 motifs et 127 rfrences arrires 36 valeurs dune liste 63 valeurs de tableau 56 valeurs scalaires 51 interprteur, Perl 16, 443, 445, 963 accder depuis C 507, 508

Index
compilateur, interactions avec 450454 intgrer dans des applications 446 invoquer avec une ligne #! (shebang) 456 multiples, lancer 445 persistant 507 interprteurs 5 de commandes 455 isolement (quotation) sur les systmes non-Unix 459 destruction dobjet la terminaison 304 threads 418 interruption, gestionnaire pour les signaux d 385 intersection densembles 204 intervalle (.. et ...), oprateur 90 intervalles caractres 148 jeux de caractres, spcifier dans 139 ints 721 inverser des instructions print et printf (handles de fichier lis) 355 inverser des tableaux et des hachages 735 invocation de mthode explicite 286 invocation de mthode implicite 286 invoquant 285 invoquer voir excuter IO (Internal I/O object) 963 IO (internal I/O object) voir aussi objets indirects IO::*, modules 519 IO::Dir, module 822 IO::File, module 822 IO::Handle, module 822 IO::Pipe, module 822 IO::Poll, module 822 IO::Pty, module 403 IO::Seekable, module 822 IO::Select, module 822 IO::Socket, module 410, 823, 854 IO::Socket::INET, module 411, 823 IO::Socket::UNIX, module 823 ioctl, fonction 694 dterminer la taille de la fentre avec 867 exemple dutilisation 694 h2ph et 790 portabilit de 588 valeur de retour 694 IP (Internet Protocol) 409, 963 adresses noms de rseau et 685 UTF-8, reprsentation des 375 utiliser la notation v-chane pour 683 IPC (interprocess communication) 383416 entre processus sur la mme machine 384

customer_8566

Index
fichiers 390397 modules pour 822 pipes 397405 bidirectionnelle 402404 portabilit et 592 signaux 384390 sockets 409416 clients en rseau 411 passage de message 415 serveurs en rseau 412414 sur lInternet 383 IPC System V 405409 appels systme 383 manque de fiabilit des signaux 388 fonctions pour 647 fonctions pour les smaphores 741 IPC::SysV, module 824 mmoire partage, fonctions pour la 744 messages, appels systme pour les 703 portabilit des 592 tuer des groupes de processus 696 IPC::Open2 824 IPC::Open2, module 856 IPC::Open3, module 507, 824, 856 IPC::Semaphore, module 824 IPC::Shareable, module 406 IPC::SysV, module 824 isa, mthode (paquetage UNIVERSAL) 299 @ISA, tableau 295, 633, 891, 931, 941 hritage avec 296 use base, pragma et 794 isolement (quotation), marques chanes changer le style daffichage des chanes 490 non-Unix sur les systmes non-Unix 459 itration 963 voir aussi boucles voir boucles ithreads 418 API Perl pour les 445 itimer, routines 649 IV (valeur entire interne) 500, 963

1011
Unicode 373381 join, fonction 695 efficacit de 565 exemple dutilisation 56, 138, 236, 753 pack ou 722 split ou 754 voir aussi split join, mthode (Thread, module) 422 capturer des exceptions depuis 423 journaux, fichiers modules Perl pour les 519 justification 214 justification droite 217 justification gauche 217

K
-k (sticky), test de fichier 85 keys, fonction 11, 37, 67, 695 tourderies courantes avec 559 exemple dutilisation 204, 253 hachages lis et 354 pour compter les entres dans un hachage 698 voir each, fonction ; values, fonction kill, fonction 384, 696 exemple dutilisation 387 faire linventaire des signaux 386 Microsoft, systmes et 387 portabilit de 588 traitement de END et 453

L
-l (fin de ligne automatique), option de la ligne de commande 465 -l (lien symbolique), test de fichier 85 langage assembleur, Perl comme 18 langage BASIC, oprateurs logiques du 23 langage C prprocesseur 970 langage rassembleur, Perl comme 963 langages artificiels 4 informels 42 naturel vs. artificiel 4 naturels 4 variables denvironnement contrlant la gestion de Perl pour les 471 traduire 585 vrifier des caractres pour 154 langages de programmation modules Perl pour sinterfacer avec des 518 larges, API de caractres activer lutilisation par Perl sur le systme cible 461 appels systme utilisant des 375

J
JAPH (Just Another Perl Hacker) 963 Java, modules Perl pour 517 jeux modules Perl pour les 520 jeux de caractres ASCII voir ASCII ordre et intervalles de caractres dans 139 portabilit des 593

customer_8566

1012
last, oprateur 30, 103, 106, 110, 564, 571, 576, 697 contrles de boucle et 108 exemple dutilisation 105 utilisation dans un do while 109 @LAST_MATCH_END 633 @LAST_MATCH_START 633 $LAST_PAREN_MATCH 634 $LAST_REGEX_CODE_RESULT 634 lc, fonction 697 exemple dutilisation 37, 101, 111, 128 trier avec 748 lcfirst, fonction 698 le, oprateur 24 voir aussi angle gauche dans les symboles voir aussi lt, oprateur length, fonction 698 enrobages orients octet pour 377 exemple dutilisation 85 pos et 725 positions de caractres et 379 less, pragma 804, 826 lexeur 963 lexicale, analyse 500 dans le compilateur Perl 438 lexicales, variables 704 afficher avec B::Showlex 829 stockage dans les piles de mmoires de travail lexicales 445 threads, accder aux 425 lexicalisation 12 lexicaux, avertissements $^W et 470 ${^WARNING_BITS} 641 liaison 964 oprateurs (=~, !~) 32, 81, 127 variables et paquetages 335 lib, pragma 276, 804, 828 liens 956, 963 HTTP, recherche de 31 hyperliens voir aussi CGI voir aussi HTML voir aussi HTTP voir liens symboliques liens en dur (vers des noms de fichiers) 698 liens symboliques 763 lstat, fonction et 701 obtenir les noms de fichiers depuis 731 risques de scurit dans Unix 537 voir symlink liens, nombre et stat 758 lier fichier DBM avec hachage 661 Tie::Array, module 826

Index
Tie::Handle, module 826 Tie::Hash, module 826 lier des variables 243, 335369 hachages 349355 handles de fichier 355366 pige de dliement 366368 scalaires 337344 tableaux 344349 LIFO (Last In, First Out) 964 ligne vidage du tampon par 636 ligne de commande apparence lcran de la 489 appel de linterprteur depuis la 16 modules Perl pour diter 518 modules pour le traitement de la 821 ligne de commande, options voir options lignes 964 assertions de limite 161 lignes de continuation 107, 629 lignes images 214, 680 lignes vides, valeur boolenne des 28 lignes, compteur voir $., variable lignes, numros de du fichier dentre 584 limit, cration de tableau 345 limites de mot voir \b and \B assertions line numbers 966 #line, directive 584 __LINE__, token 59, 584 LineInfo, option du dbogueur 489 link, fonction 698 portabilit de 588 voir liens symboliques voir symlink lint (vrificateur de programmes C) 449 lire dans des fichiers, mode douverture et 710 des donnes via des appels systme de bas niveau 767 ID dun segment de mmoire partage 745 lisible, oprateur de test de fichier 85 $LIST_SEPARATOR 634 liste de mots 63 liste, contexte valuer des expressions dans le dbogueur 481 fonctions dans un 645 forcer un contexte scalaire au lieu dun 737 oprations se comportant diffremment dans un 555 reconnatre dans le dbogueur 477

customer_8566

Index
listen, fonction 698 exemple dutilisation 412 portabilit de 588 lister du code 482 listes 8, 37, 60, 99, 964 affectation 64 convertir en scalaires 11 des threads courants dans le processus 424 embotements de 245 en tant quarguments de fonctions 643 enregistrements ordonns dans un tableau 251 interpolation 63 listes, LISTE 62 map, fonction et 702 mise plat 643 nulles 63, 964 renverser 735 rplication avec loprateur x 82 scalaires, retour de fonction et valeurs de paramtres 199 tableaux vs. 6265 traitement, fonctions pour 646 trier 747 tronquer avec chop 655 voir aussi tableaux listes non ordonnes voir hachage littraux 124, 964 chane 50 numriques 50, 51 pseudo-littraux voir oprateurs dentr UTF-8, permettre lutilisation dans les 377 little-endian voir petit-boutiste local 964 affectation dun gestionnaire de signaux 386 handles de fichiers 67 variables voir dclarations local local, dclarations erreurs de programmation courantes avec 555 my ou 556 sauvegarder les valeurs internes des 444 local, fonction 699 locale, pragma 806, 822 locales dclarations, comparaisons de chanes et 88 locale, pragma avec les classes de caractres POSIX 158 modules et pragmas pour les 518, 822 point dcimal dans les formats 214 raccourcis de classes de caractres Perl et 149

1013
Unicode et 697 localisation voir locales localtime, fonction 700, 820 exemple dutilisation 64, 303, 835 File::stat et 759 inverser 867 strftime et 859 supplanter 823, 868 time, fonction et la fonction time 772 voir gmtime voir time lock, fonction 426431, 701 exemple dutilisation 537 rfrences comme arguments de 223 locked, attribut de sous-programme 210, 315, 429 log (logarithme), fonction 701 complexes, nombres et 857 LOGDIR, variable denvironnement 471 logiciel source ouvert 964 login fonctions pour 647 login, noms gergrnam, fonction renvoyant 682 getgrent, fonction 681 getgrid, fonction renvoyant 682 getlogin, fonction pour 684 logs voir journaux, fichiers longs 721 longueur dune chane dtecte 160 dune correspondance 633 de chanes 698 de chanes Unicode 377, 379 des chanes dans les motifs 563 lstat, fonction 701 _ et 87, 623 portabilit de 588 supplanter 821 voir liens symboliques voir stats voir symlink lt, oprateur 24 voir aussi angle gauche dans les symboles voir aussi le, oprateur lvalues 44, 46, 966 ?: et 93 efficacit des 577 identifier avec ref 732 lvalue, attribut de sous-programme 211 212 mthodes, dclarer pour indiquer un retour de 314

customer_8566

1014
modificateurs et 115 oprateurs daffectation et 93 oprateurs et 2122 rfrences et 79 sous-programmes et 47 utilisation doprateurs de recherche de motif sur 128

Index
Makefile 964 crer pour les extensions Perl 828 Makefile.PL 503, 520, 522 MakeMaker 522 malloc erreurs 634 PERL_DEBUG_MSTATS, variable denvironnement, utilisation avec 472 man, commande xix, 275, 486, 964 voir aussi perldoc man, pages de xix, 968 Pod::Man, module 827 voir aussi pages de manuel MANIFEST, fichier 503, 828 map, fonction 37, 571, 702 contexte vide et 571 exemple dutilisation 37, 175, 262 mise en majuscules avec 357 transformation schwartzienne et 750 voir grep, fonction marquage fonctions retournant une donne marque 648 marquage, vrification 414, 469, 526 -D et 462 activer avec -T 527 CGI, programmes et 547 code interpol et 550 dfinie 525, 527 File::Glob et 847 handles de fichiers, supprimer pour les 853 marquage, mode 526 motifs et 192, 808 PERL5LIB et 472 programmes exigeant une 526 Safe, compartiments et 547 marques dinterpolation chanes 7 marques de protection 6 chanes et 52 contexte interpolatif 61 dans les accolades 53 enlever les 55 oprateurs de protection 54 valeurs false 958 marshalling (formatage de prsentation), modules de 838 masques de bits 740 $MATCH 635 Math::BigFloat, module 820 Math::BigInt, module 319, 820 Math::Complex, module 820 Math::trig, module 820 mathmatiques bibliothque (C, langage) 506 fonction mathmatiques, surcharge 326

M
-M (date de modification) oprateur de test de fichier 86, 87, 625 -M (use module), option de la ligne de commande 466 blib, pragma et 795 -m (use module), option de la ligne de commande 466 /m, modificateur de motif 130, 134, 136 m// (correspondance), oprateur 61, 483, 554, 701 pos, fonction et 725 m// (match), oprateur 124, 133135 =~, utilisation avec loprateur de liaison 128 fournissant interpolation en guillemets doubles 127 modificateurs pour 130, 133 m//g, modifications entre les versions de Perl 560 m?? (correspondance), oprateur 483 reset, fonction et 734 m??, oprateur 135 machine virtuelle, Perl 443, 445 Macintosh, systme dexploitation File::Spec::Mac, module 821 invoquer des applications Perl sur 458 isoler (quoting) sur 459 MacOS interface de la ligne de commande sur 16 magique 964 magique, autodcrmentation et autoincrmentation 80, 91, 325, 342 mail envoyer, portabilit et 592 modules Perl pour le 519 main, paquetage 267 majuscules convertir en 52, 135 dans les noms de modules 819 uc et ucfirst, fonctions 773 majuscules/minuscules changer 140 conversion en majuscules (\u) 135 dans les noms de module 276 noms dtiquette 101 noms de mthode, variables lies 337 noms de sous-programme 198

customer_8566

Index
modules Perl pour les 517 oprateurs 19, 75 maximale, dtection 142, 159 mmoire 965 dpassements 634 efficacit de la 566 gestion, destructeurs et 303 ID dun segment de mmoire partage 745 ramasse-miettes 244 statistiques sur la, afficher 472 mmoire partage, IPC System V accs contrl la 406 fonctions pour la 744 messages afficher lentre et la sortie des sousprogrammes 489 envoyer sur des sockets 742 fonctions pour les 703 IPC::Msg, module 823 passer avec UDP 415 recevoir sur des sockets 731 script inclus dans des 470 messages davertissement intercepter 639 messages warning -w, affichage avec 17 mesure du temps avec des alarmes 649 comparer les temps dexcution de sousprogrammes 495498 temps dexcution de versions diffrentes de code, comparer 831833 mtacaractre \s (espace) 32 mtacaractre \w (mot) 32 mtacaractres 124, 965 dans des motifs 141148 dans les arguments de exec 671 chappement avec quotemeta 728 protection avec des antislashs (\) 141 shell, dans les commandes pipes 711 structurels 125 system, fonction 566 mtacaractres structuraux dans les expressions rationnelles 125 mtasymboles 965 alphanumriques, dans des motifs 143 dans des motifs 141148 syntaxe dextension pour 143 mtasymboles jokers 147 classes de caractres et 148, 149 mtasymboles structurels 141 mto modules Perl pour la 520 Method (dans le pragma overload) 332 method, attribut de sous-programme 210, 315 mthode importer 962

1015
mthodes 233, 283, 965 ajout une classe existante 299 appeles par des variables lies 337 autochargement 301 de donnes de classe, fonctionnant comme des accesseurs 316 de liaison de hachage 350355 de liaison de tableaux 345348 dclarations, indiquant le retour de lvalues 314 hritage avec les classes Perl 305 invocation 285291 appels de sous-programme ou 292 explicite ou implicite 286 utilisant loprateur flche 287 utilisant les objets indirects 288291 liaison de scalaires 338342 mthodes prives, ignorer lhritage avec 302 noms de 572 pour les hachages lis 349 pour les handles de fichiers lis 355 pour les tableaux lis 344 recherche de hritage de classe 295 hritage par le tableau @ISA 296 rfrences 239 sous-programmes comme 285 sous-programmes contre 197 sous-programmes et 286 surcharge 297 UNIVERSAL, classe 299 ajout 301 verrouiller (mthodes dobjet) 429 mthodes accesseurs 293 cration 305 gnration par autochargement 309 gnration par fermetures 311 mthodes de donnes de classe, fonctionnant comme 316 pseudo-hachages et 307 mthodes daccs 965 mthodes dinstance 283 rfrences dobjets comme invoquants de 285 mthodes de classe 283, 965 constructeurs comme 292 noms de paquetage comme invoquants pour les 285 mthodes supplantes (classe de base), invocation de toutes les 300 mthodes:Thread, classe 421 Microsoft Windows ActiveState, distribution de Perl, installer 458

customer_8566

1016
appels systme utilisant des API de caractres larges 375 File::Spec::Win32, module 821 fork et clnage dinterprteurs sur 418 globs de fichiers avec File::DosGlob 821 informations sur le portage (perlwin32) 384 isoler (quoting) sur NT 459 modules de CPAN, installer sur 520 modules Perl pour 519, 830 registre, manipulation de 335 shell, positionner une possibilit lusage de Perl 472 signal numro 0 sur 387 Win32::Pipe, module 404 MIDI modules Perl pour 520 MIME modules Perl pour 519 minimale, recherche 142, 159 minuscule, conversion en 52 minuscules, mise en lc et lcfirst, fonction 697 minuter les oprations lentes 389 mise au point voir dbogage mise en ligne des fonctions constantes 208 empcher 209 mkdir, fonction 702 exemple dutilisation 573 ou mkdir, appel systme 565 mkfifo, fonction 404 MLDBM, module 368 Data::Dumper, utiliser avec le module 838 mod_perl 445, 507 mode autosplit (avec slecteur -a) 949 mode par enregistrement 632 mode par paragraphe 632 mode, et stat 758 modes, ouvrir des fichiers avec des 709 modifiable, oprateur de test de fichier 85 modificateurs instructions quantificateurs contre 126 simples 98 motif 130133 clotr 168 m// (match), oprateur 133 s/// (substitution), oprateur 136 tr/// (translittration), oprateur 139 modification, date pour un fichier 758, 780 modules xv, 12, 266, 275282 casse des 47 classes ou 266 classes, stockage pour espace priv 303 CPAN 13, 516

Index
catgories de 517 construire 521 crer 522 dcompresser et dpaqueter 520 installer dans la bibliothque Perl 521 mail, envoyer 592 portabilit des 592 rendre accessibles depuis un programme 520 rpertoire pour les 515 stockage dans le 266 cration 277281 espace priv et Exporter 278281 vrification de version 280 diviser en plusieurs fichiers 274 empcher lexport de symboles 280 exporter les noms vers dautres modules 693 fonctions internes, supplanter 281282 fonctions pour 647 importer 828 modules tie sur CPAN 368369 noms de 572 sorties (backends) 446 standards 819870 accs orient objet aux fichiers, aux rpertoires et aux IPC 822 avertissements et exceptions 827 bibliothques de gestion des fichiers DBM, chargement des 824 classes de base et facilits 826 communication rseau et interprocessus 823 compilateur Perl et gnrateur de code 829 interfaces du systme dexploitation, manipuler 823 interfaces utilisateurs, fournissant des 825 internationalisation et locales 822 langage Perl, extensions et mcanismes internes 825 scurit, soccupant de 825 support dinstallation 827 support de dveloppement 829 support de documentation 827 texte, manipulation avec 820 traitement de la ligne de commande 821 types de donnes 820 web 824 systme de classes et 297 tester 503, 506, 523 thread modules de 431 thread, scurit et 420 voir aussi paquetages

customer_8566

Index
modules centraux, Perl 517 modulo (%), oprateur 82 moins (-), oprateur 80 Mongueurs de Perl xxv motifs (et expressions rgulires) 3036, 123 195 altrer le comportement par dfaut des 826 apostrophes dans les 54 approche dclarative dans 187 assertions dans 125 assertions, dfinir vos propres 194 autosplit via loption -a 463 capture et regroupement dans 164168 caractres dans 124126 caractres, correspondre des, au lieu doctets 378 classes de caractres 32, 148158 confusion avec les index de tableau 56 code Perl lintrieur de 187 contrle de la dtection 170183 compilateur de regex 176 contrle de flux Perl, dcider de lexcution dun motif 170 correspondance oprateurs de 31 correspondance avide 34 correspondance minimale 34 dbogueur, commandes pour la correspondance 483 dlimiteur de fin pour 127 dtection de motifs $, $&, $, variables et 130, 135 oprateurs pour 126141 sous-chanes correspondant des sousmotifs 129 valuation de code au moment de la recherche 190 valuation de substitution 189 fonction split et 128 fonctions pour la recherche 646 gnrs 187 gourmande, recherche 180 grep, fonction et 692 interpolation conditionnelle dans 194 interpolation de motifs lors de la recherche 193 mtacaractres et mtasymboles dans 141 148 mtasymboles 146 mtasymboles alphanumriques 143 modificateurs 130133 clotre, pour un 168 modifications entre les versions de Perl 559 motifs personnels 183195 positions pour la dtection 161164

1017
pour rendre des donnes non marques 530 prcdence de la dtection 178183 proprits Unicode, correspondre aux 378 quantificateurs dans 126, 142, 158161, 180 recherche rcursive 193 rfrences arrires 36, 164 regroupements dans 167 soucis de scurit 550 split, fonction et 752 study, fonction 759 style de programmation pour 186 syntaxe dextension 143 assertions priphriques 183185 trouver les doublons dans des paragraphes 132 voir m//, oprateur m??, oprateur motifs gnrs 187 mots 965 capture 134 listes de, raliser une compltion programmable par commande sur des 825 mots cls voir mots rservs mots de passe 757 crypt, fonction et 660 modules Perl pour les 518 passwd, fichier 687 mots rservs 47 mots simples, conflits possible avec 55 mots simples viter, raisons pour 556 modifications entre les versions de Perl 558 vrification de leur utilisation avec le pragma strict 122 MS-DOS, systme dexploitation invoquer des applications Perl avec 458 msgctl, fonction 703 portabilit de 588 msgget, fonction 703 portabilit de 588 msgrcv, fonction 703 portabilit de 588 msgsnd, fonction 703 portabilit de 588 multidimensionnels, hachages 255259 accs et affichage 257 gnration 256 multidimensionnels, tableaux 245252 multiplicatifs, oprateurs 82 multiplication 20 chane, oprateur de rptition 20 multiprocessus processeur, accs imprvisible au 536 multithread 417

customer_8566

1018
my, fonction 48, 97, 104, 114, 115, 116 affectation de listes 64 dclaration 704 fermetures et 237 voir local, dclaration ; our, dclaration efficacit de 564 tourderies courantes avec 555 exemple dutilisation 202 local contre 120 local ou 556 our vs. 48 paquetages et 267 rgles des contextes et 60 variables de boucle et 101 voir porte lexicale ; local, dclarations ; our, dclarations

Index
sortie de blocs usage unique avec 108 NFS (systme de fichiers en rseau) 966 limitation de 409 \NNN, mtasymbole 146 no, dclarations 112, 277, 342, 707 voir aussi pragmas nom absolu 47 nom de variables dans les tables de symboles imbriques 48 nom/numro, conversion 686 nombre en virgule flottante 966 nombres 5 alatoires 728, 757 chanes, conversion en 50 chiffres dans les noms 47 conversion de variables non numriques en 323 entiers voir entiers fonctions pour 646 hexadcimaux 136, 692 justification sur le point dcimal 214 mtacaractre \d (digit) 32 octaux 51, 707 oprateurs de comparaison pour les 24 oprateurs sur les bits, travailler avec 89 soulign dans les 51 tableau, mmoriser dans un 8 taille des 589 tronquer avec int 693 typage en Perl 50 valeur boolenne des 26 virgule flottante voir nombres en virgule flottante virgules, insrer dans 217 nombres alatoires produire avec des handles ou des scalaires 365 nombres en virgule flottante 50 Math::BigFloat, module 820 nombres octals 51 nomethod, clef de surcharge 329 nomms caractres 52 insrer 377 mtasymboles pour 147 pipes 404 tubes 978 unaires, oprateurs 8385 liste de 83 noms 5, 4650 adresses rseau, obtenir depuis des 682, 684 attribut 211 classes, distinguer des sousprogrammes 290

N
\n voir sauts de ligne -n (boucle implicite), option de la ligne de commande 466 voir -p NDBM_File, module 825 ne, oprateur 24, 554 voir aussi point dexclamation dans les symboles ngation classe de caractres 34 classes de caractres 148, 149 classes de caractres POSIX 157 oprateur (!) logique 80 surcharge 324 oprateur ~ sur les bits 80 oprateur arithmtique (-) 80 voir aussi point dexclamation dans les symboles ngatives de prvision, assertions 180, 183 ngatives de rtrovision, assertions 184 Net::hostent, module 824 Class::Struct, utiliser pour crer des objets et des accesseurs 835 Net::netent, module 684, 824 Net::Ping, module 824 Net::proto, module 686 Net::protoent, module 824 Net::servent, module 824 networks, fichier voir /etc/networks new, mthode 421 news voir Usenet next, oprateur 30, 101, 106, 706 dans un do {} while 109, 557 next if, construction 562

customer_8566

Index
commandes 14, 966 constructeurs 293 convention des majuscules en Perl 47 convertir en adresses rseau 685 de fichiers temporaires 541 de format voir formats ; dclarer de format associs un handle de fichier 213 de modules/packages 572 de signaux 386 de sockets 650 de variables 5, 45, 572 des systmes dexploitation 635 du programme voir dollar, $0 dans les symboles tiquette et filehandle 47 fichier voir noms de fichier fonction 14 groupes 682 hachage 45 hachage, mmoriser dans un 8 htes, convertir en adresses rseau 683 identificateurs vs. 47 login voir login, noms mthodes, variables lies 337 modules 276 majuscules/minuscules dans 276 ordinateur voir nom dhte paquetage 268 gestion 13 paramtres ne ncessitant pas de 200 ports, obtenir depuis des numros 688 protocoles convertir vers/depuis les numros 686 obtenir depuis des numros de ports 688 recherche des 4850 restreindre une porte 115 sous-programme 47, 198 mise en majuscules de 198 table de symboles 269 tableau 45 typeglob 67 noms dhtes convertir en adresses 685 noms de base, fichiers 821 noms de fichier 59, 966 & (esperluette) dans les 712 donnes externes dans les, risques de scurit des 533 expansion des 689

1019
globalisation 71 voir aussi fonction glob globs de 591 hachage %INC des 630 lier avec des liens en dur 698 modes douverture 710 modifier 733 obtenir depuis des liens symboliques 731 visualiser un programme ou une instruction eval diffrent 483 noms de variables internes, Perl 47 noms indfinis, recherche des 48 non interactif, mettre le dbogueur en mode 491 not (!), oprateur 80 voir aussi point dexclamation dans les symboles notation exponentielle 51 notation shebang voir #! dans les symboles nouvelle ligne 42 enlever 19 ligne blanche, valeur boolenne et 28 noyau Unix, bogue des scripts set-id dans le 537 noyaux fiabilit des signaux dans les 388 fossoyer automatiquement les processus zombies 387 gnrer des signaux 384 threads et 419 nul handle de fichier 70 nulle liste 63, 65 valeurs 964 numros commandes, historique pour le dbogueur 476 de lignes (symbole __LINE__) 59, 584 de protocole 686 ports, obtenir les noms de protocole depuis 688 pour les pages 630 numros de lignes 59 dans le fichier en entre 631 voir dollar, $. dans les symboles NV (valeur double interne) 500

O
-o (UID effectif), test de fichier 85 -O (UID rel), test de fichier 85 /o (une seule fois), modificateur de motif 131, 134, 136, 146, 172 O, module 447, 449, 830

customer_8566

1020
objets 12, 283318, 978 classes 266 gestion de donnes de classe 315318 consacrer 79 consacrs (avec bless) 651 constructeurs 291295 hritables 292 initialisation 293 voir constructeurs conversion en chanes 236 destructeurs dinstance 303 ramasse-miettes avec 304 destruction (globale), contrler 472 donnes dinstance gnration daccesseurs par autochargement 309 gnration daccesseurs par fermetures 311 gnration de classes avec Class::Struct 309 gestion 304315 nouvelles fonctionnalits, Perl 5.6 314 objets privs, utilisation de fermetures pour 312314 fonctions pour 647 hritage 295303 par le tableau @ISA 296 indirect voir objets indirects mthodes 233 rfrences voir fermetures threads 421 verrouiller 429 rfrences , dans les scalaires 7 stockage dans dautres objets compar lhritage 304 systme objet de Perl 285 variables lies, sous-jacentes 336 rompre les rfrences aux 367 objets indirects 967 ambiguts avec les 288291 chemin explicite, passer dans lemplacement des 529 dfinition 288 exemple dutilisation 260 oct, fonction 51, 707 chmod, utilisation avec 654 exemple dutilisation 51 voir hex voir sprintf octaux, nombres 707 caractres, reprsenter 146, 374 spcifier $/ comme 460

Index
octets 41, 967 caractres ou 373, 645 lecture 729 lire 767 oprateurs de dcalage de bits 83 places mmoires voir gros-boutiste ; petit-boutiste ODBC modules Perl pour 519 offsets 955 $OLD_PERL_VERSION 635 OLE modules Perl pour 519 one-liner, script 16, 967 OO voir programmation oriente objet Opcode, module 825 opcodes voir codes dopration open, fonction 18, 399, 707 $. et 658 $^F et 641 binmode et 650 convertir un descripteur de fichier en handle de fichier 396 fichiers temporaires et 541 FileHandle, module ou 851 fileno, fonction et 676 fork-open 399, 712 voir fork, fonction handles de fichier lis et 356 liste de fichiers et 228 modes dans la forme trois arguments 709 open, pragma et 807 Open2 et Open3 ou 402 passer des handles de fichiers avec 395 pipe forme deux arguments 712 forme avec un argument de liste, viter le shell avec 549 risques de scurit poss par 533 pipes nomms et 405 portabilit de 588, 591, 592 scurit et 527 serveurs en rseau et 413 set-id, programmes et 534 sur un pipe 398 sysopen ou 765 verrouillage de fichier et 392 voir sysopen open, pragma 807 Open2, Open3, modules de bibliothque 402 opendir, fonction 716 voir readdir oprandes, pile d 444

customer_8566

Index
oprateur 731 oprateur adresse-de (en C) 967 oprateur angle (<>) 18, 69, 463, 556 ARGV et 625 avec les handles de fichier lis 357 utilisation de la globalisation au lieu de l 72 oprateur arithmtique 967 oprateur circonfixe 967 oprateur dauto-incrmentation (++) 22, 949 oprateur dautodcrmentation (--) 22 oprateur de concatnation (.) 20 exemple dutilisation en affectation 22 oprateur de correspondance de motif 32 oprateur de globalisation 71 oprateur de lecture de ligne 18 oprateur de ligne de commande voir oprateur dexcution de commande (backtick) oprateur de rptition (x) 20 oprateur de test en criture 25 oprateur de test en lecture 25 oprateur itratif, surcharge 327 oprateurs 19, 7596, 967 accs, restreindre avec le module Safe 546 associativit de 75 C (langage) 96 daffectation 2122 de protection 54 de recherche et de substitution 124 dtection de motif 126141 modificateurs pour 130133 guillemets, quivalence syntaxique des 7 les verbes comme 14 logiques 23 positions ou longueurs dans Unicode 379 pour le contrle de boucle 106 prcdence 75 conserver la prcdence de C en Perl 77 prcdence de 20 sur les chanes 20 surchargeables 77, 319333, 820, 975 daffectation 325 de comparaison 326 de conversion 323 de drfrence 327 de ngation logique 324 itratif 327 oprateurs arithmtiques 324 rfrences circulaires, problmes avec 328 sur les bits 325 oprateurs additifs 83 oprateurs arithmtiques 80 binaires 20, 80 ordre dvaluation 20 surcharge 321, 324

1021
oprateurs binaires 19, 967 oprateurs court-circuit voir oprateurs logiques oprateurs daffectation 2122, 44, 947 valeurs, retour de 22 oprateurs de comparaison 24 oprateurs de liste 75, 77, 95, 967 distinguer des oprateurs unaires 84 oprateurs de mutation, copie et 328 oprateurs de postincrment et postdcrment 22 oprateurs de princrment et prdcrement 22 oprateurs entre de ligne voir oprateur angle oprateurs infixes 19, 962 oprateurs logiques 23, 95, 967 et (&&), oprateur 89 ngation (!), oprateur 80 ou (||), oprateur 89, 170 utilisation avec les oprateurs de liste 113 prcdence des 289 sparation de processus, pre et fils 418 surcharge 324 oprateurs prfixs 19 oprateurs sur les bits 7596 surcharge 320 oprateurs ternaires 19 oprateurs unaires 19 arithmtique 22 boolen 25 nomms 73 operateurs sur listes, distinguer des 59 oprations, contexte et 59 ops, pragma 825 optimiser dans le compilateur Perl 438 performance et 561 options modules Perl pour le traitement des 518 options, ligne de commande 456, 460471 , option 460 -0, option 456, 460 -a, option 461, 629 -C, option 461 -c, option 461 -D, option 462 -d, option 461, 475, 494 -e, option 456, 463 -F, option 461, 463 -h, option 463 -I, option 456, 465 -i, option 463 -l, option 465 -m, option 466 -n, option 466

customer_8566

1022
-P, option 467 -p, option 467 -S, option 468 -s, option 467 -T, option 414, 469, 526 -U, option 469 -u, option 469 -V, option 469 -v, option 469 -W, option 470 -w, option 17, 470, 871 affichage des warnings 17 -X, option 471 -x, option 456, 470 dfaut, prendre des options par 472 un seul caractre, traitement avec regroupement 821 voir noms doptions individuelles; interprteur, Perl options, modules Perl pour le traitement des 821 or, oprateur 89, 90, 95, 170, 572 | (sur les bits) 88 prcdence, compare || 289 utilisation avec les oprateurs de liste 113 voir aussi barre verticale dans les symboles ord, fonction 657, 716 portabilit de 593 seechr 657 Unicode et 379 ordre voir precedence ordre des octets pour les 589 orgueil 968 origine des temps ($^T) 625 OS/2, systme dexploitation File::Spec::OS2, module 821 invoquer des applications Perl avec 458 $OS_ERROR 635 %OS_ERROR, hachage 635 $OSNAME 635 ou exclusif (xor), oprateur 88, 95 ou, oprateur 23 prcdence, ou vs. || 23 our, dclaration 48, 97, 115, 116, 716 my ou 704 pragmas subs et vars ou 792 raison de son existence 122 strict, pragma et 813 variables globales, porte lexicale 118 vars, pragma et 814 out-of-memory, erreurs 634 $OUTPUT_AUTOFLUSH 636 $OUTPUT_FIELD_SEPARATOR 636 $OUTPUT_RECORD_SEPARATOR 636

Index
ouvrir des fichiers via des appels systme de bas niveau 765 sockets 746 %OVERLOAD, hachage 636 overload, pragma 320, 807

P
-p (affichage pendant une boucle implicite), option de la ligne de commande 467 p (correspond la proprit) 378 P (ne correspond pas la proprit) 378 -P (prprocesseur C), option de la ligne de commande 467 -p (tube nomm), test de fichier 85, 404 pack, fonction 589, 718722 caractres des canevas pour 718 exemple dutilisation 58, 703, 742, 764 longeur de chane et 379 ordre de octets et 589 UTF-8 et 379 vec et 782 voir unpack package, dclaration 267, 722 packages 968 pads 46 page daccueil de Perl xxiv pages de manuel doc, sous-rpertoire de CPAN contenant 515 paires cl/valeur voir hachage PalmPilot modules Perl pour 517 paquetage courant 968 paquetage de plus haut niveau 49 paquetage par dfaut 114 paquetage principal 49 paquetage, dclaration de 114 paquetages 12, 46, 48, 265274 ajout de mthodes un paquetage existant 299 attacher des variables aux 770 citation 290 consacrer des objets (avec bless) en 651 dans le tableau @ISA, hritage par 296 dlimiteurs de 268 clater pour autocharger 827 identificateurs 267 importer des smantiques dans les 778 mthodes et sous-programmes, rsolution de 286 noms de 56, 572 paquetage courant 968 paramtres de la fonction bless 291

customer_8566

Index
relier des variables aux 778 tables de symboles 269273 afficher 490 voir aussi modules ; espaces de noms paquets 409, 968 paragraphe, mode 461, 632 parallle, traitement modle de thread 419433 paramtres sous-programmes changer sur place 200 travailler avec 200 voir arguments parent, processus voir processus parenthses () voir parenthses dans symboles paresse 968 partage mmoire, IPC System V 406 partags, verrous de fichier 391 pas pas, parcourir du code 479 passage de rfrence 199, 203, 947 prototypes dclarant les appels de fonctions comme 223 passage par valeur 948 copie des valeurs de @_ dans une liste my 200 PATH, variable denvironnement 468, 471 scurit et 533 PAUSE 522 PDL (Perl Data Language) 517 performances xvi mesurer 772 Perl, efficacit dans les programmes 561 569 priphrique nul, Unix 365 priphrique, et stat 758 Perl bibliothque, installer des modules de CPAN dans 521 black 613 C, utiliser depuis 501507 crer des extensions 503505 tendre avec XSUB 506 fonctions dune bibliothque C externe, utiliser 506 caractres spciaux dans 5 emplacement sur votre systme 460 extensions et mcanismes internes, modules pour les 825 histoire de 611 insrer dans C 507512 compiler des programmes insrs 508 Perl, ajouter un interprteur un programme C 508

1023
insrer en C instruction Perl, valuer depuis C 510 pile de Perl, manipuler depuis C 511 sous-programme Perl, appeler depuis C 509 machine virtuelle 443, 445 modules pour sinterfacer ou muler dautres langages 518 programmer, techniques courantes 553 586 programmes, cycles de vie 436 thread, programmer en 420 utilisation dUnicode, prcautions sur 380 versions de 635, 637 Perl Data Language (PDL), module 249 Perl Package Manager (PPM) 520 Perl, interprteur 436 options voir options, ligne de commande -s, option 475 sticky bit 566 Perl/Tk 568 modules Perl pour 518 PERL_DEBUG_MSTATS, variable denvironnement 472 PERL_DESTRUCT_LEVEL, variable denvironnement 304, 472 $PERL_VERSION 637 PERL5DB, variable denvironnement 472 dbogueur, personnaliser avec 488 PERL5LIB, variable denvironnement 472 PERL5OPT, variable denvironnement 472 PERL5SHELL, variable denvironnement 472 perlapi, documentation 510 perlcall, documentation 511 perlcc, commande 447, 626 pby, script rsultant de 447 $PERLDB 637 PERLDB_OPTS, variable denvironnement AutoTrace, option, tracer les instructions de la phase de compilation 478 personnalisation du dbogueur via 487 perldoc, commande xix, 275 perlembed, documentation 507, 511 perlfork, documentation 384 perllocale, documentation 697 perlmodinstall, documentation 520 perlport, documentation 384 informations sur la portabilit de fonction 648 perlwin32, documentation 384 permissions 766, 774 interprtation des oprateurs de permission de fichier 86 utilisateurs, accorder des permissions limites 526

customer_8566

1024
permissions, et stat 758 persistant, interprteur Perl 507 personnalisation, dbogueur 487490, 494 fichiers dinitialisation, en utilisant des 487 implmentaion de lditeur pour la 487 options 488490 petit-boutiste 589, 969 exemple de 722 pack et 719 phase de compilation 969 pi 649, 797 PID (processus ID) 638 obtenir le groupe du processus depuis 685 voir processus pieds de page 218 pige de dliement 366368 piles 9, 245 disciplines 715 valuation dune expression 44 machine virtuelle Perl 444 Perl, manipuler depuis C 511 sous-programmes, appels courants dans 652 trace arrire avec la commande T 477 pilotes matriels modules Perl pour interagir avec les 517 pipe (|) voir barre verticale dans les symboles pipe, fonction 724 portabilit de 588, 592 socketpair ou 403, 747 Win32 et 404 pipelines sur plusieurs niveaux, pour les entres 399 sur plusieurs niveaux, pour les sorties 398 pipes bidirectionnelle, communication interprocessus 402404 dans les communications interprocessus 397405 pipes nomms 404 processus soliloquant 399 fermer 658 handles de fichiers en lecture seule, ouverture 711 IO::Pipes, module 822 open, fonction, risques de scurit poss par 533 places mmoires lvalues for 964 pour les octets voir grand-boutiste ; petit-boutiste plain old documentation voir pod pluralits 8 .pm, fichiers 266 chargement de fichiers associs 277

Index
pod 595610 directives 598, 955 Insertion dans Perl 43 modules 603 modules Perl pour 517 traducteurs de 595, 603 Pod::Checker, module 827 Pod::Functions, module 827 Pod::Html, module 827 Pod::InputObjects, module 827 Pod::Man, module 827 Pod::Parser, module 827 Pod::Select, module 827 Pod::Text, module 827 Pod::Text::Termcap, module 827 Pod::Usage, module 827 POE (Perl Object Environment) 517 posie en Perl 613 point voir point dans les symboles point dcimal, aligner 214 pointeurs 44 en C 221 rfrences, impossible de convertir vers 50 vers des chanes 720 points darrt 969 lister tous 481 positionner 475, 478, 480 supprimer 480 surveillance, expression et 481 points de suspension (...) 141 politiques dordonnancement et de premption, threads 420 poll, fonction 822 pollution de lespace de noms 278 polymorphisme 284, 969 ponctuation, dtection des limites de mots et 162 ponctuation, variables avec, grer avec le module English 826 pop, fonction 245, 724, 744 exemple dutilisation 64, 204, 695 splice et 751 split et 752 tableaux lis et 348 voir shift popen, fonction (C, langage) 507 portabilit des fichiers et des systmes de fichiers 590 des programmes Perl 587594 des signaux 591 fonctions, informations sur 648 gethostent et 684 informations sur la 384 tester lefficacit de la 568

customer_8566

Index
portages de Perl vers des systmes dexploitation 516 portes 5, 46, 969 bloc 99, 116 dans les boucles for 102 dans les boucles foreach 104 dans les boucles while 101 dans les instructions if 100 dans les threads 432 de la gestion des signaux 386 dclarations 114 voir aussi local ; my ; our dclarations de paquetage 267 dynamiques 119, 970 fichier 116 fonctions pour 646 lexicales 48, 116 oprations de recherche de motif 130 pile de porte 444 pragma strict et 13 sous-programmes 201 variables my et our 267 variables prives voir lexicales, variables portes dynamiques 114, 116, 970 local, utilis sur les variables globales 119 variables de motifs 130, 135 portes lexicales 46, 48, 116, 970 analyseur lexical ou 439 dclaration de 114 voir aussi my espace priv et 312 espaces de noms et 787 fermetures et 238 fichiers et 49 our, dclarations et 716 pragma et 121 variables attaches aux 48 variables de paquetage, recherche de 49 variables et 202 voir aussi scopes ports 969 nom/numros, conversions pour 688 ports srie modules Perl pour les 517 pos, fonction 162, 725 + et 633 \G et 163 longeur de chane et 379 position de dpart dune correspondance 633 position, assertions de 163 changement avec lordre de la recherche 169 positions 161164 dtection des dbuts de chanes 161

1025
dtection des fins de chanes 161 dtection des frontires de mots 162 longeur de chane et 379 manipulation avec la fonction substr 161 prcdence dans la recherche 178 spcification de position aprs la recherche prcdente 163 POSIX, classes 148 POSIX, classes de caractres de type 157158 POSIX, module 823 avoir accs aux fonctions et variables exportes par 277 bloquer des signaux avec 389 strftime, fonction 701 Posix, module getattr, fonction 681 postcurseur 970 postincrment et postdcrment, oprateurs 75 $POSTMATCH 637 PostScript modules Perl pour 518 pourcent (%) voir pourcent dans les symboles PPM (Perl Package Manager) 520 pragmas 13, 113, 120, 266, 466, 778, 791818 porte lexicale 121 caractres nomms 52 modules et 276 noms, casse dans les 47 pr-tendre des tableaux 565 prcdence 77, 643, 970 and contre &&, ou contre || 90 defined 75 diagnostic, messages de 871 documentation en ligne xx expressions rationnelles 178183 modificateurs contre virgules 115 modifications entre les versions de Perl 559 my et 115 oprateurs logiques 23, 95, 289 oprateurs unaires, plus haute que celles des oprateurs binaires 83 sous-programmes lvalue et 212 prcurseur 970 prdclarer des sous-programmes 302, 826 prdfini 970 prfixe, oprateurs 75 mtacaractres fonctionnant comme 141 $PREMATCH 637 prendre le contrle autour des boucles implicites 467 prprocesseur (langage C) 970 prprocesseur Perl 970 prtraitement de Perl 584 prts, descripteurs de fichiers 740

customer_8566

1026
prvision 183 print, fonction 19, 37, 565, 725 efficacit de 561, 565 erreur de virgule avec 554 exemple dutilisation 773 handles de fichier lis et 357 notation dobjet indirect de 288 objets et 323 parenthses et 84 read ou 729 select et 739 sparer les champs avec $, 636 supplanter, lever une exception lorsque 842 terminer des enregistrements avec $\ 636 vidage avec $| 636 voir printf write ou 216, 785 printf 754 printf, fonction 92, 726, 754 $# et 623 efficacit de 561 exemple dutilisation 659, 683, 759 handles de fichier lis et 359 style et 582 supplanter, lever une exception lorsque 842 voir print voir sprintf PrintRet, option du dbogueur 489 priorit, processus 686, 743 prise de contrle dobjets lors de leur destruction 303 priv, espace 284 modules Perl et 278281 prives, mthodes, ignorer lhritage avec 302 prives, variables voir local privs, objets, utiliser des fermetures 312314 procdural, style de programmation 186 procdures 14 $PROCESS_ID 638 processeur voir CPU processus attendre des 782 communication interprocessus 383416 entre processus sur la mme machine 384 fichiers 390397 IPC System V 405409 sockets 409416 sur lInternet 383 de processus 386 envoyer des signaux des groupes de processus 386 fonctions pour 647

Index
fork, fonction 678 identifiants (PID) 714 multitches, accs la CPU dans des environnements 537 obtenir le groupe pour des 743 priorit, modifier 743 priorit, renvoyer 686 STDIN, STDOUT, et STDERR dans 18 threads et 418 tuer 696 umask pour les 774 variables pour 627 vrifier lexistence de 387 zombies 387 processus fils ID, renvoyer 678 processus ID (PID) obtenir le groupe du processus depuis 685, 743 renvoy avec fork 678 renvoyer 686 waitpid, fonction 782 processus zombie 980 profiler avec Devel::DProf 825 profileur, Perl 494498 $PROGRAM_NAME 638 programmation oriente objet 266, 283318 abstraction et 285 modules Perl pour 517 modules pour 275 oprations portables sur les fichiers 821 rfrences en Perl, muler 267 programmer, en Perl 553586 avec aisance 573582 crire des programmes portables manipulant des fichiers 590 efficacit 561569 erreurs courantes des dbutants 553560 gnrateurs de programmes autres langages en Perl 583 filtres de code source 585 gnrer du Perl dans dautres langages 584 gnration de programmes 582586 portabilit 587594 style 186, 569573 programmes contrler le dbogueur depuis 478 core dumps (copies du cur du programme) dans 667 excuter 768 excution 958 finir avec exit 674 moyenne des notes dlves, calculer et imprimer 15

customer_8566

Index
nom de lexcutable Perl 628 nom du script perl 638 one-liner 967 parcourir pas pas avec le dbogueur 479 sortie de 3 progressive, dtection 163 projets (grands), avantages du pragma strict dans 13 propritaire, fichier 656 proprits casse, Unicode 379 en programmation oriente objet 293 Unicode 148, 379 proprits de bloc, Unicode 154 proprits Unicode standard 151 protection de ligne voir documents ici-mme protections, et stat 758 prototype, fonction, lever une exception lorsquon la supplante 842 prototypes 205210, 971 & (esperluette), omission des noms de sousprogrammes 205 fermetures 240 fonctions internes, muler 205 mise en ligne des fonctions constantes 208 passage de rfrence implicite dans 223 utilisation prudente de 209 pseudo-commandes, recevoir/envoyer via un pipe 400 pseudo-hachages 233 implmenter des classes avec 705 hritage et 308 pragma use fields, utiliser avec 307 simuler avec la fonction overload 328 pseudo-littraux voir oprateurs dentre pseudo-oprateurs, surcharge et 323 pumpkins et pumpkings 971 push, fonction 44, 245, 727, 744 muler 205 exemple dutilisation 204, 247 fonction pop 45 hachage et 9 rfrences de tableaux et 230 splice et 751 tableaux lis et 348 voir unshift push-pop (PP), codes 443 PV (valeur de chane interne) 500 pwd, commande (Unix) 566 Python 42 diffrences avec Perl 554

1027

Q
q// (citation), oprateur 331 qr// (quote regex), oprateur 128, 174 modificateurs pour 130 qr// (regex protge), oprateur 61 Qt modules Perl pour 518 quantificateurs 32, 33, 126, 142143, 158161, 563 atomes et 180 classes de caractres et 149 gourmand 160 minimal et maximal 143, 159 utilisation du mtacaractre point (.) avec 147 quarantaine, mettre le code suspect en 544 queues voir files dattente quitter dbogueur Perl 485 des boucles infinies 103 quotation voir isolement quotemeta, fonction 728 exemple dutilisation 193 qw (mots protgs), oprateur 55, 63 qx// (excution protge), oprateur 54, 61, 69, 731 open, pragma et 807 portabilit de 588 voir aussi backtick devant les symboles ; fonction systme

R
-r (accessible en lecture par son uid/gid), test 25 -R (lisible par luid/gid rel), test de fichier 85 -r (lisible par luid/gid rel), test de fichier 85 raccourcir les tableaux 65 race conditions (situations de concurrence) test de fichiers et 803 ramasse-miettes 244 avec les mthodes DESTROY 304 des globales 971 objets associs des variables lies 341 rand, fonction 78, 728 exemple dutilisation 78, 111, 327, 549 voir srand random, fonction exemple dutilisation 660 rapport de bogues Perl xxv rapports, gnration 213 rationnelles voir expressions rgulires

customer_8566

1028
RE voir motifs re, pragma 808, 826 read, fonction 729 handles de fichier lis et 359 print ou 729 signaux et 388 voir sysread readdir, fonction 729 voir opendir readline, fonction 69, 730 ReadLine, module voir Term::ReadLine, module readlink, fonction 731 portabilit de 588 readpipe, fonction 731 portabilit de 588 $REAL_GROUP_ID 638 $REAL_USER_ID 638 recallCommand, option du dbogueur 488 recherche chemin pour les recherches de bibliothque 630 de sous-chanes 135 des scripts 468 des sous-chanes 693 expressions rgulires dans les 30 grep, fonction pour 692 linaire, ou hachages 561 rgles pour la recherche de mots 49 recherche de texte modules Perl pour la 518 recherche globale voir /g modifier rechercher-remplacer, global 136 recompilation de motif, limiter avec le modificateur /o 131 rcursion des piles de mmoires de travail lexicales 445 rcursivit dans les recherches de motifs 193 des sous-programmes 201 recv, fonction 731 exemple dutilisation 415 portabilit de 588 sockets et 742 voir send redo, oprateur 106, 107 redondance dans Perl 24 rduction canonique 951 ref, fonction 291, 732 attributes, pragma et 793 defined 236 exemple dutilisation 293, 310, 321, 325, 340

Index
rfrencement et drfrencement implicite 223 rfrences 7, 221244 des donnes anonymes 224226 des entres de table de symboles 228, 272 des fonctions stockage dans des structures de donnes 259 des gestionnaires de signaux (dfinis par lutilisateur) 384 des hachages 251 hachages multidimensionnels 259 des handles de fichiers 227 des objets 226, 233, 285, 291 invoquants pour mthodes dinstance 285 surcharge et 319 des sous-programmes 198 des sous-programmes, rcuprer de ou passer 271 des structures de donnes 223 des tableaux lis 345 des variables objet lies, annuler 367 des variables scalaires lies 339 accolades et crochets avec 242 affaiblir et annuler 304 circulaire mmoire utilise par 244 surcharge, viter avec la 328 consacrer 291 conversion en chanes 236, 243, 248, 249 cration 223229 avec loprateur antislash 223 dans des tableaux multidimensionnels 246 dans les tables de symboles, vers dautres tables de symboles 269 dfinition 221223 destruction (globale), contrler 472 dures 972 en dur 79 faibles 244 hachage, clefs de, fournies en tant que 826 indirection et 49, 221 passage par 199, 203 Perl, pointeurs C contre 96 programmation oriente objet et 267 symbolique 241 typage vers dautre types de pointeurs 50 valeur boolenne des 26 vrifier les 732 verrouiller 426 vers des handles de fichiers 708 rfrences arrires 36, 133, 554, 623, 972 accs avec les variables numrotes 165 cration avec des parenthses 166

customer_8566

Index
motifs gnrs en fonction de leurs propres rfrences arrires 193 voir aussi capture ; motifs rfrences circulaires 244 annulation de boucles 304 surcharge, viter avec la 328 rfrences en dur 79, 221, 223, 972 %SIG, hachage 384 utilisation 229241 fermetures 237241 rfrences faibles 244 rfrences symboliques 221, 241, 972 rfrents 222 objets en tant que 285 reftype, fonction (pragma attributes) 291 regexps voir motifs registre, base de (Microsoft Windows) .pl, extensions et 458 manipuler 830 registre, base de (Microsoft Wiondows) manipuler 519 regroupement dans des motifs 167 sans capture, raisons pour 167 regroupement, oprateur de 126, 142, 181 embotement 165 pour les expressions 77 rgulires, expressions voir motifs relation, oprateurs de 87 non-associativit de 88 relier des variables aux paquetages 770, 778 remplacement doccurrences voir s/// (substitution) operator remplacement, chanes de, construction avec le modificateur /e 189 remplacer des lments de tableaux 751 rename, fonction 733 exemple dutilisation 464, 670 portabilit de 591 rendu bidirectionnel, proprits Unicode 153 repres, pile de 445 rpertoire de base 972 rpertoires ajouter au dbut de @INC 465 changer le rpertoire de travail 653 crer 702 crer ou supprimer de manire portable 821 de travail courants, obtenir le chemin des 821 DirHandle, module 822 fermer 659 fonctions pour 646 handles 961 IO::Dir, module 822

1029
lire des entres depuis les 729 modules Perl pour les 518 opendir, fonction 716 oprateur de test de fichier 25 redfinir la racine 657 rewinddir, fonction 736 seekdir, fonction 739 supprimer 736, 776 tests de fichiers dans des arborescences 821 rptition (x), oprateur 20, 82 require, fonction 113, 276, 630, 733 @INC et 789 __DATA__ et 59 base, pragma et 794 caller et 653 chargement de fonction et 203 dclaration de paquetage et 267, 723 do ou 666 lib, pragma et 804 portes et 117 tie et 337 use ou 778 voir use rseau adresses rseau convertir en noms 684 adresses, convertir en noms 682 clients en 411 informations rseau, fonctions pour la recherche 647 modules pour la communication 410, 517, 823 serveurs en 412414 services modules Perl pour interagir avec les 519 systme de fichier en rseau voir NFS Win32, module rseaux 830 rseaux connexion (entre client et serveur) 953 reset, fonction 734 retour arrire 52, 178 dans les recherches de motifs 178 sous-motifs sans retour arrire 185 retour chariot 52 dans une classe de caractre POSIX 157 voir sauts de ligne retours, pile de 445 rtrovision 183 return, fonction 106, 199, 735 erreurs et 201 eval et 108, 669 thread, terminaison avec 422 rutilises, afficher le contenu des adresses 490 rutiliser du code 573 reval, mthode, lancer du code suspect avec 545

customer_8566

1030
reverse, fonction 37, 735 exemple dutilisation 37, 103, 325 prohibe avec sort 560 scalar et 379 rvisions voir versions rewinddir, fonction 736 voir opendir rindex, fonction 736 longeur de chane et 379 rmdir, fonction 736 root directory (rpertoire racine), redfinir 657 rot13, cryptage 139 routines voir sous-programmes RS (variable awk) voir $INPUT_RECORD_SEPARATOR RSTART (variable awk) voir signe arobase, @- dans les symboles RTF modules Perl pour 518 RV (valeur de rfrence interne) 500 rvalues 44

Index
sauvegarde de structures de donnes 262 sauvegardes, fichiers 465 sauvegardes, pile de 444 scalaire, contexte fonctions dans un 645 forcer 737 oprations se comportant diffremment dans un 555 reconnatre dans le dbogueur 477 virgule, sparateur en 560 scalaires 5, 6, 44 application doprateurs de dtection de motif 128 caractres, longueur de 698 constant voir aussi constantes conversion des listes en 11 ensemble non ordonn de voir hachage fonctions pour manipuler 646 lier 337344 dfinitions dune classe de base, fournir des 826 empcher lutilisation non localise de variables $_ 342 mthodes pour 338342 variables compteur magiques 342 liste de voir tableaux paramtres et liste de retour, sousprogrammes 199 Perl, convertir en types C 510 rfrences 7 rfrences en dur comme 222 structures de donnes complexes reprsentes avec des 12 SV (valeur scalaire) 500 valeurs 5059 chanes littrales 5154 documents ici-mme 56 interpolation des valeurs de tableau 56 littraux numriques 51 oprateurs pour 77 v-chane littrales 58 variables en contexte de guillemets doubles 135 noms de 45 vrit, valuation avec les 26 scalaires sans qualifiants 50 scalar, fonction 60, 737 exemple dutilisation 236 prototypes et 205 reverse et 379 tableaux et hachages, dterminer la taille 698

S
-s (analyse doptions), option de la ligne de commande 467, 475 -S (recherche de scripts), option de la ligne de commande 468 -S (socket), oprateur de test de fichier 85 -s (taille non nulle), test de fichier 85 /s, modificateur de motif 130, 134, 136, 142 s/// (substitution), oprateur 61, 124, 135138, 554, 975 =~ et !~, oprateurs de liaison 128 fournissant une interpolation de guillemets doubles 127 modificateurs pour 130, 136 Safe, module 544, 825 code non sr, grer du 544 saturation des serveurs, problmes (motifs et expressions rgulires), soucis de scurit 550 saut de ligne 3, 588 correspondance avec le mtacaractre point (.) 147 correspondances sur des chanes en contenant 131 dans les chanes littrales 53 dans les noms de fichiers, risques de scurit des 534 portabilit des 588 suppression des 19 supprimer avec la fonction chomp 655 saut de page 629

customer_8566

Index
scalars 973 scripts associer avec linterprteur 16 CGI, mode de marquage et 527 construire avec loption -e 463 de langage naturel, vrifier 154 dboguer 461 voir dboguer dure dexcution de 87 erreurs courantes pour les dbutants 553 560 excuter 768 gnrer des core dump 469 idiomatique, en utilisant du Perl 573582 inclure dans des messages 470 interprtation, en shell ou en Perl 558 marqueur de fin de 59 noms des voir dollar, $0 dans les symboles non srs 543 passer implicitement via lentre standard 456 pause dans les 746 performance des 561569 rechercher des 468 rechercher et compiler 456 rpertoire CPAN des 516 style 569573 terminer avec exec 671 test, scripts de 829 vrifier la syntaxe des 461 SDBM_File, module 825 Search::Dict, module 820 scurit xvi, 525, 757 cracker 954 grer des donnes non sres 526, 533 accs aux commandes et aux fichiers avec des privilges restreints 534 dtecter et blanchir des donnes marques 529 grer du code non sr 543 compartiments de scurit pour 544 dguiser du code en donnes 548 grer les problmes de synchronisation 536 bogues de scurit du noyau Unix 537 fichiers temporaires 541 situations de concurrence 538 modules Perl pour la 518 modules pour la 825 oprateurs de test de fichier et 803 Win32::FileSecurity, module 830 sed 30, 138 seek, fonction 738 -x option et 470 DOS, mode texte et 588

1031
exemple dutilisation 393 Fcntl, module et 842 File::Temp et 543 handles de fichier lis et 358 voir tell, fonction seekdir, fonction 739 telldir et 770 voir opendir voir telldir select (descripteurs de fichiers prts), fonction 676, 739, 740, 822 dormir un peu avec 405 exemple dutilisation 415 fileno et 676 IPC::Open3 et 856 sendormir rapidement avec 741, 746 select (handle de fichier de sortie), fonction 726, 739 exemple dutilisation 216, 412, 465, 713, 784 FileHandle, module de substitution pour 851 IPC::Open3 et 402 portabilit de 588 pour les variables de format 216 variables et 620 select, appel systme, multiplexer les entres/sorties entre les clients 413 slecteur, ligne de commande slecteur -e 16 SelectSaver, module 822 self, mthode (Thread, module) 424 SelfLoader, module 274, 828 Devel::SelfStubber, module, utiliser avec 828 smantique doctets, raccourcis pour les classes de caractres en 149 smantiques, importer dans des paquetages 778 smaphores 973 fonctions pour les 741 IPC::Semaphore, module 824 mmoire partage 406 thread, scurit et 420 Thread::Semaphore, module 432 utilisation dans le verrouillage de fichier 393 Win32::Semaphore, module 830 semctl, fonction 741 portabilit de 588 semget, fonction 742 portabilit de 588 semop, fonction 742 portabilit de 588 send, fonction 742 portabilit de 588 voir recv

customer_8566

1032
sparateur de champ diffrent, spcifier un 952 sparateurs, dfinition avec loprateur split 31 squence dchappement pour les caractres de contrle 51 squence de tri 973 squences de caractres combins, correspondre avec \X 378 squences de touches, gnrer des signaux avec des 384 squences de traduction lintrieur de guillemets doubles 173 srialiser des structures de donnes Perl 825 server-push, scripts CGI 824 serveurs 412414 clnage avec fork pour soccuper des connexions entrantes 413 marquage, importance dactiver le mode de 527 modules Perl pour les 519 TCP 411 service, port, conversions nom/numro 688 set-id, programmes 526 bogues du noyau Unix problmes de scurit avec les 537 dangereuses, grer des oprations 534 setgid 526 voir set-id, programmes setgrent, fonction 681 portabilit de 588 sethostent, fonction 684 portabilit de 588 setnetent, fonction 647, 685 portabilit de 588 setpgrp, fonction 386, 743 portabilit de 588 setpriority, fonction 743 portabilit de 588 setprotoent, fonction 687 portabilit de 588 setpwent, fonction 687 portabilit de 588 setservent, fonction 689 portabilit de 588 setsockopt, fonction 743 exemple dutilisation 412, 415 portabilit de 588 setuid 526 voir set-id, programmes sh (Bourne shell) 974 #! (shebang), notation et 457 eval exec, bidouille et 17, 468 exec et 671 pipe, recevoir/envoyer via un 398 piper avec 711 system, fonction et 527

Index
User::pwent et 869 valeurs de sortie depuis 768 voir shells shadow, entres de mots de passe 687 Shell, module 823 shells 974 apostrophe, passer via 463 Bourne shell (sh) 457 commandes dans les 952 commandes du dbogueur et 484 commandes pipes avec des mtacaractres, passer au 711 court-circuiter avec -| 400 engendrer, caractres pour 488 environnement, variables 471 positionner temporairement 471 viter avec des open sur des pipes avec plusieurs arguments 398 viter lutilisation de 535 flux I/O, paramtrer un 18 Perl ou 557 piges de scurit en utilisant, viter 549 pipe, commandes avec des caractres speciaux, manipuler 398 possibilit pour Perl, systmes Windows 472 variables denvironnement 806 trous de scurits 533 shift, fonction 28, 83, 245, 744 _ et 575 efficacit de 561 exemple dutilisation 704 files et 727 splice et 751 voir pop voir unshift shmctl, fonction 744 portabilit de 588 ShMem, paquetage 407 shmget, fonction 745 exemple dutilisation 407 portabilit de 588 shmread, fonction 745 exemple dutilisation 408 portabilit de 588 shmwrite, fonction 745 exemple dutilisation 408 portabilit de 588 shorts 756 shutdown, appel systme 412 shutdown, fonction 412, 745 exemple dutilisation 747 portabilit de 588 %SIG, hachage 384, 639 sigaction, appel systme 388 SIGALRM, signal 649

customer_8566

Index
signalLevel, option du dbogueur 488 signatures de messages modules Perl pour les 518 signaux 383, 384390 %SIG, hachage 384, 639 en Perl ou en langage C 557 bloquer 389 envoyer des groupes de processus 386 intercepter avec le pragma sigtrap 385, 823 minuter les oprations lentes 389 portabilit des 591 provoquer dans la bibliothque C 385 sources des 384 Thread::Signal, module 433 threads, dlivrer aux 420 tuer des processus avec 696 zombies, processus et 387 sigprocmask, appel systme 389 sigtrap, pragma 385, 809 simple apostrophe () inhiber linterpolation des variables 6 sin (sinus), fonction 746 complexes, nombres et 857 exemple dutilisation 443, 650 singularits voir scalaires situations de concurrence (race conditions) grer 538 noyaux Unix et 537 oprations lentes et 389 test de fichiers et 803 verrouillage de fichier et 340, 391 sleep, fonction 746 alarm et 649 exemple dutilisation 103 rsolution en dessous de la seconde 741 select, fonction au lieu de 741 slurping files 974 socket, fonction accept et 648 autovivification avec 700 portabilit de 588 Socket, module 410, 824 client en rseau, se connectant un serveur 411 inet_ntoa, fonction 683 socketpair, fonction 403, 747 portabilit de 588 sockets accepter les connexions de clients 648 arrter une connexion 745 attacher une adresse 650 bas niveau, fonctions pour laccs 647 connecter 659 dans les communications

1033
interprocessus 409416 clients en rseau 411 passage de message 415 serveurs en rseau 412414 envoyer des messages sur des 742 fermer 658, 745 fonctions pour les 409, 689 listen, fonction pour 698 modifier les options 743 modules pour les 823 obtenir une adresse avec un empaquetage sockaddr 685 ouvrir avec socket, fonction 746 protocoles et 383 recevoir des messages sur des 731 sauts de ligne, envoyer via des 588 TCP et 409 Unix, domaine 409 sommes de contrle 777 sort, fonction 11, 37, 747751 hachages et 255 les oprateurs de comparaison dans la 24 locales et 806 localisation de $a et $b 620 longueur de chane et 379 optimisation de 442 reverse et 560 variables 624 sortie 17 accumulateur du format de sortie 680 blocs un seul passage 108 blocs if ou unless 108 canal de sortie courant 951 de programmes 3 dbogueur, slectionner 491 dclarer un format denregistrement de 213 des boucles infinies 103 des pipes 397405 bidirectionnels 402 filtrer 400 STDOUT en tant que pipe vers un autre programme 398 tridirectionnels 402 slectionner les handles de fichiers pour la 739 sparateur denregistrements en voir dollar, $\ dans les symboles sparateur de champs en voir dollar, $, dans les symboles STDOUT, handle de fichier 677 tableau et hachage, changer le style (dbogueur) 490 vrifier les descripteurs de fichiers pour la 740

customer_8566

1034
sortie standard voir STDOUT sorties fichiers, mode douverture pour les 710 fonctions pour 646 utiliser ioctl pour les 694 XSUB 506 sorties (backends), compilateur 830 sorties du compilateur 446 modules 446 sortir dbogueur Perl 485, 489 souches (stubs) pour les modules, gnrer 828 Souligne, module 343 source voir code source source, code tranger, excuter du code 525 sous-chanes 974 remplacement avec loprateur s/// 135 sous-classes 284 attributs, supplanter des anctres de surclasse 306 sous-espaces de nommage des variables 46 sous-motif de code dans les expressions rationnelles 974 sous-motifs sans retour arrire 185 sous-programmes 6, 14, 197212, 285 annuler avec exit 674 anonyme 197 rfrences 226 appel excuter sans les parcourir pas pas 479 indirect 198 invocation de mthode compare 292 arguments 625 attributs, consulter et positionner 825 autochargement 273274, 301, 827 B::Xref, module, rfrences croises avec du C 449 chargement de dfinitions depuis dautres fichiers 113 classes de mme nom 290 commandes du dbogueur pour lister les correspondances de motifs 483 constantes 271 contrles de boucle et 108 dclaration 112 dans le paquetage avec AUTOLOAD 302 dclarer 761 dfinition 199 do SOUS-PROGRAMMES, oprateur 667 embotements de 240 excution 958

Index
externes 501 portabilit des 592 importation depuis un autre module 198 indication derreurs 201 lvalue 314 mthodes compares 286 mots simples, confondre avec les 558 nomms, interactions compilateur/interprteur 451 noms de 46, 47, 198 passage de donnes en entre et en sortie 199 passage de rfrences 203 performance et 563 Perl, appeler depuis C 509 pile dappels 652 porte lexicale 704 problmes de porte 201 prototypage 205210 utilisation prudente de 209 redfinition et mise en ligne 209 rfrences dans les scalaires 7 rcuprer de ou passer 271 renvoyer des rfrences 226 rsolution de mthode, tapes de 295 substitution par goto 112, 692 travailler avec une liste de paramtres 200 valeurs de retour 199, 735 verrouiller pour des threads 428 locked, attribut 429 voir aussi fonctions sous-programmes non dfinis, appel avec AUTOLOAD 273 soustraction de jeux de caractres 156 modificateurs de motif avec les clotres 168 objets surchargs 321 spciales, variables 622 splice, fonction 751 delete ou 664 efficacit de 561 exemple dutilisation 327, 343, 725, 727 modifications entre les versions de Perl 559 tableaux lis et 348 split, fonction 31, 128, 167, 752 des champs de longueur variable, extraire avec 952 efficacit de 562, 565 exemple dutilisation 15, 64, 98, 252, 254, 574, 702 join et 138 patterns et 31 reverse et 325 supplanter, lever une exception lorsque 842 voir aussi join

customer_8566

Index
sprintf, fonction 359, 754757 annee sur deux chiffres et 691 arrondir avec 694 exemple dutilisation 136, 338, 707 handles de fichier lis et 355, 359 longueur de chane et 379 notation de vecteur point 683 voir hex voir oct voir printf sqrt (racine carre), fonction 757 complexes, nombres et 857 exemple dutilisation 746 srand, fonction 757 src, rpertoire (CPAN) 516 stat, fonction 758 _ et 87, 623 exemple dutilisation 63 File::stat et 531 handles de fichiers, appeler sur des 540 permissions de fichiers et 707 portabilit de 588 scripts de super-utilisateur et 86 supplanter 821 voir File::stat, module voir lstat statique, dition de liens 502 statique, porte voir portes lexicales statiques, variables (en C/C++) 202 statistiques modules Perl pour les 517 statut de retour dun processus 625 STDERR, handle de fichier 573, 621, 640, 677 envoyer une sortie un autre processus 369 passer des handles de fichiers de nouveaux programmes via 395 raffecter 414 STDIN, handle de fichier 621, 640, 677 -i, option de la ligne de commande et 465 lire un seul caractre depuis 681 passer des handles de fichiers de nouveaux programmes via 395 raffecter 414 STDOUT, handle de fichier 621, 640, 677 -i, option de la ligne de commande et 465 afficher dans 725 passer des handles de fichiers de nouveaux programmes via 395 raffecter 414 sticky bit 566 stockage de donnes complexes dans un fichier DBM 368 stockage des donnes lvalues pour 21

1035
stopper voir terminer strict, pragma 13, 48, 121, 241, 812814, 826 mots simples et 556 stringification (transformation en chanes) modules pour la 838 struct muler 309 Struct::Class, module 306 structure case 109 structures formatter 721 structures de contrle 2530 vrit, dfinition 26 structures de donnes 245263, 517, 975 autorfrentielles, classes conteneur avec pointeurs sur 304 complexes, reprsentes par des scalaires 11 conversion en chanes 262 labores, enregistrements de 259262 hachages de fonctions 259 hachages de tableaux 252254 hachages multidimensionnels 255259 objets voir objets organisation en Perl 251 persistantes, avec tie 369 plates, linaires en Perl 221 pour objets 291 rfrences 223 sauvegarde 262 tableaux de hachages 254255 structures de donnes complexes cration en Perl 245 reprsentes avec des scalaires 12 structures de donnes persistantes, fournies avec tie 369 StrVal (dans le pragma overload) 332 stubs (souches) pour les modules, gnrer 828 study, fonction 759 style, programmer avec 569573 sub, dclaration 197, 206, 226, 761 subs, pragma 302, 814, 826 surcharger des fonctions internes avec 281 $SUBSCRIPT_SEPARATOR 67, 640 voir signe dollar, $; dans les symboles substitution en shell ou en Perl 558 valuation de 189 operateur voir s/// substr, fonction 762 \G et 163 chop et 656 efficacit de 563, 566

customer_8566

1036
exemple dutilisation 325, 408, 607, 656 longueur de chane et 379 manipulation des positions de chane 161 variables spciales contre 633 sucre syntaxique 975 SUPER, pseudo-classe 297, 298 super-utilisateur 975 suprieur (>), oprateur voir gt voir suprieur dans les symboles suprieur ou gal (>=), oprateur voir ge voir suprieur ou gal dans les symboles supprimer caractres 655 des lments de tableaux 724, 744, 751 fichiers 775 les variables denvironnement 627 points darrt 480 rpertoires 736, 776 toutes les actions du dbogueur 483 surcharge 77, 319333, 975 lexcution 333 autognration de 324 constantes 330 constructeur de copie 328 conversion en chane 360 de fonctions 281282 dfinition, applique aux fonctions prdfinies 60 diagnostics 333 fonctions de 332 fonctions mathmatiques 326 handlers 320 hritage et 332 mthodes de classe de base 297 nomethod et fallback 329 oprateurs surchargeables 322328 overload, pragma 320, 820 Overloaded (mthode dans le pragma overload) 332 rfrences circulaires, viter 328 tri et 326 surcharge des constantes chane, transformer un texte grce 194 surclasses 284 surveillance, expressions 481 SV (valeur scalaire interne) 500 SWIG, systme gnrant des XSUB automatiquement 502 switch, instruction 109, 564, 973 programmer en Perl ou en C 557 Sx modules Perl pour 518 symboles 42 exporter 277, 280

Index
importer dans le paquetage courant 276 mtasymboles jokers gnriques 147 omettre de la liste dexport ou supprimer de la liste dimport 279 symboles, tables de Symbol, module 820 symlink, fonction 763 portabilit de 588, 590 synchronisation 976 problmes, grer 536, 537 fichiers temporaires 541 situations de concurrence, grer 538 syntaxe 976 en Perl 44 vrifier 461 Sys::Hostname, module 823 Sys::Syslog, module 823 syscall, fonction 649, 763 fileno et 676 h2ph et 790 portabilit de 588 setitimer et 746 valeur de retour de 645 syslog, liaison de handle de fichier 369 sysopen, fonction 393, 765 crasement de fichiers et 539 viter les situations de concurrence avec 405 exemple dutilisation 534, 542, 859 Fcntl, module et 842 marquage et 534 open et 714 open, pragma et 807 permissions de fichiers et 774 portabilit de 588 verrouillage de fichier et 392 voir open, fonction sysread, fonction 767 exemple dutilisation 769, 861 handles de fichier lis et 359 read ou 729 voir read sysseek, fonction 767 System V, IPC voir IPC System V system, fonction 768 $? et 453, 625, 665 efficacit de 566 exec ou 671 exit et 679 forme avec un argument de liste, viter le shell avec la 549 marquage et 528 ou apostrophes inverses 571 portabilit de 588 set-id, programmes et 534

customer_8566

Index
shells Windows et 472 supplanter, lever une exception lorsque 842 voir exec voir qx wait et 782 $SYSTEM_FD_MAX 641 systme dexploitation interprteurs de commandes pour les 455 invoquer les interprteurs avec la ligne #! 456 systme, appels performance et 566 systme, fonction portabilit de 592 systmes dexploitation xiii, 976 #!, simuler la technique sur les systmes nonUnix 458 bibliothques de traitement des threads 420 fiabilit des signaux sur les 388 flock, implmentation sur les 391 fork, implmentation sur les 397 interfaces graphiques, reposant sur des 591 interprteur Perl, dmarrer 16 manipuler les interfaces des 823 modules Perl pour les 517 noms de module, traduction en noms de rpertoire 276 noms des 635 portabilit des programmes Perl 516, 587 594 sauts de ligne, variations dans les 588 signaux et comportements par dfaut des 386 sockets, implmentation des 410 systmes de fichiers 958, 976 portabilit des 590 syswrite, fonction 355, 769 exemple dutilisation 341 gestionnaires de signaux et 639 handles de fichier lis et 355, 359

1037
tableaux 5, 8, 44, 45, 56, 976 @_, tableaux 199 copier des valeurs dans une liste my 200 ajouter des lments aux 727 analyser du texte dans des 820 anonyme, rfrences 224 anonymes, objets implments comme 306 pragma use fields, surmonter les problmes avec le 307 associatifs voir hachages AV (valeur tableau), typedef en C correspondant 500 de hachages 254255 accs et affichage 255 gnration 254 de tableaux 65 dernier lment des 65 lements, donner des valeurs temporaires aux 699 embotements de 245252 tableaux deux dimensions, cration et accs 246 exists, fonction et 673 hachages de 252254 indices ngatifs, compter depuis la fin du tableau 560 initialisation avec loprateur x 83 liaison 344349 commodit de notation 348 mthodes de 345348 lis, fonction delete et 560 listes et 6265 longueurs de 65 marqus 527 mettre des lments au dbut de 777 multidimensionnels 11, 245, 976 noms de 45 oprateur s/// et 137 passage par rfrence en entre ou sortie de fonction 203 performance et 565 pop, fonction et 724 premier lment dun 623 rfrences 223 remplacer/enlever des lments de 751 sparateur de sous-tableau voir dollar, $; dans les symboles style de sortie, changer dans le dbogueur 490 supprimer des lments de 744, 751 traitement, fonctions pour 646 variables de 56 voir aussi listes tableaux deux dimensions, cration et accs 246

T
-T (texte), test 25 -T (texte), test de fichier 86 -t (tty), test de fichier 85 -T (vrification du marquage), option de la ligne de commande 410, 469, 526 serveurs et 414 voir marquage, vrification du \t, caractre de tabulation 125 table de correspondance, pseudo-hachages 307 table de symboles paquetage 723 tableau @ARGV 70, 948 exemple dutilisation 28

customer_8566

1038
tableaux et hachages, rfrence 8 tableaux multidimensionnels 11, 976 tables voir aussi tableaux multidimensionnels tables de symboles 46, 48, 269273 afficher pour les paquetages 490 changements temporaires avec local 120 contenant des rfrences dautres tables de symboles 269 dans les noms absolus 47 identificateurs de noms de formats dans 680 nommer les entres de rfrences symboliques dans 222 paquetage courant, dterminer lutilisation de 267 paquetages 268 rfrences 228 surnom des entres de 68 tches lgres voir threads taille des nombres 589 reprsentation dun caractre 374 taille de bloc, et stat 758 taille, et stat 758 taintperl, programme 560 tampon bloc 976 commandes 976 exemple dutilisation 411 tampon, vidage 636 tamponnage ligne 977 tan (tangente), fonction 649 Math::Trig et 858 voir atan2 tar, fichiers modules Perl pour les 519 TCP 977 clients/serveurs 411 IO::Socket::INET et 411, 412 Socket, module et 411 sockets et 409 sur des sockets du domaine Internet 409 UDP ou 415 voir IO::Socket, module voir setsockopt tee, programme Unix 365 tell, fonction 770 DOS, mode texte et 588 fgetpos comme alternative 852 handles de fichier lis et 358 telldir, fonction 770 seekdir et 770 voir opendir voir seekdir

Index
tmoins, placer sur des variables Perl 369 temporaires, fichiers 850 crer avec FileHandle 852 dangers des 541 File::Temp et 542 POSIX, module et 859 risques de scurit avec les 541 temps ge dun fichier 87 dormir 746 temps origine ($^T) 625 Tengwar, caractres 378 Term::Cap, module 825 Term::Complete, module 825 Term::ReadKey, module 487, 681 Term::Readline, commande 825 Term::ReadLine, module 487 dsactiver limplmentation dans le dbogueur 491 Term::Rendezvous, module 491 termes 44, 977 expression avec des oprateurs de leurs relations 75 prcdence 77 terminaison des boucles infinies 103 terminaison des chappements 53 terminal pour les entres/sorties de dbogage 491 terminer processus 696 ternaire, oprateur 75 ?: comme 91, 110 surcharge, ne fonctionne pas avec 320 test dentachement 964 test de la sous-classe vide 977 test de sous-classe vide 295 test, commande (Unix) 17 Test, module 829 test.pl 503, 506 Test::Harness, module 829 tester les donnes marques 529 tester des modules 523 par de gentils volontaires 524 pour linstallation 523 tests de fichiers 25, 8587, 404 portabilit de 588 situations de concurrence avec les 539 voir oprateurs de test de fichier tests sur fichier 967 Text::Abbrev, module 820 Text::ParseWords, module 820 Text::Warp, module 820 texte capacit de Perl pour en traiter 123

customer_8566

Index
donnes pod, convertir en format ASCII 827 modules Perl pour le 518, 820 porte lexicale et 46 rorganisation 219 Unicode en tant que mdium pour le 373 voir aussi chanes texte, fichiers (oprateur de test de fichiers -T) 86 Thread, module 420425 cder la priorit au processeur 424 cration de thread 421 destruction de thread 422 identifier les threads 424 join, mthode, capturer des exceptions depuis 423 Thread, module detach, mthode, arrter des threads avec 423 Thread::Queue, module 431 Thread::Semaphore, module 420, 430, 432 Thread::Signal, module 433 threads 417433, 701 attributs locked et method 315 modle de processus 418 modle de thread 419433 accs aux donnes 425433 multiples, dans un seul interprteur 445 verrouiller 701 threads, objets 424 tid, mthode (Thread, module) 424 tie, fonction 335, 770 bless et 336 DBM, fichiers et 393 exemple dutilisation 243, 838 modules CPAN pour 368 pige de dliement avec 366 portabilit de 591 use ou require et 337 voir tied voir aussi lier des variables tie, modules sur CPAN 368369 Tie::Array, module 344 utilisation du sous-programme SPLICE 348 Tie::Counter, module 342 Tie::DBI, module 368 Tie::DevNull, module 364 Tie::DevRandom, module 364 Tie::Hash, module 349 Tie::Persistent, module 369 Tie::RefHash, module 826 Tie::Scalar, module 338, 826 Tie::SecureHash, module 314, 369 Tie::StdArray, module 344 Tie::STDERR, module 369 Tie::StdHash, module 349 Tie::StdScalar, module 338

1039
Tie::SubstrHash, module 826 Tie::Syslog, module 369 Tie::Tee, module 364 Tie::TextDir, module 369 Tie::TransactHash, module 369 Tie::VecArray, module 369 Tie::Watch, module 369 tied, fonction 336, 772 exemple dutilisation 353 voir tie tilde (~) voir tilde dans les symboles time, fonction 772, 820 convertir en champs 690, 700 portabilit de 593 voir gmtime voir localtime voir utime Time::gmtime, module 823 Time::HiRes, module 649 Time::localtime, module 823 Time::tm, module 823 timelocal, sous-programme 700 times, fonction 772 portabilit de 588 Tk 488 voir Perl/Tk tokenisation voir lexicale, analyse tokens 438 analyser du texte dans une liste de 820 caractres ambigus, problmes avec 84 tr/// (traduction), oprateur 773, 785 caractres, traduire avec 379 tr/// (translittration), oprateur 127, 138141 =~ et !~, oprateurs de liaison 128 modificateurs pour 130 tracer dans le dbogueur 477, 481 traduction entre les langages de programmation 585 traitement den-tte de page 630 traiter des commandes shell 456 tranches 45 affectation des 59 de hachages, exemple dutilisation 802 de tableaux bourdes avec les 555 exemple dutilisation 64, 91 syntaxe 80 de tableaux multidimensionnels 248 flches et drfrencement 232 initialisation avec 83 interpolation de 53, 634 local et 115, 120 rfrences et 235

customer_8566

1040
transformation en chanes (stringification) modules pour la 838 translittration 773, 785 voir tr/// transtypage (en C) 96 tri des clefs et valeurs, hachages 695 hachages 258 listes 747 surcharge et 326 tableaux dans des hachages de tableaux 253 trigonomtrie avec Math::Trig 820 troff 977 troncation tableaux 65 tronquer 978 des nombres 693 liste darguments 490 truncate, fonction 773 portabilit de 588 try, bloc 669 tty 403 tube deux bouts, ouverture avec un handle de fichier li 362 tubes nomms 978 tuer voir terminer typage chanes et 50 types de donnes 977 typage des variables conversion entre types 50 scalaires 50 typedefs (langage C) 500, 978 typeglobs 5, 47, 67, 221, 237 afficher le contenu des 490 alias de table de symboles avec 272 anonymes 228 gnrer avec le module Symbol 820 autovivification de 356 contre les rfrences de typeglobs 227 cration de rfrences des handles de fichier 227 dans les hachages de tables de symboles 270 IO::Handle (objet) 228 local, fonction, utiliser avec 700 sous-programmes, rsolution jusqu 286 symbole de prototype (*) 6 variables, liaison une classe via 336 typemap 503 types de donnes 5 convertir entre C et Perl 511 internes 4345 internes, Perl et C 500 scalaires voir scalaires TYPE, dclarations en Perl 705 typeglobs 67

Index

U
-u (core dump), option de la ligne de commande 469 -U (dangereuses), option de la ligne de commande 469 -u (setuid), test de fichier 85 \u, chappement 135 uc, fonction 379, 773 exemple dutilisation 313, 357, 844 trier avec 748 ucfirst, fonction 379, 773 exemple dutilisation 305, 869 UDP 978 exemple dutilisation 415 paquets 409 passage de messages avec 415 sockets et 409 TCP ou 415 UID rel ($REAL_USER_ID) voir dollar, $< et $> dans les symboles UID (user ID) 656 effectif ($EFFECTIVE_USER_ID) voir dollar, $< et $> dans les symboles entre dans le fichier passwd 688 rel ($REAL_USER_ID) 627, 638 uid, et stat 758 umask, fonction 774, 978 exemple dutilisation 535 mkdir et 702 open et 710 portabilit de 588 sysopen et 766 unaires, oprateurs 7596 distinction davec les oprateurs de liste 84 fonctions se comportant comme 77 identifier dun coup dil 556 idographiques 80 nomms 78, 8385 liste de 83 prototypage de fonctions comme 209 surcharge 320 undef (valeur) 64, 662 select et 405, 741 voir defined undef, fonction 565, 775 efficacit de 566 exemple dutilisation 664 gober de fichiers avec $/ et 263 gober des fichiers avec $/ et 632 hachages et 696 tableaux, librer la mmoire des 65 voir aussi valeur undef

customer_8566

Index
Unicode 42, 373381 caractre sparateur de ligne 43 caractre sparateur de paragraphe 43 casse de titre, conversion des chanes en 140 casse, tables de traduction de 379 convertir en caractres 657 dans les identificateurs 47 diteurs pour 377 informations au sujet de 150 locales et 697 mtacaractres joker, dtection avec 147 proprits 148, 150157 composites Perl 151 dcomposition de caractres 152 proprits de bloc 154 raccourcis de classes de caractres Perl et 149 rendu bidirectionnel 153 standard 151 syllabaires, classification par son de voyelle 154 proprits, base de donnes des 379 rsum de, accder un 380 smiley 52, 657 support de, basculement vers 822 Unicode Standard, Version 3.0 380 utilisation en Perl, prcautions sur 380 \w (mot) mtacaractre et 33 unit de compilation 48 units de compilation 978 UNIVERSAL, classe 299301, 826 mthodes, ajout 301 Unix 6, 978 #! et 16 accolades dans 242 bogues de scurit 537 caractre fin de ligne sous 651 chemins dans 469 chemins de fichiers sur 590 commande test, scripts de test et 17 date et heure sur 772 descripteurs de fichiers sur 677 mulation sur Windows 830 eof (fin de fichier) sur 584 fonctions en Perl 648 fork sur 679 glob de fichiers sur 821 installer Perl sur xix invocation de Perl et 455 IPC et 383 isoler (quoting) sur 459 la ligne de commande xxvi les anctres de Perl et xiii modules de CPAN, installer sur 520 permissions 774

1041
sauts de ligne sur 588, 714 shells 6 signaux et 387, 389 sockets et 409, 823 supplanter des fonctions pour muler 281 tronquer linterprtation par le noyau de la ligne #! 456 Unix, systme dexploitation File::Spec::Unix, module 821 unless, instruction 27, 98 instruction if contre 100 unlink, fonction 775 exemple dutilisation 61, 353 portabilit de 591 Socket, module et 863 unpack, fonction 589, 718, 776 des champs de longueur fixe, utilisation avec 952 efficacit de 563 exemple dutilisation 661, 694, 716, 757, 764, 777 longueur de chane et 379 ordre de octets et 589 portabilit de 568 UTF-8 et 379 vec et 782 voir pack unshift, fonction 245, 744, 777 exemple dutilisation 607, 644, 699 splice et 751 voir push voir shift unsigned shorts 756 untie, fonction 335, 367, 661, 778 exemple dutilisation 394, 770 rfrences restantes, nlimine pas 337 until, boucles 98, 101 up, mthode (Thread::Semaphore, module) 432 upcase, fonction 200 use 13, 112, 113, 120, 266, 276, 500 fonction tie et 337 porte globale et lexicale de 114 voir aussi modules ; pragmas use, fonction voir require Usenet groupe dutilisateurs de Perl xxiv modules Perl pour 519 user ID voir UID User::grent, module 682, 823 User::pwent, module 688, 823 Class::Struct, utiliser pour crer des objets et des accesseurs 835

customer_8566

1042
UTF-8 42, 149, 374, 374381 binmode et 650 CGI, scripts et 547 convertir depuis/vers des octets 376 convertir en voir expat convertir vers des entiers 379 dtection de caractres 144 disciplines dentres/sorties et 807 efficacit de 563 la figure smiley et 58 ou utf8 375 portabilit de 568, 590 voir aussi utf8 pragma utf8, pragma 147, 150, 377, 641, 822 exemple dutilisation 156 locales et 158 voir aussi UTF-8 utilisateur root 975 utilisateurs accorder des privilges limits aux 526 authentifier modules Perl pour 518 groupes voir aussi GID ; groupes groupes dutilisateurs 960 recherches dinformations sur 647 temps CPU 772 utilitaire grep 32, 960 utime, fonction 780 portabilit de 588 voir time utmp, fichier voir /etc/utmp UV (valeur entire non-signe interne) 500

Index
rfrencer 223 restreindre une porte 115 scalaires voir scalaires, valeurs tableau voir tableaux vs. variables 5 valeurs false 958 valeurs temporaires 44 valeurs vritables, dtecter avec la fonction defined 662 valeurs vraies valuation 26 values, fonction 668, 780 hachages lis et 349, 354 voir each voir keys variable denvironnement PATH 16 variable numrote 623 variable, taille de caractre voir UTF-8 variables 45, 77, 229 affichage dans le dbogueur avec V 270 anonyme 224 attacher avec tie 770 attributs, consulter et positionner 825 B::Xref, module, rfrences croises avec du C 449 condition, variables de 430 de classe 315 de contrle dans les boucles foreach 103 dbogueur, personnaliser 488 dclaration 97, 114 globales 118 lexicales 116 en Perl ou en C, noms des 557 environnement 627 format 216 global voir global hachage 66 voir hachages initialisation avant lappel de sousprogrammes 203 interpolation voir interpolation de variables liaison 335369 hachages 349355 handles de fichier 355366 pige de dliement 366368 scalaires 337344 tableaux 344349 locales voir local, dclarations marquage et 527

V
-V (version), option de la ligne de commande 469 -v (version), option de la ligne de commande 469 v-chanes (vecteur ou version) 58, 979 dans $^V 637 vaisseau spatial (<=>), oprateur 88 valeur par dfaut 955 valeur true 978 valeur undef 26, 60 voir aussi undef, fonction valeur vrai valuation laide de if et unless 27 valeurs hachages, trier 695 indfinie, valeur boolenne 26 indfinies 775 modifier en copiant 956

customer_8566

Index
modules, exportation vers les programmes 278 my voir my noms de 5, 572 our voir our, dclarations paquetage 48, 267 afficher 482 mmoire, usage 490 pleinement qualifies, y accder hors du paquetage 545 porte lexicale 704 porte, utilisation du pragma strict avec les 13 prives voir local programmer en shell ou en Perl 557 relier aux paquetages 778 rendre locales 699 scalaires entre loprateur angle 71 voir scalaires spciales 622 statiques (en C/C++) 202 substitutions rptition sur 137 tableau voir tableaux tmoins, placer sur 369 traduction avec 140 utiliser comme motif vis--vis de chanes connues 172 valeurs, affectation et 22 voir aussi types de donnes vs. valeurs 5 voir aussi rfrences variables denvironnement 979 modules, utilisation par Perl de 473 PERL_DESTRUCT_LEVEL 304 PERLDB_OPTS, positionner les options du debogueur avec 491 variables de dcrmentation 955 variables de paquetage 48, 49 dclarer 716 emballage dune dclaration dans la porte dun bloc 317 stockage de donnes de classe dans les 316 threads, aucune protection dans les 425 voir globales, variables variables lexicales 114, 216, 979 porte de fichier, stockage de sousprogramme anonyme dans 303 accs depuis des fonctions 202 persistence travers les appels de fonction 202

1043
rfrences symboliques et 241 type 963 variadiques, fonctions en Perl 199 variations grammaticales dans du texte modules Perl pour les 518 vars, pragma (obsolte) 814, 826 vec, fonction 781 efficacit de 566 exemple dutilisation 415, 740 longueur de chane et 379 vecteur de bits, interface de tableau sur un 369 verbes 14 paquetages, gestion des 13 verbosit des avertissements 826 vrifications daccs, spcification dans le constructeur 313 vrifier le marquage 527 verrou mortel dans les threads 427 verrouiller des fichiers 390 DBM, fichiers 393 dissoudre les verrous en fermant les fichiers 392 fichiers DBM 662 flock, fonction 677 verrous partags et exclusifs 391 verrouiller des mthodes 429 VERSION, mthode 300 versions de Perl 635 dterminer avec $^V 637 modifications entre Perl 4 et 5 558560 module, vrification de 280 placer dans la ligne #! 457 spcifier 460 vi implmentation pour le dbogueur 487 vidage automatique des buffer 976 vidage de fichiers 710 vidage du tampon 979 avec pipe 724 dans IPC::Open2 856 de commande 636 par bloc 636 par ligne 636 pipes bidirectionnels, problmes avec 402 tampons non vids dans les versions de Perl 678 un seul caractre en entre et 681, 860 vide, contexte 571, 783 reconnatre dans le dbogueur 477 vido modules Perl pour la 520 vider un hachage 353 virgule (,) voir virgule dans les symboles

customer_8566

1044
virgule flottante, nombres 721 rand, fonction, renvoyant 728 stockage par lordinateur, ordre 589 vision priphrique 183 vitesse voir efficacit ; performance VMS, systme dexploitation File::Spec::VMS, module 821 invoquer des applications Perl avec 458 voir aussi mots simples voyelles, tri de syllabaires selon 154 VRML modules Perl pour 519 ${^WARNING_BITS} 641 warnings, pragma 121, 475, 569, 815, 827 __WARN__ et 639 voir aussi avertissements lexicaux warnLevel, option du dbogueur 488 WeakRef, module 304 web xiv info sur le chameau xxvii modules Perl pour le 519, 824 sites Perl xxiv voir aussi CGI voir aussi HTML voir aussi HTTP voir aussi mod_Perl while, boucles 98, 101 eof, fonction dans 668 wide-characters voir larges, API de caractres ${^WIDE_SYSTEM_CALLS} 641 Win32::ChangeNotify, module 830 Win32::Console, module 830 Win32::Event, module 830 Win32::EventLog, module 830 Win32::File, module 830 Win32::FileSecurity, module 830 Win32::Internet, module 830 Win32::IPC, module 830 Win32::Mutex, module 830 Win32::NetAdmin, module 830 Win32::NetResource, module 830 Win32::ODBC, module 830 Win32::OLE, module 830 Win32::OLE::Const, module 830 Win32::OLE::Enum, module 830 Win32::OLE::NLS, module 830 Win32::OLE::Variant, module 830 Win32::PerfLib, module 830 Win32::Pipe, module 404 Win32::Process, module 830 Win32::Semaphore, module 830 Win32::Service, module 830 Win32::Sound, module 830 Win32::TieRegistry, module 335, 830 Win32API::File 831 Win32API::Net 831 Win32API::Registry 831 Windows voir Microsoft Windows World Wide Web voir web wrapper 957 write, fonction 213, 214, 784 $% et 630 $- et 629 $= et 629

Index

W
-w (accessible en criture par son uid/gid), test 25 -W (avertissements), option de la ligne de commande 470 -w (avertissements), option de la ligne de commande 116, 121, 470, 629, 871 -w (modifiable par luid/gid effectif), test de fichier 85 -W (modifiable par luid/gid rel), test de fichier 85 \w (mot), mtacaractre 144 correspondre des idogrammes avec 378 \W (non mot), mtacaractre 144 wait, fonction 782 $? et 625 die et 658 fork et 679 portabilit de 588 voir waitpid zombies, processus et 387 waitpid, fonction 782 close et 658 exemple dutilisation 394, 403, 724, 859 IPC::Open2 et 402 IPC::Open2 ou 856 IPC::Open3 et 856 portabilit de 588 processus zombies et 782 voir wait zombies, processus et 387 wantarray, fonction 60, 201, 783 exemple dutilisation 201, 401, 775 warn, fonction 783 CGI, scripts et 834 exemple dutilisation 108 numros de lignes et 584 voir Carp, module warn, routine 800 __WARN__, routine 639640 exemple dutilisation 784 $WARNING 641

customer_8566

Index
$^A et 624, 680 $^L et 629 $| et 636 exemple dutilisation 680 formline et 680 i, option -i, option et 463 lignes dimages et 680 longueur de chane et 379 pieds de page et 218 select et 739 voir format

1045
modules Perl pour 518 xor, oprateur logique 23, 88, 95 XS, langage code, portabilit du 592 fonctions, faire correspondre entre C et Perl 501 sous-programmes externes, envelopper 501 XSLoader, module 829 XSUB entres et sorties 506 envelopper des sous-programmes pour Perl 501 voir XS, langage xsubpp, compilateur 501

X
-X (avertissements, dsactivation), option de la ligne de commande 471 -x (excutable par luid/gid effectif), test de fichier 85 -X (excutable par luid/gid rel), test de fichier 85 -x (extraction), option de la ligne de commande 470 x (rptition), oprateur 20 x extraire -x (extraire le programme), options de la ligne de commande 456 \X, mtasymbole joker 147, 378 /x, modificateur de motif 130, 131, 134, 136 x, oprateur de rptition 82 x=, oprateur de rptition et affectation 93 XML

Y
y/// (traduction), oprateur 785 y///, oprateur de translittration 127, 138 yield, fonction (Thread, module) 424

Z
^Z (Ctrl-Z) pour eof 584 \Z (limite de chane), mtacaractre 161 \z (limite de chane), mtacaractre 161 -z (taille nulle), test de fichier 85 zip voir compression zombies, processus 387 fossoyer fork de serveurs et 414

customer_8566

customer_8566

propos des auteurs


Larry Wall est linventeur du langage Perl. Associ de OReilly & Associated, Larry est aussi fort clbre pour avoir crit les logiciels gratuits les plus populaires du monde UNIX, et notamment le lecteur de news rn, lincontournable programme patch. Il est galement connu pour metaconfig, un programme qui crit des scripts Configure, et pour le jeu de guerre de lespace warp, dont la premire version a t crite en BASIC/PLUS la Seattle Pacific University. Larry est en fait linguiste de formation, il a tran entre lU.C. Berkeley et lU.C.L.A. pendant ses tudes (assez curieusement, il navait rien voir avec les dveloppements UNIX en cours pendant quil se trouvait Berkeley). Les annes suivantes le virent chez Unisys, JPL, Netlabs et Seagate, o il joua avec des choses aussi diverses que des simulateurs dvnements discrets ou des systmes de gestion de rseau, sans oublier quelques fuses (il lui arrive aussi de jouer avec ses quatre enfants de temps en temps, mais ils gagnent trop souvent). Cest Unisys, o il essayait dassembler un systme transcontinental de gestion de configuration sur une ligne chiffre 1 200 bauds partir dune version trafique de Netnews, que naquit Perl. Tom Christiansen est consultant indpendant spcialis dans la formation et la programmation Perl. Aprs avoir travaill pendant plusieurs annes chez TSR Hobbies (clbre pour Dungeons and Dragons), il repartit au collge en passant un an en Espagne et cinq en Amrique, soccupant de musique, de linguistique, de programmation et dune demi-douzaine de langages parls. Tom repartit de UW-Madison avec des BA despagnol et dinformatique, ainsi quun MS dinformatique. Il passa ensuite cinq ans chez Convex comme lectron libre, travaillant tant sur ladministration systme que sur le dveloppement dutilitaires et de noyaux, en ajoutant le support utilisateur et la formation pour faire bonne mesure. Tom a galement pass deux mandats au Board of Directors de la USENIX Association. Tom est impliqu dans le dveloppement de Perl depuis 1987. Il est lauteur de The Perl Cookbook, (Perl en action) et co-auteur de Learning Perl, (Introduction Perl) et de Learning Perl on Win32 Systems. Tom prsente des sminaires annuels bass sur plus de quinze ans dexprience dadministration systme et de programmation UNIX. Vivant dans les collines de Boulder, Colorado, environn de daims, de mouffettes et loccasion de pumas et dours bruns, il passe tous les ts faire des excursions, tailler des arbres, lever des oiseaux, faire de la musique et chasser. Jon Orwant est le CTO dOReilly & Associates et il est diteur en chef de The Perl Journal. Il est aussi co-auteur de Mastering Algorithms with Perl (OReilly) et auteur de Perl 5 Interactive Course (Macmillan). Avant de rejoindre OReilly, il tait membre du groupe groupe ddition lectronique MIT Media Lab. Il a alors effectu des recherches sur le comportement dutilisateurs, lautomatisation du jeu de programmation et des nouvelles et divertissements personnaliss gnrs par ordinateur. Jon travaille galement avec les comits consultatifs de VerticalSearch.com, Focalex, Inc. et YourCompass, inc. Jon participe souvent des confrences, parlant de manifestations comme celles de programmeurs ou de journalistes. Il prend plaisir crire du code comme de la prose et ses trois vices sont le jeu, le vin et les mathmatiques. Il a galement cr le premier jeu sur lInternet.

customer_8566

propos des traducteurs


Philippe Bruhat, consultant spcialis en scurit des rseaux, programme en Perl depuis 1996. Il fait partie des Mongueurs de Perl depuis les tous dbuts du groupe parisien en 1999 et est vice-prsident de lassociation ponyme fonde en 2001. Il est bien connu dans la communaut Perl pour ses exercices de programmation assombrie (quil considre comme une forme dexpression artistique). Kai Carver, ingnieur logiciel bas aux tats-Unis et en France, travaille dans les domaines de linformatique linguistique, dInternet et des bases de donnes. Mongueur Perl parisien, il collabore rgulirement avec OReilly. Grald Sdrati a travaill pendant 6 ans chez Bull dans le dveloppement de logiciels concernant ladministration de systmes, rseaux et applications. Actuellement, ses talents sont employs par Xylme, startup issue de chercheurs de lINRIA, qui dveloppe et met en service un moteur de recherche reposant sur XML. Il a commenc pratiquer le dveloppement en Perl il y a prs de cinq ans qui, depuis, est devenu son langage informatique de prdilection ; il en apprcie normment, entre autres, le souci linguistique dans lequel il a t conu. Grald est trs attach la philosophie du Logiciel Libre qui rejoint quelques-unes de ses autres proccupations extra-informatiques comme lengagement auprs dassociations comme Attac qui lutte pour quune autre mondialisation soit possible . Il a galement publi un recueil de pomes, intitul Embryon .

Vous aimerez peut-être aussi