Introduction à Perl

Perl est un langage de script, qui tourne sur un très grand nombre de systèmes et qui permet de réaliser des tâches complexes avec un minimum de développement. Perl est, pour résumer, un langage qui vous aide à faire votre travail. L'auteur du langage Perl se prénomme Larry Wall, il dit avoir créé Perl parce que ce langage lui permettait de se libérer d'une charge de travail conséquente. Que peut-on faire en Perl ? A peu près tout en fait : il existe une grande variété de modules Perl qui permettent d'étendre le langage et de faire à peu près ce que l'on veut. De plus, des mécanismes ( dépassant le cadre de cette formation ) permettent d'interfacer Perl avec d'autres langages comme le C, ce qui ouvre l'accès à Perl à toutes les interfaces de programmation écrites pour le C. Ainsi il est possible en Perl, de lire son mail, de scripter son Palm, de programmer en OpenGL, de programmer des interfaces graphiques sous Windows ou Linux à l'aide de Tk, ou encore de Gtk voire avec les API Win32 accessibles depuis Perl. Le domaine de prédilection de Perl reste cependant le traitement des chaînes de caractères et la manipulation de textes. En effet, même si le C possède beaucoup de fonctions pour transformer des chaînes ( à travers des bibliothèques spécialisées ), il faut toujours passer par de fastidieuses manipulations de pointeurs qui rendent le programme plus fragile qu'efficace, ce qui n'est pas souhaitable pour de petits programmes vite faits et bien faits.

A. Syntaxe

1. Ecriture d'un programme

Réaliser un programme Perl, c'est très simple !

Il n'y a pas de compilation, pas de "Makefile"s à écrire, pas de bibliothèques à linker ( là j'exagère un peu ) ... Sous unix, comme sous windows tout programme perl commence ( ce n'est pas obligatoire, cela dit ) par #!/usr/bin/perl. Pourquoi cette ligne ? Elle permet au shell de savoir quel interpréteur utiliser pour lancer le script en l'occurence /usr/bin/perl ( ce chemin peut changer suivant votre configuration ).

On peut alors ( si on a fait un chmod +x nom_du_script ) exécuter son script depuis la ligne de commande en tapant ./nom_du_script. Bien sur il existe d'autres façons de faire : la plus simple étant encore de taper perl nom_du_script. Enfin il y a une façon rigolote de programmer en perl c'est d'utiliser perl -e. Avec cette utilisation on peut programmer directement sur la ligne de commande.

Exemple 1
Tapez sur la ligne de commande perl -e 'print "Hello World!\n";'.

Satisfait ?

Lors de l'écriture d'un programme :

Une fonction s'écrit sub ma_fonction { ... } . Nous verrons plus loin comment récupérer les paramètres passés à une fonction.

2. Variables, types de données

Il existe trois types de données en Perl.

Exemple 2

# Nombres
$a = 1 ; # Variable scalaire de valeur 1
$a = 0xFFFF ; # Hexadécimal
$a = 0777 ; # octal
$a = 1.3 ; $a = 3e+07 ;

#Chaînes de caractères
$b = "Coucou"; # Même chose, valeur "coucou"
$b = 'Coucou';
$b = "Coucou\n"; # Coucou suivi d'un retour chariot
$b = 'Coucou\n' ; # coucou suivi de \n ...
$b = "Coucou $b" ; # coucou coucou \n maintenant
$b = 'Coucou $b' ; # coucou $b

#Tableaux
@a = (1,2,3,4,5) ;
$a = 1 ; # $a n'est pas @a
print $a[1] ; # 2
$c =@a ; # $c vaut 5
$c = $#a ; # $c vaut aussi 5

#Comment ajouter des éléments à un tableau
$a[5] = 1 ; # La plus simple
push @a,5 ; # On se sert du tableau comme d'un pile
pop @a ; # on dépile
shift @a ; # on enlève le premier élément et on renvoie sa valeur.
unshift @a,'bla','toto',5 ; # on ajoute en tete de tableau 3 éléments

# Autres fonctions
sort {$a cmp $b},@a ; # $a et $b sont deux variables prédéfinies, en conflit avec aucune autre variable dans le bloc entre crochets.
reverse @a ;

# Assignation multiple
($a,$b) = (1,2) # $a vaut 1 et $b vaut 2
@tab = (A..C) ; # intéressant pour mettre d'un coup un intervalle d'entier ou de caractères dans un tableau.
($a,$b,$c) = @tab ; # $a vaut A , $b B , $c C

#Hachages
%hash = { "Dim" => "Dimanche", "Lun" => "Lundi", ... }
print $hash{"Lun"} ; # Affiche Lundi
$hash{"Mer"} = "Mercredi"; # Affectation d'un hachage
keys %hash ; # Renvoie un tableau contenant ('Dim','Lun',...) dans un ordre non prévisible
values %hash ; # Même chose avec les valeurs

Les fichiers : on ouvre un fichier en faisant open(FICHIER,"nomdefichier"); Pour préciser ce qu'on veut faire avec le fichier, il faut ajouter à "nomdefichier" des caractères spéciaux.

Ensuite on peut procéder de la manière suivante : $texte = ; # on récupère la ligne avec son retour chariot. chomp $texte ; # permet d'enlever le retour chariot. Et quant on a fini : close(FICHIER);.

3. Variables spéciales

4. Opérateurs

Tous les opérateurs du C sont présents +,-,*,/,%, ** .

Pour concaténer des chaînes on utilise ..

Comparaison comme en C sauf pour les chaînes ...

Exemple 3

$a + $b ;
$a % $b ;
$a = 1 ;

$a++ ; # ça marche aussi
$a /= 2 ; # divise a par 2
$a == 1 ; # expression booléene, teste si $a vaut 1

$b = 'Coucou';
$b eq 'Coucou' ; # test d'égalité pour une chaîne
$b neq 'truc' ; # l'inverse
$b lt 'Bimbo' ; # comparaison lexicographique
$b gt 'Donkey Kong' ; # même chose

 

5. Constructions du langage

Instructions if, else, elif : s'utilisent comme en C. Attention à bien délimiter les instructions avec les accolades, ça n'est pas forcément strictement nécessaire mais recommandé pour faire du code lisible.

Instruction for, while : comme en C.

Perl ajoute 2 nouvelles constructions :

Enfin il faut noter l'existence des mots reservés next et last qui permettent respectivement de sauter une itération ou de sauter directement à la fin d'un bloc.

Exemple 4

if ($a == 1) {
print '$a vaut 1' ;
} elsif ($a != 2) {
print '$a ne vaut pas 2';
} else {
print '$a vaut 2';
}

# Comment parcourir un fichier

open(FICHIER,"data.txt");
while(<FICHIER>) {
print ; # la ligne est lue et est stockée dans $_
}
close(FICHIER);

# Comment parcourir un tableau

@a = ('a'..'z'); reverse @a;
foreach $element (@a) {
print $element." " ;
}

# Comment parcourir un hachage

while ( ($cle, $valeur) = each(%hash)) {
print "$cle => $valeur\n";
}

# ou encore

foreach $cle (keys %hash) {
print $hash{$cle};
}


Deux instructions peuvent parfois permettre d'éviter les boucles : map et join.

map permet d'appliquer un bloc d'instruction à chaque élément de la liste donnée en paramètre, l'élément étant stocké dans $_ .

join permet de "recoller" une liste en une chaîne de caractères en utilisant un caractère donné comme "colle".

Exemple 5

map { ++$_ } ('h','e','l','l','o') ; # incrémente d'un caractère tous les éléments de la liste
join '-',('a'..'c') ; # renvoie "a-b-c"

@chars = 0..9,'a'..'z','A'..'Z';
$password = join '', map { $chars[rand @chars] } 0 .. 7; # un générateur de mot de passe aléatoire assez performant mais perfectible

6. Autres bizarreries

eval ( chaîne ) permet d'évaluer ( i.e d'éxécuter ) du code Perl stocké dans une chaîne. Ca peut servir dans des cas extrêmes ou tout simplement si on a peu de scrupules à écrire du code pas très propre. Néanmoins cela permet de faire des choses vraiment.

On peut faire des alias entre variables ( typeglobs ) genre : *machin = *truc et avec ça $machin, @machin, %machin sont la même chose que $truc, @truc, %truc.

On peut récupérer la sortie d'une commande sans passer par un pipe avec $resultat = `commande`; ( apostrophes inversées )

@liste = <*.c>; permet de récupérer tout les fichiers se terminant par .c dans le répertoire courant.

B. Expressions régulières

On arrive à une des caractéristiques essentielles de Perl : les expressions régulières.
Les expressions régulières sont des chaînes de caractères qui permettent de décrire un motif c'est à dire un agencement particulier de caractères.

Exemple 6

Imaginons que l'on veuille tester si une chaîne donnée contient la chaîne toto, tata ou titi.
On peut évidemment tester toutes les sous chaînes avec une boucle pénible ou alors

if ($chaine =~ m/t[oai]t[oai]/i) {
print "ok";
}


ce qui fait la même chose, sans tenir compte de la casse.

Comment on fait ?

Il faut définir son motif à voix haute puis "traduire" en Perl.
Dans l'exemple précédent, on pouvait dire "je veux soit toto, soit tata, soit titi" ce qui se traduit immédiatement par (toto|tata|titi)
ou alors si on est tordu comme moi on peut dire "je veux un t suivi de o, a ou i puis encore un t suivi de o,a ou i" ce qui donne t[oait[aoi

Voici donc les règles qui permettent de construire un expression régulière

Je notre expr un caractère, un expression qui compte pour un caractère ou un morceau d'une expression régulière groupé entre parenthèses.

expr : motif filtrant expr ( ! )
expr* : motif filtrant zéro, une ou plusieurs occurences de expr
expr+ : motif filtrant une ou plusieurs occurences de expr
expr? : motif filtrant zéro ou exactemen une occurence de expr
(expr_1|expr_2) : motif filtrant expr_1 ou expr_2
^expr_1 : motif filtrant expr_1 uniquement en début de ligne
expr_1$ : motif filtrant expr_2 uniquement en fin de ligne

Enfin on peut chercher un caractère parmi une classe de caractères du genre [a-zA-Z, la négation s'écrivant [^a-zA-Z .

Comment on utilise les expressions régulières ?

On a le choix :

1.On veut faire un test à ce moment là, on utilise l'opérateur m// ( match )qui s'applique par défaut à $_ .
On peut préciser des options sur la recherche en utilisant des modificateurs que l'on place après le deuxième slash.

On peut aussi utiliser directement /expression régulière/ ce qui permet d'éviter d'écrire le m ...

2. On veut effectuer un remplacement l'opérateur s/expression régulière/remplacement/ entre en action. Les modificateurs marchent comme avec m.
Si on veut récupérer des morceaux de chaînes dans le motif il suffit de mettre des parenthèses autour des endroits intéressants et Perl affecte alors les variables $1, $2, $3, etc. avec le texte concerné.

3. On peut aussi éclater une chaîne de caractère en un tableau par l'intermédiaire de split / /, $chaine qui prend comme premier paramètre une expression régulière.

Exemple 7

Quelques expressions régulières :

if m/s?html?/i { ... } # filtre toutes les occurences de shtml, shtm, html, htm

# un classique ...

while (<FICHIER>) {

next if /^#/ ; # on saute les lignes de commentaires
}

# comment rajouter des liens à la Outlook dans du texte

s/(http:\/\/[^\s *)/<a href="$1">$1</a>/ig ; # je filtre toute portion de texte sans espace commençant par http:// et je remplace ça par un lien vers l'adresse désignée par cette portion

# un autre grand classique

while (<FICH>) {
chomp;
($champ1,$champ2,$champ3) = split /;/ ;
}

# Attention aux groupements !

m/toto+/ ; # filtre totooooooo....o
m/(toto)+/; # filtre toto répété 1 ou plusieurs fois.

C. Les modules Perl existants

Bien entendu, Perl possède beaucoup d'autres fonctions qui disponibles en standard dans le langage.
Voici différentes catégories de fonctions supportées par Perl (extrait de la page de manuel ):

  
       Functions for SCALARs or strings
            chomp, chop, chr, crypt, hex, index, lc, lcfirst,
            length, oct, ord, pack, q/STRING/, qq/STRING/,
            reverse, rindex, sprintf, substr, tr///, uc, ucfirst,
            y///


       Regular expressions and pattern matching
            m//, pos, quotemeta, s///, split, study, qr//

       Numeric functions
            abs, atan2, cos, exp, hex, int, log, oct, rand, sin,
            sqrt, srand

       Functions for real @ARRAYs
            pop, push, shift, splice, unshift

       Functions for list data
            grep, join, map, qw/STRING/, reverse, sort, unpack

       Functions for real %HASHes
            delete, each, exists, keys, values

       Input and output functions
            binmode, close, closedir, dbmclose, dbmopen, die,
            eof, fileno, flock, format, getc, print, printf,
            read, readdir, rewinddir, seek, seekdir, select,
            syscall, sysread, sysseek, syswrite, tell, telldir,
            truncate, warn, write


       Functions for fixed length data or records
            pack, read, syscall, sysread, syswrite, unpack, vec

       Functions for filehandles, files, or directories
            -X, chdir, chmod, chown, chroot, fcntl, glob, ioctl,
            link, lstat, mkdir, open, opendir, readlink, rename,
            rmdir, stat, symlink, umask, unlink, utime

       Keywords related to the control flow of your perl program
            caller, continue, die, do, dump, eval, exit, goto,
            last, next, redo, return, sub, wantarray

       Keywords related to scoping
            caller, import, local, my, package, use

       Miscellaneous functions
            defined, dump, eval, formline, local, my, reset,
            scalar, undef, wantarray

       Functions for processes and process groups
            alarm, exec, fork, getpgrp, getppid, getpriority,
            kill, pipe, qx/STRING/, setpgrp, setpriority, sleep,
            system, times, wait, waitpid

     
       Keywords related to classes and object-orientedness
            bless, dbmclose, dbmopen, package, ref, tie, tied,
            untie, use

       Low-level socket functions
            accept, bind, connect, getpeername, getsockname,
            getsockopt, listen, recv, send, setsockopt, shutdown,
            socket, socketpair

       System V interprocess communication functions
            msgctl, msgget, msgrcv, msgsnd, semctl, semget,
            semop, shmctl, shmget, shmread, shmwrite

       Fetching user and group info
            endgrent, endhostent, endnetent, endpwent, getgrent,
            getgrgid, getgrnam, getlogin, getpwent, getpwnam,
            getpwuid, setgrent, setpwent

       Fetching network info
            endprotoent, endservent, gethostbyaddr,
            gethostbyname, gethostent, getnetbyaddr,
            getnetbyname, getnetent, getprotobyname,
            getprotobynumber, getprotoent, getservbyname,
            getservbyport, getservent, sethostent, setnetent,
            setprotoent, setservent

       Time-related functions
            gmtime, localtime, time, times

       Functions new in perl5
            abs, bless, chomp, chr, exists, formline, glob,
            import, lc, lcfirst, map, my, no, prototype, qx, qw,
            readline, readpipe, ref, sub*, sysopen, tie, tied,
            uc, ucfirst, untie, use

Pour le détail de ces fonctions, il suffit de se reporter à la page de manuel correspondate : man perlfunc qui contient la doc sur toute les fonctions.

Bien que le langage intègre plein de fonctions de base de nombreux modules ont été écrits pour regrouper des fonctions effectuant des tâches précises. Pour les utiliser, il suffit de mettre au début de son programme use nom_du_module ; après l'avoir correctement installé.

Pour les installer généralement la suite de commandes suivante suffit :

tar zxvf module_perl.tar.gz
cd module_perl
perl Makefile.PL
make
make test
make install