Académique Documents
Professionnel Documents
Culture Documents
INTRODUCTION
T'
3 4
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
123
143
4.1. E 4.2. S
NONCES OLUTIONS
145 149
157
juin 1995
Page 1
Le langage PERL
juin 1995
Page 2
Le langage PERL
INTRODUCTION
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!
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
juin 1995
Page 5
Le langage PERL
juin 1995
Page 6
Le langage PERL
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
<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
STDOUT
celui de la sortie et
STDERR
celui du fichier
erreur.
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,
juin 1995
Page 7
Le langage PERL
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
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
#. ;.
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.
En ligne :
> perl
-e
juin 1995
Page 8
Le langage PERL
#!,
#!/usr/bin/perl
Le fichier contenant le script doit tre excutable (chmod script, on peut ensuite taper:
u+x nomfic);
pour excuter le
> nomfic
eval
'/usr/bin/perl
-S
$0
${ 1 + "$@" }'
if
0 ;
La variable en awk).
$_
Elle permet daccder la ligne courante d'un fichier que l'on est en train de consulter (cf. $0
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
$credit
!=
(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:
> equivcat
toto
tutu
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:
<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.
Lautre faon dexprimer une condition en Perl est dutiliser if. Lexemple suivant est lquivalent du grep du shell:
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
spcifier si on le dsire.
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 == != > >= < <= <=>
Signification gal diffrent suprieur suprieur ou gal infrieur infrieur ou gal diffrent, avec retour du signe
$a $b if if
= = ( (
juin 1995
Page 11
Le langage PERL
Oprateurs logiques
$a && $b $a || $b ! $a
Oprateurs arithmtiques
$a exposant $b
incrmentation dcrmentation tire alatoirement une valeur entre 0 et
$a
concatnation
$a rpte $b fois
extraction dune sous chane de
$a $a $a $a
-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
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
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
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 :
INDEX
ARRAY la liste ventuelle dont les lments seront insrs dans ARRAY
Un exemple d'utilisation :
va disparatre.
LONGUEUR
@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 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
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
est valu dans un contexte de tableau, il renvoie la liste qu'il contient. S'il tait
juin 1995
Page 16
Le langage PERL
@speinf = ('seb','cricri','pascal','xav','gilles','hugo','sissou');
Oprations Rsultats
reverse @speinf
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
$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
juin 1995
Page 18
Le langage PERL
$var
et le tableau
@ARGV
en une
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:
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:
$fred = "pay"; $fredday = "wrong!"; $barney = "It's $fredday"; $barney = "It's ${fred}day";
juin 1995
Page 19
Le langage PERL
//, 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 : (\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 "13:26:00"
juin 1995
Page 21
Le langage PERL
%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
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:
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:
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
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:
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
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:
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 \"
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:
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
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:
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;
Perl dispose aussi de l'auto-incrmentation et de l'auto-dcrmentation, qui peuvent tre utilises sous forme de prfixe ou de suffixe:
quivaut
$a += 1;
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:
juin 1995
Page 28
Le langage PERL
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"
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
print "Donnez un nombre :"; $a = <STDIN>; chop($a); print "Votre nombre : $a";
L'oprateur
print "coucou";
juin 1995
Page 29
Le langage PERL
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
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:
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:
# diffrent de @tableau
juin 1995
Page 31
Le langage PERL
2.2.3. Laffectation
@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 );
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:
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
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:
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:
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:
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:
pop() renvoie la valeur undef si la liste qu'on lui a passe en paramtre est vide.
juin 1995
Page 33
Le langage PERL
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.
Cet oprateur permet dinverser lordre des lments dun tableau. Il retourne une liste; exemples:
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
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 ?" )
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.
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
}
Cest donc une squence dinstructions spares par des points virgules, et encadre par des accolades. Perl excute les instructions dans lordre.
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
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... .
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
Linstruction
while
permet de rpter
lexcution
dun
bloc
dinstructions
tant
que
while,
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
until;
Elle est trs semblable celle dont on dispose en C; elle est en effet de la forme:
test_exp
test_exp
, tant que
juin 1995
Page 39
Le langage PERL
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:
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:
juin 1995
Page 40
Le langage PERL
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
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
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()
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().
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()
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
STDIN
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:
$_
<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
<STDIN>:
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:
<>
@ARGV
chapitre 1. Pour ceux qui nont pas suivi, ce tableau est la liste des arguments de la ligne de commande.
Perl utilise
et
printf
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
$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:
juin 1995
Page 47
Le langage PERL
juin 1995
Page 48
Le langage PERL
tre dcrite avec lun des outils Unix peut galement tre crite en Perl, sans ncessairement utiliser les mmes caractres.
Si lon dsire rcuprer les lignes du fichier nomfic comportant la chane commande:
abc,
on utilise la
abc
grep
abc
est considre comme une expression rgulire si elle est encadre par des
grep
} $_,
qui contient la ligne courante du fichier pass en
paramtre au script. La sortie se fait sur la sortie standard. Si maintenant on veut trouver les lignes de nomfic contenant un et dun
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:
} 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
$_)
et dun
$_
c. def.
Les patterns un seul caractre Le plus simple est un unique caractre qui se matche lui-mme. Ainsi, rechercher la lettre
/a/
permet de
Le point, ".", permet de matcher nimporte quel caractre sauf newline (\n). Par exemple,
/a./
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]/
une classe de caractres: tout caractre ne se trouvant pas dans la liste sera match.
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
?,
/fo+ba?r/
matche un
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:
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:
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:
c.
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])
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,
fredxbarneyy
ne lest pas.
/a(.)b(.)c\2d\1/;
juin 1995
Page 52
Le langage PERL
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.
/a(.*)b\1c/;
matche un
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|b|c,
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
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, 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:
commenant par a comportant un a, suivi de ^ contenant le caractre ^ dont le dernier caractre est
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
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
=~
et
!~
<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"
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:
juin 1995
Page 56
Le langage PERL
=~
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"
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
$_;
/\s+/.
@mots = split;
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:
juin 1995
Page 58
Le langage PERL
Pour faire appel une subroutine, nimporte o dans le programme, on fait prcder son nom par le symbole &; exemple:
juin 1995
Page 59
Le langage PERL
Une subroutine peut faire appel dautres subroutines faisant elles-mmes appel dautres subroutines...
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:
# $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
Si lappel une subroutine est suivi dune liste parenthse, la liste est automatiquement range dans le tableau
ce tableau pour savoir combien il y a darguments et quelle est leur valeur. Exemple:
juin 1995
Page 60
Le langage PERL
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.
@_
@_,
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
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
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
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
for, foreach, while et les blocs if ou une subroutine ou un bloc plus important).
Comme
last, next
lexcution dun corps de boucle, sans terminer le bloc. Il est utilis comme suit:
juin 1995
Page 63
Le langage PERL
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; ... }
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.
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
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
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
juin 1995
Page 65
Le langage PERL
Un exemple dutilisation: sortir dune boucle quand une certaine condition est vrifie:
exp2 while exp1; # quivaut while (exp1) { exp2;} exp2 unless exp1;# quivaut unless (exp1) { exp2;} exp2 until exp1; # quivaut until (exp1) { exp2;}
Une autre faon dcrire: si ceci, alors cela , est dutiliser le et-logique:
si
ceci
est vraie, alors lexpression ci-dessus nest pas encore totalement value
puisquelle dpend de si
ceci est fausse, alors lexpression ci-dessus est fausse aussi; pas besoin dvaluer cela. cela
est value uniquement si
Donc
ceci
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.
juin 1995
Page 66
Le langage PERL
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
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
# 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
# ouverture en criture
Pour ouvrir un fichier et crire la suite de ce quil contient dj, il suffit dcrire:
juin 1995
Page 67
Le langage PERL
open retournent vrai si louverture sest droule avec succs, faux sinon.
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
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:
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
juin 1995
Page 68
Le langage PERL
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
STDOUT:
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
-s
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
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:
$_;
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
2.9.7. Le filehandle _
A chaque utilisation de
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
_.
stat()
ou
lstat(),
$nomfic
_:
juin 1995
Page 71
Le langage PERL
juin 1995
Page 72
Le langage PERL
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.
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,
=.
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 @<<<<<<<<<<; 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.
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:
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:
write
write
est le filehandle sur lequel est effectue la sortie et que le format du mme nom est utilis par
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:
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,
^<<<<<).
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,
$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
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.
$%
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:
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:
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()
$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;
$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
juin 1995
Page 79
Le langage PERL
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
juin 1995
Page 80
Le langage PERL
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:
2.11.2. Le globbing
[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:
<\.c$>
.c !
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
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
MANIP
juin 1995
Page 82
Le langage PERL
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:
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.
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
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
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
juin 1995
Page 85
Le langage PERL
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
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
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
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
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:
rmdir("rep");
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:
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:
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()
modification, et une liste de noms de fichiers; il retourne le nombre de fichiers pour lesquels lopration a russi. Exemple:
juin 1995
Page 89
Le langage PERL
juin 1995
Page 90
Le langage PERL
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()
system("date");
Loprateur
system()
STDOUT.
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:
juin 1995
Page 91
Le langage PERL
Loprateur
system()
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.
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" ; }
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:
juin 1995
Page 92
Le langage PERL
who
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
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:
LPR,
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.
Une autre mthode pour lancer un nouveau processus est de cloner le processus Perl avec la primitive Unix fork. Loprateur Perl
fork
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
system,
pour excuter une commande shell, il remplace le processus courant par le shell. Pour obtenir quelque chose dquivalent un appel
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()
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
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
et
STDERR
sont inchanges. Avec les backquotes, la sortie est capture sous forme dune chane
de caractres;
STDIN
et
STDERR
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
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
&traite_sigint
au
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:
juin 1995
Page 96
Le langage PERL
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
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:
$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
rindex()
troisime paramtre qui est la position gauche de laquelle la recherche est effectue.
Extraire une chane de caractres peut se faire grce aux expressions rgulires. On peut galement utiliser loprateur substr(), qui a pour syntaxe:
$chaine
partir de la position
$pos
et de longueur
# # # #
$s $s $s $s
= = = =
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
gauche
$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
printf()
sprintf()
fait la mme
ASCII croissant. Et si on veut raliser dautres tris, par exemple un tri numrique? Eh bien, en
sort
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
un nombre positif si
sub by_number { if ($a < $b) { -1; } elsif ($a > $b) { 1; } elsif ($a == $b) { 0; } }
Comment lutiliser? Prenons par exemple la liste suivante:
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:
@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
des chanes de caractres. Une faon de trier une liste par ordre ASCII croissant (sort classique) est 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"
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///.
par
et tous les
par des
a?
s///
tr /ab/ba/;
Cet oprateur prend deux arguments: la vieille chane et la nouvelle chane. Ils agissent comme les deux arguments de
s///. tr///
$_;
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:
tr///; exemple:
tr /a-z/A-C/d ;
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,
tr///
juin 1995
Page 101
Le langage PERL
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///
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///
$_
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.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:
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()
/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()
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
accder
d'informations,
sprintf().
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:
juin 1995
Page 104
Le langage PERL
ou
DCBA
$buf2
contient
ABCDEFGH
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:
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.
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:
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;
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
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.
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
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
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.
Pour associer une base de donnes DBM un tableau DBM, on utilise l'oprateur dbmopen(), qui a pour syntaxe:
on utilise des majuscules pour marquer la ressemblance avec les filehandles. Le paramtre
$mode
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:
%FRED
dans le rpertoire courant. Si ces fichiers n'existaient pas, ils sont crs avec le mode 0644.
dbmopen()
ne veut pas que les fichiers soient crs, il suffit de donner au mode la valeur undef; exemple:
dbmclose(%FRED);
Cet oprateur retourne faux si quelque chose s'est mal pass.
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
foreach,
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"; }
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
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()
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:
SPEINF
enregistrements contenus dans ce fichier est 82 octets). C'est sur cette ligne que s'opreront les
print()
tre sr de la longueur de la donne crite. Pour obtenir cette longueur, on fait appel
pack(). Exemple:
SPEINF,
les premier et
deuxime champs ont pour longueur 40 octets et le troisime est un short (2 octets).
$nom,
read()
retourne le
unpack()
pack()
et
unpack()
juin 1995
Page 112
Le langage PERL
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
et que
$^I
$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,
@ARGV.
a pour valeur
$^I
.bak
ou
~.
Si
$^I
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:
$^I.
-e indique que largument qui suit est un morceau de code Perl excuter dans le corps de la boucle
while. @ARGV.
juin 1995
Page 114
Le langage 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
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
une explication. Il vaut donc mieux consulter le script Perl obtenu aprs conversion afin de
L'oprateur s2p convertit un programme sed en programme Perl. Il s'utilise de la mme faon que
a2p.
juin 1995
Page 115
Le langage 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()
juin 1995
Page 116
Le langage PERL
2.18. COMPLEMENTS
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:
abbrev.pl
lequel figure cette instruction. Du code peut ainsi tre partag entre diffrents programmes
require
ligne:
1;
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
juin 1995
Page 117
Le langage PERL
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.
On peut faire de
un alias de
en crivant
*b = *a.
$a
et
$b
rfrencent
@a
et
@b,
et
b. *b
local(*b).
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:
$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:
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
Il existe les oprateurs de dcalage de bit gauche, cependant des proprits arithmtiques de la machine.
>>,
et droite,
<<.
Le rsultat dpend
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:
Si le nom du paquetage est nul, ce paquetage est considr comme le paquetage principal ou main package. Alors
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,
et
SIG
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
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:
juin 1995
Page 125
Le langage PERL
juin 1995
Page 126
Le langage PERL
. format MENU = ************************************************************** ** Bienvenue sur notre systeme de reservation! ** ************************************************************** Nous vous offrons les services suivants : 1. 2. q. renseignements/reservations facture quitter
. format FORMAT3 =
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
Pas d'autre vol. Tapez q pour quitter a pour autre recherche r pour menu principal a
juin 1995
Page 137
Le langage PERL
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
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
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
************************************************************** ** 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
============================================================= 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
=============================================================== heure depart| heure arrivee| code vol| classe| nb places| prix =============================================================== 22h30 | 23h50 | AF330 | club | 17 | 1030
Tapez q r s a r
Nom du client: grossiord Accompte: 0 numero de resa = 2 Reservation effectuee. Tapez q pour quitter r pour menu principal q
1 2
:poiraud
:AF457:nice
:22h00:paris
:grossiord :AF330:lille
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
Ecrire un programme qui attend que lutilisateur saisisse un rayon avant de calculer le primtre du cercle.
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.
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
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.
Ecrire un programme faisant la mme chose que cat mais inversant lordre des lignes.
Ecrire un programme qui parcourt /etc/passwd, cherche deux utilisateurs ayant le mme nom et affiche ces noms.
Ecrire une subroutine qui prend les valeurs numriques de deux chiffres, les additionne et affiche le rsultat sous la forme:
Modifier le problme prcdent de faon ce que lopration soit rpte jusqu ce que le mot
juin 1995
Page 146
Le langage PERL
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.
Ecrire un programme ouvrant /etc/passwd et affichant les logins utilisateur, les UID et les vrais noms sous forme de colonnes.
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.
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
Ecrire un programme affichant les logins et les vrais noms dutilisateur du fichier /etc/passwd, ordonns par le prnom.
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
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.
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.
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
juin 1995
Page 157
Le langage PERL
juin 1995
Page 158