Ceci n'est qu'une introduction au Perl, car nous pourrions écrire 4 ou 5 livres, voir plus, sur ce sujet ! ;-) Donc ne vous attendez pas à faire le tour de la question...
Et je précise aussi, que ce n'est pas non plus un cours de programmation : cet article s'adresse à des personnes possédant des bases de programmation et voulant se mettre à Perl.
Perl est un langage de programmation extrêmement efficace pour traiter les fichiers et les chaînes de caractères. Venant du monde Unix, il intègre toutes les fonctions que l'on peut retrouver en shell avec des commandes comme grep, sed, awk, ... Sa syntaxe générale ressemble beaucoup à celle du C et du shell. De plus, il est très apprécié des administrateurs système afin de gérer les fichiers de log.
Note de Jice : Perl est un langage très polyvalent. LE jeu, j'ai nommé Frozen Bubble, est même programmé en Perl !
Dans cette partie, je n'aborde que l'installation de Perl sur un système Linux, et ce quelle que soit la distribution. Enfin, j'espère... ;-)
Il y a des chances pour que Perl soit déjà installé avec notre distribution ou que celle-ci fournisse un package Perl. Pour vérifier si Perl est déjà sur notre système faisons, en console :
perl -v
Ceci doit nous retourner un message du genre:
This is perl, v5.6.1 built for i386-linux
Copyright 1987-2001, Larry Wall
Perl may be copied only under the terms of either the Artistic licence or the GNU General Public licence, which may be found in the Perl 5 source kit.
Complete documentation for Perl, including FAQ lists, should be found on this system using `man perl' or `perldoc perl'. If you have access to the Internet, point your browser at http://www.perl.com/, the Perl Home Page.
Si c'est le cas, nous pouvons sauter le paragraphe suivant.
Pas de chance... Donc allons voir si notre distribution fournit un package et si oui, installons-le. Sinon...
Les binaires sont accessibles ici : http://www.activestate.com/Products/Download/Get.plex?id=ActivePerl&_x=1
Note : je viens de remarquer que maintenant il demande e-mail, prénom et nom pour télécharger Perl.
Les sources sont accessibles ici : http://www.perl.com/pub/a/langage/info/software.html#sourcecode
Maintenant détarons le package
tar -xvzf <votre package>
Allons sous le répertoire créé.
Si nous souhaitons choisir nos paramètres en répondant à des questions :
./Configure -Dprefix=/usr
make
En root (su)
make install
Sinon, pour une installation par défaut :
./Configure -Dprefix=/usr -d -e
make
En root (su)
make install
Vérifions que Perl est bien installé
perl -v
Le fait de définir l'interpréteur dans le script permet de l'exécuter directement. Pour ce faire il faut placer la ligne suivante au tout début du script :
#!/usr/bin/perl
Ce qui permettra d'exécuter le script directement par :
./script.pl
Sans cette ligne il faudrait exécuter le script comme ceci :
perl script.pl
En ajoutant l'option -W, nous obtenons la liste des toutes les erreurs et de tous les avertissements lors de l'interprétation du script.
Un commentaire débute par un caractère dièse (#). Tout ce qui suit ce caractère jusqu'à la fin de la ligne sera considéré comme du commentaire.
Par exemple :
# Ceci est un exemple de commentaire
print "test"; # un 2ème commentaire
L'extension des fichiers librairies (ou module) est pm. pm signifie Perl Module.
Pour appeler une librairie, on ajoute la directive :
use la_librairie;
Pour indiquer à perl où chercher nos librairies personnelles, on utilise la directive :
use lib "le chemin d'accès";
Remarque : les chemins de recherche des librairies sont définis dans le tableau @INC
Cela se fait automatiquement lors de la première utilisation de la variable. Cependant, lorsqu'on utilise use strict, il faut déclarer les variables globales par la directive suivante : use vars qw($var1 $var2 @tab1 %hash1);
Remarque : le mot clef local s'applique à une variable globale (local $variable;). Il permet à l'intérieur d'un bloc de cacher une variable globale par une autre valeur. La variable reste globale, c'est à dire que dans les procédures appelées dans le bloc, la nouvelle valeur est utilisée ; à la fin du bloc, l'ancienne valeur est restaurée.
Une variable lexicale n'existe qu'à l'intérieur d'un bloc. On parle aussi de variable locale.
On la déclare par my $variable ou my @tableau...
Pour déclarer plusieurs variables et un tableau en une seule commande, faire :
my ($var1, $var2, @tab);
Voici les opérateurs les plus couramment utilisés. Pour plus d'info sur les opérateurs : man perlop
! | : négation logique. Si $a vaut vrai, !$a vaudra faux. |
- | : négation arithmétique. Si $a vaut 2, -$a vaudra -2. |
~ | : négation binaire ou complément à 1. |
++ | : incrémentation ; si ++ est placé avant la variable, l'interpréteur l'incrémente avant de retourner la valeur, si ++ est placé après, il retourne la valeur puis l'incrémente. Exemple : $A++ |
-- | : décrémentation ; idem. |
+ - * / % ** | : opérations arithmétiques (% est le modulo, ** est l'exponentiation). |
. | : concatène deux chaînes : "aze"."rty" vaut "azerty". |
x | : "multiplie" une chaîne : "to" x 2 vaut "toto". |
& | ^ << >> | : opérations sur les bits : et, ou, ou exclusif (xor), décalage à gauche, à droite. |
&& || | : et logique, ou logique. |
?: | : cet opérateur particulier est nommé "opérateur conditionnel". Il fonctionne à la manière d'un si alors sinon. Si l'expression à gauche du ? est vraie, l'argument avant le : est retourné, sinon l'argument après le : est retourné. Mieux vaut un exemple : print (($n>1)?'s':''); affichera 's' si $n est plus grand que 1, et n'affichera rien ('') sinon. |
< <= > >= | : plus petit, plus petit ou égal, plus grand, plus grand ou égal |
== != | : égal, différent |
lt le gt ge | : plus petit, plus petit ou égal, plus grand, plus grand ou égal |
eq ne | : égal, différent |
=~ !~ |
: teste si une chaîne de caractères correspond à une expression régulière. Voir le paragraphe [#expressions_regulieres expressions régulières]. |
L'opérateur d'affectation "normal" est '='. Par exemple :
$variable = mavaleur;
affecte la valeur mavaleur à la variable $variable.
D'autres opérateurs d'affectation sont un raccourci pour les opérations binaires.
Par exemple $a += 2 est un raccourci pour $a = $a + 2.
Les opérateurs d'affectation les plus couramment utilisés sont :
= | : affectation "standard" |
+= -= *= /= %= | : pour les opérations arithmétiques (+, -, *, / et modulo) |
&&= ||= != | : pour les opérations logiques (et logique, ou logique, non logique) |
&= |= ^= ~= <<= >>= | : pour les opérations logiques sur les bits (et, ou, ou exclusif, complément à 1, décalages gauche et droite) |
.= | : pour les opérations sur les chaînes de caractères (concaténation) |
=~ !~ |
: pour les expressions régulières (voir plus bas). |
use English; permet d'utiliser les noms des variables au lieu des noms standards des variables spéciales (ex : $ARG au lieu de $_).
@_ ou @ARG : Tableau d'arguments. Sert pour le passage de paramètres.
$_ ou $ARG : Variable par défaut des fonctions unaires entrées/sorties, recherche...
$/ ou $RS ou $INPUT_RECORD_SEPARATOR : fin de ligne lorsqu'on lit un fichier, \n par défaut sous unix et \r\n sous windows.
$! ou $ERRNO : suivant le contexte d'utilisation, retourne le numéro de la dernière erreur système, ou le message d'erreur système.
$0 ou $PROGRAM_NAME : Nom du fichier qui contient le script Perl.
$^0 ou $OSNAME : Nom du système d'exploitation.
Utiliser une variable d'environnement
$variable = $ENV{"nom de la variable d'environnement"}; Remarque, ce n'est que l'utilisation du hachage %ENV.
Pour plus d'information sur ces variables : man perlvar
Ce test classique peut s'écrire de la manière suivante :
if (test) {bloc}
if (test) {bloc} else {bloc}
if (test) {bloc} elsif (test) {bloc} ... else {bloc}
test étant toute expression qui retourne une valeur.
exemple :
if (!open(F,$FICHIER)) { die "impossible d'ouvrir $FICHIER: $!"; }
Il y a d'autres manières de faire la même chose, vous pouvez utiliser par exemple :
instruction if test; | exécute l'instruction si le test est vrai. exemple : die "impossible d'ouvrir $FICHIER: $!" if !open(F,$FICHIER); |
instruction unless test; | exécute l'instruction si le test est faux. exemple : die "impossible d'ouvrir $FICHIER: $!" unless open(F,$FICHIER); |
commande1 or commande2; | exécute la commande1 ; si elle retourne faux, alors la commande2 sera exécutée. Sinon on passe à la suite. exemple : open(F,$FICHIER) or die "impossible d'ouvrir $FICHIER: $!"; |
test?commande1:commande2; | exécute la commande1 si la condition du test est remplie, sinon il exécute la commande2. |
Note : Pour ceux qui connaissent, il n'y a pas d'équivalent au 'case' ou 'switch'. Il y a plusieurs façons de faire, notamment utiliser if elsif ... else.
man perlsyn vous donnera plus d'informations.
Il y a deux types de boucles for, le for 'style C', et le for/foreach Perl.
Dans ce cas, for et foreach sont synonymes. On peut utiliser l'un ou l'autre pour améliorer la lecture, par habitude, etc.
Pour aller de 1 à 9 :
for $cpt (1 .. 9) {bloc} ou foreach $cpt (1 .. 9) {bloc}
(dans {bloc}, $cpt prend successivement les valeurs de 1 à 9)
ou
for (1 .. 9) {bloc}
ici, à chaque itération, la variable par défaut $_ prend la valeur suivante.
Pour parcourir chaque éléments d'un tableau :
foreach $variable (@tableau) {bloc}
A chaque itération, $variable prendra la valeur suivante de @tableau.
Si on omet $variable, alors la valeur de l'élément sera stocké dans la variable $_ :
foreach (@tableau) {bloc}
Remarque : l'écriture 1..9 définit en réalité un tableau de 9 éléments (1,2,3,4,5,6,7,8,9).
La construction 'classique' à la C est possible, mais tellement moins Perl...
for ($cpt=1 ; $cpt < 10 ; $cpt++) {bloc}
Cette construction est néanmoins très puissante, et permet de faire beaucoup plus de choses que de simples itérations... A vous de voir !
A noter que dans les exemples ci-dessus, les variables $cpt ou $variable sont locales à la boucle. Si elles doivent être déclarées, vous pouvez les faire précéder du mot clef my :
for my $cpt (1 .. 9) {bloc}
for (my $cpt=1 ; $cpt < 10 ; $cpt++) {bloc}
Les boucles while se construisent comme suit :
while (test) {bloc1}
while (test) {bloc1} continue {bloc2}
Le bloc1 puis le bloc2 sera exécuté tant que le test est vrai.
L'exécution des boucles peut être pilotée à l'intérieur des blocs par les commandes next, last et redo.
Par exemple, le code suivant lit l'entrée standard, et ignore les commentaires (lignes commençant par #)
while (<STDIN>) {
next if /^#/;
...
}
Autre exemple, une itération de 1 à 9
$cpt = 1;
while ($cpt < 10) {
...
$cpt++;
}
ou bien :
$cpt = 1;
while ($cpt < 10) {
...
}
continue {
$cpt++;
}
Pour plus d'information sur ces constructions : man perlsyn.
Une fonction peut être déclarée n'importe où dans le script Perl, mais pour des questions de lisibilité, il est préférable de déclarer les fonctions regroupées soit en début, soit en fin de script.
On peut pré-déclarer les fonctions par :
sub mafonction;
ou les déclarer directement par :
sub mafonction {bloc}
Les paramètres sont passés comme une liste de valeurs scalaires (nombre, chaîne...) à plat.
Par exemple :
ma_fonction($variable, "chaîne");
Pour lire valeur des paramètres passés dans la fonction, il suffit de lire la variable @_ qui est le tableau contenant les paramètres.
Une façon simple de les lire est d'écrire en début de fonction :
my ($variable, $chaine) = @_;
On peut aussi récupérer les arguments en dépilant les éléments du tableau @_ avec la commande shift.
my $variable = shift @_;
qui peut s'abréger en
my $variable = shift;
car le tableau @_ est l'argument par défaut de shift.
Les paramètres sont passés par valeur. Pour pouvoir modifier le contenu d'une variable passée en paramètre à une fonction, il faut passer à cette fonction une référence sur la variable (on parle de passage par référence). Une référence est un type scalaire particulier qui permet de se référer à une variable. La notation consiste à faire précéder la variable par un caractère '\'. Pour récupérer la variable cachée derrière la référence (ou déréférencer), il faut faire précéder la référence du caractère de type correspondant, et optionnellement entourer la référence d'accolades.
Exemple :
$a = 1;
$b = \$a; # $b est une référence à $a
$c = $$b + 1; # $c = 2
$c = ${$b} + 1; # synonyme
Démonstration :
sub test1 {
my $a=shift; # récupération du paramètre
$a += 1; # on ajoute un
}
sub test2 {
my $ref_a=shift;
$$ref_a += 1; # le premier $ déréférence la référence
}
$a = 1;
print $a; # affiche 1
test1($a);
print $a; # affiche 1
test2(\$a); # \$a est une référence sur $a
print $a; # affiche 2
Le passage par référence a aussi pour d'intérêt de pouvoir passer des tableaux ou des hachages en paramètres à une fonction. En effet, on a vu que les paramètres d'une fonction sont passés comme une liste de valeurs scalaires à plat. Si on désire passer 2 tableaux @tab1=(1,1,1) et @tab2=(2,2) à une fonction, et que l'on écrit :
mafonction (@tab1, @tab2);
alors perl traduira cela comme :
mafonction (1,1,1,2,2);
car il met toutes les valeurs à plat dans une liste. Une fois dans la fonction on sera bien embêté pour savoir distinguer les éléments du premier tableau de ceux du deuxième.
On va donc passer une référence sur chaque tableau :
mafonction (\@tab1, \@tab2);
Exemple :
sub liste_gt {
my ($l1ref, $l2ref) = @_;
$n1 = @$l1ref; # @$l1ref représente le tableau référencé par $l1ref
$n2 = @$l2ref;
# (affecter un tableau dans un scalaire retourne le nombre d'éléments)
if ($n1 > $n2) { return 1; }
else { return 0; }
}
@tab1 = (1,2,3);
@tab2 = ("a",2,"r",5);
if (liste_gt(\@tab1, \@tab2)) {
print "tab1 a plus d'éléments que tab2\n";
} else {
print "tab2 a plus d'éléments que tab1\n";
}
Tout cela s'applique de la même façon aux hachages.
Pour plus d'informations sur les références, voir man perlreftut (tutoriel) et man perlref (références).
Une fonction peut renvoyer une ou des valeurs, grâce à la commande return :
sub ecrire
{
...
return $valeur;
... # renvoie une valeur unique
return $valeur1, $valeur2;
... # renvoie une liste de valeurs
}
Cette commande provoque la sortie immédiate du sous-programme pour retourner dans le programme appelant.
return permet de renvoyer une valeur ou une liste de valeurs. Cela permet donc à une fonction de retourner soit un tableau :
@resultat = ma_fonction;
soit plusieurs valeurs :
($a, $b) = ma_fonction;
De même que pour le passage de paramètres, la liste de valeur est une liste "à plat", ce qui signifie que pour retourner plusieurs tableaux, il faut également passer par les références :
($ref_a, $ref_b) = ma_fonction;
où $ref_a est une référence sur le tableau @$ref_a et où ma_fonction retourne une liste de deux références.
Pour plus d'information sur les fonctions de Perl, voir man perlsub.
Perl est un langage très pratique pour manipuler du texte. Un des éléments qui le rend si adapté à cet usage est la présence des expressions régulières, qui permettent de déterminer si une chaîne de caractère correspond à un masque prédéfini, d'extraire des éléments d'une chaîne de caractères suivant un masque, de remplacer des parties d'une chaîne suivant un masque, etc. C'est ce masque, défini sous forme d'une chaîne de caractères, que l'on appelle expression régulière.
Par exemple, $a =~ /lea/ teste si la chaîne "lea" est dans la chaîne $a, $a =~ /^lea/ si $a commence par "lea", $a =~ /l[eé]a/ si la chaîne $a contient "lea" ou "léa"...
De prime abord, ce sont des sortes de formules qui semblent ne rien vouloir dire, mais une fois que nous les maîtrisons, elles se révèlent extrêmement pratiques et puissantes.
Les éléments les plus utilisés sont :
m/regex/ ou /regex/ (sans le m) teste si une chaîne correspond (match) à une regex donnée.
s/regex/substitution/ remplace la partie de la chaîne correspondant à la regex par la substitution.
Pour appliquer un test m// ou une substitution s/// à une chaîne de caractères, on utilise l'opérateur =~ ou !~.
Par exemple :
if ($s =~ /win(dows)?/) { kickban(); }
teste si la chaîne $s contient "win" ou "windows".
Si on ne précise pas de chaîne, le test se fait sur la variable par défaut $_ :
if (/win(dows)?/) { kickban(); }
teste si $_ contient "win" ou "windows".
L'opérateur !~ correspond quant à lui à la négation : $s !~ /coin/ teste si la chaîne $s ne contient pas "coin".
Les expressions régulières peuvent de plus être suivies de modifieurs ou options, qui en modifient le comportement, notamment :
Par exemple :
"Bonjour Léa" =~ m/jour/; # correspond
"Bonjour Léa" =~ m/Jour/; # ne correspond pas
"Bonjour Léa" =~ m/Jour/i; # correspond
Si une partie d'une regex est entre parenthèses, alors la partie de la chaîne qui correspond à cette parenthèse sera affectée à la variable $1 (on dit "capturée"). Si une deuxième parenthèse est présente dans la regex, la variable $2 sera utilisée, et ainsi de suite. Si la parenthèse commence par ?: alors il n'y aura pas d'affectation à une variable $1, $2, etc.
Ainsi :
if (/win(?:dows)?\s(..)/i) {
if ($1 eq "xp") { kickban(); }
else { kick(); }
}
teste si $_ contient "win" ou "windows", suivi d'un espace, puis de 2 caractères, que l'on va capturer dans $1. La première parenthèse (?:dows) permet de regrouper les quatre caractères "dows" afin de leur appliquer le quantifieur '?' (0 ou 1).
Les captures $1, $2... peuvent être utilisées lors d'une substitution :
$s =~ /win(?:dows)?\s(..)/winblows $1/
Par exemple, pour tester si une chaîne contient le mot "lea" (le i de la fin permet de ne pas différencier majuscules et minuscules) :
if (/lea/i) ...
Pour tester si une chaîne commence par la lettre 'a', on peut faire :
if (/^a/) ...
Pour tester si une chaîne se termine par 'z' :
if (/z$/) ...
Enfin pour tester si une chaîne contient un quadruplet héxadécimal (i.e. 4 chiffres de 0 à 9 ou A à F) :
if (/[0-9A-F]{4}/) ...
Ici, par défaut, c'est la valeur contenu dans $_ qui est utilisée pour le test. Et bien entendu, nous pouvons compliquer à loisir l'expression régulière, et utiliser le groupement (voir plus haut) afin de récupérer les valeurs trouvées dans les chaînes pour s'en servir par la suite.
Rappel : la syntaxe est s/regex décrivant l'élément à remplacer/élément remplaçant/options
Exemples :
$variable =~ s/a/b/;
Cette commande va remplacer le premier 'a' de la ligne par 'b'. Pour remplacer tous les 'a' faire :
$variable =~ s/a/b/g;
Si en plus nous voulons que cela ne fasse pas la différence entre les majuscules et les minuscules (case sensitive), faire
$variable =~ s/a/b/gi;
Pour remplacer tous les ensembles de caractères commençant par 'a', finissant par 'e' et avec au moins un caractère au milieu sans être sensitif par 'toto', faire :
$variable =~ s/a.*e/toto/gi;
Cette construction "à la regex" permet de remplacer des caractères par d'autres dans une chaîne, à la manière de la commande unix 'tr'.
La syntaxe est tr/éléments à traduire/éléments traduits/
Ou y/éléments à traduire/éléments traduits/
Exemple :
$variable =~ tr/a-b/A-B/;
Cela va transformer tous les 'a' et 'b' minuscules en majuscules.
Plus d'info sur :
man perlre
man perlretut (le tutoriel sur les regex, une bonne lecture !)
On a vu plus haut que les tableaux Perl ne possèdent qu'une seule dimension (il ne peuvent contenir que des éléments de type scalaire). On a aussi vu plus haut l'existence de références, type scalaire particulier qui permet de se référer à une variable, donc en l'occurence à un tableau.
Ainsi pour représenter la matrice
0 1 2
3 4 5
6 7 8
Nous allons pouvoir faire :
@ligne1 = (0, 1, 2);
@ligne2 = (3, 4, 5);
@ligne3 = (6, 7, 8);
@matrice = (\@ligne1, \@ligne2, \@ligne3);
Perl introduit une nouvelle notation pour ce faire : au lieu d'entourer la liste avec des parenthèses, nous allons le faire avec des crochets, ce qui aura pour effet de retourner une référence :
$ligne1_ref = [0, 1, 2];
etc...
ou plus simplement :
@matrice = (
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
);
Dans tous ces cas, @matrice est un tableau de trois éléments, qui sont chacun une référence vers un autre tableau. $matrice[1] est une référence sur la 2ème ligne de la matrice.
Afin d'accéder aux éléments de la matrice, nous pouvons utiliser une nouvelle notation : la flèche '->'.
En effet, afin d'accéder au 3ème élément de $ligne1_ref définie plus haut, nous utiliserons $ligne1_ref->[2] (ce qui est synonyme de ${$ligne1_ref}[2].)
Ainsi, afin d'accéder au '5' dans notre matrice, nous ferons : $matrice[1]->[2].
Mais... Perl est gentil avec nous, car entre deux indices de tableau, la flèche est optionnelle ! Donc nous pouvons écrire : $matrice[1][2], ce qui ressemble maintenant à un tableau bi-dimensionnel.
De même, si $hash_ref est une référence vers un hachage, $hash_ref->{'nom'} renverra l'élément du hachage indexé par 'nom'.
L'ensemble tableaux, hachages et références peut bien sûr être mixé dans l'ordre qui vous plaira. Par exemple, pour réaliser un tableau de personnes, nous écrirons :
@staff = (
[ prenom => "jice", nom => "cardot" ],
[ prenom => "fred", nom => "bonnaud" ],
[ prenom => "serge", nom => "tchesmeli" ],
);
et pour accéder au prénom de la première personne, nous ferons : $staff[0]->{'prenom'}(meuh non je ne suis pas mégalo ;) ou $staff[0]{'prenom'} car ici aussi la flèche est optionnelle.
Notes :
On a vu ci-dessus une utilisation des références, pour le passage et le retour de valeurs dans les fonctions. On vient de voir également leur utilité pour travailler avec des structures de données complexes.
Les références peuvent aussi servir dans un autre contexte : si vous déréférencez une variable contenant une valeur scalaire plutôt qu'un référence vers une autre variable, elle sera considérée comme une référence symbolique, c'est à dire que la valeur scalaire sera utilisée en tant que nom de la variable.
Exemple :
$test = "toto";
$$test = 144; # affecte 144 à $toto
${$test} = 12; # affecte 12 à $toto
$test->[1] = 12; # affecte 12 à $toto[1]
@$test = (1,2,3); # affecte le tableau @toto
Cela peut aller beaucoup plus loin, car vous pouvez mettre une chaîne de caractères entre les accolades :
${$test x 2} = 12; # affecte 12 à $totototo
$titi = 2;
${"$toto$titi"} = 2; # affecte 2 à $toto2
etc.
Remarque : l'utilisation des références symboliques avec use strict; (tel que préconisé au début de l'article) n'est pas possible. Pour contourner ce problème, il faut appeler l'instruction no strict 'refs'; dans le bloc où on veut utiliser les références symboliques.
Autre exemple d'utilisation :
$min = 12;
$max = 144;
while (<FICHIER>) {
if (/^([A-Z]+)\ (\d+)\ (\d+)\ (\d+)$/) {
# les masques ont affecté $1, $2, $3 et $4 (voir [#regex_capture groupement/capture])
print "$1: ";
# on va effectuer une même opération sur $2, $3 et $4 :
for $i (2 .. 4) {
no strict 'refs';
# on utilise les références symboliques : si $i = 2, alors $$i est $2
if ($$i > $max) print "sup ";
elseif ($$i < $min) print "inf ";
else print "ok ";
}
}
}
Comme toujours en Perl, il y a plusieurs moyens de faire une même opération.
Cette façon de faire offrant un moyen simple d'ouvrir un fichier en lecture / écriture est empruntée du shell.
open(FILE, "< nom du fichier"); # ouvre en lecture
open(FILE, " nom du fichier"); # idem
open(FILE, "> nom du fichier'); # ouvre en écriture
open(FILE, ">>nom du fichier'); # ouvre en ajout
Remarque : le fichier "moins" correspond à l'entrée standard stdin en lecture et à la sortie standard stdout en écriture. Par exemple open(SORTIE,">-") ouvre la sortie standard.
La fonction sysopen de Perl correspond à l'appel système open(2) du C. Cela permet une plus grande maîtrise sur l'ouverture des fichiers, au prix d'une plus grande complexité.
Synoptique : sysopen DESCRIPTEUR, CHEMIN, FLAGS, [MASQUE]
MASQUE correspond au masque octal des permissions du fichier (utile pour la création d'un fichier), combiné avec l'umask du processus perl. voir [../admin/permissions.php3 l'article sur les permissions].
Je vous renvoie vers un cours de C pour la signification des exemples suivants, et vous donne la correspondance avec l'open "à la shell".
à la Shell | à la C |
---|---|
open(F, "< $chemin"); | sysopen(F, $chemin, O_RDONLY); |
open(F, "> $chemin"); | O_TRUNC | O_CREAT); |
open(F, ">> $chemin"); | O_APPEND | O_CREAT); |
Bien sûr, sysopen permet de faire plus de choses que le simple open(), en jouant sur les flags ci-dessus et O_RDWR, O_RDONLY, O_EXCL, O_NONBLOCK, O_BINARY. Pour plus d'informations, voir man perlopentut ou man 2 open.
close(FILE);
FILE étant le descripteur du fichier ouvert.
STDIN et STDOUT sont définis dès le lancement de votre programme. Ils correspondent respectivement à l'entrée et à la sortie standard. Rien ne vous empêche de les redéfinir, en les ouvrant sur un autre fichier, par exemple : open(STDIN, "mon_fichier");
À chaque appel, <DESCRIPTEUR DE FICHIER> (on appelle <> l'opérateur "diamant") retourne la ligne suivante du fichier (en fait jusqu'à la fin de ligne définie par $/, voir le paragraphe sur les [#var_particulieres variables prédéfinies].), ou renvoie faux en fin de fichier.
exemple :
open (F, "mon_fichier");
$premiere_ligne = <F>;
while (<F>) {
... traitement en fonction de $_ ...
}
close(F);
exemple : pour lire tout un fichier dans une variable :
open (F, "mon_fichier");
undef $/;
$contenu_fichier = <F>;
close(F);
La lecture sur l'entrée standard est extrêmement simplifiée, car STDIN est déjà ouvert, et <STDIN> et <> sont synonymes. Ainsi, il suffit de faire :
while (<>) {
... traitement de la ligne en cours ...
}
Il suffit de spécifier à la commande print ou printf le descripteur de fichier à utiliser.
Exemple :
open(FLOG, ">> fichier.log");
print FLOG "nouveau log\n";
close(FLOG);
voir man perlfunc pour la liste exhaustive des commandes intégrées de Perl.
split correspond en partie à la fonction cut en shell. Elle permet de découper une chaîne de caractères.
Exemple :
($variable, @tableau) = split (":", "prenom:nom:age:adresse:ville:telephone");
Renvoie "prenom" dans $variable et le reste dans des cases distinctes du tableau @tableau.
exec permet de lancer un programme extérieur.
system de même que exec, mais produit un fork, processus fils.
Exemple :
@args = ("ls", "-lrt", "toto*");
system(@args);
Cela va lancer la commande :
ls -lrt toto*
Attention, l'utilisation de ces commandes rend votre script beaucoup moins portable ! En général, il y a moyen de tout faire en Perl, il faut éviter de recourir à ces fonctions.
chomp supprime tous les caractères de fin de ligne d'une chaîne de caractères et renvoie le nombre de caractères supprimés.
Exemple :
$nb_car = chomp($chaine);
Contrairement à chop qui enlève seulement le dernier caractère de fin de ligne.
Le [perl_script.pl script] va se lire lui-même et sortir à l'écran son contenu modifié :
#!/usr/bin/perl -W
# Fichier script.pl
use strict qw(subs vars refs);
my $file = "$0";
open(FILE, "<$file");
#Lecture du fichier ligne par ligne jusqu'à la fin du fichier.
while (<FILE>) {
#Remplace tous les mots 'file' par 'fichier'.
$_ =~ s/file/fichier/ig;
#Transforme les lettres minuscules de 'a' à 'e' en majuscules.
$_ =~ tr/a-e/A-E/;
#Affiche le résultat des transformations à l'écran.
print $_;
}
close(FILE);
#Fin script.pl
Ce script est totalement inutile mais je crois que cela montre la facilité d'utilisation.
Oui, j'en conviens, en shell cela tiens en une ligne : cat script.pl | sed -e 's/file/fichier/ig' | sed y/a-e/A-E/. Bizarre, cela ressemble au Perl !? ;-)
Et oui ! Sur notre propre machine il y a plein de sources de documentation sans même le savoir.
La première qui viens à l'esprit naturellement c'est LE man.
man perl vous donne quelques généralités, ainsi que la liste de toutes les sections du manuel de perl (perlsyn, perlre, perlvar, perlop, perlfun...).
Ensuite, il y a le man propre à Perl, qui est perldoc. Le meilleur moyen de voir comment cela marche, c'est d'essayer :
perldoc perldoc
Bon, l'inconvénient, c'est que tout ceci est en anglais...
Sur Internet, nous trouverons plein de sites parlant de Perl. En général, ils parlent des scripts CGI (scripts Perl pour serveur web). Mais néanmoins, il y a
Sinon, si on a les moyens les livres O'Reilly sur Perl sont très bien écrits et sont la référence en la matière.
Surtout n'hésitez pas à m'envoyer vos remarques, vos corrections et vos idées, merci.
@ Retour à la rubrique Développement
Copyright © 03/04/2002, Jonesy, Jice
![]() ![]() ![]() ![]() |
Ce document est publié sous licence Creative Commons Attribution, Partage à l'identique, Contexte non commercial 2.0 : http://creativecommons.org/licenses/by-nc-sa/2.0/fr/ |