<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//FR"> <HTML> <HEAD> <META http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <META NAME="GENERATOR" CONTENT="lfparser_2.8"> <META NAME="LFCATEGORY" CONTENT="Software Development"> <TITLE>lf136, Software Development: Perl partie III</TITLE> <!-- stylesheet added by lfparser: --> <style type="text/css"> <!-- pre { font-familiy:monospace,Courier } --> </style> </HEAD> <BODY bgcolor="#ffffff" text="#000000"> <!-- this is generated html code. NEVER use this file for your translation work. Instead get the file with the same article number and .meta.shtml in its name. Translate this meta file and then use lfparser program to generate the final article --> <!-- lfparser can be obtained from http://main.linuxfocus.org/~guido/dev/lfparser.html --> <!-- 2pdaIgnoreStart --> <MAP name="top"> <AREA shape="rect" coords="367,9,418,30" alt="Sommaire" href="../index.shtml"> <AREA shape="rect" coords="423,9,457,30" alt="Carte" href="../map.html"> <AREA shape="rect" coords="463,9,508,30" alt="Index" href="../Themes/index.html"> <AREA shape="rect" coords="514,9,558,30" alt="Recherche" href="../Search/index.html"> </MAP> <MAP name="bottom"> <AREA shape="rect" coords="78,0,163,15" alt="Nouvelles" href="../News/index.shtml"> <AREA shape="rect" coords="189,0,284,15" alt="Archives" href="../Archives/index.html"> <AREA shape="rect" coords="319,0,395,15" alt="Liens" href="../Links/index.html"> <AREA shape="rect" coords="436,0,523,15" alt="A propos" href="../aboutus.html"> </MAP> <!-- IMAGE HEADER --> <CENTER> <IMG src="../../common/images/Topbar-fr.gif" width="600" height="40" border="0" alt="[Barre Superieure]" ismap usemap="#top" ><BR> <IMG src="../../common/images/Bottombar-fr.gif" width="600" height="21" border="0" alt="[Barre Inferieure]" ismap usemap="#bottom"> </CENTER> <!-- SSI_INFO --> <!-- tr_staticssi include virtual --> <!-- tr_staticssi exec cmd --> <!-- addedByLfdynahead ver 1.1 --><TABLE ALIGN="right" border=0><TR><TD ALIGN="right"><FONT SIZE="-1" FACE="Arial,Helvetica">Cet article est disponible en: <A href="../../English/January2000/article136.shtml">English</a> <A href="../../Castellano/January2000/article136.html">Castellano</a> <A href="../../Deutsch/January2000/article136.shtml">Deutsch</a> <A href="../../Francais/January2000/article136.shtml">Francais</a> <A href="../../Nederlands/January2000/article136.shtml">Nederlands</a> <A href="../../Turkce/January2000/article136.shtml">Turkce</a> </FONT></TD></TR></TABLE><br> <!-- 2pdaIgnoreStop --> <!-- SHORT BIO ABOUT THE AUTHOR --> <TABLE ALIGN=LEFT BORDER=0 hspace=4 vspace=4 WIDTH="30%" > <TR> <TD> <!-- 2pdaIgnoreStart --> <!-- PALM DOC --> <TABLE BORDER=0 hspace=4 vspace=4> <TR> <TD> <font size=1> <img src="../../common/images/2doc.gif" width=34 align=left border=0 height=22 alt="convert to palm"><a href="http://cgi.linuxfocus.org/cgi-bin/2ztxt">Convert to GutenPalm</a><br>or <a href="http://cgi.linuxfocus.org/cgi-bin/2pda">to PalmDoc</a></font> </TD> </TR> </TABLE> <!-- END PALM DOC --> <!-- 2pdaIgnoreStop --> <br> <IMG SRC="../../common/images/Guido-S.gif" ALT="[Photo of the Author]" HEIGHT=164 WIDTH=173> <BR>par <A HREF="mailto:guido.socher@linuxfocus.org">Guido Socher</A> <BR><BR> <I>L´auteur:</I><BR> <P> Guido est un fan de Linux de longue date et un passionné de Perl. Vous pouvez visiter sa home page Linux à <a href="http://www.oche.de/~bearix/g/">www.oche.de/~bearix/g/</a>. </P> <BR><i>Sommaire</i>: <UL> <LI><A HREF="#lfindex0">Tableaux de variables</A></LI> <LI><A HREF="#lfindex1">Boucles sur les tableaux</A></LI> <LI><A HREF="#lfindex2">La ligne de commande</A></LI> <LI><A HREF="#lfindex3">Une pile</A></LI> <LI><A HREF="#lfindex4">Lire des répertoires</A></LI> <LI><A HREF="#lfindex5">Un outil pour la recherche de fichier</A></LI> <LI><A HREF="#lfindex6"> Références </A></LI> <LI><A HREF="http://cgi.linuxfocus.org/cgi-bin/lftalkback?anum=136&lang=fr">Discussion sur cet article</A></LI> </UL> </TD></TR></TABLE> <!-- HEAD OF THE ARTICLE --> <H2>Perl partie III</H2> <IMG SRC="../../common/images/illustration114.gif" ALT="[Illustration]" HSPACE=10 HEIGHT=100 WIDTH=100> <!-- ABSTRACT OF THE ARTICLE --> <P><i>Résumé</i>: <P> <a href="../September1999/article114.html"> Perl partie I </a> offrait une vue d'ensemble de Perl. Dans perl <a href="../November1999/article126.html">partie II</a> nous écrivions notre premier programme. Dans la partie III nous allons regarder de plus près les tableaux de variables. </P> <HR size="2" noshade align="right"><BR> <!-- BODY OF THE ARTICLE --> <A NAME="lfindex0"> </A> <H2>Tableaux de variables</H2> <p>Un tableau consiste en une liste de variables à laquelle vous accédez par un indice. Nous avons vu que les "variables normales", aussi nommées variables scalaires, commencent par un signe dollar ($). Les tableaux commencent par un signe @ même si les données d'un tableau sont composées de plusieurs variables scalaires. Vous devez donc écrire un signe dollar lorsque vous faites référence à un champ du tableau. Regardons un exemple: <CENTER><TABLE BORDER=0 WIDTH="70%" BGCOLOR="#99B8F6" > <TR> <TD> !/usr/bin/perl -w <br># vim: set sw=8 ts=8 si et: <br># on déclare un nouveau tableau: <br>my @myarray; <br># on l'initialise avec quelques données: <br>@myarray=("data1","data2","data3"); <br># on accède au premier élément (indice 0): <br>print "Le premier élément de myarray est: $myarray[0]\n"; </TD> </TR> </TABLE></CENTER> Vous remarquerez que nous écrivons @myarray lorsque nous nous référons à l'ensemble et $myarray[0] lorsque nous faisons référence à un élément. Les tableaux dans Perl commencent à l'indice 0. De nouveaux indices sont automatiquement crées dès que vous ajoutez des données. Au moment de la déclaration du tableau, vous n'avez pas besoin de connaître sa taille. Comme vous le voyez ci-dessus, vous pouvez initialiser un tableau avec des données en listant celles-ci séparées par des points virgules et entre parenthèses.<br> ("data1","data2","data3") <br>est un tableau anonyme. Par conséquent vous pouvez écrire ("data1","data2","data3")[1] <br>pour obtenir le deuxième élément de ce tableau: <CENTER><TABLE BORDER=0 WIDTH="70%" BGCOLOR="#99B8F6" > <TR> <TD> !/usr/bin/perl -w <br>print "Le deuxième élément est:" <br>print ("data1","data2","data3")[1]; <br>print "\n" </TD> </TR> </TABLE></CENTER> <A NAME="lfindex1"> </A> <H2>Boucles sur les tableaux</H2> La boucle foreach dans Perl, permet l'itération de tous les éléments d'un tableau. Elle fonctionne ainsi: <CENTER><TABLE BORDER=0 WIDTH="70%" BGCOLOR="#99B8F6" > <TR> <TD> #!/usr/bin/perl -w <br># vim: set sw=8 ts=8 si et: <br>my @myarray =("data1","data2","data3"); <br>my $lvar; <br>my $i=0; <br>foreach $lvar (@myarray){ <br> print "le numéro de l'élément $i est $lvar\n"; <br> $i++; <br>} </TD> </TR> </TABLE></CENTER> Exécuter ce programme nous donne: <CENTER><TABLE BORDER=0 WIDTH="70%" BGCOLOR="#99B8F6" > <TR> <TD> l'élément numéro 0 est data1 <br>l'élément numéro 1 est data2 <br>l'élément numéro 2 est data3 </TD> </TR> </TABLE></CENTER> Foreach extrait chaque élément du tableau et l'intègre dans la variable de la boucle ($lvar dans l'exemple ci-dessus). Il est important de remarquer que les valeurs ne sont pas copiées du tableau dans la variable de la boucle. Au contraire, la variable de la boucle est une sorte de pointeur et le fait de la modifier modifie les éléments du tableau. Le programme suivant transforme tous les éléments du tableau en majuscules. Dans perl <tt>tr/a-z/A-Z/</tt> est équivalent à la commande unix "tr". Dans ce cas, il transforme toutes les lettres en majuscules. <CENTER><TABLE BORDER=0 WIDTH="70%" BGCOLOR="#99B8F6" > <TR> <TD> #!/usr/bin/perl -w <br># vim: set sw=8 ts=8 si et: <br>my @myarray =("data1","data2","data3"); <br>my $lvar; <br>print "before:\n"; <br>foreach $lvar (@myarray){ <br> print "$lvar\n"; <br> $lvar=~tr/a-z/A-Z/; <br>} <br>print "\nafter:\n"; <br>foreach $lvar (@myarray){ <br> print "$lvar\n"; <br>} </TD> </TR> </TABLE></CENTER> Lorsque vous lancez le programme vous constatez que @myarray ne contient plus que des majuscules dans la seconde boucle: <CENTER><TABLE BORDER=0 WIDTH="70%" BGCOLOR="#99B8F6" > <TR> <TD> <pre> avant: data1 data2 data3 après: DATA1 DATA2 DATA3 </pre> </TD> </TR> </TABLE></CENTER> <A NAME="lfindex2"> </A> <H2>La ligne de commande</H2> Dans Perl II nous avons vu qu'une fonction &getopt peut être utilisée pour lire la ligne de commande et toutes ses options. &getopt est comme son équivalent en C. C'est une fonction de bibliothèque. Les valeurs de la ligne de commande dans Perl sont affectées à un tableau nommé @ARGV. &getopt récupère cet @ARGV et en évalue les éléments. <br> Au contraire du C, le contenu du premier élément du tableau n'est pas le nom du programme mais le premier argument de la ligne de commande. Si vous voulez connaître le nom du programme Perl, vous devez lire $0 mais ce n'est pas le sujet de cet article. Voici un programme exemple nommé <a href="../../common/src/article136/add.txt">addition</a>. Il récupère deux nombres de la ligne de commande et les additionne: <CENTER><TABLE BORDER=0 WIDTH="70%" BGCOLOR="#99B8F6" > <TR> <TD> > add 42 2 <br>42 + 2 is:44 </TD> </TR> </TABLE></CENTER> .... et voici le programme: <CENTER><TABLE BORDER=0 WIDTH="70%" BGCOLOR="#99B8F6" > <TR> <TD> #!/usr/bin/perl -w <br># vérifier que nous avons 2 arguments: <br>die "USAGE: add number1 number2\n" unless ($ARGV[1]); <br>print "$ARGV[0] + $ARGV[1] is:", $ARGV[0] + $ARGV[1] ,"\n"; </TD> </TR> </TABLE></CENTER> <A NAME="lfindex3"> </A> <H2>Une pile</H2> Perl possède certaines fonctions internes qui utilisent un tableau de variables comme pile. <ul> <li> push ajoute un élément à la fin du tableau <li> pop lit un élément à la fin du tableau <li> shift lit un élément au début du tableau <li> unshift ajoute un élément au début du tableau </ul> Le <A href="../../common/src/article136/array3.txt">programme suivant</a> ajoute deux éléments à un tableau existant: <CENTER><TABLE BORDER=0 WIDTH="70%" BGCOLOR="#99B8F6" > <TR> <TD> #!/usr/bin/perl -w <br>my @myarray =("data1","data2","data3"); <br>my $lvar; <br>print "the array:\n"; <br>foreach $lvar (@myarray){ <br> print "$lvar\n"; <br>} <br>push(@myarray,"a"); <br>push(@myarray,"b"); <br>print "\nafter adding \"a\" and \"b\":\n"; <br>while (@myarray){ <br> print pop(@myarray),"\n"; <br>} </TD> </TR> </TABLE></CENTER> Pop supprime les éléments à la fin du tableau et la boucle while se poursuit jusqu'à ce que le tableau soit vide. <A NAME="lfindex4"> </A> <H2>Lire des répertoires</H2> Perl offre les fonctions opendir, readdir et closedir pour lire le contenu d'un répertoire. readdir renvoie un tableau contenant tous les noms de fichier. En utilisant une boucle foreach vous pouvez parcourir tous les noms de fichier et rechercher un nom donné. Voici un <a href="../../common/src/article136/search_in_curr_dir.txt">simple programme</a> qui recherche un nom de fichier donné dans le répertoire courant: <CENTER><TABLE BORDER=0 WIDTH="70%" BGCOLOR="#99B8F6" > <TR> <TD> #!/usr/bin/perl -w <br># vim: set sw=8 ts=8 si et: <br>die "Usage: search_in_curr_dir filename\n" unless($ARGV[0]); <br>opendir(DIRHANDLE,".")||die "ERROR: impossible de lire le répertoire courant\n"; <br>foreach (readdir(DIRHANDLE)){ <br> print"\n"; <br> print "found $_\n" if (/$ARGV[0]/io); <br>} <br>closedir DIRHANDLE; </TD> </TR> </TABLE></CENTER> Regardons le programme. D'abord nous vérifions que l'utilisateur a fourni un argument à la ligne de commande. Dans la négative nous affichons un message d'utilisation et quittons le programme. Ensuite nous ouvrons le répertoire courant ("."). opendir est équivalent aux <tt>fonctions d'ouverture</tt> des fichiers. Le premier argument est un handle que vous devez passer aux fonctions readdir et closedir. Le deuxième argument est le chemin du répertoire. <br> Vient ensuite la boucle foreach. La première chose intéressante est que la variable de la boucle est manquante. Dans ce cas Perl fait de la magie en créant pour vous une variable nommée $_ qui est alors utilisée comme variable de la boucle. readdir(DIRHANDLE) renvoie un tableau et nous utilisons foreach pour voir chaque élément. /$ARGV[0]/io compare les <a href="../July1998/article53.html">expressions régulières</a> contenues dans $ARGV[0] par rapport à la variable $_. io signifie que la recherche ne tient pas compte de la casse et compile une seule fois les expressions régulières. La dernière chose est une optimisation accélérant le programme. Vous pouvez l'utiliser si vous avez une variable dans une expression régulière et si vous êtes certains qu'elle ne changera pas à l'exécution. <br> Essayons. En supposant que nous ayons les fichiers article.html, array1.txt et array2.txt dans le répertoire courant, si nous cherchons "HTML" le programme affichera: <pre> >search_in_curr_dir HTML . .. article.html found article.html array1.txt array2.txt </pre> Comme vous le voyez, la fonction readdir a trouvé 2 fichiers supplémentaires. "." et "..". Ce sont les noms du répertoire courant et du précédent. <A NAME="lfindex5"> </A> <H2>Un outil pour la recherche de fichier</H2> J'aimerais terminer cet article sur un programme plus complexe et utile. Il est censé être un programme de recherche de fichier. Nous l'appelons pff (perl file finder). Il fonctionne pratiquement comme le programme ci-dessus mais recherche également les sous-répertoires. Comment pouvons-nous créer un tel programme? Plus haut, nous avons du code qui lit le répertoire courant et y recherche des fichiers. Nous devons commencer par le répertoire courant mais si l'un des fichiers (sauf . et ..) est un autre répertoire nous devons également y faire une recherche. C'est un algorithme récursif type: <pre> sub search_file_in_dir(){ my $dir=shift; ...lit le répertoire $dir .... ...si un fichier est un autre répertoire alors on appelle &search_file_in_dir(ce fichier).... } </pre> Dans Perl vous pouvez vérifier qu'un fichier est bien un répertoire et non un lien symbolique en utilisant <tt>if (-d "$file" && ! -l "$dir/$_"){....}</tt>. <br>Nous avons maintenant toutes les fonctionnalités requises et nous pouvons écrire <a href="../../common/src/article136/pff.gz">le code (pff.gz)</a>. <CENTER><TABLE BORDER=0 WIDTH="70%" BGCOLOR="#99B8F6" > <TR> <TD> #!/usr/bin/perl -w <br># vim: set sw=8 ts=8 si et: <br># written by: guido socher, copyright: GPL <br># <br>&help unless($ARGV[0]); <br>&help if ($ARGV[0] eq "-h"); <br> <br># commence dans le répertoire courant: <br>search_file_in_dir("."); <br>#----------------------- <br>sub help{ <br> print "pff -- perl regexp file finder <br>USAGE: pff [-h] regexp <br> <br>pff recherche dans le répertoire courant et ses sous-répertoires <br>des fichiers correspondants à une expression régulière donnée. <br>La recherche ne tient jamais compte de la casse. <br> <br>EXEMPLE: <br> recherche d'un fichier contenant la chaîne foo: <br> pff foo <br> recherche d'un fichier se terminant par .html: <br> pff \'\\.html\' <br> recherche d'un fichier commençant par la lettre \"a\": <br> pff \'^a\' <br> recherche d'un fichier contenant le nom article<qqchose>html: <br> pff \'article.*html\' <br> remarquez le .* au lieu de seulement * <br>\n"; <br> exit(0); <br>} <br>#----------------------- <br>sub search_file_in_dir(){ <br> my $dir=shift; <br> my @flist; <br> if (opendir(DIRH,"$dir")){ <br> @flist=readdir(DIRH); <br> closedir DIRH; <br> foreach (@flist){ <br> # ignorer . et .. : <br> next if ($_ eq "." || $_ eq ".."); <br> if (/$ARGV[0]/io){ <br> print "$dir/$_\n"; <br> } <br> search_file_in_dir("$dir/$_") if (-d "$dir/$_" && ! -l "$dir/$_"); <br> } <br> }else{ <br> print "ERROR: impossible de lire le répertoire $dir\n"; <br> } <br>} <br>#----------------------- </TD> </TR> </TABLE></CENTER> Regardons un peu le programme. Nous vérifions d'abord que l'utilisateur a fourni un argument à la ligne de commande. Si c'est non, c'est une erreur et nous affichons un petit texte d'aide. Nous affichons aussi un texte d'aide si l'option -h est donnée. Autrement, nous commençons la recherche dans le répertoire courant. Nous utilisons l'algorithme récursif comme décrit plus haut. Nous lisons le répertoire, recherchons les fichiers, vérifions si un fichier est un répertoire, si oui nous rappelons search_file_in_dir(). <br> <br> Dans la partie où nous vérifions s'il s'agit de répertoires nous vérifions aussi qu'il ne s'agit pas d'un lien vers un répertoire. Nous devons le faire parce que quelqu'un peut avoir crée un lien symbolique vers "..". Un tel lien forcerait le programme à s'exécuter indéfiniment si nous ne faisions pas cette vérification. <br> <br> Nous n'avons pas encore parlé du <tt>next if ($_ eq "." || $_ eq ".."); </tt>. L'opérateur "eq" est l'opérateur de comparaison de chaîne de Perl. Ici, nous testons si le contenu de la variable $_ est équivalent à ".." ou ".". S'il est équivalent alors "next" est exécuté. "next"dans une boucle foreach signifie redémarrer au début de la boucle avec l'élément suivant du tableau. Il est similaire au "continue" du C. <A NAME="lfindex6"> </A> <H2> Références </H2> Voici une liste d'autres intéressants tutoriels perl <ul> <li><a href="http://fpg.uwaterloo.ca/perl/">fpg.uwaterloo.ca/perl/</a> <li><a href="http://www.programmingtutorials.com/">www.programmingtutorials.com</a> <li><a href="http://www.ncsa.uiuc.edu/General/Training/PerlIntro/">www.ncsa.uiuc.edu/General/Training/PerlIntro</a> <li><a href="http://www.geocities.com/SiliconValley/Orchard/2320/perl.html">www.geocities.com/SiliconValley/Orchard/2320/perl.html</a> </ul> <!-- vim: set sw=2 ts=2 et: --> <!-- 2pdaIgnoreStart --> <A NAME="talkback"> </a> <h2>Discussion sur cet article</h2> Chaque article possède sa page de discussion. Vous pouvez y soumettre un commentaire ou lire ceux d´autres lecteurs: <center> <table border="0" CELLSPACING="2" CELLPADDING="1"> <tr BGCOLOR="#C2C2C2"><td align=center> <table border="3" CELLSPACING="2" CELLPADDING="1"> <tr BGCOLOR="#C2C2C2"><td align=center> <A href="http://cgi.linuxfocus.org/cgi-bin/lftalkback?anum=136&lang=fr"><b> page de discussion </b></a> </td></tr></table> </td></tr></table> </center> <HR size="2" noshade> <!-- ARTICLE FOOT --> <CENTER><TABLE WIDTH="95%"> <TR><TD ALIGN=CENTER BGCOLOR="#9999AA"> <A HREF="../../common/lfteam.html">Site Web maintenu par l´équipe d´édition LinuxFocus</A> <BR><FONT COLOR="#FFFFFF">© Guido Socher, <a href="../../common/copy.html">FDL</a> <BR><a href="http://www.linuxfocus.org">LinuxFocus.org</a></FONT> <BR><a href="http://cgi.linuxfocus.org/cgi-bin/lfcomment?lang=fr&article=article136.shtml" target="_TOP">Cliquez ici pour signaler une erreur ou envoyer un commentaire à Linuxfocus</A><BR></TD> <TD BGCOLOR="#9999AA"><!-- TRANSLATION INFO --> <font size=2>Translation information:</font><TABLE> <tr><td><font size=2>en</font></td> <td><font size=2>-></font></td> <td><font size=2>--</font></td> <td><font size=2><a href="mailto:guido.socher@linuxfocus.org"><FONT COLOR="#FFFFFF">Guido Socher</FONT></a></font></td> </tr> <tr><td><font size=2>en</font></td> <td><font size=2>-></font></td> <td><font size=2>fr</font></td> <td><font size=2><a href="mailto:gete@wanadoo.fr"><FONT COLOR="#FFFFFF">Georges Tarbouriech</FONT></a></font></td> </tr> </TABLE></TD> </TR></TABLE></CENTER> <p><font size=1>2001-03-18, generated by lfparser version 2.8</font></p> <!-- 2pdaIgnoreStop --> </BODY> </HTML>