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)
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é :
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à !
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 <
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 !
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
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;
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
";
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.
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;
Les boucles permettent d'exécuter un certain nombre de fois un bloc d'instructions
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;
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; }
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... }
Les opérateurs manipulent ou testent des variables
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 :
Une condition est soit vraie soit fausse
On peut donc exécuter une instruction ou un bloc d'instructions selon une ou des conditions
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";
}
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
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 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 |
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 |
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];
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
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 |
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 |
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 /> |
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]*)?$/ |
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");