Sommaire Carte Index Recherche Nouvelles Archives Liens A propos
[Barre Superieure]
[Barre Inferieure]
[Photo of the Author]
par Guido Socher

L´auteur:

Guido est un fan de Linux de longue date et un passionn� de Perl. Ces derniers temps il est tr�s occup� � r�nover sa maison et � planter salades et autres trucs dans le jardin.

Sommaire:

Perl partie II

[Illustration]

Résumé:

Perl partie II est le premier article de notre s�rie Perl dans lequel nous allons r�ellement traiter d'un programme utile. Perl partie I offrait une vue d'ensemble de Perl.



 

Un mod�le pour votre programme

Perl est id�al pour �crire de petits programmes, specialis�s dans une t�che. Pour acc�l�rer le processus de d�veloppement c'est une bonne id�e d'avoir un mod�le sous la main qui offre une structure et des fonctionnalit�s de base que vous aimeriez retrouver dans la plupart des programmes. Le code suivant offre une option d'analyse basique et poss�de d�j� une sous-routine pour afficher un message d'aide.

!/usr/bin/perl -w
# vim: set sw=8 ts=8 si et:
#
# supprimer le commentaire devant strict pour rendre
# le compilateur plus rigoureux sur les d�clarations:
#use strict;
# global variables:
use vars qw($opt_h);
use Getopt::Std;
#
&getopts("h")||die "ERROR: Option inexistante. -h pour l'aide.n";
&help if ($opt_h);
#
#>>your code<<
#
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
sub help{
print "help message\n";
exit;
}
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
__END__

Observons le code. &getopts() lit les options de la ligne de commande. Il d�finit les variables globales du nom $opt_<option> selon les options tap�es sur la ligne de commande. Chaque option commence par un "-" (signe moins) et doit suivre le nom du programme et pr�c�der tous les autres arguments. La cha�ne de caract�res donn�e � getopts (le "h" dans le programme ci-dessus ) liste les lettres de toutes les options autoris�es. Si l'option r�cup�re un argument il faut ajouter deux-points (:) apr�s la lettre d'option &getsopt("d:x:h") signifie que ce programme a les options -d, -x and -h. Les options -d et -x re�oivent un argument. Ainsi "-o quelque chose" sera valide par contre "-o -x n'importe quoi" provoque une erreur puisque le -o n'est pas suivi d'un argument.
Le &help if ($opt_h); appelle la sous-routine help si l' option -h a �t� donn�e sur la ligne de commande. Le sub help{ d�clare la sous-routine. Pour l'instant, il n'est pas si important que vous compreniez chaque d�tail du code. Prenez-le simplement comme un mod�le dans lequel vous ajouterez votre fonctionnalit� principale.

 

Utilisation du mod�le

Ecrivons un petit convertisseur de nombre qui utilise ce mod�le. Le programme, que nous appellerons numconv, devrait convertir des nombres hexad�cimaux et d�cimaux.
numconv -x 30 devrait afficher l'�quivalent hexad�cimal du d�cimal 30.
numconv -d 1A devrait afficher l'�quivalent d�cimal de l'hexad�cimal 1A.
numconv -h devrait afficher un texte d'aide.
La fonction perl hex() convertit des nombres hexad�cimaux en d�cimaux et la fonction printf() peut �tre utilis�e pour convertir des d�cimaux en hexad�cimaux. Les ins�rer dans notre mod�le nous donne tr�s vite un programme sympathique:

#!/usr/bin/perl -w
# vim: set sw=8 ts=8 si et:
#
# supprimer le commentaire devant strict pour rendre
# le compilateur plus rigoureux sur les d�clarations:
#use strict;
# global variables:
use vars qw($opt_d $opt_x $opt_h);
use Getopt::Std;
#
&getopts("d:x:h")||die "ERROR: Option inexistante. -h pour l'aide.n";
&help if ($opt_h);
if ($opt_d && $opt_x){
    die "ERROR:les options -x et -d s'excluent mutuellement.\n";
}
if ($opt_d){
    printf("decimal: %d\n",hex($opt_d));
}elsif ($opt_x){
    printf("hex: %X\n",$opt_x);
}else{
    # mauvaise utilisation -d ou -x doivent �tre pr�cis�s:
    &help;
}
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
sub help{
    print "convertit un nombre en hexad�cimal ou d�cimal.
USAGE: numconv [-h] -d hexnum
    umconv [-h] -x decnum

OPTIONS: -h pour l'aide
EXAMPLE: numconv -d 1af
\n";
    exit;
}
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
__END__

cliquez ici pour t�l�charger le code du programme numconv figurant ci-dessus.
Dans les paragraphes suivants nous regarderons ce programme d'un peu plus pr�s et nous essaierons de le comprendre.

 

Branchements conditionnels If

Le branchement if dans perl se pr�sente sous 2 formes:
expr if (cond);
ou
if (cond) BLOCK [[elsif (cond) BLOCK ...] else BLOCK]

BLOCK est un nombre de conditions entre crochets {}. Cela signifie que vous pouvez par exemple �crire:

printf("hello\n") if ($i);

if ($i == 2){
   printf("i is 2\n");
}elsif ($i == 4){
   printf("i is 4\n");
}else{
   printf("i is neither 2 nor 4\n");
}

Comme en C, il est �galement possible d'utiliser les op�rateurs && et ||.
printf("hello\n") if ($i);
Peut par cons�quent �tre �crit sous la forme
($i) && printf("hello\n");
Le || tel qu'utilis� dans notre mod�le traduit parfaitement les mots en langage parl�.
&getopts("d:x:h")||die "ERROR\n";
"Get the options or die". La fonction die() est �quivalente � un printf suivi d'exit. Ainsi, il affiche un message et termine le programme.
&getopts("d:x:h")||die "ERROR\n";
est �quivalent �
die "ERROR\n"; if (! &getopts("d:x:h"));
O� le ! est un op�rateur logique not. Encore une fois ceci peut ausi �tre �crit sous la forme
die "ERROR\n"; unless (&getopts("d:x:h"));
unless est �quivalent � if-not et il est plus �l�gant � lire que if(!..)

 

Variables

Dans le premier article sur perl nous avons vu que les variables scalaires (les $-variables) �taient utilis�es sans les d�clarer. Elles se cr��ent au moment d'�tre utilis�es. C'est une caract�ristique int�ressante pour de petits programmes mais qui peut entra�ner des erreurs difficiles � trouver dans des programmes plus longs. D�clarer une variable donne au compilateur la possibilit� de faire des v�rifications compl�mentaires sur les fautes de frappe.
"use strict;" vous force � tout d�clarer.
Consid�rons le code suivant.

#!/usr/bin/perl
#
$i=1;
print "i is $tpyerr\n";

Ce code fonctionnera parfaitement dans perl et donnera "i is ". Le module perl "use strict;" peut forcer le compilateur � se plaindre d'un tel programme. Lorsque vous utilisez "strict" tout doit �tre d�clar� sinon c'est une erreur.

#!/usr/bin/perl
use strict;
my $i=1;
print "i is $tpyerr\n";

Ceci g�n�re le message suivant et rend la faute de frappe facile � trouver

Global symbol "$tpyerr" requires explicit package name at ./vardec line 4.
Execution of ./vardec.txt aborted due to compilation errors.
Exit 255

Maintenant il est facile de corriger le code du programme:

#!/usr/bin/perl
use strict;
my $i=1;
print "i is $i\n";

Les variables dans perl peuvent �tre d�clar�es en utilisant "my" ou, comme nous l'avons d�j� vu dans le mod�le, "use vars":
use vars qw($opt_h);

Les variables globales sont d�clar�es par use vars. Ces variables sont globales pour toutes les biblioth�ques incluses.
Les variables locales au fichier du programme en cours (globales parmi toutes les sous-routines de ce fichier) sont d�clar�es par my au d�but du programme (en dehors d'une sous-routine).
Les variables locales � la sous-routine en cours sont d�clar�es par my � l'int�rieur de la sous-routine.

Les personnes exp�riment�es en programmation shell peuvent �tre tent�es de laisser de c�t� le signe $ en d�clarant la variable ou en lui attribuant une valeur. Ce n'est pas possible dans perl. Vous devez toujours �crire un signe $ lorsque vous utilisez une variable scalaire quoi que vous fassiez avec.

Vous pouvez aussi attribuer directement une valeur � la variable lorsque vous la d�clarez. my $myvar=10; d�clare la variable $myvar et d�finit sa valeur initiale � 10.

 

Sous-routines

Nous avons d�j� utilis� la sous-routine "help" dans le programme numconv ci-dessus. Les sous-routines peuvent �tre utilis�es pour programmer des fonctions personnalis�es. Elles aident � structurer votre programme.
Une sous-routine peut �tre incluse n'importe o� dans le texte du programme (avant ou apr�s qu'elle soit appel�e. Ca n'a pas d'importance). Vous lancez une sous-routine par sub name(){... et vous l'appelez par $retval=&name(...arguments...). La valeur retourn�e est la valeur de la derni�re commande ex�cut�e dans la sous-routine. Les arguments donn�s � la sous-routine sont pass�s au code � l'int�rieur de la sous-routine dans le tableau r�serv� @_. Nous verrons cela plus en d�tail lorsque nous aborderons les tableaux de variables. Pour l'instant, il suffit de savoir que les valeurs des variables scalaires peuvent �tre lues dans la sous-routine en utilisant shift. Voici un exemple:

#!/usr/bin/perl
use strict;
my $result;
my $b;
my $a;
$result=&add_and_duplicate(2,3);
print "2*(2+3) is $result\n";

$b=5;$a=10;
$result=&add_and_duplicate($a,$b);
print "2*($a+$b) is $result\n";

# additionner deux nombres et les multiplier par 2:
sub add_and_duplicate(){
    my $locala=shift;
    my $localb=shift;
    ($localb+$locala)*2;
}
 

Un vrai programme

Maintenant que nous avons trait� une grosse partie de la syntaxe de perl et des �l�ments du langage, il est temps d'�crire un vrai programme.
Perl a �t� con�u pour manipuler des fichiers texte avec tr�s peu d'effort de programmation. Notre premier programme Perl doit comparer une liste d'abr�viations et trouver les doublons dans cette liste. Par doublons nous entendons abr�viations apparaissant plusieurs fois dans la liste. La liste ressemble � ce qui suit:

Il est facile de manipuler des fichiers texte avec Perl
AC Access Class
AC Air Conditioning
AFC Automatic Frequency Control
AFS Andrew File System
...

Vous pouvez t�l�charger la liste ici. La syntaxe de ce fichier est la suivante:

Comment lire un tel fichier texte? Voici une partie du code perl pour lire le texte ligne par ligne:


....
open(FD,"abb.txt")||die "ERROR: can not read file abb.txt\n";
while(){
   #do something
}
close FD;
....

La fonction open prend un descripteur de fichier comme premier argument et le nom du fichier � lire comme second argument. Les descripteurs de fichiers sont une sorte de variables particuli�res. Il n'est pas n�cessaire de comprendre ce qu'est r�ellement un descripteur de fichier. Vous le mettez simplement dans la fonction open, vous l'utilisez dans la fonction qui lit les donn�es du fichier et pour finir vous le renvoyez � la fonction close. La lecture du fichier est faite par <FD>. Les <FD> peuvent �tre pass�s comme argument � une boucle while et le r�sultat est une lecture ligne par ligne.
Traditionnellement les descripteurs de fichiers sont �crits en majuscules dans Perl.

O� vont nos donn�es? Perl poss�de un certain nombre de variables implicites. Ce sont des variables que vous n'avez pas d�clar�es. Elles sont toujours pr�sentes. Une telle variable est $_. Cette variable contient la ligne lue � ce moment par la boucle while mentionn�e ci-dessus. Essayons (t�l�charger le code):

#!/usr/bin/perl
use strict;
my $i=0;
open(FD,"abb.txt")||die "ERROR: can not read file abb.txt\n";
while(<FD>){
   # incr�mente le compteur de ligne. Vous connaissez
   # sans doute le ++ du C:
   $i++;
   print "Line $i is $_";
}
close FD;
La variable implicite $_ contient la ligne courante.

Vous remarquerez que nous n'avons PAS �crit print "Line $i is $_ \n". La variable $_ contient la ligne en cours du fichier texte ainsi que le caract�re nouvelle ligne (\n).

Maintenant, nous savons comment lire le fichier. Pour terminer vraiment notre programme nous devons apprendre encore 2 choses:

  1. Comment lire l'abr�viation depuis le d�but de la ligne.
  2. Comment fonctionnent les tables de hachage dans perl

Expressions r�guli�res offre un moyen sophistiqu� de rechercher un mod�le dans une cha�ne de texte. Nous recherchons la premi�re cha�ne d'une ligne jusqu'au premier espace. En d'autres termes notre mod�le correspond � "d�but de ligne-->un nombre de caract�res sans espace-->un espace". Traduit en expressions r�guli�res de perl �a nous donne ^\S+\s. Si nous int�grons cela dans un m//; perl appliquera cette expression � la variable $_ (Rappel: cette variable contient la ligne courante; �a c'est bien). Le \S+ dans les expressions r�guli�res correspond � " un nombre de caract�res sans espace". Si nous mettons le \S+ entre parenth�ses nous r�cup�rons le "caract�re sans espace" dans la variable $1. Nous pouvons ajouter cela dans notre programme:

#!/usr/bin/perl -w
# vim: set sw=8 ts=8 si et:
#
use strict;
# global variables:
use vars qw($opt_h);
my $i=0;
use Getopt::Std;
#
&getopts("h")||die "ERROR: No such option. -h for help.n";
&help if ($opt_h);
#
open(FD,"abb.txt")||die "ERROR: can not read file abb.txt\n";
while(<FD>){
    $i++;
    if (m/^(\S+)\s/){
        # $1 contient maintenant le premier mot (\S+)
        print "$1 est l' abr�viation de la ligne $i\n";
    }else{
        print "Ligne $i ne commence pas par une abr�viation\n";
    }
}
close FD;
#
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
sub help{
     print "help text\n";
     exit;
}
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
__END__

L'op�rateur match (m/ /) retourne 1 si l'expression r�guli�re a �t� correctement appliqu�e � la ligne courante. Nous pouvons donc l'utiliser dans un branchement if. Vous devriez toujours utiliser un branchement if avant $1 (or $2, $3 ...) pour vous assurer que $1 contient vraiment des donn�es valides.

   

Tables de hachage

Nous pouvons maintenant lire le fichier et obtenir l'abr�viation, tout ce qui manque c'est un moyen de savoir si nous avons d�j� lu cette abr�viation. Ici nous avons besoin d'un nouveau type de donn�es perl: Les Tables de hachage. Les tables de hachage sont des tableaux de variables qui peuvent �tre index�s par une cha�ne de caract�res. Lorsque vous voulez la table de hachage compl�te vous �crivez dans perl un caract�re % devant le nom de la variable. Pour obtenir une seule valeur vous utilisez $variable_name{"index_string"}. Nous utilisons le m�me $ que pour les autres variables scalaires puisqu'un champ de la table de hachage n'est autre qu'une variable scalaire normale. Voici un exemple:

#!/usr/bin/perl -w
my %htab;
my $index;
# Chargement du tableau avec les donn�es:
$htab{"something"}="valeur de something";
$htab{"somethingelse"}=42;
# R�cup�ration des donn�es:
$index="something";
print "%htab at index \"$index\" is $htab{$index}\n";
$index="somethingelse";
print "%htab at index \"$index\" is $htab{$index}\n";

A l'ex�cution du programme nous obtenons:

%htab at index "something" est la valeur de something
%htab at index "somethingelse" est 42

Maintenant notre programme est complet:

 1  #!/usr/bin/perl -w
 2  # vim: set sw=4 ts=4 si et:
 3  # 
 4  use strict;
 5  # global variables:
 6  use vars qw($opt_h);
 7  my %htab;
 8  use Getopt::Std;
 9  #
10  &getopts("h")||die "ERROR: No such option. -h for help.n";
11  &help if ($opt_h);
12  #
13  open(FD,"abb.txt")||die "ERROR: can not read file abb.txt\n"; 
14  print "Abbreviations with several meanings in file abb.txt:\n";
15  while(<FD>){ 
16      if (m/^(\S+)\s/){
17          # we use the first word as index to the hash:
18          if ($htab{$1}){
19              # again this abbrev:
20              if ($htab{$1} eq "_repeated_"){
21                  print; # same as print "$_";
22              }else{
23                  # this is the first duplicate we print first
24                  # occurance of this abbreviation:
25                  print $htab{$1};
26                  # print the abbreviation line that we are currently reading:
27                  print;
28                  # mark as repeated (= appears at least twice)
29                  $htab{$1}="_repeated_";
30              }
31          }else{
32              # the first time we load the whole line:
33              $htab{$1}=$_;
34          }
35      }
36  } 
37  close FD; 
38  #
39  #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
40  sub help{
41          print "finddup -- Find abbreviations with several meanins in the
42  file abb.txt. The lines in this file must have the format:
43  abrev meaning
44  \n";
45          exit;
46  }
47  #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
48  __END__ 
Vous pouvez t�l�charger le programme en cliquant ici.

Comment fonctionne-t-il? Nous lisons le fichier ligne par ligne et nous stockons les lignes dans notre table de hachage nomm�e %htab (ligne 33). L'index pour le hachage est l'abr�viation. Avant de charger la table de hachage nous v�rifions qu'il n'y a pas d�j� quelque chose de stock� dedans (ligne 18). S'il y a d�j� quelque chose dans la table nous avons 2 possibilit�s:

  1. C'est le premier doublon
  2. Nous avions d�j� plusieurs doublons de cette abr�viation
Pour diff�rencier les 2 cas nous �crivons la cha�ne "_repeated_" dans la table de hachage pour marquer que nous avons d�j� trouv� un doublon dans le fichier (ligne 29).

Il est probablement mieux de t�l�charger le code et de le tester.

 

Et apr�s?

Dans cet article vous avez d�j� appris quelques d�tails du langage perl. Nous n'avons pas encore abord� tous les types de donn�es de perl et vous vous demandez sans doute �galement s'il est possible de ne pas coder en dur le nom de fichier "abb.txt" dans notre programme ci-dessus. Vous savez d�j� comment utiliser une option pour �viter cela (e.g finddup -f abb.txt). Essayez de modifier le programme! La mani�re g�n�rale de lire la ligne de commande dans perl sera trait�e dans le prochain article.
Site Web maintenu par l´équipe d´édition LinuxFocus
© Guido Socher
LinuxFocus 1999
Translation information:
en -> -- Guido Socher
en -> fr Georges Tarbouriech

1999-11-12, generated by lfparser version 0.7