Vous êtes sur la page 1sur 158

Le langage PERL

Table Des Matires

INTRODUCTION

T'

IS, C'EST QUOI PERL? AS PAS ENCORE PERL SUR TA MACHINE?

3 4

1. LES PRINCIPES ESSENTIELS DE PERL

1.2. L

OUR COMMENCER... ES LISTES 1.3. L'INTERPOLATION DE VARIABLE 1.4. LA SELECTION PAR LES PATTERNS : LE MATCHING 1.5. LES TABLEAUX ASSOCIATIFS
1.1. P

7 14 19 20 22

2 . PERL EN DETAIL

23

ES VARIABLES SCALAIRES ES LISTES ET LES TABLEAUX 2.3. STRUCTURES DE CONTROLE 2.4. LES TABLEAUX ASSOCIATIFS 2.5. LES ENTREES/SORTIES 2.6. LES EXPRESSIONS REGULIERES 2.7. LES FONCTIONS 2.8. DIVERSES STRUCTURES DE CONTROLE 2.9. LES MANIPULATEURS DE FICHIERS ET LES TESTS SUR LES FICHIERS 2.10. LES FORMATS 2.11. LES REPERTOIRES 2.12. MANIPULATION DE FICHIERS ET DE REPERTOIRES 2.13. LA GESTION DE PROCESSUS 2.14. AUTRES TRANSFORMATIONS SUR LES DONNEES 2.15. ACCES AUX DONNEES SYSTEME 2.16. MANIPULATION DE BASES DE DONNEES UTILISATEUR 2.17. CONVERTIR DAUTRES LANGAGES EN PERL 2.18. COMPLEMENTS
2.1. L 2.2. L 3. EXEMPLE DAPPLICATION

25 31 37 41 45 49 59 63 67 73 81 85 91 97 103 109 115 117

123

N SYSTEME DE RESERVATION DE VOLS E PROGRAMME PERL 3.3. RESULTATS


3.1. U 3.2. L 4. EXERCICES

125 127 137

143

4.1. E 4.2. S

NONCES OLUTIONS

145 149

ANNEXE : LE GUIDE DE REFERENCE DE PERL

157

juin 1995

Page 1

Le langage PERL

juin 1995

Page 2

Le langage PERL

INTRODUCTION

DIS, C'EST QUOI PERL?

Cr tout dabord pour traiter efficacement du texte grce au matching, Perl s'est dvelopp tant et si bien quil est aujourdhui galement un puissant langage de manipulation de fichiers: renommage, dplacement, modification des droits; et de processus: cration, destruction, communication, contrle de flux. Cest mme un langage rseau, puisquil offre la possibilit de communiquer avec des processus se trouvant sur dautres machines, par lintermdiaire de sockets. Perl permet donc dexcuter dune faon plus concise et lisible des tches ordinairement effectues par un programme en C ou par lun des shells. C ne permet pas de faire tout ce que lon peut faire avec un shell, et vice versa. Perl comble cette lacune: cest une passerelle entre le C et les shells. Perl fonctionne sous divers systmes dexploitation; on sintressera en particulier son fonctionnement sous Unix. Cest un langage simple. Les structures et les types quil emploie sont faciles comprendre et utiliser. Pas besoin de connatre Perl en dtail pour commencer crire de petits programmes sympas. Pas de formule magique, non plus, pour compiler un programme Perl: il sexcute comme un script shell. Cependant, Perl est galement un langage riche, puisquil emprunte ses fonctionnalits au C, aux shells mais aussi sed et awk. Il permet de dvelopper des programmes rapidement. En tant que langage script interprt, il fournit un feedback immdiat si une erreur est dtecte. De plus, un debugger symbolique est intgr, qui comprend n'importe quelle expression Perl puisqu'il est crit en Perl.

Dans ce document, les principes essentiels de Perl dans sa version 4.0 seront tout d'abord rapidement prsents travers quelques exemples simples. Nous verrons ensuite plus en dtail les structures et les types utiliss par ce langage. Puis nous verrons un exemple de programmation en Perl. Enfin, nous complterons cette approche avec quelques exercices et un guide de rfrence, bien pratique pour vrifier rapidement certains points en cas de doute.

juin 1995

Page 3

Le langage PERL

Paralllement , il existe une page man pour Perl: perl(1). Le newsgroup Usenet sur Perl est une source d'informations supplmentaire. Il n'y a pas de question trop bte pour tre pose... il n'y a que des questions trop btes pour qu'on y rponde!

T'AS PAS ENCORE PERL SUR TA MACHINE?

Pas de panique! La gratuit tant la seule monnaie de l'art, Perl est gratuit.

Il est disponible par ftp anonyme sur les machines suivantes: uunet.uu.net tut.cis.ohio-state.edu jpl-devvax.jpl.nasa.gov 192.48.96.2 128.146.8.60 128.149.1.143

Pour ceux qui ne sont pas sur Internet, Perl est disponible par uucp anonyme partir de uunet et de osu-cis. Sur uunet.uu.net, Perl se trouve dans un unique fichier archive: gnu/perl-3.0.41.tar.Z. Sur jpldevvax.jpl.nasa.gov, il est dans le rpertoire pub/perl.3.0; sur tut.cic.ohio-state.edu, il est dans perl/3.0 (bientt ce sera 4.0 pour les deux).

juin 1995

Page 4

Le langage PERL

1. LES PRINCIPES ESSENTIELS DE PERL

juin 1995

Page 5

Le langage PERL

juin 1995

Page 6

Le langage PERL

1.1. POUR COMMENCER...


Perl est facile apprendre et simple d'utilisation. Il n'y a pas grand chose dire avant de dire effectivement ce que l'on veut dire. Par exemple, il n'y a aucune dclaration effectuer avant d'crire du code.

1.1.1. Les manipulateurs de fichiers (filehandle)

Voici un exemple de script Perl simple:

print "Donnez un nombre: \n"; $nombre = <STDIN>; print "Nombre lu : $nombre \n";
Ce script permet de lire une entre de l'utilisateur avec un retour d'information. La variable

$nombre

reoit ce que l'utilisateur vient de taper; en effet, le symbole

<STDIN>

indique

simplement qu'il faut lire la ligne courante de l'entre standard. La commande print possde un paramtre optionnel indiquant la redirection de la sortie;

STDOUT est la sortie par dfaut. On aurait aussi bien pu crire: print STDOUT "Nombre lu : $nombre\n";
Ainsi

STDIN

est le nom de l'entre,

STDOUT

celui de la sortie et

STDERR

celui du fichier

erreur.

STDIN, STDOUT, STDERR

sont des manipulateurs de fichier, ou filehandles, qui existent en

permanence dans une application Perl. Un filehandle est un nom que l'on donne un fichier, un pipe ou une socket afin de pouvoir y raliser facilement des entres/sorties. Pour crer un filehandle et l'associer un fichier, on utilise la fonction open. Exemples:

open( MANIPULE, "NomDeMonFichier"); open( MANIPULE, "> nomfic"); open( MANIPULE, "| commande de sortie du pipe"); MANIPULE
donne alors accs au fichier ou au pipe auquel il a t associ jusqu' ce que cette

association soit ferme ou que l'on effectue un nouvel open sur ce filehandle.

STDIN,

STDOUT, STDERR peuvent tre ferms et rouverts.

juin 1995

Page 7

Le langage PERL

1.1.2. Les variables

Dans notre premier exemple, nous n'avons donc pas eu dclarer la variable effet, le symbole $ indique Perl que Il y a d'autres variables:

$nombre.

En

$nombre

peut contenir une variable: un nombre ou une

chane de caractres. Nous appellerons cela une variable scalaire.

VARIABLE $VARIABLE @VARIABLE %VARIABLE &VARIABLE *VARIABLE

un filehandle une variable scalaire un tableau index par des nombres un tableau index par des chanes de caractres une subroutine tout ce qui s'appelle VARIABLE

On peut affecter des variables, modifier leur valeur; exemples:

$nombre = 4278; $chaine = "coucou"; $commande = `who | grep toto`;


En Perl, un commentaire est prcd par

# un entier # une chane de caractres # une commande

#. ;.

Une ligne d'instruction Perl se termine toujours par

Si une variable n'est pas initialise par l'utilisateur, elle est automatiquement initialise la valeur nulle (0). Une variable est value comme un nombre, une chane, un boolen ou un lment de tableau en fonction du contexte. Perl Ainsi: effectue la conversion automatiquement.

$magic = "45"; print $magic+1, "\n";


Le rsultat de l'excution de ce script est "46".

1.1.3. Comment lancer un script Perl?

Il y a plusieurs manires pour lancer votre premier script!

En ligne :

> perl

-e

'print "coucou \n" ; '

juin 1995

Page 8

Le langage PERL

Si on utilise un fichier pour stocker le script:

> perl nomfic

Si votre systme supporte tte du script l'incantation:

#!,

vous pouvez spcifier le nom de linterprteur en mettant en

#!/usr/bin/perl
Le fichier contenant le script doit tre excutable (chmod script, on peut ensuite taper:

u+x nomfic);

pour excuter le

> nomfic

En dernier recours, on peut remplacer l'incantation ci-dessus par la ligne:

eval

'/usr/bin/perl

-S

$0

${ 1 + "$@" }'

if

0 ;

1.1.4. Une variable sympa : $_

La variable en awk).

$_

est affecte par un grand nombre d'oprations.

Elle permet daccder la ligne courante d'un fichier que l'on est en train de consulter (cf. $0

1.1.5. Comment exprimer des conditions?

Perl dispose d'une boucle while dont le corps s'excute tant que la condition est vraie. Exemple:

!#/usr/bin/perl $credit = 10; while ($credit != 0) { print "Joffre un caf Rouv ! \n $credit - = 2.5; } print " Jai plus de sous! \n ";

";

juin 1995

Page 9

Le langage PERL

La condition

$credit!=0

est vraie tant que

$credit

ne vaut pas 0. Loprateur

!=

(diffrent) compare deux valeurs numriques et retourne vrai si la premire est diffrente de la seconde; sinon il retourne faux. Perl na pas de type boolen; une valeur est vraie si elle est diffrente de 0 ou "0" ou ''''

(chane vide). Les oprateurs relationnels tels que ==, !=, <, ... retournent 1 pour vrai, 0 pour
faux. Dautres oprateurs peuvent retourner dautres valeurs non nulles pour vrai et la chane

vide pour faux. Donc tout ce qui a une valeur peut tre utilis comme condition dun while; par exemple, une affectation, puisquelle retourne la valeur finale de la variable affecte:

!#/usr/bin/perl while ( $_ = <ARGV>) { print $_; }


Ce script permet de faire afficher les unes la suite des autres toutes les lignes des fichiers passs en argument dans la ligne de commande. Cest lquivalent de la commande shell cat.

ARGV est un filehandle; <ARGV> est lentre.


Si ce script est enregistr sous le nom equivcat et que toto, tutu et titi sont des fichiers, la ligne de commande:

> equivcat

toto

tutu

titi $_ et son impression sur la sortie $_ et affiche. Et ainsi de suite

a pour rsultat le stockage de la premire ligne de toto dans standard. Puis la deuxime ligne de toto est range dans

jusqu puisement de toto. Lopration est alors ritre avec tutu, puis avec titi. Le script prcdent peut encore tre simplifi:

!#/usr/bin/perl while ( <>) { print ; }


On obtient le mme rsultat que prcdemment. En effet,

<ARGV> et <>

reprsentent la mme

chose; de plus, un symbole dsignant une entre, utilis seul dans une condition de boucle

while, affecte automatiquement la variable $_; print, le contenu de $_ est affich par dfaut.

enfin, si lon ne prcise pas de paramtre

Lautre faon dexprimer une condition en Perl est dutiliser if. Lexemple suivant est lquivalent du grep du shell:

!#/usr/bin/perl $pattern = shift( @ARGV ); while (<>) { if ( /$pattern/) { print ; } }

juin 1995

Page 10

Le langage PERL

Le premier argument pass la commande est le pattern rechercher; il est stock dans la variable

$pattern.

Le reste des arguments est considr comme des noms de fichiers; cest

dans leur contenu que le pattern va tre recherch. Les lignes dans lesquelles reconnu sont ensuite affiches. Que se passe-t-il si la recherche est effectue dans une ligne vide?

$pattern

a t

Une ligne vide contient en fait le caractre ''\n'', dont la valeur est vrai; elle n'est donc pas vraiment vide! On continue alors la recherche dans la ligne suivante. Toute ligne se termine d'ailleurs par ''\n''. La fonction

print

n'effectue pas de retour la ligne automatique; on est donc oblig de

spcifier si on le dsire.

1.1.6. La vrit sur les tests

Les oprateurs de test ne sont pas les mmes suivant que l'on compare des valeurs numriques ou des chanes de caractres. Ces oprateurs retournent 1 si la comparaison est vraie, 0 sinon.

Oprateur de test sur les nombres == != > >= < <= <=>

Oprateur de test sur les chanes eq ne gt ge lt le cmp

Signification gal diffrent suprieur suprieur ou gal infrieur infrieur ou gal diffrent, avec retour du signe

Il faut donc faire attention quand on crit un test; exemple:

$a $b if if

= = ( (

"5"; "10"; $a < $b ) $a gt $b )

{ print " $a < $b \n";} { print " $a gt $b \n";}

Le rsultat de ce script est: 5 < 10 5 gt 10 # comparaison numrique # car la valeur ASCII de

1 est plus petite que celle de 5

juin 1995

Page 11

Le langage PERL

1.1.7. Les oprateurs scalaires

Voici une liste doprateurs, parmi les plus importants:

Slection par les patterns

$a = /pat/ $a = s/p/m/ $a = tr/a-z/A-Z/

matching; retourne vrai si substitution des

$a contient le pattern pat p dans $a par des m

conversion des minuscules en majuscules

Oprateurs logiques

$a && $b $a || $b ! $a

et logique ou logique ngation

Oprateurs arithmtiques

$a + $b $a - $b $a * $b $a / $b $a % $b $a ** $b ++ $a, $a ++ -- $a, $a -rand($a)

addition soustraction multiplication division modulo

$a exposant $b
incrmentation dcrmentation tire alatoirement une valeur entre 0 et

$a

Oprateurs sur les chanes de caractres

$a . $b $a x $b substr( $a, $i, $l) index( $a, $b)

concatnation

$a rpte $b fois
extraction dune sous chane de

$a commenant la position $i et ayant pour longueur $l position de la chane $b dans $a

Oprateurs pour laffectation

$a $a $a $a

= $b +=$b -=$b .=$b

affectation addition et affectation soustraction et affectation concatnation et affectation

Oprations sur les fichiers

-r -w -d -f -T

$a $a $a $a $a

retourne vrai si

$a est autoris en lecture retourne vrai si $a est autoris en criture retourne vrai si $a est un rpertoire retourne vrai si $a est un fichier rgulier retourne vrai si $a est un fichier texte

juin 1995

Page 12

Le langage PERL

Les oprateurs && et || sont des oprateurs court-circuit. Cela signifie que si lvaluation de la partie gauche est suffisante pour dcider de la valeur finale de lexpression, la partie droite nest pas value. Il y a bien sr dautres oprateurs, mais ceux-ci suffisent pour commencer!

1.1.8. Complments

Voici un exemple qui reprend ce que nous avons vu jusquici, plus quelques petites choses nouvelles:

#!/usr/bin/perl open(FIND," find . -print |")||die"find na pas dmarr:$!\ n"; FILE: while ( $nomfic = <FIND>) { chop $nomfic; next FILE unless -T $nomfic; if ( ! open( FICTEXT, $nomfic ) ) { print STDERR "Ouverture de $nomfic impossible "; next FILE; } while ( <FICTEXT> ) { foreach $mot ( @ARGV ) { if ( index($_, $mot) >= 0) { print $nomfic, " \n "; next FILE; } } } }
Le but de ce programme est de retrouver, dans les fichiers texte du rpertoire courant, les arguments passs lors de lappel du script.

$! contient le message derreur produit par le systme lors de lchec douverture FIND. Il est possible d'tiqueter une boucle; le label FILE permet next de faire appel de nouveau la boucle. Loprateur next indique la boucle effectuer en spcifiant son tiquette. foreach est une structure de boucle puisquelle permet $mot de prendre pour valeur les lments de @ARGV, successivement. La fonction index retourne la position de $mot dans la ligne courante sil a t trouv, -1
La variable du filehandle sinon.

juin 1995

Page 13

Le langage PERL

1.2. LES LISTES


En plus des oprateurs scalaires, Perl dispose de nombreux oprateurs travaillant sur les listes. La force de Perl, c'est de pouvoir agir sur plusieurs objets en une seule ligne de commande.

1.2.1. Quest-ce qu'une liste?

Une liste est tout simplement un ensemble ordonn de scalaires. On peut donc avoir des listes de nombres, de chanes de caractres, ou un mlange des deux. Une liste portant un nom est appele tableau. Comme une liste est ordonne, on peut donc parler de son premier lment, de son deuxime lment ..., et de son dernier lment. Les lments d'une liste sont donc accessibles sparment. Le premier lment porte le numro 0, le second le numro 1, etc. Lorsqu'on tape une commande Perl, ses arguments sont rangs dans le tableau

@ARGV. Donc

@ARGV[0]
est le premier argument et

@ARGV[$#ARGV]
est le dernier, sachant que

$#ARGV donne accs la position du dernier lment.

L'oprateur range, not .. , produit une liste de valeurs comprises entre les valeurs des oprandes gauche et droit. Par exemple, le script suivant permet de faire afficher tous les arguments de la commande faisant appel lui :

#!/usr/bin/perl foreach $i (0..$#ARGV) { print $ARGV[$i]; if ($i == $#ARGV) { print "\n"; } else { print " " ; } }

juin 1995

Page 14

Le langage PERL

L'oprateur de construction d'une liste est la virgule, sparateur des diffrents lments. Perl s'attend en gnral trouver une liste entre parenthses; par exemple :

@speinf = ('seb','cricri','pascal','xav','gilles','hugo','sissou'); @chiffre = ( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); # mme chose que ( 1..9 ) @etudiant = ( $no_etudiant, $nom, $prenom, $adresse );
Les parenthses sont ncessaires ici; en effet, la virgule est moins prioritaire que l'affectation.

Une liste parenthse de scalaires peut tre affecte directement par une liste de valeurs, comme le montrent les exemples suivants :

( $no_compte, $debit, $credit ) = ( 14578963, 2000, 0 ); ($nom,$passwd,$uid,$gid,$gcos,$home,$shell)=split(/:/,<PASSWD>); ( $tab[0], $tab[1], $tab[2], $tab[3] ) = @speinf;
split cre une liste de chanes de caractres en scindant la ligne courante du fichier que

PASSWD

permet de manipuler, chaque occurrence des : . Le troisime exemple montre que

l'on peut affecter une liste partir d'un tableau, quelque soit la taille de celui-ci. Si le tableau est trop grand, les dernires valeurs ne sont pas prises en compte. S'il est trop petit, les valeurs non affectes de la liste demeurent indfinies.

La taille d'un tableau peut tre modifie: des lments peuvent tre ajouts, supprims. La fonction splice permet de manipuler ainsi des tableaux. Sa syntaxe est :

splice ( ARRAY, INDEX, LONGUEUR [, LIST] ) ARRAY


est le tableau auquel s'applique splice.

INDEX

est le premier lment de

ARRAY la liste ventuelle dont les lments seront insrs dans ARRAY
Un exemple d'utilisation :

va disparatre.

LONGUEUR

est le nombre d'lments de

qui vont disparatre.

ARRAY qui LIST est partir de la position INDEX.

@arbre = ( 'sapin', 'pica', 'chne', 'peuplier', 'htre' ); @modif = splice ( @arbre, 1, 3, 'boulot', 'palmier' );
Le rsultat de cette fonction est une modification du tableau

@arbre; on a maintenant :

@arbre = ( 'sapin', 'boulot', 'palmier', 'htre' ); splice retourne la liste des lments de @arbre qu'elle a modifis : @modif = ( 'pica', 'chne', 'peuplier' );

juin 1995

Page 15

Le langage PERL

Les fonctions suivantes sont utiles et simples pour travailler avec des listes:

$a = shift(@tab); $b = pop(@tab); unshift(@tab, $a ); push(@tab, $b );

# $a contient le premier lment de @tab; @tab a perdu cet lment # $a contient le dernier lment de @tab; @tab a perdu cet lment # insertion de $a en tte de @tab # insertion de $b en fin de @tab

1.2.2. S'il vous plat! On ne s'endort pas!

Il y a deux choses importantes retenir sur les listes. Premirement, il est important pour certains oprateurs de savoir s'ils sont valus comme un lment d'une liste. Ils retournent alors l'intrieur d'une liste des valeurs diffrentes de celles qu'ils auraient retournes ailleurs. Prenons l'exemple de l'oprateur d'entre

<> :

$a

= <STDIN>;

@tab = <STDIN>;

# $a contient la ligne courante de l'entre standard # @tab contient toutes les lignes qu'il reste dans l'entre standard

Deuximement, une liste (la structure syntaxique) concatne toujours ses valeurs scalaires et ses tableaux, comme s'il s'agissait d'une seule et longue liste. Chaque lment de la liste est valu comme une expression dans un contexte de tableau, et s'il produit une liste, les valeurs de cette liste sont ajoutes la liste de dpart, comme s'elles avaient t spcifies sparment. Un exemple, pour claircir tout :

@a = ( 1 .. 3); @b = (78,45,@a,92); @a = (); @b = ( 0, @a, 4 );


Comme

# quivaut @b = (78,45,1,2,3,92) # liste vide # quivaut @b = ( 0, 4 )

@a

est valu dans un contexte de tableau, il renvoie la liste qu'il contient. S'il tait

valu dans un contexte scalaire,

@a renverrait le nombre d'lments qu'il comporte. Exemple:

while (@a) { #code }

# la boucle est effectue autant de fois que @a contient d'lments.

juin 1995

Page 16

Le langage PERL

1.2.3. Quelques oprateurs usuels sur les listes

On utilise le tableau suivant comme argument :

@speinf = ('seb','cricri','pascal','xav','gilles','hugo','sissou');
Oprations Rsultats

$speinf[2] @speinf[3, 6] sort @speinf

('pascal') ('xav','sissou') ('cricri','gilles','hugo','pascal', 'seb','sissou' ,'xav') ('sissou','hugo','gilles','xav', 'pascal', 'cricri', 'seb')


('xav','sissou','seb','pascal','hugo', 'gilles','cricri')

reverse @speinf

reverse sort @speinf

grep(/ill/, @speinf) 3..7 reverse 3..7 @speinf[0..2]

('gilles') ( 3, 4, 5, 6, 7 ) ( 7, 6, 5, 4, 3 ) ('seb', 'cricri', 'pascal')

1.2.4. Et on fait quoi avec les listes?

Forts de tout ce que nous venons d'apprendre, nous allons passer un exemple plus pratique d'utilisation des listes. Imaginons qu'on veuille rcuprer les noms de tous les fichiers texte de notre compte. Il suffit de faire appel au script suivant, grce la ligne de commande:

> nom_du_script *
* donne les noms de tous les fichiers et rpertoires du compte.

juin 1995

Page 17

Le langage PERL

#!/usr/bin/perl while (@ARGV) { $fichier = shift @ARGV; push(@fichier_texte, $fichier) if -T $fichier; } print join(' ', @fichier_texte), "\n";
Dans le

while, @ARGV

est valu dans un contexte scalaire. Il retourne donc le nombre

d'arguments passs au script (ici, le nombre de fichiers et rpertoires du compte). La variable

$fichier reoit le premier lment de la liste @ARGV. @ARGV perd cet lment. Si $fichier est effectivement un fichier texte (test avec -T), alors il est rang la fin de la liste @fichier_texte.
La fonction join permet ensuite de constituer une chane de caractres o les lments de

@fichier_texte sont spars par un espace.


Autre possibilit :

#!/usr/bin/perl print join(' ', grep(-T, @ARGV)), "\n";


La fonction grep de Perl est plus puissante que la fonction d'Unix. En effet, elle accepte non seulement les expressions rgulires comme critre, mais aussi les expressions Perl. Si on avait voulu la liste des fichiers texte classs par ordre alphabtique, on aurait crit :

#!/usr/bin/perl print join(' ', sort grep(-T, @ARGV)), "\n";

juin 1995

Page 18

Le langage PERL

1.3. L'INTERPOLATION DE VARIABLE


Considrons les lignes de code suivantes :

print "$var \n"; print "@ARGV \n";


Ces commandes interpolent respectivement le scalaire chane de caractres (par dfaut, les lments de

$var

et le tableau

@ARGV

en une

@ARGV seront spars par un espace).

Attention, l'interpolation de variable n'a pas lieu entre quotes simples. Pour mieux comprendre, prenons un exemple; soit le script afficharg, auquel on passe les arguments suivants:

> afficharg pascal gilles xav


Si dans afficharg on utilise les commandes suivantes, on obtient les rsultats suivants:

print "@ARGV"; print @ARGV; print '@ARGV\n';

pascal gilles xav pascalgillesxav @ARGV\n

L'interpolation de variable est galement excute l'intrieur de backquotes, mais elle s'accompagne de l'excution de la chane contenue dans les backquotes comme d'une commande dont le rsultat peut tre affect:

$lignes = `wc -l $nomfic`;


Si les caractres suivant le nom d'une variable interpoler peuvent prter confusion, il faut dlimiter ce nom avec des accolades; exemple:

$fred = "pay"; $fredday = "wrong!"; $barney = "It's $fredday"; $barney = "It's ${fred}day";

# "It's wrong!" # "It's payday"

juin 1995

Page 19

Le langage PERL

1.4. LA SELECTION PAR LES PATTERNS : LE MATCHING


Perl dispose de deux oprateurs de slection par les patterns:

//, oprateur de slection; il recherche le pattern entre // dans une chane de caractres et retourne vrai ou faux suivant que le pattern a t trouv ou non. s///, oprateur de substitution; il fait la mme chose, mais, en plus, remplace la partie matche de la chane par ce qui se trouve entre les deux derniers dlimiteurs.

Les patterns sont spcifis en utilisant les expressions rgulires. En voici quelques exemples: . [a-z0-9] [^a-z0-9] \d | \D \w | \W \s | \S \n | \r | \t | \f | \b \0 | \000 \nnn \metachar (abc) \1 \2 | \3
x? x* x+ x{m, n}

matche n'importe quel caractre sauf newline matche un caractre de cet ensemble matche tout caractre ne figurant pas dans cet ensemble matche un chiffre | matche tout sauf un chiffre matche un caractre alphanumrique | contraire matche un caractre d'espacement | contraire matchent respectivement newline, return, tab, formfeed, backspace ( l'intrieur de crochets seulement) matchent le caractre nul matche le caractre ASCII ayant cette valeur octale matche le caractre lui-mme (\| , \. , \*, ...) enregistre la slection matche le premier pattern contenu dans la slection matche le deuxime | troisime pattern contenu dans la slection matche 0 ou 1 x o x est un des motifs ci-dessus matche 0 ou plusieurs x matche 1 ou plusieurs x matche au moins m x et au plus n matche tous les a, b, c matche ok ou coucou ou he matche un dlimiteur de mots | contraire donne accs au dbut de ligne ou de chane donne accs la fin de ligne ou de chane

abc ok | coucou | he \b | \B ^ $

Lorsque l'on fait de la slection par pattern, il y a galement des variables magiques qui sont affectes lorsque le matching russit:

$&, contient le pattern recherch $`, contient tout ce qu'il y a avant la slection $', contient tout ce qu'il y a aprs la slection $1, $2, ..., $9 contiennent les patterns matchs

juin 1995

Page 20

Le langage PERL

Un exemple de matching en Perl; imaginons que l'on dispose d'un fichier dont la ligne courante (contenue dans

$_) est :

Date : 3 juin 1995 13:26:00 GMT


Cette ligne peut tre dcompose comme suit:

/^Date : (\d+)(\w+)(\d+)(\d+):(\d+):(\d+)(.*)$/; $jour = $1; # rcupre "3" $mois = $2; # rcupre "juin" $annee = $3; # rcupre "1995" $heure = $4; # rcupre "13" $minute = $5; # rcupre "26" $seconde = $6; # rcupre "00" $reference = $7; # rcupre "GMT"
Si on avait fait les regroupements suivants:

/^Date : ((\d+)(\w+)(\d+))((\d+):(\d+):(\d+))(.*)$/
on aurait la dcomposition:

$date = $1; $jour = $2; $mois = $3; $annee = $4; $temps = $5; $heure = $6; $minute = $7; $seconde = $8; $reference = $9;

# rcupre "3 juin 1995"

# rcupre "13:26:00"

juin 1995

Page 21

Le langage PERL

1.5. LES TABLEAUX ASSOCIATIFS


On peut dire que c'est la partie la plus importante de cette prsentation de Perl, puisque c'est la proprit principale de ce langage. Les tableaux associatifs permettent de mettre en place des structures rcursives telles que les arbres. Un tableau associatif est une liste constitue de paires de valeurs indexes par la premire valeur de chaque paire, appele cl. Les cls sont ranges dans une table de hachage, ce qui permet de consulter rapidement le tableau auquel elles sont associes, quelque soit sa taille. Un tableau associatif est dclar par le symbole %. Exemple:

%caracteristiques= (

'xav', 'discret', 'cricri', 'marrant', 'seb', 'rleur', 'gilles', 'emport', 'pascal', 'cultiv', 'hugo', 'dlire', 'sissou', 'bavarde' );

On utilise donc la mme notation que pour les tableaux simples. Lors de l'valuation de

%caracteristiques dans un contexte de tableau, on n'obtiendra pas

forcment les paires dans cet ordre (cela dpend de la fonction de hachage). Pour accder un lment d'un tableau associatif, on utilise les accolades et la cl:

$caract = $caracteristiques{'xav'}; $home = $ENV{'HOME'}; $SIG{'UP'} = 'IGNORE';

# $caract prend la valeur 'discret'

Les deux derniers tableaux associatifs cits font rfrence deux tableaux propres Perl:

%ENV permet de consulter et fixer les variables d'environnement de l'utilisateur; %SIG permet de fixer les valeurs des signaux systme.

Les tableaux associatifs permettent de lier un ensemble de chanes un autre ensemble de chanes. Ainsi, ils se rapprochent des pointeurs disponibles dans les autres langages. La fonction keys permet d'accder la liste des cls d'un tableau associatif. Cette fonction est souvent utilise comme suit:

foreach $key ( sort keys( %tab_nom ) ) {... }


Les tableaux associatifs sont des structures puissantes qui permettent des consultations rapides et qui ncessitent peu de code.

juin 1995

Page 22

Le langage PERL

2 . PERL EN DETAIL

juin 1995

Page 23

Le langage PERL

juin 1995

Page 24

Le langage PERL

2.1. LES VARIABLES SCALAIRES


Nous avons vu plus haut que pour Perl les variables scalaires sont des nombres ou des chanes de caractres. Des oprateurs permettent de les manipuler: elles peuvent tre affectes, lues et crites dans des fichiers.

2.1.1. Les nombres

Une variable scalaire peut contenir un entier ou un dcimal. De toute faon, Perl utilise la mme reprsentation pour les deux: flottant double prcision (lquivalent de double en C). Un littral est la faon dont une valeur est reprsente dans le texte dun programme Perl. Perl accepte tous les littraux flottants disponibles en C. Exemples:

1.435 +3.78 -23e-4 45.7E7


Les littraux entiers sont reprsents simplement par:

45 -67
Ils ne doivent pas commencer par 0; en effet, Perl reconnat les littraux octaux et hexadcimaux, dont les reprsentations commencent respectivement par 0 et 0x ou 0X. Les chiffres hexadcimaux A F reprsentent les valeurs 10 15. Exemples:

0377 -0xff

# 377 octal, quivaut 255 en dcimal # -FF hexadcimal, quivaut 255 en dcimal

juin 1995

Page 25

Le langage PERL

2.1.2. Les chanes de caractres

Ce sont des suites de caractres pris dans lensemble des 256 caractres cods sur 8 bits. La plus petite chane est la chane nulle; la plus longue remplirait toute la mmoire disponible. Comme les nombres, les chanes ont une reprsentation littrale; il y en a deux en fait: entre simples quotes et entre doubles quotes.

Les simples quotes ne font pas partie de la chane de caractres quelles encadrent; elles sont l pour indiquer Perl le dbut et la fin de la chane. Une chane entre simples quotes peut contenir nimporte quel caractre; il y a cependant deux exceptions: pour avoir une simple quote ou un antislash dans une chane entre simples quotes, ceux-ci doivent tre prcds par un antislash. Exemples:

'coucou' # 6 caractres: c, o, u, c, o, u 'c\'est pas gagn! ' # cest pas gagn 'A bientt \n' # A bientt \n
\n entre simples quotes nest pas interprt comme un retour la ligne mais comme deux caractres, \ et n.

Une chane entre doubles quotes est lquivalent dune chane de caractres en C. Lantislash permet donc de spcifier certains caractres de contrle ou tout caractre par ses reprsentations octale et hexadcimale. Exemples:

"coucou \n" "nouveau \177"

# coucou, un espace et un retour la ligne # nouveau , un espace et le caractre delete

Un antislash peut prcder de nombreux caractres pour signifier diffrentes choses, comme le montre la table suivante: \n \r \t \f \b \v \a \e \007 \x7f \cC \\ \l \L \u \U newline return tab formfeed backspace vertical tab bell escape nimporte quelle valeur octale ASCII (ici, 007=bell) nimporte quelle valeur hexadcimale ASCII (ici, 7f=delete) nimporte quel caractre de contrle (ici, control C) antislash mettre la lettre suivante en minuscule mettre toutes les lettres suivantes en minuscule, jusqu \E mettre la lettre suivante en majuscule mettre toutes les lettre suivantes en majuscule, jusqu \E

juin 1995

Page 26

Le langage PERL

\E \"

permet dachever \L et \U double quote

A lintrieur des doubles quotes, linterpolation de variable peut avoir lieu, comme nous lavons annonc au paragraphe 1.3. Pour empcher la substitution, on peut utiliser les simples quotes ou faire prcder le caractre $ par un antislash; exemple:

$a = "Seb"; $b = "Salut " . '$a'; $b = "Salut \$a";

# $b contient "Salut $a" # idem

2.1.3. Les oprateurs

Une liste doprateurs sur les variables scalaires est disponible au paragraphe 1.1.7. Perl dispose des oprateurs arithmtiques que lon trouve gnralement dans des langages tels que le C. Mais il possde galement l'oprateur d'exponentiation ** :

3 ** 7

# 3 la puissance 7

On trouve aussi des oprateurs sur les chanes de caractres:

loprateur . , qui permet la concatnation de deux chanes; exemple:

"hello " . "world";

# quivaut "hello word"

les oprateurs de comparaison de chanes de caractres; ils sont numrs dans le chapitre 1.1.6. l'oprateur x, qui permet de rpter une chane autant de fois que l'indique la valeur de l'oprande droit; exemple:

"coucou" x 4 "eh" x (3+1)


Les parenthses permettent

# quivaut "coucoucoucoucoucoucoucou" # quivaut "eh" x 4, soit "eheheheh"


l'valuation de l'expression qu'elles renferment, avant

l'excution de la rptition. La partie entire de l'oprande droit est calcule et utilise pour la rptition. La multiplication et la division sont prioritaires par rapport l'addition et la soustraction. L'usage de parenthses permet de modifier les priorits.

juin 1995

Page 27

Le langage PERL

Si

une

chane

est

utilise

comme

oprande

d'un

oprateur

numrique,

Perl

effectue

automatiquement la conversion, de mme si une valeur numrique a t utilise l o une chane tait attendue. Pour donner une valeur une variable, on utilise l'affectation:

$a = 3; $b = $b * 2;
Une affectation scalaire a une valeur; cette valeur est le nombre affect: 3. C'est pratique pour copier la mme valeur dans plusieurs variables:

$a = 3 a pour valeur

$b = 4 + ($a = 3); $c = $d = 5;

# $a contient 3 et $b contient 7 # $c et $d contiennent 5

Perl dispose d'oprateurs d'affectation binaires:

$a += 3; $b *= $a; $str .= " ";

quivaut quivaut quivaut

$a = $a + 3 ; $b = $b * $a ; $str = $str . " ";

Perl dispose aussi de l'auto-incrmentation et de l'auto-dcrmentation, qui peuvent tre utilises sous forme de prfixe ou de suffixe:

++$a; $d = $c = 17; $e = ++ $d; $e = $c --;

quivaut

$a += 1;

# $d et $e valent tous les deux 18 # $e vaut 17 et $c vaut 16

2.1.4. Les noms de variables scalaires

Le nom d'une variable est constant tout au long d'un programme alors que la valeur qu'elle contient varie. Les noms de variables scalaires commencent par $, peuvent contenir des lettres, des chiffres ou des underscores et tre aussi longs qu'on veut. Une diffrence est faite entre minuscule et majuscule:

$A et $a ne font pas rfrence la mme variable.

juin 1995

Page 28

Le langage PERL

2.1.5. L'oprateur chop()

Cet oprateur prend comme unique paramtre le nom d'une variable, retire le dernier caractre de la chane laquelle cette variable est gale ou quivalente et retourne le caractre limin. Exemple:

$var = "bonjour a tous"; $lettre = chop($var); # $var contient maintenant "bonjour a tou"; $lettre contient "s"

2.1.6. La variable scalaire <STDIN>

Lorsque

<STDIN>

est utilise l o une valeur scalaire est attendue, Perl lit la ligne courante

de l'entre standard (jusqu'au prochain newline) et utilise cette chane pour donner une valeur

<STDIN>. S'il n'y a rien lire, le programme Perl s'arrte et attend qu'une valeur soit saisie. La valeur chane de <STDIN> se termine donc par un \n. L'oprateur chop()permet de

l'liminer. Un exemple d'utilisation:

print "Donnez un nombre :"; $a = <STDIN>; chop($a); print "Votre nombre : $a";

2.1.7. L'oprateur de sortie print()

L'oprateur

print

permet d'obtenir sur la sortie standard (par dfaut) la valeur scalaire du

paramtre qu'on lui passe; exemple:

print "coucou";

# coucou s'affiche l'cran

juin 1995

Page 29

Le langage PERL

2.1.8. La valeur undef

Si une variable est utilise avant d'avoir t initialise, ce n'est pas grave; les variables non initialises ont pour valeur undef, qui est un 0 quand on parle de nombres ou la chane vide quand on parle de chanes de caractres. De nombreux oprateurs retournent la valeur undef lorsque les paramtres qu'on leur a pass n'ont pas de sens.

<STDIN>
undef.

retourne normalement la ligne courante de l'entre; s'il n'y a rien lire, il retourne

juin 1995

Page 30

Le langage PERL

2.2. LES LISTES ET LES TABLEAUX


Un tableau est une liste ordonne de scalaires. Le nombre dlments dun tableau est illimit. Le plus petit tableau na pas dlment; le plus grand remplirait toute la mmoire disponible.

2.2.1. Reprsentation littrale

Un tableau est donc un ensemble de scalaires spars par des virgules et encadr par des parenthses. Ces lments ne sont pas forcment des constantes: ils peuvent tre des expressions qui seront values chaque utilisation. Exemples de tableaux:

( 1, 2, 3 ) ("coucou", 4.5 ) () # tableau vide


Il existe galement un oprateur de construction de liste: range, not .. . Il permet de crer une liste dont les valeurs sont comprises entre loprande gauche et loprande droit et sont obtenues partir de loprande gauche par incrmentations successives de pas 1; exemples:

( 1..3 ) ( 3.3 .. 6.1 )

# quivaut la liste (1, 2, 3 ) # quivaut la liste ( 3.3, 4.3, 5.3 )

2.2.2. Les variables tableaux

Un nom de tableau vrifie les mmes proprits quun nom de scalaire, si ce nest quil commence par le caractre @ . La valeur dun tableau qui na pas encore t initialis est la liste vide (). Exemples:

@tableau @Tableau @un_tableau

# diffrent de @tableau

juin 1995

Page 31

Le langage PERL

2.2.3. Laffectation

Elle permet de donner une valeur une variable tableau; exemples:

@tab = ( 1, 2, 3 ); @chiffres = 6;
Dans ce deuxime exemple, le scalaire 6 devient lunique lment du tableau automatiquement par ses lments; exemple:

@chiffres.

Le nom dun tableau peut apparatre lintrieur dune liste. Perl le remplace alors

@chiffres = ( @tab, 6 );

# quivaut @chiffres = (1,2,3,6)

Si un tableau contient uniquement des rfrences des variables, il peut tre trait comme une variable. En particulier, il peut constituer la partie gauche d'une affectation; exemples:

( $a, $b, $c ) = ( 1, 2, 3 ); ( $d, @tab ) = ( $a, $b, $c );

# $a contient 1, $b 2, $c 3 # $d a la mme valeur que $a, @tab contient( $b, $c )

Si le nombre d'lments affects ne correspond pas au nombre de variables, les valeurs en trop ( droite de l'affectation) sont limines et les variables non affectes ( gauche de l'affectation) reoivent la valeur undef. Si une variable scalaire est affecte par un tableau, elle reoit en fait le nombre d'lments de ce tableau; exemples:

@tab = ( 1, 2, 3 ); $a = @tab; # $a contient la valeur 3 ($a) = @tab; # $a contient le premier lment de @tab : 1
Le troisime exemple est une affectation entre tableaux, alors que le deuxime est une affectation entre scalaires. La valeur d'une affectation entre tableaux est un tableau, ce qui permet d'affecter des tableaux en cascade; exemples:

@tab = ( @chiffres = ( 1, 2, 3 ) ); # @tab et @chiffres contiennent tous les deux ( 1, 2, 3 ) @tab = @chiffres = ( 1, 2, 3 ); # mme chose

juin 1995

Page 32

Le langage PERL

2.2.4. L'accs aux lments

Les lments d'un tableau sont reprs par des entiers; le premier lment est index par 0. Ils sont accds par des variables scalaires ou des tableaux; exemples:

@tab = ( 1, 2, 3 ); $a = $tab[0]; $b = $tab[ $a ]; @tab2 = @tab[0, 2];

# $a contient le soit 1 # $b contient le @tab, soit 2 # @tab2 contient lment de @tab,

premier lment de @tab, deuxime lment de le premier et le dernier soit( 1, 3 )

Dans le dernier exemple, on accde une liste d'lments du mme tableau et on cre donc un tableau, d'o le signe @. Si on tente d'accder un lment dont l'indice est suprieur au nombre d'lments du tableau, la valeur undef est retourne; exemple:

@tab = ( 1, 2, 3 ); $val = $tab[7];

# $val contient undef

Si on affecte un lment dont l'indice est suprieur au nombre d'lments du tableau, celui-ci est tendu automatiquement, et les valeurs non affectes reoivent la valeur undef; exemple:

@tab = ( 1, 2, 3 ); $tab[5] = 6; # @tab contient maintenant ( 1, 2, 3, undef, undef, 6 )


Enfin, la variable

$#tab permet d'accder l'indice du dernier lment du tableau @tab.

2.2.5. Les oprateurs push() et pop()

push permet d'ajouter un lment ou une liste d'lments la fin d'un tableau. pop permet d'liminer le dernier lment d'un tableau; exemples:

push ( @tab, $a ); push ( @tab, 4, 5, 6 ); $b = pop ( @tab );

# @tab = (@tab, $a) # @tab = (@tab, 4, 5, 6) # @tab = (1, 2, 3, 4, 5) et $b = 6

pop() renvoie la valeur undef si la liste qu'on lui a passe en paramtre est vide.

juin 1995

Page 33

Le langage PERL

2.2.6. Les oprateurs shift() et unshift()

shift permet dliminer le premier lment dun tableau. unshift permet dajouter un lment ou une liste dlments en dbut de tableau; exemples:

@tab = ( 1, 2, 3 ); unshift ( @tab, $a ); # @tab = ( $a, @tab ) unshift ( @tab, 4, 5, $c ); # @tab = ( 4, 5, $c, @tab ) $b = shift ( @tab ); # @tab = (5,$c,1,2,3) et $b = 4 shift() renvoie la valeur undef si la liste qu'on lui a passe en paramtre est vide.

2.2.7. Loprateur reverse()

Cet oprateur permet dinverser lordre des lments dun tableau. Il retourne une liste; exemples:

@tab = ( 1, 2, 3 ); @inv_tab = reverse ( @tab ); # @inv_tab = ( 3, 2, 1 ) @b = reverse ( @b ); # inverse @b et le range dans @b

2.2.8. Loprateur sort()

Cet oprateur permet de classer dans lordre croissant des caractres ASCII les lments du tableau quon lui passe en argument; exemples:

@x = sort ("petit", "moyen", "grand" ); # @x=("grand","moyen","petit") @y = ( 1, 2, 4, 8, 16, 32, 64 ); @y = sort (@y); # @y = ( 1, 16, 2, 32, 4, 64, 8 )

juin 1995

Page 34

Le langage PERL

2.2.9. Loprateur chop()

Il fonctionne comme sur les variables scalaires: chaque lment du tableau quon lui passe en paramtre est amput de son dernier caractre; exemple:

@machin = ("Coucou \n", "Ca va ? \n" ); chop ( @machin ); # @machin = ("Coucou", "Ca va ?" )

2.2.10. Le tableau <STDIN>

Dans un contexte de tableau, cet oprateur renvoie une valeur diffrente que dans un contexte scalaire. En effet, il retourne une liste dont les lments sont toutes les lignes restantes de lentre standard partir de la ligne courante, prises sparment. Les newline sont pris en compte.

2.2.11. Interpolation de tableaux

Les tableaux et leurs lments peuvent eux aussi tre interpols lintrieur des doubles quotes; exemples:

@speinf = ("seb", "cricri", "hugo"); $phrase1 = "$speinf[0] joue bien au baby." # $phrase1 = "seb joue bien au baby" $phrase11 = "$speinf[0, 1] jouent bien au baby." # $phrase1 = "seb cricri jouent bien au baby" $phrase2 = "@speinf soccupent du 486." # $phrase2 = "seb cricri hugo soccupent du 386" $speinf = "coucou"; $phrase3 = "voici $speinf[1]"; $phrase4 = "voici $speinf \[1]"; $phrase5 = "voici $speinf" . "[1]"; $phrase6 = "voici ${speinf }[1]"; # # # # $phrase3 $phrase4 $phrase5 $phrase6 = = = = "voici "voici "voici "voici cricri" coucou [1]" coucou [1]" coucou [1]"

Les exemples des phrases 11 et 2 montrent que les lments dune liste sont interpols dans lordre et spars par un espace. Les exemples des phrases 4, 5 et 6 montrent comment faire suivre une variable scalaire dun crochet ouvrant, sans que Perl interprte cela comme linterpolation dun lment de tableau.

juin 1995

Page 35

Le langage PERL

juin 1995

Page 36

Le langage PERL

2.3. STRUCTURES DE CONTROLE

2.3.1. Les blocs dinstructions

Un bloc dinstructions est de la forme:

instruction 1; instruction 2; ... dernire instruction;

}
Cest donc une squence dinstructions spares par des points virgules, et encadre par des accolades. Perl excute les instructions dans lordre.

2.3.2. Linstruction if / unless

Une instruction

if

est de la forme:

if (expression) { instructions excuter si lexpression est vraie; } else { instructions excuter si lexpression est fausse; }
Les accolades sont obligatoires! Lexpression est value en tant que chane lexcution. Si elle est gale la chane vide (de longueur 0) ou au caractre "0", elle est value faux. Sinon elle est value vrai. Le bloc else est optionnel.

juin 1995

Page 37

Le langage PERL

Un exemple dinstruction if:

print "Donnez votre age : \n"; $age = <STDIN>; chop ( $age ); if ($age >= 18) { print "Vous pouvez aller voter! "; } else { print "Vous tes trop jeune pour voter! "; } if peut tre remplac par unless. Cela revient unless peut avoir lui aussi un bloc else.
exemple: dire: Si lexpression est fausse, alors... .

Sil y a plus de deux choix possibles, on peut ajouter des blocs

elsif

une instruction

if;

if (expression1) { bloc1; } elsif (expression2) { bloc2; } elsif (expression3) { bloc3; } else { bloc4; }
Le nombre de blocs

elsif

nest pas limit. Perl value les expressions les unes aprs les

autres; lorsquil en rencontre une ayant pour valeur vrai, le bloc dinstructions correspondant est excut et les autres sont ignors. Si toutes les expressions sont fausses, le excut (sil y en a un).

else

est

2.3.3. Linstruction while / until

Linstruction

while

permet de rpter

lexcution

dun

bloc

dinstructions

tant

que

lexpression de contrle est vraie; cette instruction est de la forme:

while (expression) { instruction_1; instruction_2; ... instruction_n; }


Pour excuter le

while,

Perl value lexpression. Si elle est vraie, le bloc dinstructions est

excut. Lexpression est alors rvalue. Ceci se rpte jusqu ce que lexpression soit fausse; le bloc dinstructions est alors ignor.

juin 1995

Page 38

Le langage PERL

while

peut tre remplac par

until;

cela revient dire: Tant que cette expression est

fausse, excuter ...; exemple:

until (expression) { bloc dinstructions; }

2.3.4. Linstruction for

Elle est trs semblable celle dont on dispose en C; elle est en effet de la forme:

for (initial_exp; test_exp; increment_exp) { instruction_1; instruction_2; ... instruction_n; }


Cela se traduit avec les instructions tudies jusquici par:

initial_exp; while ( test_exp ) { instruction_1; instruction_2; ... instruction_n; increment_exp; }


Linitial_exp est value en premier; en gnral elle permet dinitialiser un compteur de boucle (mais ce nest pas obligatoire). Ensuite la cela est ncessaire. Lexemple suivant permet de faire afficher les nombres de 1 10, spars par un espace:

test_exp

est value; si elle est vraie, le

corps de boucle et lincrement_exp sont excuts. Perl rvalue alors

test_exp

, tant que

for ( $i = 1; $i <= 10 ; $i ++ ) { print "$i"; }

juin 1995

Page 39

Le langage PERL

2.3.5. Linstruction foreach

Cette instruction affecte une variable scalaire avec les lments dune liste pris les uns aprs les autres et excute le bloc dinstructions; elle est de la forme:

foreach $i ( @liste ) { instruction_1; ... instruction_n; }


La variable scalaire est locale la boucle; cest--dire quelle reprend la valeur quelle avait avant lexcution de la boucle lorsquon sort de celle-ci. On peut omettre le nom de la variable scalaire; dans ce cas

$_ est utilise par dfaut.

Si la liste quon utilise est en fait simplement un tableau, alors la variable scalaire devient une rfrence chaque lment de ce tableau, plutt que dtre une copie de chacun deux. Cela signifie que si la variable scalaire est modifie, alors llment du tableau quelle reprsente alors est aussi modifi; un exemple pour y voir plus clair:

@val = ( 2, 5, 9 ); foreach $chiffre (@val) { $chiffre *= 3;} # on a maintenant @val = ( 6, 15, 27 )

juin 1995

Page 40

Le langage PERL

2.4. LES TABLEAUX ASSOCIATIFS

2.4.1. Les variables tableaux associatifs

Leur dfinition est donne au paragraphe 1.5. Leur nom commence par le symbole %. Il suit ensuite les mmes rgles que les noms de variables scalaires ou de tableaux. En gnral, on ne fait pas rfrence un tableau associatif dans son entier, mais ses lments. Chaque lment est accd par sa cl; ainsi, les lments du tableau associatif sont accds par

%tab

$tab{$cle},

$cle

est une expression scalaire. Vouloir accder un

lment du tableau qui nexiste pas a pour rsultat undef. De nouveaux lments sont crs par affectation et peuvent tre manipuls comme des variables scalaires; exemples:

$tab{"coucou"} = "ca va? "; # cration de la cl "coucou", laquelle est associe la valeur "ca va? " $tab{123.5} = 4568; # cration de la cl 123.5, laquelle est associe la valeur 4568 print "$tab{"coucou"}"; # affichage de "ca va? " $tab{123.5} +=3; # la valeur associe la cl 123.5 est maintenant 4571
La reprsentation littrale dun tableau associatif est une liste de paires de cls et des valeurs qui leur sont associes. Lordre des paires dans la liste ne peut pas tre contrl; il dpend de la fonction de hachage utilise par Perl pour accder rapidement aux lments du tableau; exemples:

%autre_tab = %tab; # %autre_tab a les mmes lments que %tab @liste = %tab; # @liste = ("coucou", "ca va? ", 123.5, 4571)

juin 1995

Page 41

Le langage PERL

2.4.2. Les oprateurs sur les tableaux associatifs

Loprateur keys() Cet oprateur retourne la liste des cls du tableau associatif quon lui passe en paramtre. Lordre des lments de cette liste dpend de la fonction de hachage utilise par Perl pour accder rapidement aux lments du tableau. Les parenthses sont optionnelles. Exemples:

$tab{"coucou"} = "ca va? "; $tab{123.5} = 4568; @liste = keys(%tab); # @liste = ("coucou ", 123.5) ou bien (123.5, "coucou") @liste = keys %tab; # idem
Les lments des tableaux associatifs sont interpols lintrieur des doubles quotes; exemple:

foreach $key (keys %tab) { print "la valeur associe la cl $key est $tab{$key}."; }
Dans un contexte scalaire,

keys()

retourne le nombre de paires (cl-valeur) du tableau

pass en paramtre; exemple:

while ($i < keys %tab) { ... }

Loprateur values() Cet oprateur retourne la liste des valeurs du tableau associatif quon lui passe en paramtre, dans le mme ordre que les cls retournes par optionnelles. Exemple:

keys().

Les parenthses sont

@liste_valeurs = values(%tab); # @liste_valeurs contient("ca va?",4568)ou bien(4568,"ca va?")

Loprateur each() Pour examiner tous les lments dun tableau associatif, on peut donc faire appel puis rcuprer les valeurs correspondant aux cls. En utilisant directement une paire (cl-valeur) du tableau pass en paramtre.

keys()

each(),

on obtient

juin 1995

Page 42

Le langage PERL

A chaque valuation de cet oprateur pour un mme tableau, la paire suivante est retourne, jusqu ce quil ny ait plus de paire accder; Lexemple prcdent peut alors scrire:

each()

retourne alors la chane vide.

while ( ($cle, $valeur) = each(%tab) ) { print "la valeur associe la cl $cle est $valeur . "; }

Loprateur delete Il permet dliminer la paire (cl-valeur) du tableau associatif dont on a pass la cl en paramtre; exemple:

%tab = ("coucou ", "ca va? ", 123.5, 4571); @element = delete $tab{"coucou"}; # @element = ("coucou", "ca va?") et %tab = (123.5, 4571)

juin 1995

Page 43

Le langage PERL

juin 1995

Page 44

Le langage PERL

2.5. LES ENTREES/SORTIES

2.5.1. Les entres avec STDIN

Lire lentre standard avec le manipulateur de fichier dj fait avec loprateur

STDIN

est trs simple. Nous lavons

<STDIN> qui peut tre valu:

dans un contexte scalaire, la ligne courante de lentre standard ou undef si il ny a plus de ligne; dans un contexte de tableau, au reste des lignes contenues dans lentre standard, sous forme de liste, chaque ligne tant un lment de la liste.

Pour lire les lignes contenues dans lentre standard et les manipuler sparment, on utilise comme suit:

$_

while ($_ = <STDIN>) { # code }


Tant quil y a quelque chose lire ny a plus rien lire,

<STDIN> est valu vrai et la boucle sexcute. Quand il <STDIN> retourne undef, qui est valu faux, ce qui termine la boucle. $_; donc, lexemple prcdent peut scrire:

Quand un test de boucle consiste uniquement en un oprateur dentre (comme < ... >), Perl copie automatiquement la ligne lue dans

while (<STDIN>) { # code }

2.5.2. Les entres avec loprateur diamant <>

Cet oprateur se comporte comme

<STDIN>:

dans un contexte scalaire, il retourne une ligne ou undef;

dans un contexte de tableau, il retourne les lignes restantes.

juin 1995

Page 45

Le langage PERL

Cependant, il lit les donnes dans les fichiers spcifis dans la ligne de commande faisant appel au programme Perl. Par exemple, le script suivant:

#!/usr/bin/perl while (<>) { print; }


a le mme rsultat que la commande cat; sil est stock dans le fichier pcat et quon fait appel lui avec la ligne de commande:

> pcat fic1 fic2 fic3


les contenus des trois fichiers seront affichs la suite les uns des autres. En fait,

<>

fonctionne grce au tableau

@ARGV

dont nous avons dj fait la connaissance au

chapitre 1. Pour ceux qui nont pas suivi, ce tableau est la liste des arguments de la ligne de commande.

2.5.3. La sortie avec STDOUT

Perl utilise

print

et

printf

pour crire sur la sortie standard.

print Cet oprateur prend une liste de chanes et les envoie les unes aprs les autres sur la sortie standard.

print retourne une valeur, comme tout oprateur sur les listes: vrai si la sortie a

t effectue avec succs, faux sinon. On a donc le droit dcrire:

$a = print ("hello ", "word", "\n"); # affichage de "hello word" avec retour la ligne et $a = 1
On est parfois oblig de mettre des parenthses, en particulier si la premire chose afficher commence par une parenthse ouvrante; exemples:

print (2+3),"coucou"; # faux; naffiche que 5, ignore "coucou" print ( (2+3), "coucou"); # affichage de 5coucou print 2+3, "coucou"; # idem

juin 1995

Page 46

Le langage PERL

printf Cet oprateur prend une liste de paramtres (encadrs ou non par des parenthses). Le premier paramtre est une chane de contrle des formats, indiquant comment afficher les paramtres restant. Cest comme le printf du C; exemple:

printf "%15s %5d %10.2f \n", $s, $n, $r ;

juin 1995

Page 47

Le langage PERL

juin 1995

Page 48

Le langage PERL

2.6. LES EXPRESSIONS REGULIERES


Nous en avons parl rapidement au paragraphe 1.4. Nous allons maintenant les tudier plus en dtail. Une expression rgulire est un pattern qui est recherch dans une chane de caractres. Le rsultat de la recherche peut tre positif ou ngatif. Parfois, cest simplement ce rsultat qui nous intresse; parfois, on souhaite pouvoir remplacer le pattern par une autre chane. Les expressions rgulires sont utilises par de nombreux programmes Unix comme grep,
sed, awk, ed, vi, emacs et les diffrents shells. Nimporte quelle expression rgulire qui peut

tre dcrite avec lun des outils Unix peut galement tre crite en Perl, sans ncessairement utiliser les mmes caractres.

2.6.1. Utilisations simples des expressions rgulires

Si lon dsire rcuprer les lignes du fichier nomfic comportant la chane commande:

abc,

on utilise la

> grep abc nomfic


Ici,

abc

est lexpression rgulire utilise par

grep

pour tester toutes les lignes de nomfic.

Les lignes matches sont envoyes sur la sortie standard. En Perl,

abc

est considre comme une expression rgulire si elle est encadre par des

slashes; le script Perl quivalent la commande

grep

prcdente est donc:

while (<>) {if (/abc/) { print; }

} $_,
qui contient la ligne courante du fichier pass en

Le matching est effectu sur la variable

paramtre au script. La sortie se fait sur la sortie standard. Si maintenant on veut trouver les lignes de nomfic contenant un et dun

a suivi de zro ou plusieurs b

?, on peut utiliser la commande:

> grep "ab*c" nomfic

juin 1995

Page 49

Le langage PERL

On est oblig dutiliser des doubles quotes pour la chane contenant lastrisque, si lon ne veut pas que le shell linterprte comme un nom de fichier. En Perl, cela est ralis de la faon suivante:

while (<>) {if (/ab*c/) { print; }

} s///,
qui

Un autre oprateur sur les expressions rgulires est loprateur de substitution Exemple:

remplace la partie de la chane matche par lexpression rgulire par une autre chane.

s/ab*c/def/;
La chane (ici

$_)

est parcourue. On y recherche un

suivi de zro ou plusieurs

et dun

Si la recherche est fructueuse, la partie de Sinon, il ne se passe rien.

$_

matche est remplace par la chane

c. def.

2.6.2. Les patterns

Il y a diffrentes sortes de patterns:

Les patterns un seul caractre Le plus simple est un unique caractre qui se matche lui-mme. Ainsi, rechercher la lettre

/a/

permet de

a dans une chane. a


et ntant

Le point, ".", permet de matcher nimporte quel caractre sauf newline (\n). Par exemple,

/a./

permet de matcher toute squence de deux caractres commenant par

pas "a\n". Une classe de caractres pour le matching est reprsente par deux crochets encadrant une liste de caractres. Un seul de ces caractres doit tre prsent dans la ligne parcourue pour que le matching fonctionne. Exemple:

/[abcde]/
matche lun des cinq caractres, en minuscule. Si lon veut inclure le crochet fermant dans la liste des caractres matcher, il doit tre prcd par un antislash ou se trouver en dbut de liste. On peut figurer un intervalle de valeurs en utilisant le tiret (-). Si celui-ci doit figurer dans la liste de caractres matcher, il suffit de le faire prcder dun antislash.

juin 1995

Page 50

Le langage PERL

Exemple:

/[a-e]/

# mme chose que lexemple prcdent ^;


plac juste aprs le crochet ouvrant, il permet de nier

Il existe un caractre de ngation: Exemple:

une classe de caractres: tout caractre ne se trouvant pas dans la liste sera match.

/[^0-9]/ # matche tout ce qui nest pas un chiffre


Si on veut faire figurer dun antislash. Certaines classes sont prdfinies: Construction /d /w /s (digits) (words) (space) Classe quivalente [0-9] [a-zA-Z0-9] [ \r \n \f \t] Construction ngative /D /W /S (digits, not!) (words, not!) (space, not!) Classe quivalente [^0-9] [^a-zA-Z0-9] [^ \r \n \f \t]

dans la liste des caractres matcher, il suffit de le faire prcder

Les patterns groupants 1. Les squences Comme nous lavons vu plus haut, appelle cela une squence.

abc

matche un

suivi dun

suivi dun

c.

On

2. Les multiplicateurs Nous avons dj vu lastrisque (*); elle signifie 0 ou plusieurs pour le caractre immdiatement prcdent. On dispose galement des caractres

et

?,

signifiant respectivement 1 ou plusieurs

et 0 ou 1 pour le caractre immdiatement prcdent. Exemple:

/fo+ba?r/
matche un

suivi dun ou plusieurs

o,

suivi dun

b,

suivi de zro ou un

a,

suivi dun

r.
Ces trois patterns groupants sont dits gloutons; en effet, sils peuvent matcher plusieurs fois le mme caractre, ils en matcheront toujours le maximum. Exemple:

$_ = "Salut XXXXXXXXXX ! "; s/X*/pascal/; # on obtient "Salut pascal ! ";

juin 1995

Page 51

Le langage PERL

Si on a besoin dtre plus prcis quant au nombre de rptitions du mme caractre matcher, il faut utiliser le multiplicateur gnral. Il se prsente sous la forme de deux accolades renfermant un ou deux nombres spars par une virgule. Exemple:

/X{5,10}/
Comme pour les trois multiplicateurs dj rencontrs, le caractre immdiatement prcdent (ici, "X") doit tre trouv avec un nombre de rptitions compris entre les deux nombres contenus dans les accolades (ici, entre 5 et 10). On peut aussi avoir les patterns:

/X{5,}/ /X{5}/ /X{0,5}/ /a.{5}b/

# matche # matche # matche # matche newline,

au moins 5 rptitions de X exactement 5 rptitions de X au plus 5 rptitions de X un a suivi de 5 caractres diffrents de suivis dun b

Sil y a deux multiplicateurs dans une mme expression, cest le plus gauche qui est le plus glouton; Exemple:

$_ = "a xxx c xxxxxxx c xxx d"; /a.*c.*d/


Le premier ".*" matche tous les caractres jusquau deuxime

c.

Ici, ca ne fait pas

grande diffrence, mais nous verrons tout lheure que a peut en avoir.

3. Les parenthses pour la mmorisation Un autre pattern groupant est la paire de parenthses encadrant un pattern. Elle permet de mmoriser la chane matche par le pattern quelle renferme et de la rfrencer par la suite. Donc

(a)

matche toujours un

a, ([a-z])

matche toujours nimporte quelle

lettre minuscule. Pour rfrencer la partie de la chane qui a t mmorise, on utilise un antislash suivi dun entier qui indique de quelle paire de parenthses il sagit (on compte partir de 1). Exemple:

/fred(.)barney\1/;
matche une chane comportant les caractres un newline, suivi de chane Autre exemple:

fred,

suivis dun caractre qui nest pas

barney, suivi fredxbarneyx est matche;

du mme caractre que prcdemment. Donc la par contre, la chane

fredxbarneyy

ne lest pas.

/a(.)b(.)c\2d\1/;

juin 1995

Page 52

Le langage PERL

matche un suivi dun

a, suivi dun caractre (not #1), suivi dun b, suivi dun caractre (not #2), c, suivi du caractre #2, suivi dun d, suivi du caractre #1.

On peut enfermer plus dun caractre dans les parenthses; exemple:

/a(.*)b\1c/;
matche un

de caractres, suivie dun

a, suivi une squence de caractres, suivie dun b, suivi de la mme squence c.

Avec loprateur de substitution, la structure avec les \1, \2, etc permet dutiliser les morceaux de chane mmoriss pour la construction de la chane de remplacement; exemple:

$_ = "a xxx b yyy c zzz d"; s/b(.*)c/d\1e/;

# $_ = "a xxx d yyy e zzz d"

4. Les alternatives Une construction alternative, telle que

a|b|c,

est une autre forme de pattern groupant.

Elle signifie quil faut matcher lune des alternatives quelle comporte (a ou Les alternatives peuvent tre constitues de plusieurs caractres; exemple:

ou

c).

/coucou|salut/
Remarquez que

/a|b|c/ est quivalent /[a-c]/.

Les patterns dancrage Il y en a quatre. Ils permettent prciser quel endroit de la chane la recherche du pattern doit commencer. La premire paire dancres vrifie quune certaine partie de la chane matche se trouve ou non lune des extrmits dun mot. Une extrmit de mot est lendroit entre des caractres matchs par \w et \W, ou entre des caractres matchs par \w et le dbut ou la fin de la chane. \b exige une extrmit de mot lendroit o il est plac pour que le matching seffectue. \B exige le contraire. Exemples:

/fred\b/ /\bwiz/ /\bfred\b/ /\b+\b/ /\bfred\B/

# # # # #

matche matche matche matche matche

fred, Alfred, mais pas frederic wizard mais pas qwiz uniquement fred x+y, mais pas ++ ou + frederic, mais pas fred flintstone

La deuxime paire dancres vrifie quune certaine partie de la chane matche est au dbut ou la fin de la chane. ^ exige que le pattern qui le suit soit en dbut de chane. $ exige que le pattern qui le prcde soit en fin de chane.

juin 1995

Page 53

Le langage PERL

Exemples:

/^a/ /a^/ /\^/ /c$/ /\$/

# matche # matche # matche # matche un c # matche

les les les les

chanes chanes chanes chanes

commenant par a comportant un a, suivi de ^ contenant le caractre ^ dont le dernier caractre est

les chanes contenant le caractre $

Priorit Comme pour les oprateurs, il existe des rgles de priorit pour les patterns groupants et dancrage. Elles sont explicites dans le tableau suivant, de la priorit la plus grande la plus petite: Nom Parenthses Les multiplicateurs Squences et ancrages Alternatives Par exemple, Quand on Reprsentation () * + ? {m,n} abc ^ $ \b \B | Par contre la

/a|b*/ matche les chanes contenant un a ou plusieurs b. /(a|b)*/ matche les chanes contenant plusieurs a ou plusieurs b.
utilise les parenthses pour la priorit, elles dclenchent mmorisation. Attention donc lors de lutilisation des \1, \2, etc.

galement

2.6.3. Complments sur loprateur de matching

Nous avons dj vu lutilisation la plus simple de cet oprateur: une expression rgulire entre deux slashes. Nous allons prsent faire la connaissance des autres possibilits quoffre cet oprateur.

Les oprateurs =~ et !~ Ces oprateurs sont utiliss pour effectuer la recherche dun pattern dans une autre chane que celle contenue dans

$_. Exemple:

$a = "bonjour tout le monde! "; $a =~ /^bon/; # $a contient vrai $chaine !~ /pattern/; # quivaut !($chaine=~/pattern/);

juin 1995

Page 54

Le langage PERL

La cible des oprateurs

=~

et

!~

peut tre nimporte quelle expression dont la valeur est

une chane. On peut donc les utiliser avec

<STDIN>; exemple:

print "Bonjour, professeur Falken! Vous voulez bien jouer avec moi? " if (<STDIN> =~ /^[oO]/) { print "Je vous propose une guerre thermonuclaire globale." }

Loption i Cette option permet dignorer la diffrence entre minuscules et majuscules. On la place aprs le deuxime slash. Les lettres du pattern matchent alors les lettres de la chane, quelles soient minuscules ou majuscules. Lexemple prcdent devient:

print "Bonjour, professeur Falken! Vous voulez bien jouer avec moi? " if ( <STDIN> =~ /^o/i ) { print "Je vous propose une guerre thermonuclaire globale." }

Utilisation dun autre dlimiteur Lorsquon doit inclure un slash dans le pattern, celui-ci doit tre prcd par un antislash. Exemple:

$path =~ /^\/usr\/etc/;

Ce nest donc pas marrant sil y a plusieurs slashes dans le pattern. Perl permet donc, ici encore, de se simplifier la vie en autorisant tout autre caractre non alphanumrique servir de dlimiteur, condition quil soit prcd dun m (matching!). Exemple:

$path =~ m#^/usr/etc#; # # est utilis comme dlimiteur $path =~ m@^/usr/etc@; # @ est utilis comme dlimiteur $path =~ m/^\/usr\/etc/; # / est utilis comme dlimiteur; le m est alors optionnel

Linterpolation de variable Linterpolation de variable est effectue avant lvaluation de lexpression rgulire. Exemple:

$assertion = "Un chasseur sachant chasser"; $mot = "chasseur"; if ($assertion =~ /$mot/ ) { print "Lassertion contient le mot $mot. "; }

juin 1995

Page 55

Le langage PERL

Des variables spciales Aprs une reconnaissance de pattern russie, les variables $1, $2, etc prennent les mmes valeurs que \1, \2, etc. Exemple:

$_ = "ceci est un test"; /(\w+)\W+(\w+)/; # matche les deux premiers mots de $_ # $1 = "ceci", $2 = "est"
On peut aussi rcuprer ces valeurs en effectuant le matching dans un contexte de tableau. Lexemple prcdent peut scrire:

$_ = "ceci est un test"; ($premier, $deuxime) = /(\w+)\W+(\w+)/; # $premier = "ceci", $deuxime = "est"
$1 et $2 demeurent inchanges: $1 = "ceci" et $2 = "est". Il existe trois autres variables, accessibles en lecture uniquement, comme $1, $2, etc: 1. $& contient le bout de chane match 2. $ contient le bout de chane situ aprs la partie matche 3. $` contient le bout de chane situ avant la partie matche Exemple:

$_ = "ceci est un test simple"; /te.*t/; # matche test #$& = "test", $ = "simple", $` = "ceci est un"

2.6.4. Les substitutions

Nous avons dj vu la plus simple utilisation de cet oprateur; compltons maintenant nos connaissances. Si lon souhaite que la substitution soit effectue chaque occurrence du pattern, il suffit dajouter un g aprs le dernier slash; exemple:

$_ = "coucou! ca va? "; s/ou/ri/g; # $_ = "cricri! ca va? "

juin 1995

Page 56

Le langage PERL

Linterpolation de variable a lieu dans la chane de remplacement; exemple:

$_ = "bonjour, pascal! "; $autre = "seb"; s/pascal/$autre/;# $_ = "bonjour, seb! "


Les caractres de la chane de remplacement ne sont donc pas forcment fixs lavance et peuvent mme tre extraits des caractres matchs; exemple:

$_ = "ceci est un test"; s/(\w+)/<$1>/; $_ = "<ceci> <est> <un> <test>"


Si on ajoute un i aprs le dernier slash, les majuscules ou les minuscules sont ignores dans lexpression rgulire (mme chose quavec le matching). On peut galement utiliser des dlimiteurs diffrents du slash; exemple:

s#fred#barney#; # il suffit dutiliser trois fois le mme caractre


Loprateur

=~

permet deffectuer la substitution sur une autre chane que celle contenue par

$_. Exemple: $lequel = "ceci est un test"; $lequel =~ s/test/quizz/; # $lequel = "ceci est un quizz"

2.6.5. Les oprateurs split() et join()

Loprateur split() Cet oprateur prend comme paramtres une expression rgulire et une chane, et cherche toutes les occurrences de lexpression rgulire dans la chane. Les parties de la chane qui nont pas t matches sont retournes sous forme dune liste. Exemple:

$ligne = "merlyn::118:10:Randal:/home/merlyn:/usr/bin/perl"; @champs = split(/:/, $ligne); # dcompose $ligne en prenant : comme dlimiteur # @champs = ("merlyn","","118","10","Randal","/home/merlyn", "/usr/bin/perl")

juin 1995

Page 57

Le langage PERL

La chane par dfaut pour cet oprateur est la variable Exemple:

$_;

le pattern par dfaut est

/\s+/.

@mots = split;

# quivalent @mots = split(/\s+/, $_)

Loprateur join() Cet oprateur prend une liste de valeurs et les recolle en plaant zro, un ou plusieurs caractres collants entre chaque lment de la liste; exemple:

$grosse_chaine = join($colle, @liste); # $colle contient les caractres collants


Pour recoller la ligne de /etc/passwd dcoupe prcdemment, on peut utiliser linstruction:

$resultat = join(":", @champs);

juin 1995

Page 58

Le langage PERL

2.7. LES FONCTIONS


Lutilisateur peut dfinir ses propres fonctions en Perl. On parle alors plutt de subroutine ou
sub.

2.7.1. Dfinition dune subroutine

Une subroutine dans un programme Perl est dfinie comme suit:

sub nom_subroutine { instruction_1; instruction_2; ... instruction_n; }


Un nom de subroutine suit les mmes rgles que les noms de variables, de tableaux et de tableaux associatifs. Le bloc dinstructions suivant le nom de la subroutine devient sa dfinition. Lorsqu'on fait appel la subroutine, cest le bloc dinstructions qui est excut et tout rsultat est renvoy lutilisateur. Les subroutines peuvent tre dfinies nimporte o dans le programme. Les dfinitions des subroutines sont globales. A lintrieur dune subroutine, on peut manipuler des variables partages avec le reste du programme (globales donc!).

2.7.2. Lappel une subroutine

Pour faire appel une subroutine, nimporte o dans le programme, on fait prcder son nom par le symbole &; exemple:

for ( $i=&val-init; $i<&val_test; $i+=&val_increment) {... }

juin 1995

Page 59

Le langage PERL

Une subroutine peut faire appel dautres subroutines faisant elles-mmes appel dautres subroutines...

2.7.3. Rsultats dune fonction

Le rsultat dune subroutine est la valeur de la dernire expression value dans le corps de la subroutine, chaque appel. Une subroutine peut galement retourner une liste, dans un contexte de tableau. Exemples:

sub somme_a+b { $a + $b; } $a = 3; $b = 5; $c = &somme_a+b;

# $c = 8

sub choix_a_ou_b { if ($a > 0) { print "je choisis a ($a) \n"; $a; } else { print "je choisis b ($b) \n"; $b; } }

>. Si on avait invers les lignes avec $a et le print, on aurait 1 comme valeur de retour (print a march) plutt que $a.
Dans ce deuxime exemple, la dernire expression value est soit

$a

soit

2.7.4. Les paramtres

Si lappel une subroutine est suivi dune liste parenthse, la liste est automatiquement range dans le tableau

@_ pendant la dure dutilisation de la subroutine. Celle-ci peut accder

ce tableau pour savoir combien il y a darguments et quelle est leur valeur. Exemple:

sub bonjour_ a_qui { print "bonjour, $_[0] ! \n"; } $_[0]


$_! est le premier lment de la liste darguments. Ne pas le confondre avec la variable

juin 1995

Page 60

Le langage PERL

Un appel possible de cette subroutine:

&bonjour_a_qui ("cricri"); # affichage de "bonjour, cricri !"


Un exemple de subroutine utilisant plus dun paramtre:

sub parler { print "$_[0], $_[1] ! \n"; } &parler ("bonjour", "cricri"); # affichage de "bonjour, cricri !"
Les paramtres en trop sont ignors. Les paramtres manquant se voient attribuer la valeur
undef.

@_

est local la subroutine. Sil existait une valeur globale pour

@_,

elle est sauvegarde

avant lappel la subroutine et restaure lorsque lexcution de la subroutine est acheve. Une subroutine peut donc passer des arguments une autre subroutine sans pour autant perdre sa propre liste darguments. Reprenons lexemple de

somme_a+b

en le modifiant de faon pouvoir effectuer la somme

de deux nombres, quels quils soient:

sub somme2 { $_[0] + $_[1] ; } $c = &somme2( 3, 5); # $c = 8

Si maintenant on veut faire la somme de plusieurs nombres:

sub somme { $somme = 0 ; # initialisation foreach ( @_ ) { $somme += $_ ; } # somme de chaque lment $somme ; # dernire expression value: le rsultat } $c = &somme ( 3, 4, 6, 7); # $c = 20

juin 1995

Page 61

Le langage PERL

2.7.5. Les variables locales

Loprateur local() permet de crer des variables locales une subroutine. Il reoit une liste de noms de variables et en cre des instanciations. Si ces variables existaient dj en tant que variables globales ou locales dautres fonctions, elles sont sauvegardes avant lexcution de la subroutine qui les utilise et restaures lorsque cette excution est termine. Reprenons lexemple ci-dessus:

sub somme { local ($somme) ; # fait de $somme une variable locale $somme = 0 ; # initialisation foreach ( @_ ) { $somme += $_ ; } # somme de chaque lment $somme ; # dernire expression value: le rsultat }
Le rsultat de

local()

est une liste de variables pouvant tre affectes. On peut donner des

valeurs initiales toutes ces nouvelles variables; sinon, elles sont initialises avec undef. On peut donc modifier lexemple prcdent en remplaant les deux premires lignes par:

local ($somme) = 0 ;

juin 1995

Page 62

Le langage PERL

2.8. DIVERSES STRUCTURES DE CONTROLE

2.8.1. Loprateur last

Cet oprateur permet de sortir plus tt dune boucle (cest lquivalent du break en C). Lexcution se poursuit avec linstruction situe immdiatement aprs la boucle. Exemple:

while (expression_1) { instruction_11; instruction_12; ... if (expression_2) { instruction_21; instruction_22; last; # permet de sortir du while } instruction_1n; ... } # on reprend ici avec last last
na cet effet quavec les blocs de boucle

indpendants (ne se rapportant pas un

for, foreach, while et les blocs if ou une subroutine ou un bloc plus important).

2.8.2. Loprateur next

Comme

last, next

modifie lordre squentiel dexcution. Cet oprateur permet de sauter

lexcution dun corps de boucle, sans terminer le bloc. Il est utilis comme suit:

while (expression_1) { instruction_11; instruction_12; ... if (expression_2) { instruction_21; instruction_22; next;

juin 1995

Page 63

Le langage PERL

} instruction_1n; ... # on reprend ici avec next }

2.8.3. Loprateur redo

Cet oprateur permet de revenir au dbut du bloc ditrations et donc de lexcuter de nouveau, sans rvaluation de lexpression de contrle; exemple:

while (expression_1) { # on revient ici avec redo instruction_11; instruction_12; ... if (expression_2) { instruction_21; instruction_22; redo; } instruction_1n; ... }

2.8.4. Les blocs tiquets

Pour sortir de plusieurs blocs la fois, il suffit dutiliser les oprateurs et dtiqueter les blocs.

next, redo

et

last

Une tiquette est un nom suivant les mmes rgles que les noms de variables scalaires, de tableaux ou de subroutines. Cependant ce nom nest prcd par aucun symbole spcial; donc une tiquette telle que

print

est interdite, car elle serait confondue avec loprateur

print.

Cest pourquoi il est conseill que le nom dune tiquette soit compos uniquement de lettres majuscules et de chiffres. Ltiquette est place en tte du bloc tiqueter; passe en paramtre elle indique le bloc concern par ces oprateurs.

next, last

ou

redo,

juin 1995

Page 64

Le langage PERL

Exemple:

EXTERIEUR: for ( $i = 1; $i <= 10; $i++) { INTERIEUR: for ( $j = 1; $j <= 10; $j++) { if ( $i * $j == 63 ) { print "$i fois $j gal 63 !\n"; last EXTERIEUR; } if ( $j >= $i ) { next EXTERIEUR; } } }
Cet exemple teste des valeurs successives de

$i

et

$j

jusqu ce que leur produit soit gal

63. Lorsque la paire est trouve, on sarrte. On vrifie toujours que 1), (2, 2), (3, 1), ... Si on avait utilis

$i est plus grand que $j, sinon on passe la valeur suivante de $i; on testera donc uniquement les paires (1, 1), (2,

last et next sans tiquette et mme si on navait pas tiquet plus interne (INTERIEUR), ces oprateurs se seraient pourtant rapports ce bloc.
les oprateurs

le bloc le

On ne peut pas utiliser les tiquettes pour entrer dans un bloc, mais seulement pour en sortir;

next, last

et

redo doivent tre dans ce bloc.

2.8.5. Les modificateurs dexpression

Une autre faon de dire: Si ceci, alors cela , est: cela si ceci . Perl permet ce genre de raccourci, comme ceci:

une_expression if expression_de_contrle;
Lexpression de contrle est value en premier; si elle est vraie, alors excute. Cela revient :

une_expression

est

if (expression_de_contrle) { une_expression ; }
mais il y a moins de chose taper. Cependant expression (et non un bloc dinstructions).

une_expression

doit tre une unique

juin 1995

Page 65

Le langage PERL

Un exemple dutilisation: sortir dune boucle quand une certaine condition est vrifie:

LIGNE: while (<STDIN>) {last LIGNE if /^Date/ ;}


De la mme faon, il existe:

exp2 while exp1; # quivaut while (exp1) { exp2;} exp2 unless exp1;# quivaut unless (exp1) { exp2;} exp2 until exp1; # quivaut until (exp1) { exp2;}

2.8.6. &&, || et ?: comme structures de contrle

Une autre faon dcrire: si ceci, alors cela , est dutiliser le et-logique:

ceci && cela ;


Comment a peut marcher? Et bien:

si

ceci

est vraie, alors lexpression ci-dessus nest pas encore totalement value

puisquelle dpend de si

cela. Donc cela doit tre value.

ceci est fausse, alors lexpression ci-dessus est fausse aussi; pas besoin dvaluer cela. cela
est value uniquement si

Donc

ceci

est vraie; cest bien quivalent aux deux

constructions que nous avons vues prcdemment. De la mme faon, le ou-logique peut remplacer la structure

unless; exemple:

ceci || cela;
Si

ceci est vraie, alors inutile dvaluer cela; sinon, cela est value.

Enfin, il existe loprateur ternaire:

exp1 ? exp2 : exp3 ;


qui value

exp2 si exp1 est vraie, et exp3 sinon. Cela revient :

if (exp1) { exp2 ; } else { exp3 ; }


mais il ny a pas toute cette ponctuation!

juin 1995

Page 66

Le langage PERL

2.9. LES MANIPULATEURS DE FICHIERS ET LES TESTS SUR LES FICHIERS

2.9.1. Les manipulateurs de fichiers ou filehandles

Ils ont t prsents au paragraphe 1.1.1., mais a ne fait jamais de mal de rpter un peu! Un manipulateur de fichier est le nom, dans un programme Perl, dune connexion entre/sortie entre le processus Perl et le monde extrieur. Nous en avons dj utilis; par exemple

STDIN

est le filehandle dsignant la connexion entre

le processus Perl et lentre standard dUnix. Perl dispose aussi de

STDOUT et STDERR.

Un nom de filehandle suit les mmes rgles que les noms dtiquettes, de tableaux, de subroutines ... Cependant, comme les tiquettes, il nest rservs. prcd par aucun symbole particulier. Il est donc conseill dutiliser des majuscules et de ne pas interfrer avec les mots

2.9.2. Ouverture et fermeture de filehandle

STDIN, STDOUT et STDERR sont

ouverts automatiquement par le pre du processus Perl. Pour

ouvrir dautres filehandles, on utilise la fonction open(); exemple:

open ( MANIP, "nomfic"); MANIP

# ouverture en lecture

est le nouveau manipulateur de fichier et nomfic est le nom du fichier Unix associ

ce nouveau filehandle. Cette instruction ouvre le filehandle en lecture; pour louvrir en criture, on utilise encore

open

mais on fait prcder le nom du fichier par le signe suprieur:

open ( MANIP, "> nomfic");

# ouverture en criture

Pour ouvrir un fichier et crire la suite de ce quil contient dj, il suffit dcrire:

open ( MANIP, ">> nomfic");

juin 1995

Page 67

Le langage PERL

Ces trois formes de

open retournent vrai si louverture sest droule avec succs, faux sinon.

Pour fermer un filehandle, on utilise loprateur close() comme suit:

close ( MANIP);
Rouvrir un filehandle a pour effet de refermer automatiquement le fichier associ par le prcdent fichiers.

open.

La fin dexcution du programme Perl a pour effet de refermer automatiquement tous les

close() nest donc pas forcment ncessaire.

2.9.3. Loprateur die()

Un filehandle qui na pas t ouvert avec succs peut continuer dtre utilis sans quil y ait aucune indication de la part du programme. Si une lecture y est effectue, le caractre de fin de fichier est retourn; toute donne quon essaiera dy crire sera perdue. Bien sr, on peut utiliser une structure de contrle avec un message derreur saffichant si louverture na pas march. Mais Perl permet, ici encore, de se simplifier la vie: loprateur

die()

prend comme

argument une chane de caractres quil va crire sur lerreur standard, et tue le processus Perl (celui du programme) avec un exit Unix de statu non nul. Combin avec le ou-logique, notre test est maintenant trs simple:

open(MANIP, "> nomfic") || die ("Impossible douvrir nomfic!");


Cela se lit: Ouvre ce fichier ou meurt! .

die() nest excut que si open

retourne faux.

Le message renvoy la mort du processus comporte le nom du programme Perl et le numro de ligne o a na pas march. Si on ne dsire pas avoir ces informations, il suffit de terminer la chane de caractres de

die() par le caractre "\n".

juin 1995

Page 68

Le langage PERL

2.9.4. Utilisation des filehandles

Un filehandle ouvert en lecture peut tre lu tout comme

STDIN; exemple:

open(EP, "/etc/passwd"); while (<EP>) { chop; print "jai vu $_ dans le fichier des mots de passe! "; }
Un filehandle ouvert en criture doit tre pass en argument

print comme suit:

print MANIP "fini de rigoler!";


Par ailleurs, nous avons vu que, par dfaut, la sortie se fait sur

STDOUT:

print STDOUT "coucou!";

# quivaut print "coucou! ";

2.9.5. Les tests sur les fichiers

Ils sont regroups dans le tableau suivant: -r -w -x -o -R -W -X -O -e -z -s -f -d -l fichier ou rpertoire accessible en lecture fichier ou rpertoire accessible en criture fichier ou rpertoire excutable fichier ou rpertoire proprit de lutilisateur fichier ou rpertoire pouvant tre lu par lutilisateur rel, et non par lutilisateur effectif (diffre de -r pour les programmes setuid) fichier ou rpertoire pouvant tre crit par lutilisateur rel, et non par lutilisateur effectif (diffre de -w pour les programmes setuid) fichier ou rpertoire excutable par lutilisateur rel, et non par lutilisateur effectif (diffre de -x pour les programmes setuid) fichier ou rpertoire proprit du lutilisateur rel, et non de lutilisateur effectif (diffre de -o pour les programmes setuid) fichier ou rpertoire existant fichier existant, de taille nulle fichier ou rpertoire existant et comptant un nombre non nul de caractres lentre est un fichier lentre est un rpertoire lentre est un lien symbolique

juin 1995

Page 69

Le langage PERL

-S -p -b -c -u -g -k -t -T -B -M -A -C

lentre est une socket lentre est un pipe portant un nom (fifo) lentre est un fichier avec bloc spcial lentre est un fichier de caractres spciaux fichier ou rpertoire ayant le bit 11 (setuid) positionn 1 fichier ou rpertoire ayant le bit 10 (setgid) positionn 1 fichier ou rpertoire ayant le bit s positionn isatty() sur le filehandle retourne vrai fichier texte fichier binaire age de la dernire modification du fichier en jours age du dernier accs au fichier en jours age de la dernire modification dinode du fichier en jours

La plupart de ces tests retournent vrai ou faux. Cependant, loprateur

-s

retourne vrai si le fichier est non vide, mais cest un vrai

particulier: cest le nombre doctets du fichier, qui est valu vrai si ce nest pas 0. Les oprateurs dage fichier. Cet age

-M, -A, -C

retournent le nombre de jours qui se sont couls depuis la

dernire modification, le dernier accs au fichier et la dernire modification dinode de ce a une rsolution de 1 seconde et peut avoir une valeur dcimale: 36 heures sont notes 1,5 jours. Tous ces oprateurs peuvent prendre comme paramtre aussi bien un filehandle quun nom de fichier. Si on ne leur passe pas de paramtre, ils prennent comme oprande par dfaut le fichier dont le nom est contenu dans la variable liste de nom de fichiers il suffit dcrire:

$_;

par exemple, pour tester en lecture une

foreach ( @liste_nom_fichiers ) { print "$_ est accessible en lecture \n" if -r ; }

2.9.6. Les oprateurs stat() et lstat()

Pour obtenir toute autre information sur un fichier, on utilise loprateur

stat()

qui retourne

pratiquement tout ce que l'appel systme stat() retourne. Cet oprateur prend un filehandle ou une expression svaluant un nom de fichier comme paramtre. Il retourne soit la valeur
undef si linstruction a chou, soit un tableau de 13 lments, dcrit en dtail dans la page

man de stat(2).

juin 1995

Page 70

Le langage PERL

Lappel

stat()

avec un nom de lien symbolique renvoie ce sur quoi ce lien pointe, mais

pas dinformation sur le lien lui-mme. Pour obtenir ces informations, on dispose de loprateur

lstat(). stat() et lstat() prennent $_ comme paramtre par

Comme pour les tests sur les fichiers, dfaut.

2.9.7. Le filehandle _

A chaque utilisation de

-r, -w, stat()

etc, Perl doit demander au systme un buffer stat au

sujet du fichier (le buffer rsultat de l'appel systme stat). Cela signifie que si lon demande si un fichier est accessible en criture et en lecture, Perl ira chercher deux fois la mme information. Pour viter a, on dispose du filehandle

_.

Pass comme paramtre un test de fichier,

stat()

ou

lstat(),

il indique Perl de rutiliser le buffer stat obtenu lors du dernier test

de fichier ou du dernier appel

stat() ou lstat(). Exemple:

if ( -r $nomfic && -w _ ) { print "$nomfic est accessible en criture et en lecture \n"; }


Pour le premier test, on utilise le premier test sont rutilises.

$nomfic

pour obtenir du systme dexploitation les donnes

concernant ce fichier; pour le deuxime test, par contre, on utilise

_:

les donnes obtenues par

juin 1995

Page 71

Le langage PERL

juin 1995

Page 72

Le langage PERL

2.10. LES FORMATS

2.10.1. Quest-ce quun format?

Perl dispose dun outil de mise en page, appel format. Un format dfinit une partie constante (entte, labels, texte fixe, etc.) et une partie variable (les donnes auxquelles va sappliquer le format). Lutilisation dun format consiste en trois points: 1. dfinir le format 2. charger les donnes afficher dans les parties variables du format 3. faire appel au format Le premier point est effectu une fois, nimporte o dans le texte du programme, les deux autres sont effectus de faon rptitives.

2.10.2. Dfinition dun format

Un format est dfini par une dfinition de format. Celle-ci peut figurer nimporte o dans le texte du programme, comme les subroutines. Elle est de la forme:

format nomdeformat = ligne de champ valeur_1, valeur_2, valeur_3 ligne de champ valeur_1, valeur_2, valeur_3 ligne de champ valeur_1, valeur_2, valeur_3 .
La premire ligne contient le mot rserv

format,

suivi du nom du format et du signe

=.

Le

nom du format doit vrifier les mmes rgles que les autres noms de variables. Il peut cependant tre un mot rserv, puisquil nest pas utilis dans le corps du programme (si ce nest en tant que chane). Vient ensuite le gabarit, dont la fin est indique par une ligne contenant un seul et unique point. Attention, les gabarits sont sensibles aux espaces.

juin 1995

Page 73

Le langage PERL

La dfinition du gabarit contient un certain nombre de lignes de champ. Chacune delles peut contenir du texte fixe, texte qui sera affich tel quel chaque appel du format. Les lignes de champ peuvent comporter des fieldholders pour le texte variable; exemple:

Bonjour! Mon nom est @<<<<<<<<<< $nom


Le fieldholder est gauche. Si une ligne comporte plusieurs fieldholders, on doit spcifier autant de valeurs; celles-ci sont alors spares par une virgule; exemple:

@<<<<<<<<<<;

il spcifie un champ de 11 caractres avec alignement

Bonjour! Mon nom est @<<<<<<<<<<; jai @<< ans $nom, $age
Une ligne de champ ne comportant pas de fieldholders nest donc pas suivie par une ligne de valeurs. Les espaces sont ignors dans la ligne de valeurs. Les valeurs sont prises en compte en tant que scalaires; donc toute expression est value dans un contexte scalaire.

2.10.3. Lappel un format

On fait appel un format avec loprateur write. Celui-ci prend le nom dun filehandle comme paramtre et gnre du texte pour ce filehandle, avec le format courant de ce filehandle. Le format par dfaut est le format du mme nom (pour est utilis par dfaut). Voyons un exemple concret:

STDOUT, le format STDOUT

format ETIQUETTEADRESSE= ================================= | @<<<<<<<<<<<<<<< @<<<<<<<<<<<<<| $nom, $prenom | @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<| $adresse | @<<<< @<<<<<<<<<<<<<<<<<<<<<<<<| $code_postal, $ville ================================= . open(ETIQUETTEADRESSE, ">etiquette-a-imprimer") || die ("Cration impossible! "); open (ADRESSES, "adresses") || die ("Impossible douvrir adresses! "); while (<ADRESSES>)

juin 1995

Page 74

Le langage PERL

{ chop; ($nom, $prnom, $adresse, $code_postal, $ville) = split (/:/); write ETIQUETTEADRESSE; }
On commence par dfinir un format pour les tiquettes. Notez quon lui donne le mme nom quau filehandle utilis pour la sortie. On ouvre celui-ci et le filehandle contenant les adresses, qui sont censes avoir le format suivant:

Poiraud:Cecile:19 avenue du docteur Donat:06800:Cagnes-sur-Mer


Chaque ligne de ce filehandle est lue, dcoupe, et les 5 morceaux sont affects aux 5 champs de ltiquette. Notez que les noms des variables recueillant les morceaux sont les mmes que ceux utiliss dans la dfinition du format; a aussi, cest important. Enfin, loprateur dfaut. Chaque champ du format est alors remplac par la valeur correspondante; exemple:

write

fait appel au format. Notez cependant que le paramtre de

write

est le filehandle sur lequel est effectue la sortie et que le format du mme nom est utilis par

================================= | Poiraud Cecile | | 19 avenue du docteur Donat | | 06800 Cagnes-sur-Mer | =================================

2.10.4. Complments sur les fieldholders

Les champs de texte La plupart des fieldholders commencent par @. Les caractres suivant @ indiquent le type du champ; le nombre de caractres (en incluant @) dfinit la taille du champ. Si @ est suivi de signes infrieur (<), alors le champ est alignement gauche. Si la valeur ne remplit pas totalement le champ, celui-ci est complt droite avec des espaces. Si la valeur est trop longue, elle est automatiquement tronque. Si @ est suivi de signes suprieur (>), alors le champ est alignement droit (si la valeur est trop courte, le champ est complt gauche par des espaces). Si @ est suivi de barres verticales (|), alors le champ est centr (si la valeur est trop courte, des espaces sont rajouts de part et dautre pour quelle soit peu prs centre).

juin 1995

Page 75

Le langage PERL

Les champs numriques Il existe galement des champs numriques de prcision fixe. Ces champs commencent aussi par @, et sont suivis dun ou plusieurs # avec, en option, un point (la virgule dcimale). Ici encore, @ compte comme un caractre du champ; exemple:

format COMPTE_CL = Credit: @#####.## Debit: @#####.## Total: @#####.## $credit, $debit, $credit-$debit .
Notez lutilisation dune expression dans le format.

Les champs multilignes Perl sarrte normalement au premier newline rencontr lorsquil charge les donnes dans le format. Cependant, il existe un fieldholder permettant dinclure autant de lignes dinformations que lon veut; on le note @*, seul sur une ligne. La ligne suivante dfinit la valeur qui remplira le champ. Exemple:

format STDOUT = ++++++++++++++ @* $chaine_des_noms ++++++++++++++ . $chaine_des_noms = "cricri\nseb\ngilles\nxav\npascal\nhugo\nsissou\n"; write;


a pour rsultat:

++++++++++++++ cricri seb gilles xav pascal hugo sissou +++++++++++++++

Les champs paragraphes Ils permettent de crer des paragraphes, les lignes tant coupes la fin dun mot. Le
fieldholder est le mme que pour les champs de texte, si ce nest quil commence par ^

(par exemple,

^<<<<<).

La valeur correspondante doit tre une variable scalaire contenant du texte.

juin 1995

Page 76

Le langage PERL

Lorsque Perl remplit le champ paragraphe, il prend autant de mots dans la variable quil est possible den mettre dans le champ. Ces mots sont limins de la variable. Exemple:

format LES_GENS = Nom: @<<<<<<<<< Commentaires: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $nom, $commentaire ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $commentaire ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $commentaire ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $commentaire

.
La mme variable,

personne et les premiers mots de et 4. Si

$commentaire, apparat 4 fois. La premire ligne affiche le nom de la $commentaire. Ces mots sont limins de la variable et,

avec la deuxime ligne, laffichage des commentaires se poursuit, de mme quaux lignes 3

$commentaire

ne contient pas assez de mots pour remplir les 4 lignes, elles sont

compltes par des espaces. Pour viter limpression de lignes blanches, il suffit dutiliser lindicateur de suppression tilde (~), qui est transparent limpression et peut figurer nimporte o dans la ligne sur laquelle il porte; exemple:

format LES_GENS = Nom: @<<<<<<<<< Commentaires: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $nom, $commentaire ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $commentaire ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $commentaire ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $commentaire .
Si

$commentaire

est trop longue, inutile de copier 20 fois les deux dernires lignes en

esprant que a suffira. Perl permet de faire a tranquillement. Toute ligne contenant deux tildes successifs (~~) sera rpte automatiquement jusqu ce quelle affiche une ligne entirement vide. Notre exemple devient alors:

format LES_GENS = Nom: @<<<<<<<<< Commentaires: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $nom, $commentaire ~~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $commentaire .

juin 1995

Page 77

Le langage PERL

2.10.5. Le format haut-de-page

Perl permet de dfinir un format haut-de-page, qui enclenche un mode de pagination. Perl compte le nombre de lignes gnres par nimporte quel appel un format pour un mme filehandle. Lorsque le format courant ne loge pas sur ce quil reste de la page, Perl place un
formfeed , effectue un appel automatique au format haut-de-page et continue laffichage sur la

page suivante. Le format haut-de-page est dfini comme nimporte quel format. Son nom par dfaut est le nom du filehandle suivi de La variable

_TOP.

$%

contient le nombre dappels au format haut-de-page pour un mme filehandle;

elle peut donc tre utilise pour numroter les pages. Lexemple suivant de format haut-depage permet dviter que les tiquettes de lexemple prcdent soient coupes au changement de page et de numroter les pages dtiquettes:

format ETIQUETTEADRESSE_TOP = Mes Adresses -- Page @< $% .


La longueur par dfaut dune page est de 60 lignes.

2.10.6. Remplacer les valeurs par dfaut par des formats

Loprateur select()

print est STDOUT. En fait, pas vraiment. Le vritable filehandle par dfaut de print, de write, est le filehandle courant. STDOUT est le premier filehandle courant; cependant, on peut modifier ce filehandle avec loprateur select(), qui prend comme unique paramtre un nom de filehandle. Une fois
que le filehandle courant est modifi, cela affecte toutes les oprations venir faisant appel lui. Exemple:

Nous avons vu que le filehandle par dfaut de

print "Bonjour tout le monde! "; # affichage sur STDOUT select (LOGFILE); # le filehandle courant est maintenant LOGFILE print "Coucou! "; # affichage dans LOGFILE select (STDOUT); # STDOUT est de nouveau le filehandle courant print "Ca va? "; # affichage sur STDOUT

juin 1995

Page 78

Le langage PERL

Il faut tre prudent! Des subroutines peuvent modifier le filehandle courant; on peut alors avoir des surprises. Heureusement,

select()

retourne le nom de lancien filehandle

courant, ce qui permet de le rtablir en fin dexcution de la subroutine. Exemple:

$vieux_nom = select(LOGFILE); # sauvegarde du nom de lancien filehandle courant print "Coucou! "; select($vieux_nom); # restaure le filehandle prcdent

Pour changer le nom dun format Le format par dfaut pour un certain filehandle est le format du mme nom. Cependant, on peut associer au filehandle courant le format dont le nom figure dans la variable variable contient le format courant du filehandle courant. Si lon veut utiliser le format

$~.

Cette

ETIQUETTEADRESSE pour STDOUT, il suffit dcrire:

$~ = ETIQUETTEADRESSE;

Si lon veut associer le format

RESUME au filehandle RAPPORT:

$vieux_nom = select(RAPPORT); # changement de filehandle courant $~ = "RESUME"; # format pour le filehandle courant ... # code write RAPPORT; # impression dans RAPPORT avec le format RESUME select($vieux_nom); # retour lancien filehandle courant

Pour changer le nom du format haut-de-page Il suffit de donner la variable du filehandle courant. le nom du format haut-de-page appliquer au

$^

filehandle courant. On peut consulter cette variable pour connatre le format haut-de-page

Pour changer la longueur dune page Nous avons vu que, par dfaut, une page contient 60 lignes. Cependant, on dispose de la variable

$=; elle contient le nombre courant de lignes par page pour le filehandle courant et

peut tre modifie.

juin 1995

Page 79

Le langage PERL

Pour changer de position dans la page Si on

print

du texte dans un filehandle, le compteur de lignes du filehandle devient faux

write. Si lon veut que le compteur de $-. Cette variable contient le nombre de lignes restant dans la page courante du filehandle courant. Chaque write dcrmente cette variable du nombre de lignes effectivement imprimes; lorsque $- = 0, un appel au format haut-de-page est effectu et $- prend pour valeur $=. En dbut de programme, $- vaut zro pour tous les filehandles.
Perl reste jour, il suffit de modifier la variable

puisque Perl ne compte que les lignes issues dun

juin 1995

Page 80

Le langage PERL

2.11. LES REPERTOIRES

2.11.1. Se dplacer dans larborescence

Loprateur Perl chdir() permet de modifier le rpertoire courant dun processus. Il prend comme paramtre une expression svaluant un nom de rpertoire et attribue cette valeur au rpertoire courant. Il retourne vrai si cette modification a bien pu tre effectue, faux sinon. Exemple:

chdir ( "/etc" ) || die ( "cd /etc impossible!" ) ;


Les parenthses ne sont pas obligatoires. Chaque processus Unix possde son propre rpertoire courant. Lorsquun nouveau processus est cr, il hrite ce rpertoire de son pre. Si un programme Perl change son rpertoire, cela naffecte pas le shell qui a lanc le processus Perl. De mme, les processus crs par un programme Perl ne peuvent pas modifier le rpertoire courant de ce programme.

2.11.2. Le globbing

En shell, une simple

* permet daccder la liste des fichiers du rpertoire courant. De mme, .c.

[a-m]*.c

donne accs la liste des fichiers dont le nom commence par une lettre de la

premire moiti de lalphabet et se termine par encadr par les signes < et >; exemple:

Ce genre daction sappelle le globbing. Perl laccepte condition que le globbing pattern soit

@liste = </etc/host*>; # @liste contient la liste des noms de fichiers du rpertoire /etc commenant par host
Cela ressemble beaucoup la lecture dun filehandle: dans un contexte scalaire, le glob retourne le nom de fichier match ou undef sil ny en a pas;

juin 1995

Page 81

Le langage PERL

dans un contexte de tableau, le glob retourne la liste des noms de fichier matchs restants, ou la liste vide sil ny en a pas.

Exemple dutilisation:

while ($nomfic = </etc/host*>) { print "Un des fichiers est $nomfic \n " ; }
On peut avoir plusieurs patterns lintrieur du glob: les listes sont construites sparment puis concatnes; exemple:

@liste_ceci_cela = <ceci* cela*>;


Bien que globbing et matching fonctionnent de faon assez similaire, il ne faut pas oublier que la signification des divers caractres spciaux est diffrente: la liste des noms de fichier ayant pour extension

<\.c$>

ne permet pas dobtenir

.c !

Linterpolation de variable a lieu dans le glob avant excution de celui-ci; exemple:

if (-d "/usr/etc" ) { $ou = "/usr/etc" ; } else { $ou = "/etc" ; } @liste = < $ou/* > ;
Une exception cependant: le pattern comme globbing pattern) doit tre tard.

<$var> (signifiant quil faut utiliser la variable $var crit <${var}> pour des raisons que nous verrons plus

2.11.3. Les manipulateurs de rpertoire

Un manipulateur de rpertoire est une connexion avec un rpertoire particulier. Il est toujours ouvert en lecture uniquement: on ne peut pas lutiliser pour changer un nom de fichier ou dtruire un fichier. Pass en paramtre la fonction rpertoire auquel il est associ. Un nom de manipulateur de rpertoire suit les mmes rgles quun nom de filehandle: les majuscules sont conseilles et les mots rservs interdits. Le manipulateur de fichier et le manipulateur de rpertoire

readdir

et ses copines, il permet de manipuler le

MANIP

MANIP sont indpendants.

juin 1995

Page 82

Le langage PERL

2.11.4. Ouverture et fermeture dun manipulateur de rpertoire

La fonction opendir() prend pour paramtres le nouveau manipulateur de rpertoire et le nom du rpertoire ouvrir, auquel le manipulateur sera associ. Cette fonction retourne vrai si le rpertoire a pu tre ouvert, faux sinon. Exemple:

opendir ( ETC, "/etc" ) || die ("opendir na pas march! \n" ) ;


Pour fermer un manipulateur de fichier, on utilise la fonction closedir(); exemple:

closedir(ETC);
Comme

close(), closedir() nest pas souvent ncessaire puisque tous les manipulateurs

de rpertoires sont ferms automatiquement avant dtre rouverts ou en fin dexcution du programme Perl.

2.11.5. Lecture avec un manipulateur de rpertoire

Lorsquun manipulateur de rpertoire a t ouvert, la liste des noms de fichiers contenus dans ce rpertoire peut tre lue grce la fonction readdir(). Cette fonction prend comme unique argument le manipulateur de rpertoire et retourne:

dans un contexte scalaire, le nom de fichier courant, dans un ordre alatoire; undef, sil ne reste plus de nom; dans un contexte de tableau, les noms de fichiers restant sous forme de liste dont chaque lment est un nom.

Exemples:

opendir (ETC, "/etc") || die ("opendir na pas march!") ; while ( $nom = readdir(ETC) ) # contexte scalaire { print "$nom \n" ; } closedir(ETC) ; opendir (ETC, "/etc") || die ("opendir na pas march!") ; foreach $nom ( sort readdir(ETC) ) # contexte de tableau, tri { print "$nom \n" ; } closedir(ETC) ;

juin 1995

Page 83

Le langage PERL

juin 1995

Page 84

Le langage PERL

2.12. MANIPULATION DE FICHIERS ET DE REPERTOIRES

2.12.1. Destruction dun fichier

Loprateur Perl unlink() dtruit un nom de fichier (qui pourrait avoir plusieurs noms). Lorsque le dernier nom dun fichier est dtruit, le fichier lui-mme est dtruit. Cest lquivalent de la commande rm. Comme la plupart du temps un fichier a un nom unique, dtruire son nom, cest donc le dtruire. Exemple:

unlink($nomfic); # le fichier dont le nom est rfrenc par la variable $nomfic est dtruit
Loprateur

unlink() admet une liste de noms de fichier comme

paramtre; tous les fichiers

dont les noms figurent dans cette liste sont dtruits. Exemples:

unlink("fic1", "fic2"); # fic1 et fic2 sont dtruits unlink(<*.o>); # tous les fichiers du rpertoire courant ayant pour extension .o sont dtruits unlink()
retourne le nombre de fichiers effectivement dtruits et prend

$_

comme

paramtre par dfaut; exemple:

foreach (<*.o>) { unlink || print "Impossible de dtruire $_ \n " ; }


Tous les fichiers objet du rpertoire courant sont dtruits successivement; un message permet de connatre les noms des fichiers ne pouvant tre dtruits.

juin 1995

Page 85

Le langage PERL

2.12.2. Renommage dun fichier

Cette opration est effectue avec loprateur rename(), comme suit:

rename ($old, $new); rename ("fic", "fic1"); # le fichier fic est renomm fic1.
Cet oprateur retourne la valeur vrai si le renommage a pu tre effectu. Si la commande shell mv permet le raccourci

mv fichier un_rpertoire,

la commande

rename() ne le permet pas; il faut crire: rename("fichier", "un_rpertoire/fichier");

2.12.3. Cration de liens sur un fichier

Comme si un nom pour un fichier ne suffisait pas, parfois on en veut deux ou trois ou une douzaine. Cette opration de cration de plusieurs noms pour un mme fichier sappelle le linking. Il y a deux sortes de linking: tablissement de lien physique et tablissement de lien symbolique.

Liens physique et symbolique Un lien physique sur un fichier n'est pas distinguable du nom du fichier. Le noyau Unix met jour un compteur qui est le nombre de liens physiques se rapportant un fichier. Si un lien est dtruit, ce compteur est dcrment; si un nouveau lien est cr, le compteur est incrment. Lorsque le fichier est cr, le compteur prend la valeur 1. Chaque lien physique sur un fichier doit se trouver sur la mme partition monte. On ne peut crer qu'un seul lien physique sur un rpertoire: celui qui est tabli lors de la cration du rpertoire. Toute tentative d'en crer un deuxime est fatale. C'est pour protger la hirarchie Unix des fichiers. Un lien symbolique est une forme spciale de fichier qui contient comme donnes un chemin d'accs. Lorsque ce fichier est ouvert, le noyau Unix considre son contenu comme un aiguillage supplmentaire pour le chemin d'accs; il continue alors son avance dans la hirarchie. Un lien symbolique peut tre cr sur un rpertoire.

juin 1995

Page 86

Le langage PERL

Le contenu d'un lien symbolique n'a pas besoin d'tre un fichier ou un rpertoire existant. Il peut mme se trouver sur une autre partition monte. Un lien symbolique peut pointer sur un autre lien symbolique. Un lien physique vite la perte du contenu d'un fichier (puisqu'il est en fait un nom du fichier). Un lien symbolique ne peut empcher cette perte. Il faut tre autoris en criture dans le rpertoire o l'on cre ces deux sortes de liens, sans pour autant tre autoris ouvrir le fichier sur lequel sont crs les liens. Il faut pouvoir appliquer

stat()

au fichier sur lequel on veut crer un lien physique; ceci n'est pas

ncessaire pour crer un lien symbolique.

Cration de liens physique et symbolique avec Perl Loprateur link() permet de crer des liens physiques. Il prend comme paramtres le vieux nom du fichier et le nouvel alias pour ce fichier. Il retourne vrai si le lien a pu tre cr. Comme avec

rename(),

il faut prciser dans son entier le nouveau nom de fichier (et pas

seulement le rpertoire). Exemple:

link("fic1", "fichier_1") || die("Impossible de crer un lien physique entre fic1 et fichier_1 \n");
Pour un lien physique, le vieux nom ne peut pas tre celui d'un rpertoire et le nouvel alias doit tre sur la mme partition monte. Sur les systmes admettant les liens symboliques, loprateur symlink() permet de crer cette sorte de lien. Il prend comme paramtres le vieux nom du fichier ou du rpertoire et le nouvel alias pour ce fichier ou ce rpertoire. Le fichier ou le rpertoire n'a pas besoin d'exister pour qu'il soit possible de crer un lien symbolique sur lui. Exemple:

symlink("fic2", "fichier_2") || die("Impossible de crer un lien symbolique entre fic2 et fichier_2 \n");

L'oprateur readlink() permet de savoir ce sur quoi le lien symbolique pass en paramtre pointe. Exemple:

if ($nom = readlink("fichier_2")) { print "fichier_2 pointe sur $nom \n" ; } # $nom contient fic2 readlink() retourne undef si
symbolique. le lien test n'existe pas, ne peut tre lu ou n'est pas un lien

juin 1995

Page 87

Le langage PERL

2.12.4. Cration et destruction dun rpertoire

Loprateur mkdir() permet de crer un nouveau rpertoire dont le nom et les droits lui sont passs en paramtres. Les droits sont spcifis par un entier (le mode) interprt comme un format de droits internes. La page man chmod(2) prcise les droits internes. Si vous tes presss, le mode 0777 permet de tout faire pratiquement. Exemple:

mkdir("rep", 0777); # cration du rpertoire rep avec le mode 0777


Loprateur rmdir() permet de supprimer un rpertoire vide; exemple:

rmdir("rep");

# destruction du rpertoire rep

2.12.5. Modification de droits

Les droits sur un fichier ou un rpertoire indiquent qui a le droit de faire quoi avec ce fichier ou ce rpertoire. Loprateur Perl chmod() permet de changer ces droits. Il prend comme paramtres un entier, le mode, et une liste de noms de fichiers, et tente de modifier les droits de tous ces fichiers avec le mode indiqu. Exemple:

chmod(0666, "fic1", "fic2");


Avec le mode 0666, fic1 et fic2 deviennent accessibles en lecture et en criture pour tout le monde (utilisateur, groupe et autres).

chmod() retourne le nombre de fichiers dont il a russi modifier les droits.

2.12.6. Modification de la proprit

Tout fichier ou rpertoire a un propritaire et un groupe dans le systme de fichiers. Le propritaire et le groupe dterminent qui les droits de proprit et de groupe sappliquent. Ils sont dtermins au moment de la cration du fichier, mais on peut les changer.

juin 1995

Page 88

Le langage PERL

Loprateur chown() prend comme paramtres un UID, un GID et une liste de noms de fichiers, et tente de changer la proprit de chacun des fichiers spcifis. Il retourne le nombre de fichiers dont il a russi modifier la proprit. Remarquez quon change le propritaire et le groupe en mme temps. UID et GID doivent tre des valeurs numriques, et non les noms symboliques correspondants. Exemple:

chown(1234, 35, "fic1", "fic2");


fic1 et fic2 appartiennent maintenant lutilisateur dUID 1234 et au groupe de GID 35.

2.12.7. Modification des timestamps

Trois timestamps sont associs un fichier. Nous en avons parl brivement au paragraphe 2.9.4. Il sagit des ges de dernire modification, de dernier accs dun fichier et de dernire modification de linode de ce fichier. Loprateur utime() permet de donner aux deux premiers timestamps des valeurs arbitraires. Modifier ces deux valeurs modifie automatiquement la troisime et lui donne pour valeur le temps courant. Donc, pas besoin doprateur spcial pour a!

utime()

prend comme paramtres les ges en secondes du dernier accs et de la dernire

modification, et une liste de noms de fichiers; il retourne le nombre de fichiers pour lesquels lopration a russi. Exemple:

$atime = $mtime = 700 000 000; utime($atime, $mtime, "fic1", "fic2");


Les temps sont mesurs en temps interne Unix; ce sont des valeurs entires de secondes, comptes partir du 01/01/70 G.M.T.

juin 1995

Page 89

Le langage PERL

juin 1995

Page 90

Le langage PERL

2.13. LA GESTION DE PROCESSUS

2.13.1. Lutilisation de system()

Perl peut lancer de nouveaux processus. La faon la plus simple de le faire est d'utiliser l'oprateur shell

system(). Cet oprateur donne en fait la chane qu'on lui passe en paramtre un /bin/sh qui l'excute comme une commande. Quand l'excution est termine, system()

retourne 0 si tout s'est bien pass. Exemple:

system("date");
Loprateur

# permet d'obtenir la date

system()

hrite du processus Perl les fichiers dentre, de sortie et derreur

standards. Le rsultat de la commande shell sera donc dans redirig; exemple:

STDOUT.

Cependant il peut tre

system("date > ficdate") && die "Impossible de crer ficdate \n"; # permet d'obtenir la date dans le fichier ficdate vrifier la valeur de retour de system() system()

et

de

peut prendre comme paramtre tout ce que /bin/sh accepte dexcuter: plusieurs

commandes spares par des points virgules, des retours la ligne, des lancements en arrire plan... Exemple:

system("(date ; who) > $fic & ") ; # lancement de date et who en arrire plan avec sortie dans le ficher rfrenc par la variable Perl $fic
Perl offre la possibilit de consulter et de modifier les variables denvironnement grce au tableau associatif

%ENV, dont chaque lment est une paire (nom de variable denvironnement,

valeur de cette variable). Voici un exemple permettant dafficher toutes les variables denvironnement et leur valeur:

foreach $key (sort keys %ENV) { print "$key = $ENV{$key} \n" ; }

juin 1995

Page 91

Le langage PERL

Loprateur

system()

admet galement une liste de paramtres. Plutt que de donner cette

liste au shell, Perl interprte le premier lment de cette liste comme la commande excuter avec pour paramtres les lments suivants de la liste. Exemple:

system "grep 'seb' fic_speinf"; system "grep", "seb", "fic_speinf"; # idem mais avec une liste
Lutilisation dune liste plutt que dune chane conomise un processus shell.

2.13.2. Lutilisation des backquotes

Une autre faon de lancer un processus est dencadrer une ligne de commande /bin/sh avec des backquotes. La commande est excute et le rsultat est rcupr sur la sortie standard. Il devient la valeur de la chane entre backquotes; exemple:

$date = "on est aujourdhui".`date`; # $date contient maintenant la concatnation de la chane de caractres et du rsultat de la commande shell date
Si la commande entre backquotes est utilise dans un contexte de tableau, le rsultat est une liste de chanes, chacune tant une ligne (termine par un newline) de la sortie de la commande. Pour lexemple ci-dessus, nous naurions eu quun lment, puisquune seule ligne est gnre. Autre exemple:

foreach (`who`) { ($qui, $ou, $quand) = / (\S+) \s+ (\S+) \s+ (.*)/ ; print "$qui sur $ou $quand \n" ; }

2.13.3. Utilisation de processus comme filehandles

Une autre mthode pour lancer un processus est de crer un processus qui ressemble un manipulateur de fichier. Comme les filehandles sont ouverts soit en criture soit en lecture, il est possible de crer un processus-filehandle qui peut capturer la sortie ou fournir lentre du processus; exemple:

open (PROC, "who | " ) ; @who = <PROC>;

juin 1995

Page 92

Le langage PERL

La barre verticale droite de

who

indique Perl quil nest pas en train douvrir un filehandle

mais plutt de lancer une commande. Comme la barre est droite de la commande, le filehandle est ouvert en lecture, ce qui signifie que la sortie de lment est une ligne du

who

doit tre capture. La

deuxime ligne permet de ranger le rsultat de la commande dans un tableau dont chaque

who.

De mme, pour lancer une commande avec des paramtres, on peut ouvrir un processusfilehandle en criture en mettant la barre verticale gauche de la commande; exemple:

open (LPR, " | lpr -Pslatewriter" ) ; print LPR @report ; close(LPR) ;


Aprs avoir ouvert

LPR,

on y a crit des donnes puis on la ferm. Ouvrir un processus-

filehandle permet la commande de sexcuter en parallle avec le programme Perl.

close()

force ce programme attendre que le processus meurt. Si on ne ferme pas le processusfilehandle, le processus peut continuer de sexcuter mme aprs terminaison du programme Perl.

2.13.4. Lutilisation de fork

Une autre mthode pour lancer un nouveau processus est de cloner le processus Perl avec la primitive Unix fork. Loprateur Perl

fork

fait simplement ce que l'appel systme fork excute: il cre un

processus fils, qui partage avec son pre le mme code excutable, les mmes variables et mme les mmes fichiers ouverts. Pour distinguer les deux processus, la valeur de retour de

fork est 0 pour le fils et une valeur non nulle pour le pre. Exemple: if (fork) { # je suis le pre } else { # je suis le fils }
Perl dispose galement des oprateurs wait, exec et exit. En fait, il se contente de passer les appels ces oprateurs aux appels systme dUnix.

exec

est comme loprateur

system,

si ce nest quau lieu de crer un nouveau processus

pour excuter une commande shell, il remplace le processus courant par le shell. Pour obtenir quelque chose dquivalent un appel

system, il faut combiner fork et exec; exemple:

# mthode 1 system "date" ;

juin 1995

Page 93

Le langage PERL

# mthode 2 unless(fork) { # fork a retourn 0, # je suis donc le processus fils et jexcute: exec ("date") ; } wait; # le pre attend que le fils meurt wait permet de faire attendre le pre jusqu ce que le fils meurt.
Enfin, loprateur

exit()

permet de sortir immdiatement du processus Perl courant. Cet

oprateur peut prendre un paramtre optionnel qui est un entier indiquant la manire dont on est sorti. Par dfaut, on sort avec la valeur 0, qui indique que tout sest bien pass. Exemple:

unless(fork) { # je suis le processus fils unlink </tmp/bedrock.*> ; # destruction de tous ces fichiers exit(); # le fils arrte de sexcuter ici } # le pre continue de sexcuter ici exit, le processus fils continue continue de sexcuter ici').
Sans le dexcuter le programme Perl ( la ligne

'le pre

2.13.5. Rsum des oprations sur les processus

Le tableau suivant rsume les diffrentes faons de crer un processus avec Perl: Opration system() backquotes open() pour un filehandle en lecture open() pour un filehandle en criture fork, exec, wait Entre standard hrite du programme hrite du programme connecte au filehandle hrite du programme choix de lutilisateur Sortie standard hrite du programme capture en tant que chane hrite du programme connecte au filehandle choix de lutilisateur Erreur standard hrite du programme hrite du programme hrite du programme hrite du programme choix de lutilisateur au moment du close() au moment du close() choix de lutilisateur oui Attendu? oui

La plus simple faon de crer un processus est dappeler

system(). STDIN, STDOUT

et

STDERR

sont inchanges. Avec les backquotes, la sortie est capture sous forme dune chane

de caractres;

STDIN

et

STDERR

sont inchanges. Avec ces deux mthodes, le programme

Perl attend que le processus meurt pour continuer son excution.

juin 1995

Page 94

Le langage PERL

Pour une excution en parallle, louverture dune commande en tant que filehandle est une mthode simple. La mthode la plus souple est dutiliser les oprateurs excutions squentielle et parallle.

fork, wait

et

exec

qui sont

directement relis aux appels systme du mme nom. On peut alors choisir entre les

2.13.6. Envoi et rception de signaux

Une mthode de communication interprocessus sous Unix est lenvoi et la rception de signaux. Un signal est un message de 1 bit envoy un processus par un autre processus ou par le noyau Unix. La rponse un signal sappelle action du signal. Certains signaux ont pour action par dfaut de tuer ou de suspendre le processus. Dautres sont compltement ignors par dfaut. Quand un processus Perl capte un signal, une subroutine de votre choix est lance automatiquement, interrompant temporairement ce qui tait en train de sexcuter. Lorsque la subroutine a t excute, le contexte est restitu, comme sil ne stait rien pass (sauf si la subroutine a excut des instructions). En gnral, une telle subroutine fait lune de ces deux choses:

aprs avoir effectuer des instructions de nettoyage, elle arrte lexcution du programme; elle positionne un flag (par exemple une variable globale) que le programme consulte rgulirement.

Les noms des signaux sont disponibles dans la page man de l'appel systme signal. Pour associer une subroutine de traitement de signal un signal, on utilise le tableau associatif

%SIG.
signal

Ce tableau a pour cls les signaux. Pour associer la subroutine

&traite_sigint

au

SIGINT, il suffit dcrire:

$SIG{'INT'} = 'traite_sigint'; sub traite_sigint { $sigint_flag = 1 ; } # positionnement dun flag

Cette subroutine positionne donc une variable globale et se termine tout de suite aprs. Lexcution du programme reprend l o elle stait interrompue. On peut galement donner des valeurs spciales aux signaux:

'DEFAULT': associe au signal son action par dfaut; 'IGNORE': permet dignorer le signal.

juin 1995

Page 95

Le langage PERL

Un signal peut tre gnr par lutilisateur lorsquil frappe certains caractres. Un processus peut galement gnrer un signal, grce loprateur kill(). Cet oprateur prend comme paramtres un nom ou un numro de signal et les numros des processus auxquels ce signal doit tre envoy. Exemple:

kill ( 2, 234, 237);


Le signal 2,

SIGINT, est envoy aux processus 234 et 237.

juin 1995

Page 96

Le langage PERL

2.14. AUTRES TRANSFORMATIONS SUR LES DONNEES

2.14.1. Recherche dune sous-chane

Loprateur index() permet de retrouver une sous-chane dans une chane plus longue. Exemple:

$x = index($chaine, $ss_chaine);
Cet oprateur repre la premire occurrence de la sous-chane dans la chane et renvoie un entier qui est la position du premier caractre de la sous-chane dans la chane; exemples:

$pos = index ("coucou", $pos = index ("coucou", $ss_chaine = "ba"; $pos = index ("coucou", # $pos = -1 (on na pas

"co"); "ouc");

# $pos = 0 # $pos = 1

$ss_chaine); trouv "ba" dans "coucou")

Les oprandes dindex() peuvent tre des chanes, des variables scalaires contenant des chanes ou des expressions ayant pour valeur une chane. On peut donner un troisime paramtre ce paramtre. Exemples:

index() afin de trouver les autres occurrences de la

sous-chane lintrieur de la chane. La recherche se fera droite de la position indique par

$pos = index ("coucou", "co", 1); # $pos = 3, deuxime occurrence de "co" $pos = index ("coucou","co",4); # $pos=-1, "co" napparat plus aprs la position 4
On peut effectuer la recherche en partant de la droite; pour cela il existe loprateur rindex(). La position retourne est toujours compter partir de la gauche, mais elle concerne la premire occurrence de la sous-chane en partant de la droite. Exemples:

$pos = rindex ("coucou", "co"); # $pos=3, premire occurrence de "co" en partant de la droite $pos = rindex ("bateau", "ba"); # $pos = 0 $pos = rindex ("hello world", "o", 3); # $pos = -1 $pos = rindex ("hello world", "o", 6); # $pos = 4

juin 1995

Page 97

Le langage PERL

Comme le montrent les deux derniers exemples,

rindex()

peut galement prendre un

troisime paramtre qui est la position gauche de laquelle la recherche est effectue.

2.14.2. Extraction et remplacement dune sous-chane

Extraire une chane de caractres peut se faire grce aux expressions rgulires. On peut galement utiliser loprateur substr(), qui a pour syntaxe:

$s = substr($chaine, $pos, $long); $s reoit la sous-chane $long; exemples: $s $s $s $s = = = =


extraite de

$chaine

partir de la position

$pos

et de longueur

substr("hello substr("hello substr("hello substr("hello

world", world", world", world",

3, 4); 2, 100); -3, 3); -3, 1);

# # # #

$s $s $s $s

= = = =

"lo w" "llo world" "rld" "r"

Une valeur ngative de la position indique la position en partant de la fin du mot. Attention, le dernier caractre est accd par la position -1, alors que le premier caractre est accd par la position 0. Si la

$pos est un nombre ngatif plus grand en valeur absolue que la longueur de la chane, alors recherche est effectue partir de la position 0. Si $pos est un nombre positif plus grand substr()
retourne tout ce qui se trouve droite de

que la longueur de la chane, alors la chane vide "" est retourne. Si on nindique pas de longueur, chane. Si le premier paramtre de

$pos,

jusqu la fin de la

substr() est une variable, alors substr() peut figurer

gauche

dune affectation; exemple:

$chaine = "hello cricri"; substr($chaine, 0, 5) = "howdy"; # $chaine = "howdy cricri"


Mais la sous-chane de remplacement na pas forcment la mme longueur que celle qui disparat. La chane finale est automatiquement allonge ou raccourcie; exemple:

$chaine = "hello cricri"; substr($chaine, 0, 5) = "hi"; # $chaine = "hi cricri" substr($chaine, -6, 6) = "sebastien"; # $chaine = "hello sebastien"

juin 1995

Page 98

Le langage PERL

2.14.3. Associer des formats aux donnes avec sprintf()

printf()

permet dafficher une liste de valeurs avec des formats.

sprintf()

fait la mme

chose, mais retourne le rsultat dans une chane de caractres; exemple:

$var = sprintf("X%05d", $y);

2.14.4. Un tri performant

Nous avons dj vu que loprateur fait

sort appliqu une liste permet de la trier suivant lordre

ASCII croissant. Et si on veut raliser dautres tris, par exemple un tri numrique? Eh bien, en

sort

est un oprateur gnral; il suffit de dfinir une subroutine de comparaison de deux

lments. Cette subroutine de comparaison est dfinie comme une subroutine ordinaire et est appele de faon rptitive, jusqu ce que la liste soit trie. Pour gagner en vitesse dexcution, les deux lments compars ne sont pas passs la subroutine sous forme de tableau, mais en tant que valeurs des variables globales subroutine retourne:

$a et $b. La

un nombre ngatif si 0 si

$a est infrieure $b

$a gale $b $a est suprieure $b.

un nombre positif si

infrieur, suprieur et gal ayant le sens quimplique la comparaison effectue. La subroutine

suivante permet deffectuer un tri numrique:

sub by_number { if ($a < $b) { -1; } elsif ($a > $b) { 1; } elsif ($a == $b) { 0; } }
Comment lutiliser? Prenons par exemple la liste suivante:

@liste = ( 1, 2, 4, 8, 16, 32, 48, 64, 128, 256);

juin 1995

Page 99

Le langage PERL

Si on utilise sort comme on le fait dhabitude, les lments de la liste comme des chanes de caractres:

@liste seront ordonns

@mauvaise_liste = sort @liste; # @mauvaise_liste = (1, 128, 2, 256, 32, 4, 48, 64, 8)
Pour un tri numrique, il faut utiliser notre subroutine de comparaison comme suit:

@bonne_liste = sort by_number @mauvaise_liste; # @bonne_liste = (1, 2, 4, 8, 16, 32, 48, 64, 128, 256)
Remarquez que le & nest pas obligatoire: Perl reconnat que la chane entre est la subroutine de comparaison. Ce genre de comparaison renvoyant -1, 0 ou 1 est si frquent que Perl dispose de loprateur
vaisseau_spatial, not <=>. Si on lutilise, notre subroutine scrit alors tout simplement:

sort

et la liste

sub by_number { $a <=> $b ; }


On peut aller encore plus loin en remplaant le nom de la subroutine par linstruction quelle excute:

@bonne_liste = sort { $a <=> $b } @mauvaise_liste; <=>,


oprateur pour la comparaison numrique, a pour quivalent cmp pour la comparaison

des chanes de caractres. Une faon de trier une liste par ordre ASCII croissant (sort classique) est dcrire:

@resultat = sort { $a cmp $b } @liste;


Ce nouvel oprateur peut sembler inutile premire vue. Pourtant il permet de garantir que la liste trie aura toujours les mmes lments la mme place. En effet, si des lments de la liste sont gaux, alors on nobtiendra pas forcment la mme liste aprs chaque tri. Supposons par exemple vouloir obtenir une liste des logins et des vrais noms des utilisateurs ordonne par les noms dutilisateur. Si ces valeurs se trouvent dans le tableau associatif index par les logins, il suffit dcrire:

%nom

@cles_triees = sort by_names keys(%nom); sub by_names { ($nom{$a} cmp $nom{$b}) || ($a cmp $b) ; } foreach @cles_triees { print "$_ a pour vrai nom $nom{$_} \n" ; }

juin 1995

Page 100

Le langage PERL

Si deux noms dutilisateurs sont identiques, on compare leurs logins, ce qui vite davoir laffichage un coup

"grossior a pour vrai nom grossiord" "seb a pour vrai nom grossiord" "seb a pour vrai nom grossiord" "grossior a pour vrai nom grossiord"

et une autre fois

2.14.5. Translitration

Si lon veut remplacer un caractre dune chane par un autre ou supprimer toute occurrence dun caractre, on peut utiliser loprateur des

s///.

Mais si lon veut remplacer tous les

par

et tous les

par des

a?

Deux appels successifs

s///

ne feront pas ce quon attend

puisque le deuxime annulera leffet du premier. Perl dispose donc de loprateur

tr/// qui est trs proche de la commande shell tr. Exemple:

tr /ab/ba/;
Cet oprateur prend deux arguments: la vieille chane et la nouvelle chane. Ils agissent comme les deux arguments de

s///. tr///

modifie le contenu de la variable

$_;

il cherche

les caractres de la vieille chane et les remplace par ceux de la nouvelle chane. Exemples:

$_ = "coucou! ca va?" ; tr /cau/fid/ ; # $_ contient maintenant "fodfod! fi vi?" tr /a-c/A-C/ ; # $_ contient maintenant "CouCou! CA vA?"
Si la nouvelle chane est plus courte que la vieille, le dernier caractre de la nouvelle chane est rpt autant de fois que ncessaire pour que la chane o seffectue la recherche conserve la mme longueur; exemple:

$_ = "coucou! ca va?" ; tr /a-z/x/ ; # $_ contient maintenant "xxxxxx! xx xx?"


Pour viter cela, il suffit dajouter le caractre d la fin de lappel

tr///; exemple:

tr /a-z/A-C/d ;

# $_ contient maintenant "CC! CA A?"

Tout caractre de la vieille chane auquel ne correspond pas une valeur dans la nouvelle chane est supprim. Si la nouvelle liste est vide et quil ny pas doption caractres matchs par la vieille chane.

d,

la nouvelle liste est alors la mme que

la vieille liste. Cela peut paratre idiot. Cependant

tr///

retourne alors le nombre de

juin 1995

Page 101

Le langage PERL

Exemples:

$_ = "coucou! ca va?" ; $nb = tr /a-z// ; $nb = tr /a-z/A-Z/ ;


Si on place un c en fin dappel

# $_ na pas chang mais $nb = 10 # $_ est en majuscule et $nb = 10

tr///, on prend comme vieille chane le complmentaire de

la vieille chane dans lensemble des 256 caractres alphanumriques; exemples:

$_ = "coucou! ca va?" ; $nb = tr /a-z//c; # $_ na pas chang mais $nb = 3 $nb = tr /a-z/_/c ; # $_ = "coucou__ca_va_" et $nb = 3 tr /a-z//cd ; # $_ contient maintenant "coucoucava"
Les options peuvent tre combines, comme le montre ce dernier exemple. La dernire option de

tr///

est s, qui a pour effet de substituer les copies successives dune

mme lettre de la nouvelle chane par une unique copie; un exemple est plus parlant!

$_ = "aaabbbcccdefghi"; tr /defghi/abcddd/s ; # $_ contient maintenant "aaabbbcccabcd" $_ = "cricri et seb, hugo et xav"; tr /a-z/X/s ; # $_ contient maintenant "X X X, X X X" $_ = "cricri et seb, hugo et xav"; tr /a-z/_/cs ; # $_ contient maintenant "cricri_seb_hugo_xav"
Comme

s///, tr///

peut tre appliqu une autre chane que

$_

en utilisant loprateur

=~; exemple: $chaine = "cricri et seb, hugo et xav"; $chaine =~ tr /a-z/_/cs ; # $chaine contient maintenant "cricri_seb_hugo_xav"

juin 1995

Page 102

Le langage PERL

2.15. ACCES AUX DONNEES SYSTEME

2.15.1. Pour rcuprer des informations sur les mots de passe et les groupes

Les informations que possde le systme sur votre nom d'utilisateur et votre UID sont publiques. En fait, pratiquement tout sauf votre mot de passe est disponible. Il suffit d'accder le fichier /etc/passwd. Ce fichier a un format particulier:

name:passwd:uid:gid:gcos:dir:shell
Les champs sont dfinis comme suit:

name passwd uid gid gcos dir shell

le login de l'utilisateur le mot de passe crypt de l'utilisateur l'identificateur d'utilisateur (0 pour le root, un nombre non nul pour les autres utilisateurs) l'identificateur de groupe par dfaut le champ GCOS, qui contient en gnral le nom de l'utilisateur, une virgule et d'autres informations le rpertoire racine de lutilisateur le shell lanc au moment du login

Perl dispose de l'oprateur getpwnam(), qui prend comme unique argument un nom d'utilisateur et retourne la ligne du fichier /etc/passwd correspondante, dcompose dans un tableau:

($name,$passwd,$uid,gid,$quota,$comment,$gcos,$dir,$shell) $quota est toujours vide; $comment et $gcos contiennent tous les deux le champ GCOS.
Si on utilise l'oprateur getpwuid() en lui passant le UID de l'utilisateur, on obtient le mme tableau.

getpwuid()

et

getpwnam()

sont des oprateurs permettant d'accder une ligne de

/etc/passwd grce une cl: le UID ou le nom de l'utilisateur. Si on dsire maintenant un accs

squentiel /etc/passwd, Perl propose les oprateurs setpwent(), getpwent() et endpwent(). Ces oprateurs passent en revue toutes les lignes de /etc/passwd. parcours au dbut du fichier. Chaque appel

setpwent()

initialise le

getpwent()

retourne la ligne courante du

juin 1995

Page 103

Le langage PERL

fichier; lorsqu'il n'y a plus de ligne lire, il retourne la liste vide. Un appel permet de librer les ressources utilises pour scanner /etc/passwd. Exemple:

endpwent()

setpwent; # initialise le parcours while (@liste = getpwent ) { # rcupre la ligne courante ($login, $home) = @liste[0, 7]; # cration d'un associatif dont la cl est le login print "Le rpertoire racine de $login est $home"; } endpwent; # libration des ressources
En gnral, on utilise d'informations. Si on

tableau

getpwuid()
souhaite

et

getpwnam()
plus

pour accder un petit nombre il vaut mieux utiliser

accder

d'informations,

setpwent(), getpwent() et endpwent().


Pour accder le fichier /etc/group, il existe de mme les oprateurs setgrent(), getgrent() et endgrent() pour un accs squentiel, et getgrgid() et getgrnam() pour un accs par le GID ou le nom du groupe. Un appel

getgrent() retourne le tableau:

($name, $passwd, $gid, $members)


Ces quatre valeurs correspondent exactement aux quatre champs du fichier /etc/group.

2.15.2. Manipulation de donnes binaires

L'oprateur Perl pack() fonctionne un peu comme

sprintf().

Il prend comme paramtre

une chane de contrle de formats et une liste de valeurs, ne faisant plus qu'une seule chane de cette liste. Cependant, il est orient vers la cration de structures de donnes binaires. Exemple:

pack ("CCCC", 140, 186, 65, 25);


Une chane est cre, qui contient quatre octets dont les valeurs sont celles des quatre entiers. Le format C permet de transformer un petit entier (une valeur de caractre non signe) en un octet. Le format l permet de gnrer une valeur long signe. Il dpend cependant de la machine; en gnral, c'est un nombre cod sur quatre octets. Exemple:

$buf1 = pack("l", 0x41424344); $buf2 = pack("ll", 0x41424344, 0x45464748);

juin 1995

Page 104

Le langage PERL

$buf1 contient ABCD ou DCBAHGFE.

ou

DCBA

(cela dpend de la machine), et

$buf2

contient

ABCDEFGH

La liste des diffrents formats pour

pack() est disponible dans la page man de Perl.

Pour raliser l'opration contraire de l'opration prcdente, on utilise l'oprateur unpack(), qui prend comme paramtres une chane de format et une chane de donnes, et retourne une liste de valeurs, images mmoire de la chane de donnes. Exemple:

($val1, $val2) = unpack("ll", "ABCDEFGH");


On obtient

$val1=0x61626364 ou 0x64636261, $val2=0x65666768 ou 0x68676665.

Les espaces ne sont pas pris en compte dans la chane de format. Un nombre dans cette chane permet en gnral de rpter le format prcdent autant de fois; exemples:

pack ("C4", 140, 186, 65, 25); # quivaut pack ("CCCC", 140, 186, 65, 25); pack ("C2C2", 140, 186, 65, 25); # idem
Un format peut galement tre suivi d'une *, ce qui permet de l'appliquer au reste de la liste ou au reste de l'image mmoire. Exemple:

pack ("C*", 140, 186, 65, 25); # quivaut pack ("CCCC", 140, 186, 65, 25); @valeurs = unpack("C*", "bonjour tout le monde! \n");
Ce dernier exemple gnre une liste de 14 lments (nombres), chacun tant associ un caractre de la chane.

2.15.3. Pour rcuprer des informations sur le rseau

Perl permet la programmation rseau d'une faon trs proche de celle du C. En fait, la plupart des routines Perl permettant d'accder au rseau ont les mmes noms et paramtres que leurs quivalents en C. En gnral, on a besoin de trouver l'adresse d'une machine du rseau dont on connat le nom, et vice versa. La routine Perl gethostbyname() permet de trouver l'adresse partir du nom; exemple:

( $name, $aliases, $addrtype, $length, @addrs) = gethostbyname($name);

juin 1995

Page 105

Le langage PERL

Le paramtre de cette routine est donc un hostname, par exemple slate.bedrock.com. Le rsultat est une liste dont le nombre d'lments dpend du nombre d'adresses associes au nom. Si le hostname n'est pas valide, la liste vide est retourne. L'information importante est le tableau convertir cette chane avec

@addrs;

chacun de ses lments est une adresse IP,

passe Perl en tant que chane de 4 caractres. Si on souhaite afficher le rsultat, il faudra

unpack(). Exemple:

($addr) = (gethostbyname("slate.bedrock.com"))[4]; print "L'adresse de Slate est ", join(".", unpack("C4", $addr)), "\n"; unpack()
prend 4 caractres et retourne 4 nombres, qui, recolls, constitue une adresse IP

comme nous avons l'habitude de les voir.

2.15.4. Pour rcuprer dautres informations

On peut galement rcuprer des informations sur une machine hte partir de son adresse, et des informations sur le rseau partir de son adresse et de son nom. Il existe aussi des routines permettant d'accder aux protocoles et la liste des services du rseau. Elles fonctionnent comme celles du C. Voir le guide de rfrence de Perl en annexe.

2.15.5. Un exemple de programmation rseau avec Perl

Le modle socket 1. Le processus serveur cre une socket gnrique avec 2. Le serveur lie la socket une adresse convenue avec avec

socket(). bind().

Le serveur fait savoir au systme que tout est prt pour ltablissement de connexions

listen(). accept(). socket(). bind().

3. Le serveur attend la premire connexion avec

4. Le processus client cre une socket gnrique avec

5. Le client lie la socket une adresse slectionne par le systme avec

juin 1995

Page 106

Le langage PERL

6. Une fois li, le client connecte sa socket celle du serveur avec utilisant ladresse convenue. Cela tablie la connexion.

connect(),

en

7. Le serveur est averti de cette nouvelle connexion. En gnral, il fait alors appel restant en attente de la prochaine connexion.

fork

pour crer un processus fils qui sera en charge de cette nouvelle connexion, le pre

8. Le processus fils lit les donnes partir de la socket envoye par le client; il y crit galement des donnes qui peuvent ensuite tre lues par le client. Ces E/S sont traites comme sil sagissait de filehandles. 9. Lorsque le fils et le client ont termin leur communication, ils ferment le filehandle, fermant ainsi le connexion.

Un exemple de client Ce client est connect une adresse prcise (le standard daytime) sur une machine hte prcise (local host) et affiche tout ce que le port gnre en sortie:

require 'sys/socket.ph'; $sockaddr = 'S n a4 x8'; chop($hostname = `hostname`); ($name, $aliases, $proto) = getprotobyname('tcp'); ($name, $aliases, $port) = getservbyname('daytime', 'tcp'); ($name, $aliases, $type, $len, $thisaddr) = gethostbyname($hostname); $thisport = pack($sockaddr, &AF_INET, 0, $thisaddr); $thatport = pack($sockaddr, &AF_INET, $port, $thisaddr); socket(S, &PF_INET, &SOCK_STREAM, $proto) || die("Impossible de crer la socket. "); bind(S, $thisport) || die("Impossible de lier la socket. "); connect(S, $thatport) || die("Connexion impossible. "); while (<S>) { print; } exit 0;

Un exemple de serveur Ce serveur cre une socket ladresse 4242 sur la machine courante. Celui qui se connecte sur ce port reoit un gteau de la chance. Chaque gteau nest utilis quune fois (de faon alatoire) jusqu ce que tous les gteaux soient mangs. La base de gteaux est alors ramorce. Ce serveur peut tre utilis avec le client ci-dessus condition de remplacer la ligne daffectation de $port par linstruction $port = 4242. localhost 4242, pour observer la sortie. On peut aussi crire

telnet

juin 1995

Page 107

Le langage PERL

require 'sys/socket.ph'; $sockaddr = 'S n a4 x8'; chop($hostname = `hostname`); ($name, $aliases, $proto) = getprotobyname('tcp'); $port = 4242; $thisport = pack($sockaddr, &AF_INET, $port, "\0\0\0\0"); socket(S, &PF_INET, &SOCK_STREAM, $proto) || die("Impossible de crer la socket. "); bind(S, $thisport) || die("Impossible de lier la socket. "); listen(S, 5) || die("Impossible decouter. "); for ( ; ; ) { accept(NS, S) || die("Impossible daccepter le socket. "); print NS &fortune; close NS; } sub fortune { @fortunes = split(/\n%%\n/, <<'END') unless @fortunes; A fool and his money are soon parted. %% A penny save is a penny earned. %% Ask not what your country can do for you; ask what you can do for your country. %% END splice (@fortunes, int(rand(@fortunes)), 1)."\n"; }

juin 1995

Page 108

Le langage PERL

2.16. MANIPULATION DE BASES DE DONNEES UTILISATEUR

2.16.1. Les donnes et tableaux DBM

La plupart des systmes Unix ont une bibliothque standard appele DBM. Cette bibliothque dispose d'un outil de gestion de base de donnes qui permet aux programmes de stocker des paires (cl, valeur) dans une paire de fichiers du disque. Ces fichiers contiennent les valeurs de la base de donnes entre deux appels aux programmes manipulant cette base. Les programmes peuvent crer de nouvelles donnes, dtruire ou modifier des donnes dj existantes. Perl permet d'accder cet outil de DBM. Un tableau associatif est associ une base de donnes de DBM de la mme manire qu'on ouvre un fichier. Ce tableau associatif (tableau DBM) est ensuite utilis pour accder et modifier la base de donnes DBM. La taille, le nombre et la nature des cls et valeurs de la base de donnes DBM sont limites; on a donc les mmes limitations pour le tableau DBM. En gnral, si on ne dpasse pas 1000 caractres binaires pour les cls et les valeurs, ca passe.

2.16.2. Ouverture et fermeture des tableaux DBM

Pour associer une base de donnes DBM un tableau DBM, on utilise l'oprateur dbmopen(), qui a pour syntaxe:

dbmopen(%NOM_DE_TABLEAU, "nom_du_fichier_dbm", $mode); %NOM_DE_TABLEAU


sur le disque est un tableau associatif Perl. S'il contient dj des valeurs, elles sont tant que paire de fichiers:
nom_du_fichier_dbm.dir

crases. Ce tableau est connect au fichier DBM nom_du_fichier_dbm, gnralement stock en et


nom_du_fichier_dbm.pag . N'importe quel nom est accept pour le tableau, mais en gnral

on utilise des majuscules pour marquer la ressemblance avec les filehandles. Le paramtre

$mode

est un nombre contrlant les droits de la paire de fichiers si ces fichiers

doivent tre crs. Ce nombre est spcifi en octal: la valeur 0644 donne l'accs tout le

juin 1995

Page 109

Le langage PERL

monde en lecture uniquement; seul le propritaire est autoris en lecture et en criture. Si les fichiers existent dj, ce paramtre n'a pas d'effet. Exemple:

dbmopen(%FRED, "mabasededonnees", 0644);


Le tableau

%FRED

est associ aux fichiers mabasededonnees.dir et mabasededonnees.pag

dans le rpertoire courant. Si ces fichiers n'existaient pas, ils sont crs avec le mode 0644.

dbmopen()

retourne vrai si la base de donnes a pu tre ouverte ou cre, faux sinon. Si on

ne veut pas que les fichiers soient crs, il suffit de donner au mode la valeur undef; exemple:

dbmopen(%A, "/etc/xx", undef) || die("Impossible d'ouvrir la DBM /etc/xx. \n");


Si les fichiers /etc/xx.dir et /etc/xx.pag n'ont pu tre ouverts, ils ne sont pas crs et un message est renvoy l'utilisateur. Le tableau DBM reste ouvert pendant toute la dure d'excution du programme. Quand celuici s'achve, l'association se termine aussi. On peut galement mettre fin l'association avec dbmclose(); exemple:

dbmclose(%FRED);
Cet oprateur retourne faux si quelque chose s'est mal pass.

2.16.3. Utilisation dun tableau DBM

Une fois que la base de donnes est ouverte, toute rfrence au tableau DBM est interprte comme une rfrence la base de donnes. Toute modification, destruction ou ajout d'une valeur du tableau engendre les entres correspondantes dans les fichiers de la base de donnes. Exemple:

dbmopen(%FRED, "mabasededonnees", 0644); %FRED{"fred"} = "bedrock"; # cre (ou modifie) un lment delete $FRED{"barney"}; # dtruit un lment de la base de donnes foreach $key (keys %FRED) { print "$key a pour valeur $FRED{$key} \n"; }

juin 1995

Page 110

Le langage PERL

Avec l'oprateur comme suit:

foreach,

on parcourt deux fois le fichier de la base de donnes: une fois

pour les cls et une seconde fois pour les valeurs. Il vaut mieux ici utiliser l'oprateur

each

while ( ($key, $value) = each(%FRED) ) { print "$key a pour valeur $value \n"; }

2.16.4. Bases de donnes de longueur fixe et d'accs alatoire.

Une autre forme persistante de donnes est le fichier disque orient enregistrements de longueur fixe. Chaque enregistrement est compos des mmes champs de longueur fixe; tous les enregistrements ont donc la mme longueur. Par exemple, soit le fichier

SPEINF

contenant les enregistrements pour les annes spciales

info 95; chaque enregistrement possde trois champs:

40 octets pour le nom 40 octets pour le prnom 2 octets pour l'age

Un enregistrement a donc une longueur fixe de 82 octets. Perl permet de manipuler de tels fichiers disques. Cependant il faut savoir: 1. ouvrir un fichier disque en lecture et en criture 2. se dplacer dans ce fichier 3. rcuprer des donnes en connaissant la longueur dune ligne plutt qu'en cherchant le caractre de fin de ligne 4. crire des donnes sous forme de blocs de taille fixe L'oprateur

open()

prend un signe + devant ses spcifications d'E/S pour indiquer que le

fichier est ouvert en lecture et en criture; exemple:

open(A, " + < b"); # le fichier b est ouvert en lecture et en criture open(C, " + > d"); # le fichier d est cr avec les droits en lecture et en criture open(E, " + >> f"); # le fichier f est ouvert ou cr avec les droits en lecture et en criture

juin 1995

Page 111

Le langage PERL

Une fois qu'un fichier est ouvert, il faut pouvoir s'y dplacer. On utilise pour cela l'oprateur seek(), qui prend trois paramtres. Le premier est un filehandle; le second est un offset, interprt en conjonction avec le troisime paramtre. En gnral, on donnera la valeur 0 celui-ci, de faon ce le deuxime paramtre soit interprt comme une nouvelle position absolue pour la prochaine lecture ou criture; exemple:

seek(SPEINF, 4*82, 0);


Le pointeur est positionn au dbut de la cinquime ligne du fichier prochaines entres et sorties. Pour crire dans le fichier de la base de donnes, l'oprateur l'oprateur

SPEINF

(la taille des

enregistrements contenus dans ce fichier est 82 octets). C'est sur cette ligne que s'opreront les

print()

est utilis, mais il faut

tre sr de la longueur de la donne crite. Pour obtenir cette longueur, on fait appel

pack(). Exemple:

print SPEINF pack("A40A40s", $nom, $prenom, $age ); pack()


permet de spcifier que, dans un enregistrement du fichier

SPEINF,

les premier et

deuxime champs ont pour longueur 40 octets et le troisime est un short (2 octets).

$nom,

$prenom et $age doivent vrifier cela.


Pour aller chercher un enregistrement particulier dans le fichier, on utilise l'oprateur read(). Exemple:

$nb = read(SPEINF, $buf, 82);


Le premier paramtre est un filehandle, le deuxime est une variable scalaire qui contiendra les donnes qui seront lues, le troisime est le nombre d'octets lire. nombre d'octets effectivement lus. L'oprateur exemple:

read()

retourne le

unpack()

permet de dcouper la chane de 82 octets qui vient d'tre lue;

($nom, $prenom, $age) = unpack("A40A40s", $buf);


Remarquez que les formats de

pack()

et

unpack()

sont les mmes. En gnral cette chane

est stocke en dbut de programme puisqu'elle est caractristique du fichier tudi.

juin 1995

Page 112

Le langage PERL

2.16.5. Bases de donnes de longueur variable

La plupart des bases de donnes systme et utilisateur sont une srie de lignes de texte comprhensible, avec un enregistrement par ligne. En gnral, elles sont modifies directement avec un diteur de texte. Perl permet une telle mise jour des bases de donnes constitues de lignes grce l'dition en ligne. Cette mthode consiste en une modification de la faon dont loprateur diamant ddition est accd en positionnant loption -i de la ligne de commande. Avant de lancer l'dition en ligne, il faut donner une valeur la variable scalaire variable est importante et nous verrons plus bas en quoi elle consiste. Lorsque loprateur

<>

lit les donnes des fichiers spcifis dans la ligne de commande. En gnral, ce mode

$^I.

Cette

<> est utilis marques par ##INPLACE## dans de loprateur <>:

et que

$^I

a une valeur (diffrente de undef), les lignes

le code suivant sont ajoutes la liste dactions implicites

$ARGV = shift @ARGV; open(ARGV, "<$ARGV"); rename($ARGV, "$ARGV$^I"); ## INPLACE## unlink($ARGV); ## INPLACE## open(ARGVOUT, "> $ARGV"); ## INPLACE## select(ARGVOUT); ## INPLACE##
Les lectures effectues par

<>

sont faites partir du vieux fichier, les critures sont faites sur

une nouvelle copie du fichier. Le vieux fichier reste dans le fichier de backup, dont le nom est le nom du fichier suivi de lextension contenue dans la variable les fichiers de En gnral,

$^I. Ceci est rpt pour tous

@ARGV.
a pour valeur

$^I

.bak

ou

~.

Si

$^I

est la chane vide "", le vieux fichier est

limin. Cependant, il faut tre prudent: si un incident a lieu pendant lexcution du programme, vous perdez alors toutes vos vieilles donnes. Voici une faon de changer le shell de lancement pour tous les utilisateurs du fichier
/etc/passwd:

@ARGV = ("/etc/passwd"); # affectation de loprateur diamant $^I = ".bak"; # crit /etc/passwd.bak pour plus de scurit while (<>) { # pour chaque ligne de /etc/passwd s#:[^:]*$#:/bin/sh#; # change shell de lancement en /bin/sh print; # envoi la sortie sur ARGVOUT: le nouveau /etc/passwd }

juin 1995

Page 113

Le langage PERL

Ce programme est simple; pourtant on peut faire la mme chose avec une unique ligne de commande:

> perl -p -i.bak -e 's#:[^:]*$#/bin/sh#' /etc/passwd


-p permet dencadrer le programme avec une boucle -i permet de fixer la valeur de

while incluant une instruction print.

$^I.

-e indique que largument qui suit est un morceau de code Perl excuter dans le corps de la boucle

while. @ARGV.

Le dernier paramtre donne une valeur initiale

juin 1995

Page 114

Le langage PERL

2.17. CONVERTIR DAUTRES LANGAGES EN PERL

2.17.1. Conversion de programmes awk en Perl

Si vous avez un programme awk que vous voulez faire tourner avec Perl, vous pouvez effectuer une traduction mcanique avec loutil a2p fourni avec Perl. Cet outil convertit la syntaxe awk en syntaxe Perl et permet, pour la majorit des programmes awk, dobtenir un script Perl prt lemploi. Pour utiliser

a2p, mettre le programme awk dans un fichier spar et appeler a2p avec le nom

du fichier comme argument ou avec une redirection en entre avec ce fichier. La sortie est un programme Perl excutable. Exemple:

> a2p < mon_pg_awk > mon_pg_perl > perl mon_pg_perl <arguments>
Un programme awk converti en Perl aura gnralement la mme fonction, mais s'excutera plus rapidement. Le code du programme Perl obtenu peut parfois tre optimis. Certaines conversions ne sont pas mcaniques. Par exemple, awk utilise l'oprateur comparer des chanes ou des nombres, alors que Perl utilise chanes.

>

pour

> avec les nombres et gt avec les

a2p

essaie de deviner quel oprateur Perl convient en fonction de ce qu'il sait des

oprandes. S'il n'est pas sr de son choix, corriger ce genre d'erreur. Pour en savoir plus sur

a2p marque la ligne avec #?? (commentaire Perl) et

une explication. Il vaut donc mieux consulter le script Perl obtenu aprs conversion afin de

a2p, consulter sa page man.

2.17.2. Conversion de programmes sed en Perl

L'oprateur s2p convertit un programme sed en programme Perl. Il s'utilise de la mme faon que

a2p.

Cependant il n'y a en gnral pas d'erreur de conversion.

s2p est crit en Perl!

juin 1995

Page 115

Le langage PERL

2.17.3. Conversion de programmes shell en Perl

Il n'y a malheureusement pas de convertisseur shell/Perl. Le problme est que, dans un shell script, la plupart des commandes ne sont pas excutes par le shell; des appels sont effectus des programmes indpendants pour rcuprer des morceaux de chanes, comparer des nombres, concatner des fichiers... Donc, c'est vous de jouer au convertisseur: tudiez le script shell, comprenez-le et crivez un script Perl ralisant la mme chose! L'oprateur rapidement.

system()

peut vous aider traduire

juin 1995

Page 116

Le langage PERL

2.18. COMPLEMENTS

2.18.1. Loprateur require

Cest lquivalent du include du C. Des programmes Perl peuvent tre stocks dans un ou plusieurs fichiers indpendants et tre ensuite inclus dans tout programme Perl qui a besoin deux; exemple:

require ' abbrev.pl';


permet dinclure le texte du fichier Perl. Cependant, les subroutines incluses doivent retourner une valeur non nulle pour que

abbrev.pl

comme sil faisait partie du fichier dans

lequel figure cette instruction. Du code peut ainsi tre partag entre diffrents programmes

require
ligne:

fonctionne. Par exemple, toutes les routines de la bibliothque se terminent par la

1;

2.18.2. La bibliothque Perl

Elle contient des programmes Perl utiles, vitant de devoir les rcrire soi-mme. Pour savoir dans quel rpertoire elle se trouve, il suffit dimprimer le premier lment du tableau loprateur

@INC. La

plupart des routines sont commentes. Pour les utiliser dans un programme, il suffit dutiliser

require ci-dessus en dbut de programme.

juin 1995

Page 117

Le langage PERL

2.18.3. Les Here Strings

Aprs les chanes entre simples ou doubles quotes, voici les here strings (mme chose que les
here documents en shell):

$a = <<"@HEAD"."\n".$body; To: merlyn@ora.com From: $username Subject: What, do you think? Date: $now HEAD
Elles ne sont vraiment pas ncessaires.

2.18.4. Les alias

On peut faire de

un alias de

en crivant

*b = *a.

Cela signifie que

$a

et

$b

rfrencent

la mme variable, tout comme

@a

et

@b,

ou mme les filehandles et les formats

et

b. *b

peut galement tre utilis localement avec linstruction

local(*b).

2.18.5. Loprateur eval() et s///e

Cest lquivalent de loprateur du mme nom en shell. Il permet dvaluer du bout de code pass en paramtre lors de lexcution du programme Perl. Un exemple, pour tre plus clair:

print "Donnez la commande excuter : "; chop($code = <STDIN>); eval $code; die("eval : $@") if $@; # on teste si eval sest bien pass
Ce script permet dexcuter une commande passe par lutilisateur pendant lexcution comme si elle faisait partie du programme. On peut mettre du code Perl dans la chane de remplacement de loprateur de substitution si celui-ci est suivi du flag e. Cela permet davoir des chanes de remplacement compliques, faisant par exemple appel des subroutines retournant des rsultats.

juin 1995

Page 118

Le langage PERL

Exemple:

while(<>) { s/^(\S+)/$var+1/e; print; }


Le premier mot de chaque ligne de lentre est remplac par la valeur de

$var+1.

2.18.6. Le debugger

Si lon fait appel Perl avec loption -d, le script tourne sous le moniteur de deboggage. Pour connatre les commandes de deboggage, il suffit alors de taper h: cela donne accs la page daide. En tapant simplement:

> perl -de 0


le debugger dmarre sans script.

2.18.7. Loprateur , (virgule)

Cet oprateur value son oprande gauche, limine le rsultat de cette valuation, puis value son oprande droit, retournant cette dernire valuation comme rsultat de lexpression (cela est pratique lorsque loprande gauche est valuer uniquement pour ses effets secondaires, comme lincrmentation dune variable ou lappel une subroutine). Exemple:

$a = ( 1, 3);
affecte

$a avec la valeur 3.

juin 1995

Page 119

Le langage PERL

2.18.8. Les oprateurs sur les bits

Il existe les oprateurs de dcalage de bit gauche, cependant des proprits arithmtiques de la machine.

>>,

et droite,

<<.

Le rsultat dpend

On dispose galement des oprateurs logiques sur les bits:

&, et logique |, ou logique ^, ou exclusif

Ces oprateurs travaillent sur des valeurs numriques entires.

2.18.9. Les paquetages

On dsire parfois que les donnes dun programme soient prives et inaccessibles dautres programmes. Perl dispose pour cela dun mcanisme de paquetage, qui fournit un espace dadressage indpendant. On peut alors avoir deux variables portant le mme nom dans deux programmes diffrents: elles sont indpendantes. Le mot rserv package permet de dclar des paquetages, nimporte o dans le programme. Une telle dclaration est effective de la ligne o elle est effectue la fin du bloc la contenant. Exemple:

package pecan; sub tarte { $reponse = <STDIN>; # une variable package canari; $reponse = <STDIN>; # une autre variable }
Il est possible de rfrencer les variables et les filehandles dun paquetage lintrieur dautres paquetages; il suffit de faire prcder leur nom du nom du paquetage et dune quote simple. Lexemple prcdent devient alors:

sub pecan'tarte { $pecan'reponse = <STDIN>; $canari'reponse = <STDIN>;

Si le nom du paquetage est nul, ce paquetage est considr comme le paquetage principal ou main package. Alors

$'tarte est la mme chose que $main'tarte.

juin 1995

Page 120

Le langage PERL

Seuls les identificateurs dont les noms commencent par une lettre sont stocks dans la table de symboles du paquetage. Les autres symboles (toutes les variables spciales) et

STDIN,

STDOUT, STDERR, ARGV, AGVOUT, ENV, INC


principal.

et

SIG

sont conservs dans le paquetage

La table de symboles de chaque paquetage est stocke dans un tableau associatif situ dans la table de symboles du paquetage principal. Le nom de la table de symboles du paquetage nest autre que

bleu

%_bleu.

juin 1995

Page 121

Le langage PERL

juin 1995

Page 122

Le langage PERL

3. EXEMPLE DAPPLICATION

juin 1995

Page 123

Le langage PERL

juin 1995

Page 124

Le langage PERL

3.1. UN SYSTEME DE RESERVATION DE VOLS


Comme nous lavons vu dans le chapitre 2, Perl a des domaines dutilisation trs varis:

Manipulation de bases de donnes Administration du systme Manipulation de fichiers, de textes, de processus Communication interprocessus ...

En voici un exemple concret: un systme de rservation de vols. Le fichier place_disp joue le rle de base de donnes. Il contient des enregistrements de la forme:

code-vol:ville-dpart:ville-arrive:heure-dpart:heurearrive:date-dpart:classe:nb-places-dispo:prix
Le fichier suivant est utilis pour tester le programme:

AI132:Paris:Nice:10h00:11h20:22/06/95:eco:8:400 AF330:Lille:Toulouse:22h30:23h50:23/07/95:club:16:1030 BA120:Paris:Londres:15h40:17h00:21/08/95:prem:8:2500 AF562:Nice:Paris:21h00:22h20:21/07/95:eco:44:400 AF457:Nice:Paris:22h00:23h20:21/07/95:eco:20:400 IB120:Lisbonne:Lille:12h00:14h30:10/08/95:club:23:3000 KL498:Amsterdam:Nice:17h00:19h30:17/09/95:eco:60:1500


Une interface permet l'utilisateur d'indiquer le vol qui l'intresse. Le fichier place_disp est parcouru, la recherche d'un vol qui correspond aux saisies de l'utilisateur. Il est possible d'effectuer des rservations. Le fichier reservation reoit alors les donnes. Enfin, des factures peuvent tre imprimes; pour cela, le fichier reservation est consult.

juin 1995

Page 125

Le langage PERL

juin 1995

Page 126

Le langage PERL

3.2. LE PROGRAMME PERL


################# Formats ####################################### format ENTETE = Vol @<<<<<<<<< -> @<<<<<<<<< le @<<<<<<< $VD, $VA, $date . format FORMAT1 = =============================================================== heure depart| heure arrivee| code vol| classe| nb places| prix =============================================================== @|||| | @|||| | @|||| | @|||| | @|| | @<<<< $HD, $HA, $codevol, $classe, $nb_place, $prix

. format MENU = ************************************************************** ** Bienvenue sur notre systeme de reservation! ** ************************************************************** Nous vous offrons les services suivants : 1. 2. q. renseignements/reservations facture quitter

. format FORMAT3 =

Ville de depart: @<<<<<<<<< $VA Ville d'arrivee: @<<<<<<<<< $VD .

juin 1995

Page 127

Le langage PERL

format FACTURE = ============================================================= FACTURE ============================================================= no reservation : @<<<< $no_resa nom : @<<<<<<<<< $nom @<<<<<<< @<<<<<<<<< $date, $VD, $HD @<<<<<<<<< $VA, $HA @<<<< @<<<<

code du vol : @<<<< $codevol classe : @<<<< $classe somme a payer : @<<<< $prix somme versee $verse somme due $prix-$verse . ----: @<<<< : @<<<<

format ENREGISTRE = @<<<<:@<<<<<<<<<:@<<<<:@<<<<<<<<<:@<<<<:@<<<<<<<<<:@<<<<:@<<<<<<<:@< <<<:@<<<<:@<<<< $no_resa, $nom, $codevol, $VD, $HD, $VA, $HA, $date, $classe, $prix, $verse .

################## Programme principal ######################### # initialisation des numeros de resa $no_resa = 0; #lancement &menu_principal($no_resa);

juin 1995

Page 128

Le langage PERL

##################

Subroutines ################################

sub menu_principal { #### nettoyage de l'ecran system("clear"); #### recuperation du numero de reservation $no_resa = $_[0]; #### impression du menu $~ = "MENU"; write; print "Votre choix: "; chop($choix=<STDIN>); print "\n"; #### Traitement du choix de l'utilisateur if ($choix == 1) { #### nettoyage de l'ecran system("clear"); #### obtenir des renseignements et eventuellement reserver #### Saisie des donnees et #### appel a la subroutine renseign &renseign(&saisie_cherch, $no_resa); } elsif ($choix == 2) { #### nettoyage de l'ecran system("clear"); #### imprimer une facture &facture; } else { #### On sort du programme exit 0; } }

sub saisie_cherch { #### Saisie des villes de depart, d'arrivee et de la date de depart print "Ville de depart: "; chop($VD = <STDIN>); print "\n";

juin 1995

Page 129

Le langage PERL

print "Ville d'arrivee: "; chop($VA = <STDIN>); print "\n"; print "Date de depart: "; chop($date = <STDIN>); print "\n"; #### valeur de retour @donnees = ($VD, $VA, $date); }

sub reserv { #### Saisie des donnees print "Nom du client: "; chop($nom = <STDIN>); print "\n"; ($VD, $VA, $date, $o_resa, $codevol, $HD, $HA, $classe, $nb_place, $prix) = @_; print "Accompte: "; chop($verse = <STDIN>); print "\n"; #### mise a jour du numero de reservation $no_resa ++; # modification du nombre de places disponibles # ouverture en lecture du fichier place_disp open(A, "< place_disp"); # ouverture en ecriture d'un fichier temporaire open(C, ">> temp_fic"); # parcours du fichier place_disp while(<A>) { $sauv = $_; if ( $sauv =~ /^$codevol:$VD:$VA:$HD:$HA:$date:$classe:/i) { $sauv = $&; ($nb_place, $prix) = split(/:/, $'); $nb_place --; $rempl = $sauv.$nb_place.":".$prix; s/^.*$/$rempl/; } print C; } close(A); close(C); unlink("place_disp"); open(A, ">> place_disp"); open(C, "< temp_fic");

juin 1995

Page 130

Le langage PERL

while(<C>) { print A unless (/^$/); } close(A); close(C); unlink("temp_fic"); #### enregistrement dans le fichier reservation open(B, ">> reservation"); select(B); $~ = "ENREGISTRE"; write; select(STDOUT); print "\n\nReservation effectuee.\n\n\n"; print "numero de resa = $no_resa\n\n\n"; print " Tapez q pour quitter\n principal\n"; chop($choix = <STDIN>); #### traitement du choix de l'utilisateur if ($choix eq 'r') { #### nettoyage de l'ecran system("clear"); #### retour au menu pricipal &menu_principal($no_resa); } else { #### on sort du programme exit 0; } } r pour menu

sub renseign { #### Initialisations $trouve = 0; @tab1 = ($VD, $VA, $date, $no_resa) = @_; #### ouverture en lecture du fichier place_disp open (A, "< place_disp"); #### Consultation du fichier PLACE_DISP #### Recherche des renseignements BLOC: while (<A>) { #### Sauvegarde de $_ $sauv = $_;

juin 1995

Page 131

Le langage PERL

#### Recherche des vols remplissant les conditions if (/$VD:$VA:.*:.*:$date/i) { $_ = $sauv; $~ = "ENTETE"; write; #### Recuperation des informations @tab2 = ($codevol, $HD, $HA, $classe, $nb_place, $prix) = /^(\S+):.*:.*:(\S+):(\S+):.*:(\S+):(\S+):(\S+)$/; #### un vol a ete trouve $trouve ++; #### Affichage des informations $~ = "FORMAT1"; write; print " Tapez q pour quitter \n s pour suivant\n a pour A/R\n"; chop($choix = <STDIN>); #### traitement du choix de l'utilisateur if ($choix eq 'q') { #### on sort du programme exit 0; } elsif ($choix eq 'r') { #### nettoyage de l'ecran system("clear"); #### fermeture de place_disp close(A); #### on effectue une reservation &reserv(@tab1, @tab2); } elsif ($choix eq 'a') { #### nettoyage de l'ecran system("clear"); #### on recherche un retour $~ = "FORMAT3"; write; print "Date de retour: "; chop($date = <STDIN>); print "\n"; #### Inversion des villes de depart et d'arrivee $sauv = $VA; $VA = $VD; $VD = $sauv;

r pour reserver\n

juin 1995

Page 132

Le langage PERL

#### Reinitialisation de l'index $trouve = 0; #### Modification de @tab1 @tab1 = ($VD, $VA, $date, $no_resa); #### Reinitialisation du pointeur sur la ligne courante de place_disp open(A,"< place_disp"); #### on relance la recherche next BLOC; } } } if ($trouve == 0) { #### aucun vol n'a ete trouve correspondant aux exigences print "Pas d'avion pour ce trajet a cette date.\nVoulez-vous saisir une autre date (o/n)? "; chop($rep = <STDIN>); print "\n"; close(A); #### traitement du choix de l'utilisateur if ($rep=~/^o/) { #### nettoyage de l'ecran system("clear"); #### saisie d'une nouvelle date print "Date de depart: "; chop($date = <STDIN>); print "\n"; #### on relance la recherche &renseign($VD, $VA, $date, $no_resa); } else { #### nettoyage de l'ecran system("clear"); #### retour au menu principal &menu_principal($no_resa); } } else { #### Il n'y a plus d'autres vols correspondant aux exigences print "\n\n\n\n"; print "Pas d'autre vol."; close(A);

juin 1995

Page 133

Le langage PERL

print "\n\n\n Tapez q pour quitter\n recherche\n r pour menu principal\n"; chop($choix = <STDIN>); #### traitement du choix de l'utilisateur if ($choix eq 'q') { #### on quitte le programme exit 0; } elsif ($choix eq 'a') { #### nettoyage de l'ecran system("clear"); #### une autre recherche est lancee &renseign(&saisie_cherch, $no_resa); } else { #### nettoyage de l'ecran system("clear"); #### retour au menu principal &menu_principal($no_resa); } } }

a pour autre

sub facture { #### initialisation de l'index $trouve = 0; #### saisie du numero de resa print "Donnez le numero de reservation: "; chop($no_resa = <STDIN>); print "\n"; #### recherche dans le fichier des reservations open(B, "< reservation"); while (<B>) { $sauv = $_; if (/^$no_resa/) { ($no_resa, $nom, $codevol, $VD, $HD, $VA, $HA, $date, $classe, $prix, $verse) = split(/:/, $sauv); $trouve ++; #### affichage $~ = "FACTURE"; write; } }

juin 1995

Page 134

Le langage PERL

if ($trouve == 0) { #### aucune reservation n'a ete trouvee print "Aucune reservation ne correspond a ce numero.\n"; } #### autre facture? print " Tapez a pour autre facture\n principal\n q pour quitter\n"; chop($choix = <STDIN>); #### traitement du choix de l'utilisateur if ($choix eq 'a') { #### nettoyage de l'ecran system("clear"); #### impression d'une autre facture &facture; } elsif ($choix eq 'r') { #### nettoyage de l'ecran system("clear"); #### retour au menu principal &menu_principal; } else { #### on quitte le programme exit 0; } }

r pour menu

juin 1995

Page 135

Le langage PERL

juin 1995

Page 136

Le langage PERL

3.3. RESULTATS

************************************************************** ** Bienvenue sur notre systeme de reservation! ** ************************************************************** Nous vous offrons les services suivants : 1. 2. q. renseignements/reservations facture quitter

Votre choix: 1 Ville de depart: paris Ville d'arrivee: londres Date de depart: 21/08/95 Vol paris -> londres le 21/08/95

=============================================================== heure depart| heure arrivee| code vol| classe| nb places| prix =============================================================== 15h40 | 17h00 | BA120 | prem | 8 | 2500

Tapez q r s a s

pour pour pour pour

quitter reserver suivant A/R

Pas d'autre vol. Tapez q pour quitter a pour autre recherche r pour menu principal a

juin 1995

Page 137

Le langage PERL

Ville de depart: paris Ville d'arrivee: nice Date de depart: 22/06/95

Vol paris

-> nice

le 22/06/95

=============================================================== heure depart| heure arrivee| code vol| classe| nb places| prix =============================================================== 10h00 | 11h20 | AI132 | eco | 8 | 400

Tapez q r s a a

pour pour pour pour

quitter reserver suivant A/R

Ville de depart: nice Ville d'arrivee: paris Date de retour: 21/07/95 Vol nice -> paris le 21/07/95

=============================================================== heure depart| heure arrivee| code vol| classe| nb places| prix =============================================================== 21h00 | 22h20 | AF562 | eco | 45 | 400

Tapez q r s a s

pour pour pour pour

quitter reserver suivant A/R

juin 1995

Page 138

Le langage PERL

Vol nice

-> paris

le 21/07/95

=============================================================== heure depart| heure arrivee| code vol| classe| nb places| prix =============================================================== 22h00 | 23h20 | AF457 | eco | 21 | 400 Tapez q r s a r pour pour pour pour quitter reserver suivant A/R

Nom du client: poiraud Accompte: 100 numero de resa = 1

Reservation effectuee. Tapez q pour quitter r pour menu principal r

************************************************************** ** Bienvenue sur notre systeme de reservation! ** ************************************************************** Nous vous offrons les services suivants : 1. 2. q. renseignements/reservations facture quitter

Votre choix: 2

juin 1995

Page 139

Le langage PERL

Donnez le numero de reservation: 1

============================================================= FACTURE ============================================================= no reservation : 1 nom : poiraud 21/07/95 nice paris 22h00 23h20

code du vol : AF457 classe : eco somme a payer : 400 somme versee : 100 ----somme due : 300 Tapez a pour autre facture r pour menu principal q pour quitter r

************************************************************** ** Bienvenue sur notre systeme de reservation! ** ************************************************************** Nous vous offrons les services suivants : 1. 2. q. renseignements/reservations facture quitter

Votre choix: 1

Ville de depart: lille Ville d'arrivee: toulouse Date de depart: 22/07/95 Pas d'avion pour ce trajet a cette date. Voulez-vous saisir une autre date (o/n)? o

juin 1995

Page 140

Le langage PERL

Date de depart: 23/07/95 Vol lille -> toulouse le 23/07/95

=============================================================== heure depart| heure arrivee| code vol| classe| nb places| prix =============================================================== 22h30 | 23h50 | AF330 | club | 17 | 1030

Tapez q r s a r

pour pour pour pour

quitter reserver suivant A/R

Nom du client: grossiord Accompte: 0 numero de resa = 2 Reservation effectuee. Tapez q pour quitter r pour menu principal q

Aprs ces tests, l'tat du fichier reservation, initialement vide, est:

1 2

:poiraud

:AF457:nice

:22h00:paris

:23h20:21/07/95:eco :400 :100

:grossiord :AF330:lille

:22h30:toulouse :23h50:23/07/95:club :1030 :0

juin 1995

Page 141

Le langage PERL

juin 1995

Page 142

Le langage PERL

4. EXERCICES

juin 1995

Page 143

Le langage PERL

juin 1995

Page 144

Le langage PERL

4.1. ENONCES

4.1.1. Chapitre 2.1.

Ecrire un programme qui attend que lutilisateur saisisse un rayon avant de calculer le primtre du cercle.

4.1.2. Chapitre 2.2.

Ecrire un programme qui lit un chiffre et une liste de chanes (chacune sur une ligne) et qui retourne la ligne slectionne par le chiffre.

4.1.3. Chapitre 2.3.

1. Ecrire un programme demandant la temprature extrieure, et affichant trop chaud! si elle est suprieure 30, trop froid! si elle est infrieure 20, impeccable! si elle est comprise entre 20 et 30 . 2. Ecrire un programme qui lit une liste de chanes (chacune sur une ligne) et les affiche dans lordre inverse (sans utiliser reverse, bien sr!).

juin 1995

Page 145

Le langage PERL

4.1.4. Chapitre 2.4.

Ecrire un programme qui lit une srie de mots (un mot par ligne) et qui affiche le nombre de fois que figure chaque mot dans la liste.

4.1.5. Chapitre 2.5.

Ecrire un programme faisant la mme chose que cat mais inversant lordre des lignes.

4.1.6. Chapitre 2.6.

Ecrire un programme qui parcourt /etc/passwd, cherche deux utilisateurs ayant le mme nom et affiche ces noms.

4.1.7. Chapitre 2.7.

Ecrire une subroutine qui prend les valeurs numriques de deux chiffres, les additionne et affiche le rsultat sous la forme:

"deux plus deux gale quatre. "

4.1.8. Chapitre 2.8.

Modifier le problme prcdent de faon ce que lopration soit rpte jusqu ce que le mot

end soit saisi.

juin 1995

Page 146

Le langage PERL

4.1.9. Chapitre 2.9.

Ecrire un programme prenant un nom de fichier dentre, un nom de fichier de sortie, un pattern chercher, une chane de remplacement, et qui remplace toute occurrence du pattern dans le fichier dentre par la chane de remplacement et met le rsultat dans le fichier de sortie.

4.1.10. Chapitre 2.10.

Ecrire un programme ouvrant /etc/passwd et affichant les logins utilisateur, les UID et les vrais noms sous forme de colonnes.

4.1.11. Chapitre 2.11.

Ecrire un programme qui permet de changer de rpertoire et de se retrouver dans celui saisi par lutilisateur, et qui affiche la liste des fichiers de ce rpertoire dans lordre alphabtique.

4.1.12. Chapitre 2.12.

Ecrire un programme ralisant la mme chose que mv.

4.1.13. Chapitre 2.13.

Ecrire un programme qui rcupre tous les vrais noms dutilisateur de /etc/passwd et transforme la sortie de la commande who, en remplaant les logins par les vrais noms.

juin 1995

Page 147

Le langage PERL

4.1.14. Chapitre 2.14.

Ecrire un programme affichant les logins et les vrais noms dutilisateur du fichier /etc/passwd, ordonns par le prnom.

4.1.15. Chapitre 2.15.

Ecrire un programme crant une correspondance entre UID et vrai nom dutilisateur partir de
/etc/passwd et utiliser cette correspondance pour afficher une liste de vrais noms appartenant

chaque groupe du fichier /etc/group.

4.1.16. Chapitre 2.16.

Ecrire deux programmes: lun qui lit les donnes de loprateur diamant, les dcoupe en mots, et met jour un fichier DBM indiquant le nombre de fois quapparat chaque mot; lautre qui ouvre un fichier DBM et affiche les rsultats dans lordre dcroissant.

4.1.17. Chapitre 2.17.

Convertir le script shell suivant en Perl:

cat /etc/passwd | awk -F: '{print $1, $6}' | while read user home do newsrc="$home/.newsrc" if [ -r $newsrc ] then if grep -s '^comp\.lang\.perl: ' $newsrc then echo "$user is a good person, and read comp.lang.perl! " fi fi done

juin 1995

Page 148

Le langage PERL

4.2. SOLUTIONS
Ces solutions ne sont pas uniques!

4.2.1.

$pi = 3.14; print "Donnez le rayon du cercle : \n"; chop($rayon = <STDIN>); print "Le primtre du cercle est : ".(2*$pi*$rayon);

4.2.2.

print "Donnez un chiffre: \n"; chop($compte = <STDIN>); print "Donnez une liste de chanes, terminez lentre par ^D: \n"; @tab = <STDIN>; print "La $compteime chane est $tab[$compte-1].\n";

4.2.3.

1.

print "Donnez la temprature ambiante : \n"; chop($temp = <STDIN>); if ($temp > 30) { print "Trop chaud!\n"; } elsif ($temp < 20) { print "Trop froid! \n"; } else { print "Impeccable!\n");

juin 1995

Page 149

Le langage PERL

2.

print "Donnez la liste de chanes, terminez lentre avec ^D: \n"; @liste = <STDIN>; $i = $#liste-1; unless ($i == -1) { print "$liste[$i--]\n"; } # on peut aussi utiliser pop()

4.2.4.

print "Donnez une liste de mots : \n"; @liste = <STDIN>; $tab{chop(shift(@liste))} ++; while ( ($cle, $val) = each(%tab) ) { print "Le mot $cle apparat $val fois.\n";

4.2.5.

print reverse <>;

4.2.6.

while (<>) { ($user, $pass, $uid, $gid, $gcos) = split(/:/); ($real) = split(/,/,$gcos); ($first) = split(/\s+/, $real); $seen{$first}++; } foreach (keys %seen) { if ($seen{$_} > 1) { print "$_ a t vu $seen{$_} fois.\n"; } }

juin 1995

Page 150

Le langage PERL

4.2.7.

sub card { @card_map = (0, "un", "deux", "six", "sept", "huit", "neuf"); local($nombre) = @_; if ($card_map[$nombre]) { $card_map[$nombre]; } else { $nombre; }

"trois",

"quatre",

"cinq",

print "Donnez le premier nombre: \n"; chop($prem = <STDIN>); print "Donnez le deuxime nombre: \n"; chop($deux = <STDIN>); $message = &card($prem) . "plus" . &card($prem+$deux) . ".\n"; $message =~ s/^./\u$&/; print $message;

&card($deux).

"gale"

4.2.8.

sub card { } # mme que pour lexercice prcdent while () { ##NEW## print "Donnez le premier nombre: \n"; chop($prem = <STDIN>); last if $prem eq "end"; ##NEW## print "Donnez le deuxime nombre: \n"; chop($deux = <STDIN>); last if $deux eq "end"; ##NEW## $message=&card($prem) ."plus" .&card($deux). .&card($prem+$deux) . ".\n"; $message =~ s/^./\u$&/; print $message; } ##NEW##

"gale"

juin 1995

Page 151

Le langage PERL

4.2.9.

print "Nom du fichier dentre: \n"; chop($fic_in = <STDIN>); print "Nom du fichier de sortie: \n"; chop($fic_out = <STDIN>); print "Pattern rechercher: \n"; chop($pattern = <STDIN>); print "Chane de remplacement: \n"; chop($chaine = <STDIN>); open (IN, $fic_in) || die("Impossible douvrir $fic_in!\n"); die("Je ncraserai pas $fic_out!\n) if -e $fic_out; open (OUT, "> $fic_out") || die("Impossible de crer $fic_out!\n"); while (<IN>) { s/$pattern/$chaine/g; print OUT $_; } close(IN); close(OUT);

4.2.10.

open (PW, "/etc/passwd") || die("Comment vous tes-vous logg? \n"); while (<PW>) { ($user, $passwd, $uid, $gid, $gcos) = split(/:/); ($real) = split(/,/, $gcos); write; } format STDOUT = @<<<<<<< @>>>>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $user, $uid, $real .

4.2.11.

print "O voulez-vous aller? :\n"; chop($rep=<STDIN>); chdir ($rep) || die ("Impossible daccder ce rpertoire!\n"); foreach (<*>) { print "$_\n"; }

juin 1995

Page 152

Le langage PERL

4.2.12.

($old, $new) = @ARGV; if (-d $new) { ($base = $old) =~ s#.*/##; $new .= "/$base"; } rename ($old, $new);

4.2.13.

open (PW, "etc/passwd"); while (<PW>) { chop; ($user, $passwd, $uid, $gid, $gcos) = split(/:/); ($real) = split(/,/, $gcos); $real{$user} = $real; } close(PW); open (WHO, "who |") || die ("Impossible douvrir le pipe du who!\n"); while (<PW>) { ($login, $reste) = /^(\S+)\s+(.*)/; $login = $real{$login} if $real{$login}; printf "%-30s %s\n", $login, $reste; }

4.2.14.

open (PW, "etc/passwd"); while (<PW>) { chop; ($user, $passwd, $uid, $gid, $gcos) = split(/:/); ($real) = split(/,/, $gcos); $real{$user} = $real; ($prenom = $real) =~ s/^(.*[^a-z])?([a-z]+.*).*/$2/i; $prenom =~ tr/A-Z/a-z/; $prenom{$user} = $prenom; } close(PW); for (sort by_last keys %prenom) { print "%30s %8s\n", $real{$_}, $_; } sub by_last { ($prenom{$a} cmp $prenom{$b}) || ($a cmp $b); }

juin 1995

Page 153

Le langage PERL

4.2.15.

$: = " "; while (@pw = getpwent) { ($user, $gid, $gcos) = @pw[0, 3, 6]; ($real) = split(/,/, $gcos); $real{$user} = $real; $members{$gid} .= " $user"; ($prenom = $user) =~ s/^(.*[^a-z])?([a-z]+.*).*/$2/i; $prenom =~ tr/A-Z/a-z/; $prenom{$user} = $prenom; } while (@gr = getprent) { ($gname, $gid, $members) = @gr[0, 2, 3]; $members{$gid} .= " $members"; $gname{$gid} = $gname; } for $gid (sort by_gname keys %gname) { %all = ( ); for (split(/\s+/, $members{$gid}) ) { $all{$_}++ if length $_; } @members = ( ); foreach (sort by_last keys %all) { push(@members, "$real{$_} ($_)"); } $memberlist = join(", ", @members); write; } sub by_gname { $gname{$a} cmp $gname{$b}; } sub by_last { ($last{$a} cmp $last{$b}) || ($a cmp $b) ; } format STDOUT = @<<<<<<<< @<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $gname{$gid}, "($gid) ", $memberlist ~~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $memberlist .

juin 1995

Page 154

Le langage PERL

4.2.16.

# programme 1 dbmopen (%MOTS, "mots", 0644); while (<>) { foreach $mot ( split(/\W+/) ) { $MOTS{$mot}++; } } dbmclose(%MOTS); # programme 2 dbmopen (%MOTS, "mots", undef); foreach $mot ( sort { $MOTS{$b} <=> $MOTS{$a} } keys %MOTS ) { print "$mot $MOTS{$mot}\n" ; } dbmclose(%MOTS);

4.2.17.

for ( ; ; ) { ($user, $home) = (getpwent)[0,7]; last unless $user; next unless open(N, "$home/.newsrc"); next unless -M N < 30; while (<>) { if (/^comp\.lang\.perl:/) { print "$user is a good person and reads comp.lang.perl!\n"; last; } } }

juin 1995

Page 155

Le langage PERL

juin 1995

Page 156

Le langage PERL

ANNEXE : LE GUIDE DE REFERENCE DE PERL

juin 1995

Page 157

Le langage PERL

juin 1995

Page 158

Vous aimerez peut-être aussi