PERL POUR LA MANIPULATION DE TEXTES Une Introduction par l

Transcription

PERL POUR LA MANIPULATION DE TEXTES Une Introduction par l
PERL POUR LA MANIPULATION DE TEXTES
Une Introduction par l'exemple
Sous linux, on peut exécuter un script perl en tapant dans un terminal laligne de commande
$ perl nom_du_programme.pl
Les exemples suivants, introduisent de manière graduelle les éléments de syntaxe du langage perl.
EXEMPLE 1 :
L'exemple suivant introduit une manière de traiter un fichier externe. Pour tous les exemples suivants
on va utiliser un fichier test.txt qu'il faudra copier dans le répertoire Perl.
===========
#!/usr/bin/perl
# imprime un texte avec chaque ligne précédée par un numéro de ligne.
# perl numerote_lignes.pl test.txt
$fich =shift ;
open(FICHIER, $fich) || die "Impossible d'ouvrir le fichier : $fich\n";
while (<FICHIER>) {
print "$. : $_";
}
print "\n$. lignes en tout\n\n";
============
La première ligne de n'importe quel programme perl doit être (ne jamais omettre cette ligne de code!!)
:
#!/usr/bin/perl
Cette ligne indique au système d'exploitation où trouver Perl. (Elle indique le chemin d'accès absolu
jusqu'à l'interpréteur)
Les lignes suivantes, précédées par le symbole # sont des lignes de commentaire. Elles seront
ignorées lors de l'exécution du script.
La ligne
$fich= shift;
permet de récupérer le nom du fichier qu'on cherche à traiter sur la ligne de commande. Ceci nous
permet de traiter n'importe quel fichier en utilisant le même script. Ce nom est stocké dans une
variable : $fich, dont on pourra se servir par la suite pour faire référence au fichier. Dans notre cas, la
valeur de cette variable, inchangée tout au long de ce script sera la chaîne de caractères "test.txt".
La ligne
open(FICHIER, $fich) || die "Impossible d'ouvrir le fichier : $fich\n";
permet d'ouvrir le fichier test.txt (la variable $fich vaut dans notre cas "test.txt"), et FICHIER est un
descripteur dont on pourra se servir par la suite pour lire dans le fichier $fich, qui vaut en
l'occurrence test.txt. Si cette action échoue, parce que le fichier désigne par $fich n'existe pas, (on
peut tester ce cas avec un fichier bidon toto.txt), le programme s'arrête avec le message :
Impossible d'ouvrir le fichier : toto.txt
while (<FICHIER>) {
...
}
indique qu'on cherche à exécuter les actions qui suivent pour chaque ligne du texte à traiter, en
l'occurrence FICHIER, qui est le "descripteur " de test.txt. While est un exemple de structure de
contrôle qui instruit le système de répéter ou itérer une action (ou une suite d'actions) tant qu'une
condition tient.
La syntaxe générale de la structure while est
while (condition) {
action ;
action;
...
}
Dans l'exemple présent, la condition est 'tant qu'il y a des lignes a lire'. Cette expression est exprimée
par l'opérateur <>. Les actions à accomplir (ici l'action d'imprimer à l'écran) sont encadrées pas les
guillemets.
La ligne
print "$. : $_";
fait appel à deux variables spéciales, prédéfinies en perl :
$. désigne le numéro de la ligne courante
$_ désigne la ligne courante et à l'opérateur print. Un opérateur instruit le système à accomplir une
certaine tâche.
Le résultat de cette instruction est l'impression à l'écran du numéro de la ligne courante, suivi du
signe : , suivi de la ligne courante.
Finalement, la ligne
print "\n$. lignes en tout\n\n";
permet d'imprimer, une fois que chaque ligne du fichier a été traitée, le nombre total de lignes du
fichier (lors de la dernière itération/répétition de la boucle while, la valeur de la variable $_ est la
dernière ligne du fichier et la valeur de $. est le numéro de la dernière ligne - on peut donc se servir de
cette dernière pour imprimer le nombre total de lignes du fichier.).
EXEMPLE 2 :
======================
#!/usr/bin/perl
# imprime un texte avec chaque ligne précédée par un numéro de ligne.
# perl
....._lignes.pl test.txt
$fich=shift ;
open(FICHIER, $fich) || die "Impossible d'ouvrir le fichier : $fich\n";
while (<FICHIER>) {
$len=length($_);
print "$len : $_";
}
print "\n$. lignes en tout\n\n";
======================
Exécuter le programme no 2. Que permet de faire ce programme? Ce programme introduit un
élément supplémentaire qui est la fonction prédéfinie length. Que permet de faire cette fonction?
EXEMPLE 3 : Que permet de faire le script suivant?
Les deux scripts introduisent trois éléments de plus : la structure de contrôle if, l'incrémentation
des variables et les opérateurs d'égalité sur des chaînes de caractères :
eq c-à-d equals (permettant de tester l'égalité) ou
ne c-a-d not-equals (qui permet de tester que deux chaînes de caractères sont différentes). Cet
opérateur aurait pu être utilisé à la place de eq en inversant l'ordre des blocs if-else.
Comment?
==============================
#!/usr/bin/perl
#Ce script permet de ....
#
$fich=shift ;
open(FICHIER, $fich) || die "Impossible d'ouvrir le fichier : $fich\n";
$nombre_lignes_vides = 0 ;
$nombre_lignes_non_vides =0;
while (<FICHIER>) {
if ($_ eq "\n"){
$nombre_lignes_vides++;
}else{
$nombre_lignes_non_vides++;
}
}
print "lignes vides : ", $nombre_lignes_vides, " et lignes non-vides : ",
$nombre_lignes_non_vides, "\n";
##print "lignes vides : $nombre_lignes_vides
$nombre_lignes_non_vides\n\n";
et lignes non-vides :
=======================
Deux variables son introduites avant le debut de la boucle while : $nombre_lignes_vides et
$nombre_lignes_non_vides. Ensuite, dans la boucle while chaque ligne du corpus est traitée. Si elle
correspond à la condition définie dans la branche if, alors la variable $nombre_lignes_vides est
incrémentée, sinon c'est la variable $nombre_lignes_non_vides qui est incrémentée.
NOTE : la notation
$nombre_lignes_vides ++
est équivalente à la notation
$nombre_lignes_vides =$nombre_lignes_vides+1;
Les deux instructions permettent d'affecter à la variable $nombre_lignes_vides son ancienne valeur
incrémentée de 1.
EXEMPLE 4 : Que permet de faire le script suivant? Il utilise la plupart d'éléments qu'on a déjà
rencontrés plus l'opérateur de comparaison > (supérieur). Dans notre exemple, cet opérateur permet
de comparer deux quantités numériques. L'exemple montre aussi que le bloc else dans une structure
if-else est optionnel.
===================
#!/usr/bin/perl
# ce script permet de .....
$fich=shift ;
open(FICHIER, $fich) || die "Impossible d'ouvrir le fichier : $fich\n";
$max=0;
while (<FICHIER>) {
$len=length($_);
if ($len > $max){
$max=$len;
}
}
print "MAXIMUM: $max\n";
===================
EXEMPLE 5 : Que permet de faire le script suivant?
==================
#!/usr/bin/perl
# ce script permet de ....................................
$fich=shift ;
open(FICHIER, $fich) || die "Impossible d'ouvrir le fichier : $fich\n";
while (<FICHIER>) {
tr/A-ZÂÀÄÉÈÊËÎÏÔÖÓÛÙÜÇÑ/a-zâàäéèêëîïôöóûùüçñ/;
s/([0-9]+) ([0-9]+)/$1$2/g;
s/ ([sdlmntcj]')([a-z]+)/ $1\n$2/g;
s/^([dlmntcj]')([a-z]+)/$1\n$2/g;
s/(qu|jusqu|lorsqu)'/$1'\n/g;
tr/\t//d;
s/\.\n/\n.\n/;
s/([,\.]) /\n$1 /g;
tr/ /\n/;
print $_;
}
======================
Certains éléments qu'on avait vus lors des séances de familiarisation avec l'environnement Linux,
mais leur syntaxe est légèrement différente :
tr permet de transformer des ensembles de caractères (ici les majuscules en minuscules).
NOTE : les deux ensembles de caractères doivent être de taille égale.
s permet d'effectuer des substitutions sur des chaînes de caractères. Cette instruction permet de
manipuler aussi des expressions régulières.
$1 et $2 font référence à la première et deuxième sous-expression d'une expression régulière,
qu'on souhaite réutiliser dans les substitutions. Ces deux variables spéciales sont l'équivalent
des variables \1 et \2 qu'on avait vu avecla commande grep).
Reprenons tour à tour les éléments du langage perl qu'on a vu jusqu'ici, et examinons-les d'une
manière plus approfondie :
Les variables
L'opérateur print.
Variables scalaires :
- affectation d'une valeur
- opérateurs de comparaison
Les structures de contrôle
Substitutions et transformations sur les chaînes decaractères
Ouverture des fichiers et lecture
PREMIERE PARTIE
0/ Qu'est-ce que perl et qu'est-ce qu'on peut faire avec perl?
1/ Les variables : scalaires, tableaux, tableaux associatifs
2/ L'opérateur print.
3/ Variables scalaires :
- affectation des valeurs
- opérateurs de comparaison sur les valeurs scalaires(nombres et chaînes de caractères)
- substitutions et transformations sur les chaînes de caractères
4/ Les structures de contrôle
5/ Ouverture des fichiers
0/ Qu'est-ce que Perl et pourquoi on s'y intéresse?
Perl (Practical Report and Extraction Language ou Pathological Eclectic Rubbish Lister) est un
langage de programmation. Il est particulièrement adapté pour le traitement des fichiers textes (et les
CGI). On l'utilise principalement pour
la facilité avec laquelle on peut développer des programmes
la puissance du mécanisme des expressions régulières
simplicité - possibilité de faire des manipulations de textes sans prendre des cours de
programmation avancés. (On arrive à faire pas mal de choses même en étant débutants).
les programmes écrits en Perl peuvent être exécutés sous Unix, Windows, Mac, etc sans
modification (portable)
gratuité : un nombre impressionnant de librairies et utilitaires est disponible sur internet
1/ Les variables
Un programme informatique gère des données qu’il stocke en mémoire. On nomme ces données
pour pouvoir accéder aux zones de la mémoire centrale les contenant. Ces données peuvent changer
au cours de l'exécution d'un programme : donc les noms qu'on leur donne correspond à des variables.
Par exemple, dans le script 4, la variable $max peut changer de valeur a chaque répétition de la boucle
while. De même, dans le script no. 3 les variables $nombre_lignes_vides et
$nombre_lignes_non_vides, qui au début du script valent 0 toutes les deux - on dit qu'elle sont
initialisées à 0, changent alternativement de valeur. Pour mieux se représenter ce que c'est qu'une
variable et sa valeur on peut utiliser la métaphore de la boite aux lettres : une variable est comme une
boite aux lettres nommée, et sa valeur est son contenu à un moment donné.
Il existe plusieurs types de variables qu'on manipule enPerl :
1. des scalaires : des variables ayant une valeur simple, qu'on peut manipuler simplement. Tel
est le cas des nombres entiers (comme 2, 30, etc. comme - les variables $max, $length,
$nombre_lignes_vides ont des valeurs de ce type), nombres flottants (comme 20,35) et les
chaînes de caractères (comme la variable $fich qui prend sa valeur sur la ligne de commande).
Les valeurs des chaînes de caractères sont entourées de guillemets simples ou doubles. Le
nom des variables est précédé du signe $.
2. tableaux (on reviendra sur ce type de valeur lors de la prochaine séance). Un tableau
représente une liste de valeurs scalaires ordonnées; chaque élément d'un tableau est une
variable scalaire. Les noms de variables de type tableau sont précédés par le symbole @.
Par exemple, on peut stocker une ligne qu'on lit dans un fichier dans un tableau afin
d'effectuer certaines opérations dessus:
@ligne=("the", "cat", "is", "on", "the", "mat", ".");
On peut se représenter cette variable comme ceci :
The cat
0
1
is
2
on
3
the
4
mat
5
.
6
Chaque élément du tableau est placé dans une case du tableau (une zone mémoire associée) à
laquelle on peut accéder à l'aide de l'indice de la case. NOTE : les indices dans un tableau
commencent à 0. Par exemple, si on vert accéder au 5ème mot de la phrase (qui aura donc
l'indice 4) on va utiliser la notation :
$ligne(4)
La valeur de cette variable scalaire (chaîne de caractères) vaut "the".
Lors de la lecture de la ligne suivante d'un fichier, la taille et la valeur d'une variable tableau
change :
@ligne=("the", "cat", "is", "sick", "and", "is", "waiting", "to", "get", "better", ".");
$ligne(4) vaut maintenant "and".
3.
hachages ou tableaux associatifs. (On reviendra sur ce type de valeur dans deux séances).
Les tableaux associatifs sont une type particulier de tableau. Tandis que les éléments d’un
tableau sont indexés à partir de 0, les éléments d’un hachage sont indexés par une valeur
scalaire quelconque. Il s'agit d'une collection de paires clé-valeur. La clés par laquelle les
éléments sont indexés doit être unique. Les noms des valeurs des variables de type associatif
sont précédés par le symbole %. Un exemple qui permet de se représenter le type tableau
associatif d'une façon simple est le type dictionnaire. Par exemple :
%dico = ("cat" =>"Any animal of the natural family Felidae",
"mat" => "A thick flat fabric",
"sick" => "Affected with disease of any kind");
Ou alors
%dico = ("cat" =>"Nom",
"mat" => "Nom",
"sick" => "Adjectif");
Les symboles $,@,% permettent de repérer les variables plus facilement, et indiquent aussi de quel
type de variable il s'agit. Regardons maintenant plus en détail les valeurs scalaires (avec une valeur
singulière), après une courte digression sur l'opérateur print.
2/ L'opérateur print
Il s'agit d'un opérateur qui prend en argument une liste (on peut imprimer plusieurs choses, séparées
pas des virgules), comme on a fait dans le script 3 :
print "lignes vides : ", $nombre_lignes_vides, " et lignes non-vides : ", $nombre_lignes_non_vides,
"\n";
L'opérateur print a, dans ce cas, 5 arguments.
On aurait pu écrire la même chose en incluant les variables et le texte à imprimer dans une même
chaîne de caractères. Cette opération s'appelle interpolation des variables :
print "lignes vides : $nombre_lignes_vides et lignes non-vides : $nombre_lignes_non_vides \n";
L'interpolation des variables est possible uniquement avec les guillemets doubles.
3/Variables scalaires : nombres et chaînes de caractères
Vous avez peut-être remarqué dans les exemples de scripts qu'on a étudiés que les variables nombre et
chaînes de caractères sont déclarées de la même façon, sans indiquer le type comme ceci :
$max=0;
####(entier)
$nombre1=12.5 ;
$mot="cat";
#### (nombre réel)
####(chaîne de caractères)
A l'aide de l'opérateur print on peut les imprimer les trois variables comme ceci :
print "\$max vaut $max, \$nombre vaut $nombre et \$mot vaut $mot\n";
REMARQUE : on a du protéger ici le symbole $ afin de pouvoir l'imprimer, et éviter que l'opérateur
print affiche la valeur de $max, $nombre1 et $mot. Tous les méta-caractères comme $,@ et %
doivent être protégés de cette façon fin de pouvoir les imprimer.
A la différence de Perl, dans la plupart de langages de programmation on doit déclarer le type de
chaque variable. Par exemple, en C, une déclaration+initialisation comme :
$nb_lignes_vides =0 ;
devra indiquer le type de la variable qu'on veut déclarercomme ceci :
int nb_lignes_vides = 0;
Cette ligne déclare la variable nb_lignes_vides de type entier, et lui affecte une valeur initiale qui est
égale à 0.
C'est pour cette raison que Perl est appelé un langage faiblement typé. C'est à cause de cette manque
de rigueur que Perl n'est pas utilisé pour de gros développement de programmes, mais plutôt pour de
petites moulinettes.
Déclarer et modifier les valeurs des scalaires.
Afin d'illustrer ces concepts regardons les deux scripts suivants :
#!/usr/bin/perl
$nombre = 20 ;
$nb = 3 ;
$nombre ++;
print "\$nombre vaut
$nombre--;
print "\$nombre vaut
$nombre +=22;
print "\$nombre vaut
$nombre -= 22 ;
print "\$nombre vaut
$nombre*=$nb ;
print "\$nombre vaut
$nombre /=$nb ;
print "\$nombre vaut
$nombre=$nombre**3 ;
print "\$nombre vaut
$nombre maintenant\n";
$nombre maintenant\n";
$nombre maintenant\n";
$nombre maintenant\n";
$nombre maintenant\n";
$nombre maintenant\n";
$nombre maintenant\n";
====================
#!/usr/bin/perl
$prenom = "Marion" ;
$nom = "Vallet";
$nom = $prenom." ".$nom." ";
print "\$nom vaut maintenant $nom\n";
=====================
Quel est le rôle de la fonction chop?
=====================
#!/usr/bin/perl
print "Entrez votre nom s'il vous plaît\n";
$nom= <STDIN>;
print "*$nom*\n";
### pourquoi le deuxième symbole * est-il imprimé
sur une autre ligne?
chop $nom;
print "maintenant \$nom vaut *$nom*\n";
chop $nom;
print "maintenant \$nom vaut *$nom*\n" ;
======================
Cet exemple introduit aussi un descripteur prédéfini <STDIN> ou standard input - c'est à dire l'entrée
standard. Il permet de lire la valeur d'une variable au clavier. On reviendra sur les descripteurs de
fichiers lors de la prochaine séance. Les descripteurs de fichiers permettent d'interagir avecles
fichiers, la console d'entrée, etc.
Quelle est la différence entre l'opérateur chop et chomp (à juger par le script ci-après?
#!/usr/bin/perl
print "Entrez votre nom s'il vous plaît\n";
$nom= <STDIN>;
print "$nom\n";
chomp $nom;
print "maintenant \$nom vaut *$nom*\n";
chomp $nom;
print "maintenant \$nom vaut *$nom*\n" ;
=======================