introduction au langage Perl

home
retour
SOMMAIRE chap 1 - Qu'est ce que le PERL
chap 2 - Les types de données
chap 3 - Les boucles
chap 4 - Les opérateurs
chap 5 - Les conditions
chap 6 - Fonctions utiles
chap 7 - Les expressions régulières
chap 8 - La manipulation de fichiers

exemples divers

exemple de création de votre base de données de fichiers Mp3 :
la partie préparation
les scripts perl

1- Qu'est ce que le Perl ?

Je vous épargne historique, anecdotes et compagnie déjà présents sur de nombreux sites sur le net.

Il faut savoir que c'est un langage de script (= interprété lors de l'exécution) particulièrement adapté au traitement de chaines de caractères.
On n'a pas besoin de compiler le script (en faire un exécutable)

Pourquoi quelqu'un comme vous devrait connaitre le Perl ?

Ne vous êtes vous jamais ennuyé à renommer des fichiers mp3 par exemple :
certains sont dans des répertoires auteur\album, certains ont déjà un nom, avec des espaces, sans espace, avec des caractères 'underscore', il faudrait leur donner des numéros incrémentiels etc...

Après avoir compris les notions de bases (la phase la plus difficile), ce langage vous procurera beaucoup de plaisir

Avec un peu de tenacité, vous pourrez automatiser en un minimum de lignes certaines tâches pénibles et répétitives.

Si vous voulez aller plus loin, sachez que Perl est très complet, il peut être utilisé :

Exemple pour comprendre facilement la programmation

prenons un exemple simple.
Vous avez un jeu battu de 52 cartes et devez faire un tas des 4 couleurs (Pique, coeur, carreau, trèfle)

décortiquons l'action que votre cerveau va effectuer :

pour chaque carte
{
    si couleur = pique
    {
        placer la carte sur le tas des piques
    }
    sinonsi couleur = coeur
    {
        placer la carte sur le tas des coeurs
    }
    sinonsi couleur = carreau
    {
        placer la carte sur le tas des carreaux
    }
    sinonsi couleur = trefle
    {
        placer la carte sur le tas des trefles
    }
    sinon
    {
        he la ya un truc qui va pas !
    }
}

'pour chaque carte' va être executé 52 fois : c'est une boucle
'si couleur = ?' nous faisons un test sur une donnée et faisons une action à condition que le test soit vrai
pour terminer, nous pouvons dire que les paquets de cartes forment chacun une liste (= une suite de couleurs)

Maintenant, nous voulons que le paquet de trèfle soit trié dans l'ordre croissant

trie-moi (le paquet de trefle)

un peu facile : au lieu d'écrire moi-même le mécanisme de tri, j'utilise une fonction qui existe déjà !

Prérequis

Pour comprendre ce qui suit, il faut connaitre le minimum en programmation.
Et le minimum c'est pas grand chose !

Récupérez Perl sur un site et installez-le sur votre machine :  > Download Perl <

Je vous conseille de récuperer de la documentation qui vous apportera des précisions sur la syntaxe :  > Documentation perl <

But de ces quelques pages

Commençons ...

Copiez les exemples des pages suivantes dans un fichier texte et vérifiez le resultat.

pour voir le resultat
sous windows NT4, 2000, XP cliquez sur le menu démarrer | exécuter puis taper 'cmd' puis OK
ensuite lancez le fichier avec le programme Perl comme suit :

saisir dans la console : c:\perl\perl.exe -w fichier_texte.txt

Etudiez bien les exemples !
Faites quelques changements si vous pensez comprendre le principe !

N'oubliez pas le ';' après chaque instruction !


2- Les types de données

Les variables contiennent des données que le programme va utiliser pour effectuer des traitements.
Les données :

On va parler des scalaires et des listes. Sachez qu'il en existe d'autres comme les tableaux nominatifs

1 - variables scalaire : les nombres entiers

Les scalaires contiennent une seule valeur (nombres, chaine de caractères)

fichier scalaire1.txt résultat sur la console 
# en perl, les commentaires commencent par le caractere diese
# et vont jusqu'à la fin de la ligne

# on initialise les variables : on met 4 dans $a et 5 dans $A

$a = 4;
$A = 5;

# calcul : on multiplie $a par $A et on met le resultat dans $c
$c = $a * $A;

# affichage du resultat
print $c;

D:\>c:\perl\perl.exe -w scalaire1.txt
20

explications

les variables scalaires commençent par le caractère '$'.

elles peuvent contenir des nombres entiers.
attention $a est different de $A (perl est sensible à la casse).
le retour sur la sortie standard(la console) se fait par la commande 'print'.

pour aller plus loin

tester dans le script précédent  :

print $a * $A;

au lieu de

print $c;

2 - variables scalaire : les chaines de caractères

Voyons l'utilisation de scalaires qui contiennent des chaines de caractères...

fichier scalaire2.txt résultat sur la console
# initialisation des variables
$hello = "BONJOUR";
$you =  "Nico !";

$simpleQuote = '$hello $you \n';
$doubleQuote = "$hello\n $you\nca va ?";
$concatenation = $hello . $you;

# affichage
print "\nSIMPLE QUOTE : " . $simpleQuote;
print "\nDOUBLE QUOTE : " . $doubleQuote;
print "\nCONCATENATION : " . $concatenation;

D:\>c:\perl\perl.exe -w scalaire2.txt

SIMPLE QUOTE : $hello $you \n
DOUBLE QUOTE : BONJOUR
 Nico !
ca va ?
CONCATENATION : BONJOURNico !

explications

Les variables scalaires peuvent contenir une chaine de caractères
La concaténation (assemblage de 2 scalaires) est le signe '.'(point).
Le retour à la ligne est "\n".

Les variables sont évaluées si elles sont entre doubles quotes
Les variables ne sont pas évaluées si elles sont entre simples quotes

remarque

$out .= "text";

<=>

$out = $out . "text";

pour aller plus loin

comparer le resultat de :

print "\nhello\n";

puis de

print "
hello
";

3 - variables liste

En programmation, il est souvent utile de placer les variables à la suite et dans un certain ordre, on va utiliser les listes

fichier liste1.txt résultat sur la console
$a = 1;
$b = 2;

@uneListe = ($a, $b, 3);
@autreListe = (4, 5);

# noter l'acces ou la creation d'un element d'une liste
$autreListe[2] = 6;

# (@uneListe, @autreListe)
#  <=> ((1, 2, 3), (4, 5, 6))
#  <=> (1, 2, 3, 4, 5, 6)
@tout = (@uneListe, @autreListe);

print "ma liste : @tout";
print "\n 0 : " . $tout[0];  # indice 0 : 1er element
print "\n 1 : " . $tout[1];
print "\n 2 : " . $tout[2];
print "\n 3 : " . $tout[3];
print "\n 4 : " . $tout[4];
print "\n 5 : " . $tout[5];  # indice 5 : 6eme element

D:\>c:\perl\perl.exe -w liste1.txt
ma liste : 1 2 3 4 5 6
 0 : 1
 1 : 2
 2 : 3
 3 : 4
 4 : 5
 5 : 6

explications

Les variables 'liste' commençent par le caractère '@'.

Une liste est  une suite de scalaires séparés par des virgules, le tout entre parenthèses. Elle peut contenir d'autres listes(qui sont en effet déjà une suite de scalaires).

Important pour la suite : lorsqu'on accède à un élement d'une liste cet élément est un scalaire donc il commence par '$'.
on y accède par son indice
(son numéro d'ordre) qui est mis entre crochets.

Attention : l'indice du premier élément d'une liste est 0.

4 - quelques infos utiles sur les listes

fichier liste2.txt résultat sur la console
@chiffres = (0..9);

$nbElem = @chiffres;      # contexte scalaire
$indiceMax = $#chiffres;  # syntaxe pour obtenir l'indice max

print " $nbElem \n $indiceMax \n";

D:\>c:\perl\perl.exe -w liste2.txt
 10
 9

explications

Le double point dans le cas d'une liste signifie tous les éléments entre les 2 caractères.
Une liste dans un contexte scalaire renvoi son nombre d'éléments.
En remplaçant '@' par '$#' on a l'indice max de la liste.

Nous avons bien 10 éléments (le zero et le premier, le 9 est le dixième)
l'indice max est bien 9 car on commence la numerotation des indices à 0.

Ils sont utilisés très souvent pour les boucles

pour aller plus loin

contexte scalaire implicite :
deviner le resultat de :

print @liste;

puis de

print $n = @liste;

puis de

print scalar(@liste);

le séparateur de champ en sortie ($,).
comparer les resultats de :

@liste = (1, 2, 3);
print @liste;

et

@liste = (1, 2, 3);
$, = '-';
print @liste;

3- Les boucles

Les boucles permettent d'exécuter un certain nombre de fois un bloc d'instructions

5 - manipulation de listes : boucle foreach

fichier foreach.txt résultat sur la console
# notez l'utilisation de qw :
# les elements sont separes par des espaces

@liste = qw/a b c d e f/;
print 'contenu de @liste : ';

foreach $elem(@liste)
{
  # bloc d'instructions a repeter
  print "\n". $elem;
}
D:\>c:\perl\perl.exe -w foreach.txt
contenu de @liste :
a
b
c
d
e
f

explications

foreach est totalement adapté pour parcourir tous les éléments d'une liste dont on ne connait pas le nombre à l'avance.

Notez bien la syntaxe de foreach :

pour aller plus loin

tester le code suivant :

@impairs = (1, 3, 5 ,7 ,9);
foreach $chiffre(@impairs)
{
   $chiffre = $chiffre + 1;
}
print @impairs;

6 - la variable $_

fichier liste4.txt résultat sur la console
@liste = ('a'..'f');
print 'contenu de @liste :';

print "\n 1: avec \$elem : ";
foreach $elem(@liste)
{
  print "$elem";
}

print "\n 2: avec \$_ : ";
foreach (@liste)
{
  print "$_";
}

print "\n 3: sans \$_ : ";
print foreach (@liste);

D:\>c:\perl\perl.exe -w liste4.txt
contenu de @liste :
  1: avec $elem : abcdef
  2: avec $_ : abcdef
  3: sans $_ : abcdef

explications

$_ est la variable 'en cours' dans de nombreux cas on peut ainsi l'omettre (quand on est sûr de ce qu'elle contient).

Notez la dernière ligne de code :

print foreach (@liste);

<=>

foreach (@liste) { print; }

<=>

foreach $_(@liste) { print $_; }

<=>

foreach $elem(@liste) { print $elem; }

7 - manipulation de listes : boucles for et while

A vous de choisir l'un des deux, il font la même chose comme le montrent les 2 exemples suivants

le while utilise  plus de lignes et est peut-être moins lisible (variables éparpillés)
le for regroupe tout évitant ainsi les oublis d'initialisation, test et incrémentation de compteur

fichier while.txt résultat sur la console
@liste = ("a", "b", "c", "d", "e", "f");

print "contenu de \@liste :\n";

# on initialise la ou les variables AVANT la boucle
$i = 0;
$j = 1;

while($i < @liste) 
# attention dans le while
# toujours faire le test de sortie de boucle sur une valeur
# qui varie dans la boucle
{
  print "indice $i->".$liste[$i]."(element no $j)\n";

  # on incremente de 1 la ou les variables
  $i++;   # $i++  equivaut a $i = $i + 1;
  $j++;
}

D:\>c:\perl\perl.exe -w while.txt
contenu de @liste :
indice 0->a(element no 1)
indice 1->b(element no 2)
indice 2->c(element no 3)
indice 3->d(element no 4)
indice 4->e(element no 5)
indice 5->f(element no 6)

fichier for.txt résultat sur la console
@liste = ("a", "b", "c", "d", "e", "f");

print "contenu de \@liste :\n";

# on initialise 2 variables qu'on incremente de 1 a chaque
# passage de boucle
for($i = 0, $j = 1; $i < @liste; $i++, $j++)
{
  print "indice $i->".$liste[$i]."(element no $j)\n";
}
D:\>c:\perl\perl.exe -w for.txt
contenu de @liste :
indice 0->a(element no 1)
indice 1->b(element no 2)
indice 2->c(element no 3)
indice 3->d(element no 4)
indice 4->e(element no 5)
indice 5->f(element no 6)

explications

for est totalement adapté pour parcourir tous les élements d'une liste lorsqu'on a besoin de l'indice.

notez bien la syntaxe de for :

for (initialisation compteur; test de sortie de boucle;
    incrémentation compteur) { instructions à répéter... }


4- Les opérateurs

Les opérateurs manipulent ou testent des variables

8 - opérateurs

fichier ops.txt résultat sur la console
$a = 3;
$b = 2;
$max = 0;

print $a + $b ." addition ($a + $b)\n";
print $a - $b ." soustraction ($a - $b)\n";
print $a * $b ." multiplication ($a * $b)\n";
print $a / $b ." division ($a / $b)\n";
print $a % $b ." reste de division entiere ($a % $b)\n";

# utilisation de cet operateur a 3 termes tres utilise :
# $max = $a si ($a >= $b)
# $max = $b sinon
print $max = ($a >= $b) ? $a : $b;
print " le nombre max entre $a et $b\n";

D:\>c:\perl\perl.exe -w ops.txt
5 addition (3 + 2)
1 soustraction (3 - 2)
6 multiplication (3 * 2)
1.5 division (3 / 2)
1 reste de division entiere (3 % 2)
3 le nombre max entre 3 et 2

voir la documentation pour les nombreux operateurs :


5- Les conditions

Une condition est soit vraie soit fausse

On peut donc exécuter une instruction ou un bloc d'instructions selon une ou des conditions

9 - conditions : if

fichier if.txt résultat sur la console
$a = 1;
$b = 2;
$c = "a";
$d = "a";

if($a == $b)
{
  print "$a egale $b\n";
}
elsif($a != $b)
{
  print "$a est different de $b\n";
  if ($a < $b)
  {
    print "$a est inferieur a $b\n";
  }
  else
  {
    print "$a est superieur a $b\n";
  }
}
else
{
  # CAS IMPOSSIBLE
}
# AUTRE VARIANTE DU IF SUR UNE SEULE LIGNE
# noter l'utilisation de eq
#   il test l'egalite de chaines de caracteres

#   a la place de ==

print "\nsur une ligne :\n$c egale $d\n" if($c eq $d);

D:\>c:\perl\perl.exe -w if.txt
1 est different de 2
1 est inferieur a 2

sur une ligne :
a egale a

explications

Utilisation du IF

if (condition) { code a executer si condition vraie }

ou

if (condition) { code a executer si condition vraie }
else { code a executer si condition fausse }

ou

if (condition) { code a executer si condition vraie }
elsif (autre_condition) { code a executer si autre_condition vraie et condition fausse }
else { code a executer dans tous les autres cas }

pour aller plus loin

unless est la négation du if
il n'y a pas de difference entre :

if($a == $b)
{
}
else
{
  print "$a different de $b";
}

et

unless($a == $b)
{
   print "$a different de $b";
}


6- Fonctions utiles

Quand on programme, on ne doit jamais réécrire du code et on ne doit pas écrire le programme tout d'un bloc
on crée donc des fonctions et on les appelle autant de fois que besoin
une fonction doit résoudre très bien un et un seul petit problème et comme on le dit dans le monde de l'informatique :
"on peut toujours scinder un gros problème compliqué en plusieurs petits problèmes plus simples"

On peut écrire des fonctions ou utiliser celles qui existent déjà
Une fonction prend un ou des paramètres en entrée séparés par des virgules, les transforme et renvoit un résultat.

On fait appel à une fonction comme suit : resultat = fonction(parametre_un, parametre_deux) ou bien fonction(parametre_un, parametre_deux)

il faut donc connaitre le type de résultat renvoyé par la fonction (scalaire, liste...) et les paramètres à fournir en entrée

CHOMP

Suppression du retour charriot dans une variable, attention! ne pas utiliser l'exemple tel quel

si chomp n'est pas suivi d'une variable, il s'applique à $_

# ouverture du repertoire contenant les fichiers mp3. si impossible, le script meurt
opendir (MON_REPERTOIRE,"D:/mp3/") || die "impossible d'ouvrir le dossier";

# mise en place dans une liste du nom des fichiers et sous-repertoires de ce repertoire
@dir = readdir MON_REPERTOIRE;
closedir(MON_REPERTOIRE);

$id = 0;
foreach $fic(@dir)
{
  chomp $fic;   # suppression du entree a la fin de $fic
  $id++;
  # generation de la chaine SQL pour remplir la base de donnees
  print "INSERT INTO maTable VALUES($id,'$fic');\n";
}

SORT, REVERSE

sort permet de trier une liste

reverse inverse les éléments d'une liste

@clavier = qw/a z e r t y u i o p q s d f g h j k l m w x c v b n/;

print sort(@clavier);  # tri de la liste
print "\n";
print reverse(sort(@clavier)); # inversion de la liste

abcdefghijklmnopqrstuvwxyz
zyxwvutsrqponmlkjihgfedcba

GREP

Permet de récupérer une partie d'une liste correspondant à une expression régulière dans une autre liste (voir plus bas pour des explications sur les expressions régulières)

@tout = ("AsseZ", "Alphabet", "NEZ", "alleZ");

@seulementCommancantParAetFinissantParZ = grep (/^A.*Z$/i,@tout);

print @seulementCommancantParAetFinissantParZ;

AsseZalleZ

SPLIT

Permet grace aux expressions régulières (voir plus bas pour des explications sur les expressions régulières) de découper un scalaire selon un séparateur (le point-virgule par exemple)
chaque élément est mis dans une liste.

en gros on "transforme" un scalaire en liste (on doit donc définir le séparateur choisi)

# noter que les champs sont separes entre eux par des ';'
#  les valeurs sont separees des libelles par des ':'
$carnetAdresses = "nom:DUPONT;prenom:PIERRE;age:54ans";

# on split l'enregistrement par rapport au point-virgule
#   on a donc une liste de champs
@elements = split(/;/, $carnetAdresses);
print $elements[0]."\n".$elements[1]."\n".$elements[2];

# on split le premier champ par rapport aux 2 points
#   on a donc une paire libelle-valeur
($libelle,$valeur)= split(/:/, $elements[0]);

print "\n\nle $libelle est : $valeur";

nom:DUPONT
prenom:PIERRE
age:54ans

le nom est : DUPONT

le séparateur est une expression régulière

pour aller plus loin

split renvoie une liste d'où

@elemts = split (/;/, $carnetAdresses);

<=>

($nom, $pre, $age) = split (/;/, $carnetAdresses);

<=>

$age = split (/;/, $carnetAdresses)[2];

JOIN

Permet en choisissant un séparateur de crééer un scalaire en joignant les éléments d'une liste.

en gros on "transforme" une liste en scalaire (on doit donc definir un séparateur)

@voyelles = ('a','e','i','o','u','y');

$elementsJoins = join '-=-',@voyelles;
print $elementsJoins;

a-=-e-=-i-=-o-=-u-=-y
print "sur 1 ligne de code :\n". join ';',('a','e','i','o','u','y');
sur 1 ligne de code :
a;e;i;o;u;y

POP, SHIFT, PUSH, UNSHIFT

POP
Enleve et retourne le dernier élément d'une liste. (Sa taille est diminuée d'une unité.)

SHIFT
Enleve et retourne le premier élément d'une liste. (Sa taille est diminuée d'une unité et tous les éléments restants sont décalés d'un cran)

PUSH
ajout un élément à la fin d'une liste

UNSHIFT
ajoute un élément au debut d'une liste

@lettresDuMot = (split (//,"singuliers"));
print ("avant : ",@lettresDuMot, "\n");

$derniereLettre = pop (@lettresDuMot);
print ("apres : ",@lettresDuMot, "\n");

print "element poppé : $derniereLettre\n";

avant : singuliers
apres : singulier
element poppé : s
@liste = (1,2,3,4,5);

print ("liste avant : ",@liste, "\n");

$premierElem = shift (@liste);
print ("liste apres : ",@liste, "\n");

print "element shifté : $premierElem\n";

liste avant : 12345
liste apres : 2345
element shifté : 1
@liste = (0,2,4,6,8);

print ("liste avant : ",@liste, "\n");

$nb = push (@liste,10,11);
print ("liste apres : ",@liste, "\n");

print "nombres d'element de \@liste : $nb\n";

liste avant : 02468
liste apres : 024681011
nombres d'element de @liste : 7
@liste = (0,2,4,6,8);

print ("liste avant : ",@liste, "\n");

$nb = unshift (@liste,-4,-2);
print ("liste apres : ",@liste, "\n");

print "nombres d'element de \@liste : $nb\n";

liste avant : 02468
liste apres : -4-202468
nombres d'element de @liste : 7

SPRINTF

retourne une chaine formatée sur la sortie standard

# on affiche des nombres alignes à droite dans une colonne de
# largeur 5
# on comble les vides par des espaces
for($i = 0; $i < 200; $i = $i + 20)
{
  $out = sprintf("% 5d", $i);
  print "$out\n";
}

    0
   20
   40
   60
   80
  100
  120
  140
  160
  180


MAP

remarque:

map({expression}, @liste)

<=>

foreach(@liste)
{
  expression
}

# ajout retour a la ligne HTML
@in = ("ligne1","ligne2");

# $_ prend successivement la valeur de chaque element de @in
@out = map($_."<br />\n",@in);
print @out;

ligne1<br />
ligne2<br />



7- Les expressions régulières

Je ne vais pas faire du copier-coller à partir d'un autre site pour les lister

Le truc important à bien comprendre c'est que c'est hyper utile pour rechercher un modèle dans une chaine.

les regexpr s'utilisent avec m// et s///

entre le 1er et le 2eme '/', on place l'expression à chercher
pour s///, entre le 2eme et le 3eme '/' , on place la chaine qui remplace
apres le dernier '/', on place des options (i = insensible à la casse dans la recherche, g = ne pas s'arrêter à la premier ocurrence trouvée)

la chaine à partir de laquelle on recherche le modele est par défaut $_ :

if(/modele/) { print "trouvé !"; }

sinon, si on cherche modele dans $chaine, on utilise =~

if($chaine =~ /modele/) { print "trouvé !"; }

quelques exemples pour se familiariser

un chiffre apparaissant une et une seule fois /[0-9]/
un chiffre apparaissant de une à n fois /[0-9]+/
un chiffre apparaissant de 0 à n fois /[0-9]*/
un chiffre apparaissant 0 ou 1 fois /[0-9]?/
un chiffre apparaissant 5 à 8 fois /[0-9]{5,8}/
une ligne commançant par A /^A/
une ligne se terminant par a /a$/
une ligne contenant un caractère /./
une ligne contenant un point
/\./
une ligne contenant une majuscule /[A-Z]/
une ligne non vide /^.+$/
une ligne ne contenant pas que un point /!^\.$/
une ligne se terminant par .html, .htm ou .php /(\.htm[l]?)?|(\.php)?$/
un nombre à virgule (
commence par un chiffre apparaissant 0 à n fois
puis se termine 0 ou 1 fois par : une virgule et au moins un chiffre different de 0)
/^[0-9]*(,[0-9]*[1-9]+[0-9]*)?$/


8- La manipulation de fichiers

En espérant que ces exemples suffiront à expliquer

concaténation de 2 fichiers texte
open (IN,"monFichier.txt");  # mon handle s'appelle IN, il symbolise monFichier.txt
@fic1 = <IN>;                # chaque ligne de monFichier.txt est un element de @fic1
close IN;

open (FIC,"monAutreFichier.txt");
@fic2 = <FIC>;
close FIC;

@out = (@fic1,@fic2);

open(RESULTAT,">fichierSomme.txt");  # le fichier si il existait est écrasé
print RESULTAT @out;
close RESULTAT;

# dans cet exemple, on ne passe pas par des listes intermediaires
open (IN1,"monFichier.txt");
open (IN2,"monAutreFichier.txt");

open(OUT,">fichierSomme.txt");
print OUT (<IN1>,<IN2>);

close OUT;
close IN1;
close IN2;

pour aller plus loin

tester et comparer les résultats en executant le script plusieurs fois de suite
sans remplacer puis en remplaçant la ligne

open(OUT,">fichierSomme.txt");

par

open(OUT,">>fichierSomme.txt");


Document made with Nvu

Valid HTML 4.01 Transitional