Tuteur PERL (PERL Tutorial)

Valid XHTML 1.0!                  

Texte du Tuteur écrit par Gilles HUNAULT

Liste des autres tuteurs (langages, logiciels, systèmes d'exploitations...)



Texte remanié à partir du tuteur
écrit par les étudiantes de Licence MASS
Candice CHAUVE et Véronique COLIN.

Attention : ce tuteur date du début des années 2000 et traite de Perl 5 principalement. Il sera dépassé lorsque Perl 6 sera pleinement opérationnel (ce texte est écrit en janvier 2011). Pour un texte plus adapté, nous vous conseillons aux Editions Pearson :

 

perl moderne
 
Perl moderne
(19 euros)

Pour aller plus loin, vous pouvez

Et si vous connaissez déjà Php, vous pouvez profiter du tableau synoptique des instructions Perl et Php.

Vous y trouverez aussi des exemples d'utilisation de Perl en Cgi et d'interfaçage avec des bases de données (comme MySql).

Table des Matières du tuteur

  1. Le langage Perl
  2. Quelques exemples classiques et courts de programmation en Perl
  3. Quelques exemples moins triviaux en Perl
  4. Exercices (solution)


1. LE LANGAGE PERL

INTRODUCTION

Le langage Perl a été inventé par le linguiste Larry WALL. Perl signifie (entre autres) Practical Extraction and Report Language. Il est gratuit et disponible sous tous les environnements (Unix, Windows, MacOs...) par exemple à partir du site officiel http://www.cpan.org, de http://www.perl.com ou de http://www.activestate.com (ActivePerl).

Conçu au départ pour la gestion de fichiers textes comme successeur de sed et Awk, il est rapidement devenu un langage de scripts indispensable notamment pour les scripts Web (CGI), les scripts de configuration (dont Apache).

Le langage de base de Perl est facile à appendre quoiqu'un peu "confusant" au départ à cause de symboles #, @ et $ un peu partout dans les variables ainsi qu'aux syntaxes obscures des expressions régulières.

Les milliers (si, si) de bibliothèques de sous-programmes (on dit en fait modules) du site officiel http://www.cpan.com permettent de développer rapidement une application sans avoir à tout inventer. Pour s'en convaincre, on peut consulter la liste des 7400 et quelques modules (valeur au premier janvier 2005) disponibles.

Les points forts de Perl sont la concision des programmes, l'utilisation massive des expressions régulières, le support des listes et des tables de hachage en tous genres et l'interfaçage avec le système d'exploitation.

Toutes les variables de Perl sont repérées par leur nom, préfixé par un sigil

- le symbole $ pour une variable "scalaire" c'est à dire simple,
- le symbole @ pour une variable tableau classique ou liste,
- le symbole % pour une variable tableau associatif ou "hachage".

Par exemple la variable jour est écrite $jour. Perl fait la distinction, comme Awk entre minuscules et majuscules. Ainsi la variable $Premier est différente des variables $premier et $PREmier.

Les commentaires commencent par le symbole #. Ils sont placés où l'on veut sur la ligne. Tous les caractères situés derrière le symbole # seront ignorés jusqu'à la fin de la ligne. La fin d'une instruction est matérialisée par le symbole ; et on peut bien sur écrire une instruction sur plusieurs lignes.

On notera qu'il ya de nombreuses variables prédéfinies aux noms "égyptiens" comme $_ $\ $# ... .

L'instruction print permet d'écrire, aussi bien à l'écran que dans un fichier.

Les doubles cotes " autour d'une expression induisent une interprétation des variables et des autres "séquences interprétables" contenues dans l'expression, ce qui signifie que Perl remplace les variables et les séquences par leur valeur. Par contre les simples cotes ' autour d'une expression interdisent cette interprétation. Les anti-cotes ` autour d'une expression transmettent l'expression au système d'exploitation.

Par exemple, si la variable $nom contient "Pierre" et si $age vaut 13 alors l'instruction


     print '$nom\n a $age ans.';
affichera à l'écran :

     $nom\n a $age ans.
alors que l'instruction

     print "$nom\n a $age ans.";
affichera à l'écran :

     Pierre
      a 13 ans.
car la séquence \n signifie "new line" c'est à dire passer à la ligne.

Certains séquences font de la conversion de caractères. Par exemple \U passe en majuscules ("upper") jusqu'à la prochaine séquence et \E mis pour "end". Ainsi


     print "le \Ugars $nom\E est jeune";
provoque l'affichage de

     le GARS PIERRE est jeune

Perl dispose de nombreuses options de lignes de commandes, d'un debugger et d'une "floppée" d'instructions pour produire des rapports (ce pour quoi il était conçu et qu'on utilise peu en fait). Ainsi print << MRK à l'intérieur d'un programme Perl recopie tout ce qui suit tel quel à l'écran jusqu'à rencontrer la chaine MRK. Une utilisation intensive de cette technique permet de créer des fichiers postscript à la volée (via Tex) comme notre production de pages de titres nommée titre.prl.

C'est un jeu d'enfants que d'écrire un mini-interpréteur Perl en Perl. la preuve : exécutez notre programme pt.pl. Pour cela il suffit de récupérer le fichier et de taper


     perl pt.pl

 

TYPES DE DONNEES

Une variable peut désigner :

- un nombre, entier ou réel,
- une chaîne de caractères,
- un tableau,
- une liste,
- une table de hachage,
- un fichier,
- une référence (pointeur) à une variable,
- une désignation (glob) de variables.

Perl convertit automatiquement les types :

ainsi pour $val1 = "123"; et $val2 = $val1 + 2; la variable $val2 est égale à 125.

Perl essaie de convertir selon des règles techniques ; ainsi


     @a = (1,"oui",4) ;
     print "@a\n" ;      # affiche 1 oui 4

     @b = @a ;
     print "@b\n" ;      # affiche 1 oui 4

     $c = @a ;
     print "$c\n" ;      # affiche 3 car il y a 3 éléments dans @a

     $d = $a ;
     print "$d\n" ;      # affiche une ligne vide

     $e = $#a ;
     print "$e\n" ;      # affiche 2 car c'est l'indice du dernier
                         # élément (on compte à partir de 0)

 

OPERATEURS

Les opérateurs arithmétiques sont classiques et supportent les raccourcis d'affectation comme en C :

addition   +    ++
soustraction   -    --
multiplication   *
division   /
modulo   %
exponentiation  **

Les opérateurs sur les chaînes sont similaires à ceux de php :

concaténation   .
extraction de sous-chaîne  substr
Les opérateurs logiques distinguent les numériques des chaines de caractères.
comparaison nombres chaînes de caractères
égalité == eq
inégalité != ne
plus grand que > gt
plus grand ou égal >= ge
plus petit que < lt
plus petit ou égal <= le
comparaison avec
résultat signé
<=> cmp

Le résultat des opérations <=> et cmp est

-1 si l'opérande de gauche est inférieure à l'opérande de droite,
0 si elles sont égales,
+1 si l'opérande de gauche est supérieure à l'opérande de droite.

Les expressions logiques utilisent plusieurs opérateurs pour la même action, mais avec des préférences différentes ; voir la référence correspondante en ligne pour plus de détail. On y trouvera aussi la liste des trente et quelques tests logiques sur la présence ou les attributs des fichiers :

et logique
  &   &&   and
ou logique
  |    ||       or

Ces fonctions logiques fonctionnent en "court-circuit" c'est à dire qu'elles n'évaluent pas la seconde condition si la première suffit à déterminer le résultat du test logique.

 

INSTRUCTIONS

Un bloc d'instructions est délimité en Perl par des accolades.

Sous UNIX, on peut commencer un programme Perl par la ligne :


     #! /usr/bin/perl
Cela permet, si le fichier est exécutable (chmod +x) de l'exécuter en tapant directement son nom, au lieu d'utiliser la syntaxe

     /usr/bin/perl  nom_du_programme  [paramètres éventuels]

L'affectation directe se fait par le symbole = alors que l'affectation par addition (ou "incrémentation automatique") se fait par += ; de même, l'affectation par soustraction se fait par -=. Le lecteur trouvera de lui-même la syntaxe pour les autres "auto-opérations".

Pour lire une variable sur l'entrée standard on écrit


     $var = <STDIN> ;

Avec cette syntaxe $var contient le retour chariot. Pour palier à ce problème, il suffit d'utiliser l'une des fonctions suivantes :

chop($var);qui supprime le dernier caractère de $var.
chomp($var);qui supprime le retour chariot de $var.

Pour écrire sur la sortie standard on a le choix entre

print $var ; écrit sans retour à la ligne
print $var."\n" ; écrit avec retour à la ligne
print "$var\n" ; écrit avec retour à la ligne
print "\U$var\E" ; écrit avec passage en majuscules

Les tests et boucles sont traditionnels. La condition si utilise les syntaxes


     if ( condition ) { ... }
et

     if ( condition ) { ...  }
                 else { ...  }
On peut, pour les conditions imbriquées utiliser le mot-clé elsif :

     if    ( condition ) { ...  }
     elsif ( cond1 )     { ...  }
     elsif ( cond2 )     { ...  }
     ....
     else                { ...  } ;
Les boucles tant que s'écrivent

     while ( condition(s) ) { ... }
alors que les boucles pour suivent la syntaxe :

     for ( cond1; cond2; cond3 ) { ... }

Perl dispose d'autres boucles. Signalons la boucle jusqu'à qui s'écrit


     { ... } until ( condition(s) )
et les boucles de parcours des éléments d'un tableau

     foreach élément ( liste ou tableau ) { ... }
     while   ((clé,valeur) = each(tableau_associatif))

Perl dispose de deux opérateurs annexes next qui permet de passer à la fin de l'itération courante et d'en commencer une nouvelle ainsi que last qui permet de sortir de la boucle.

Perl permet de faire appel à une commande du système grâce à la commande system (mais on peut aussi utiliser les "anti-cotes" avec la combinaison de touches AltGr-è). Il y a souvent plusieurs façons d'écrire les choses en perl. Ainsi on peut quitter un programme avec un code de retour grace à exit mais die fait la même chose avec la possibilité d'écrire un message. De même, unless permet d'inverser le test en si. On notera que chaque instruction renvoie une valeur logique ce qui permet d'écrire des lignes comme


 open( FIC ,"<$ARGV[0]")
     or die "\n impossible d'ouvrir le fichier ... \n\n" ;

 

EXPRESSIONS REGULIERES

Les expressions régulières (ou modèles de chaines de caractères) et les séquences interprétables rendent Perl très efficace dans la gestion des chaines de caractères. La comparaison d'une chaine de caractères à un modèle se fait selon la syntaxe

(chaine =~ /modèle/) pour tester la correspondance au modèle
(chaine !~ /modèle/) pour tester la non-correspondance au modèle

Pour définir un modèle on peut utiliser les symboles suivants :

^ indique le début du modèle
$ indique la fin du modèle
. caractère quelconque
* répétition 0 fois ou plus du caractère qui précède
? répétition 0 ou 1 fois du caractère qui précède
+ répétition 1 fois ou plus du caractère qui précède
{a,b} répétition de a fois à b fois exactement
\ empêche l'interprétation du caractère qui suit s'il est spécial ( ^ $ . ? etc..)
[..] classe de caractères admissibles
(..|..) alternative

On peut également utiliser les séquences :

\s   les caractères du style "espace" (comme tabulation, retour-charriot...)
\w un caractère alphanumérique (ou mot "d'identificateur")
\d un caractère numérique

Les références arrières notées \1, \2... et les variables spéciales $1, $2... correspondent aux parties de chaines correspondant aux expressions régulières spécifiées. L'utilisation des expressions régulières se fait principalement par les syntaxes


   $variable =~   m/expression/remplacement/ [egimosx]  ;
   $variable =~   s/expression/remplacement/ [egimosx]  ;
   $variable =~  tr/expression/remplacement/ [cds] ;
Par exemple

 $phr =~ tr/A-Z/a-z/ ;
convertit en minuscules (en mode américain) la phrase contenue dans $phr.

Pour plus de détails, voir la voir la référence correspondante en ligne ou le chapitre 6 du cours de F. Dagorn.

 

FICHIERS

L'ouverture se fait avec open :

- ouverture d'un fichier en lecture uniquement

     open ( descripteur,"nom_fichier");
- ouverture en écriture avec écrasement en cas d'existence préalable du fichier

     open ( descripteur,"> nom_fichier");
- ouverture en écriture avec ajout en fin de fichier

     open ( descripteur,">> nom_fichier");

Les autres opérations sur un fichier sont :

- écriture dans un fichier ouvert

     print descripteur "ce qu'il y a à ajouter";
- lecture dans un fichier : elle se fait par lignes

     $ligne = < descripteur > ;
- fermeture d'un fichier

     close descripteur ;
- destruction d'un ou plusieurs fichiers

     unlink (liste des noms de fichiers);
Pour tester la présence, les attributs d'un fichier, voir la page de référence correspondante en ligne.

 

TABLEAUX

Il y a deux sortes de tableaux :

- les tableaux classiques (indicés, en liste...) notés @tab
- les tableaux associatifs ("hachages") notés %tab.

L'expression $#tab donne l'indice du dernier élément d'un tableau classique. Le premier indice du tableau est 0. Le nombre d'éléments d'un tableau est donc $#tab+1

L'affectation d'un tableau suit les syntaxes (suivant les cas)


     @tabC = ( liste des éléments );
     %tabH = ( cle1,élément1,clé2,élément2, etc.. );
Remarque : pour un tableau associatif, on peut aussi utiliser la syntaxe

     %tabH = ( cle1 => élément1, clé2 => élément2, etc.. );
Voici des exemples d'utilisation

     @mois_let_C  = ("jan","fev","mars",...) ;
     %mois_num_H  = ("jan",1,"fev",2,......) ;
     %mois_num_H  = ("jan"=>1, "fev"=>2,......) ;
L'extraction d'un élément d'un tableau se fait suivant les cas par

     $tabC[$i]    #   c'est la i-ième élément de tabC
     $tabH{$i}    #   c'est la valeur de la i-ième clé de tabH

On notera que keys %tabH donne la liste des clés de hachage et que values %tabH donne la liste des valeurs associées aux clés de hachage. Les instructions sort et reverse permettent d'influer sur l'ordre des ces listes. L'article "Tris en Perl" de J. Quelin détaille comment effectuer ces tris.

Le parcours des éléments d'un tableau se fait par


     foreach   $var  (@tab)      {  # on traite $var }
     foreach   $cle  (keys %tab) {  # on traite $cle et $tab{$clé} } 

La transformation d'un tableau en une chaine de caractères utilise la fonction join selon la syntaxe


     $chaine = join($separateur,@tableau)

Et la transformation (inverse) d'une chaine de caractères en un tableau utilise la fonction split selon la syntaxe


     @tableau = split($separateur,$chaine)
Les listes explicites parenthésées peuvent être considérées comme des tableaux classiques. Ainsi l'instruction

     ($a,$b) = ($b,$a)

permute le contenu des deux variables $a et $b alors que l'instruction


     ($tvar[$nbve],$tval[$nbve]) = split(/=/,$ligne) ;

réalise une affectation multiple : la première variable (qui est en fait un élément de tableau) reçoit la partie de la variable $ligne qui est avant le caractère "=" et la deuxième variable ce qui est après.

 

SOUS-PROGRAMMES

La définition d'un sous-programme se fait avec l'instruction sub selon la syntaxe


   sub nomSousProgramme {
      ...
      return ($res1,...,$resp) ; # renvoi éventuel des résultats
   } ; # fin du sous-programme

La récupération des paramètres effectifs s'effectue par

      local ($var1, ... ,$varn) = @_;
et la déclaration des variables locales éventuelles par

      local $VAR1,...,$VARm ;
ou par

      my $VAR1,...,$VARm ;

L'appel d'un sous-programme se fait directement soit par


  sousProgs() ;

ou par


  sousProgs(($param1,$param2...)) ;

s'il y a des paramètres. Lorsque le sous-programme renvoie des valeurs, on peut les récupérer en liste via l'instruction :


     ($res1,$res2...) = &nom_ss_prog($param1,$param2...) ;

Il est conseillé de mettre un é-commercial ou "ampersand" devant le nom des fonctions que l'on définit soi-même comme par exemple


  &gh_copyright() ;
plutot que

  gh_copyright() ;

 

MODULES, OBJETS ET BIBLIOTHEQUES DE SOUS-PROGRAMMES

On utilise un module (fichier de type .pm) à l'aide de use ; les sous-modules sont alors précisés par le symbole : et correspondent aux sous-répertoires physiques de l'implémentation des fichiers .pm. On peut forcer à vérifier un numéro de version à utiliser via require. L'instruction bless permet de définir des classes d'objets. La syntaxe ${EXPR}->([LIST]) donne alors accès aux méthodes et attributs des objets.

La notation -> peut aussi s'appliquer aux tableaux. Ainsi $tC->[28] est le même élément que $tC[28] et $tH->{28} est le même élément que $tH{"28"}

Par exemple pour utiliser le fichier Xml/Parser.pm correctement installé, puis pour créer un objet $pgh et en utiliser la méthode parsefile on peut écrire :


    use XML::Parser;
    ...
    my $ghp= new XML::Parser( Style => 'Stream');
    ...
    $ghp->parsefile( $nf ) ;

La définition d'un module se fait avec package. On pourra consulter les chapitres 14 et 15 du cours de F. Dagorn pour comment cela fonctionne en détail. Nous fournissons à titre d'exemple notre module strFuncs.pm qui contient des fonctions utiles sur chaines de caractères pour Perl, certaines n'étant que des appels lisibles aux fonctions et variables "égyptiennes" de Perl.

 

OPTIONS DE LA COMMANDE PERL

Si on tape perl -v on obtient une description courte de la version de Perl utilisée, alors que si on tape perl -V on obtient une description longue de la version de Perl utilisée.

Si on tape perl -c nom_prog perl teste seulement si le programme est syntaxiquement correct.

Si on tape perl -d nom_prog perl exécute le programme en mode Debug.

Si on tape perl -e 'expression|s]' alors perl exécute l'expression comme s'il s'agissait d'un programme. Par exemple


     perl -e ' $a = "le chien" ; print substr($a,4,2)."\n" ; '

affiche la chaine en. On appelle cela du "one-liner" en anglais. Certains sites sont spécialisés en de telles expressions comme par exemple : en français et sial.

Attention, cela est parfois totalement illissible, comme



   perl -lne'/^(\S+).*?"(.*?)"/;length$h{$1}>length$2or$h{$1}=$2}
        {print"@a"while@a=each%h' access.log

et pourtant cela fonctionnne. Voir les explications à l'URL

http://linuxgazette.net/issue90/okopnik.html.

Signalons deux "one-liner" très utiles :


     perl -p -e 's/original/replacement/g' FICHIERS*
     perl -p -i .bak -e 's/original/replacement/g' FICHIERS*

ces deux lignes permettent de remplacer une chaine par une autre dans une série de fichiers (par exemple de remplacer "Paris, 2004" par "Angers, 2005" dans les fichiers *.htm) ; la deuxième commande crée une copie en .bak des fichiers originaux.

Pour plus de détails sur les arguments de la commande Perl, vous pouvez consulter la page française

http://www.ftls.org/fr/initiation/perl/index3.shtml

Terminons par une option intéressante en ligne de commande, celle qui permet d'installer un module connaissant son nom. Si on veut installer par exemple (en tant que "root" car il faut avoir des droits d'écriture sur le système) le module Schema décrit au CPAN comme XML::Validator::Schema, on exécute la commande


   perl -MCPAN -e 'install XML::Validator::Schema'

On voit alors à l'écran la connection puis la copie et la configuration et l'installation s'effectuer. Il ne reste plus alors qu'à indiquer aux utilisateurs qu'ils peuvent désormais mettre


   use XML::Validator::Schema
dans leurs programmes Perl...

 

EXEMPLES CLASSIQUES DE PROGRAMMATION EN PERL

Bonjour

Ce programme efface l'écran (sous Unix), demande un prénom et dit au revoir après avoir donné la date et l'heure (mois en français) et après avoir converti le prénom en majuscules.



     #!/usr/bin/perl
     system "clear";
     print " Bonjour.\n Quel est votre prénom ? ";
     chop ($pren = <STDIN>);
     @date = gmtime(time);
     print"\n";
     @mois = ("janvier","février","mars","avril","mai","juin",
              "juillet","aout","septembre","octobre","novembre","décembre");
     $an = 1900 +  $date[5] ;
     $phr  =  " Le $date[3] $mois[$date[4]] $an " ;
     $phr .=  "à $date[2]:$date[1]:$date[0], au revoir, \U$pren\E."."\n\n";
     print $phr ;

Vous pouvez utiliser le programme bonjour.pl correspondant.

Voici un exemple d'exécution (l'entrée-clavier est en bleu) :

 Bonjour.
 Quel est votre prénom ? gh

 Le 6 janvier 2005 à 9:27:21, au revoir, GH.

Table de Multiplication

Le programme attend un paramètre. Si on ne lui en passe pas, le programme affiche la syntaxe d'appel. Si le paramètre n'est pas un entier positif, il redemande une valeur entière et positive.

Enfin, lorsque le nombre est entier, on afiche sa table de multiplication avec cadrage des unités sous les unités, des dizaines sous les dizaines etc.


   #  test du passage de paramètre

   if ($#ARGV == -1) {
      print stderr "\n syntaxe : tabmult nombre_entier_positif\n\n" ;
      exit(-1) ;
   } ; # fin de si

   # affectation du paramètre

   $nbChoisi = $ARGV[0] ;

   # relance éventuelle

   while ( not entier( $nbChoisi ) ) {
       print " nombre incorrect. Redonner un nombre ENTIER "."\n" ;
       chomp($nbChoisi=<STDIN>) ;
   } ; # nombre invalide

   # boucle d'affichage

   print " Table de " ." ". $nbChoisi."\n" ;
   for ( $indb = 1  ;  $indb <= 10  ; $indb++ ) {
       $produit = $nbChoisi * $indb  ;
       $find = &format( $indb , 2 , 0 )  ;
       $fpro = &format( $produit , 5 , 0 )  ;
       print $find ." ". " fois " ." ". $nbChoisi ." ". " = " ." ". $fpro."\n" ;
   } ; # indb de1a 10

   ##### sous-programmes :

   sub  entier  {
     # renvoie "vrai" si le paramètre est un entier éventuellement signé
     my $parm_entier = $_[0] ;
     return $parm_entier =~ /^[+-]?\d+$/ ;
   } ; # fin sub entier

   sub  format  {
     # formate un nombre (syntaxe plus simple que sprintf)
     return( sprintf("%$_[1]d",$_[0]) ) ;
   } ; # fin sub format

Vous pouvez utiliser le programme tabmult.pl correspondant.

Voici un exemple d'exécution (les entrées-clavier sont en bleu) :

perl tabmult.pl

 syntaxe : tabmult nombre_entier_positif

perl tabmult.pl ok
  nombre incorrect. Redonner un nombre ENTIER
     3+2
  nombre incorrect. Redonner un nombre ENTIER
     5
 Table de  5

    1  fois  5  =      5
    2  fois  5  =     10
    3  fois  5  =     15
    4  fois  5  =     20
    5  fois  5  =     25
    6  fois  5  =     30
    7  fois  5  =     35
    8  fois  5  =     40
    9  fois  5  =     45
   10  fois  5  =     50

Factorielle

Il s'agit du classique calcul de la factorielle d'un entier. On le présente ici pour montrer la récursivité en Perl.


   #  on peut aussi écrire le sous-programme AVANT le programme principal

   sub fact {
    local ($ind )= @_  ; # transmission des paramètres
    local $res,$indmun ;
    if ( $ind == 0 ) {
       $res = 1;
    } else {
       $indmun = $ind-1;
       $res = &fact ($indmun) * $ind;
    } ; # fin de si
    return $res ; # renvoi de la valeur
   } ; # fin de sub fact

   ############  programme principal

   print "Donnez le nombre positif dont vous voulez la factorielle : " ;
   chop ($nb = <STDIN>) ;
   print "\nLa factorielle de ",$nb," est ",&fact( $nb),"\n\n" ;
   exit(12345) ; # sortie avec code-retour explicite

Vous pouvez utiliser le programme factorielle.pl correspondant.

Voici un exemple d'exécution (l'entrée clavier est en bleu) :

 Donnez le nombre positif dont vous voulez la factorielle : 5
   la factorielle de 5 est 120.

Moyenne des notes et tris

Le but du programme est de lire un fichier de noms et de notes. Il y a un nom et 3 notes par ligne (quand elle n'est pas vide). Il y a une étoile pour séparer le nom des notes. On veut un affichage par ordre alphabétique et par moyenne décroissante (ordre de "mérite"). On utilise bien sur des tableaux associatifs.


   # on recupère le fichier des noms et des notes passé en argument

   if ($ARGV[0] eq "") {
     print "\n la syntaxe est moynotes nom_de_fichier.\n\n" ;
     exit(-1) ;
   }  ; # fin de test sur les arguments

   $fiche = $ARGV[0] ; # récupération du nom du fichier

   open( FIC ,"<$fiche") || die "\n impossible d'ouvrir le fichier nommé $fiche \n\n" ;

   # parcours du fichier : on crée un tableau associatif dont
   # les clés sont les noms associés a la moyenne

   $nbElv = 0 ;
   while ($ligne=<FIC>) {

       @champs=split(/\*/,$ligne) ;

       # on supprime le retour chariot de la fin de la ligne dans champs[1]

       chomp ($champs[1]) ;

       # si la ligne est vide, on réitère la boucle

       if (length($champs[1])==0) { next ; } ;

       # on sépare les 3 notes

       @notes=split(/\s+/,$champs[1]) ;

       # on supprime la 1ère valeur des champs qui est un espace

       shift @notes ;

       $som=$notes[0]+$notes[1]+$notes[2] ;

       $moy=$som/3 ;

       $classe{$champs[0]}=$moy ;

      # on incrémente le compteur d'élèves

      $nbElv++ ;

   } ; # fin de tant_que

   print "Il y a ",$nbElv," élèves." ;

   # on trie la liste des élèves par ordre alphabétique

   print " Voici la liste des élèves par ordre alphabetique:\n" ;

   foreach $name (sort keys %classe) {

       printf "    %s %10.2f\n",$name,$classe{$name} ;

   } ; # fin pour chaque

   # on trie la liste par ordre de mérite

   print "Voici la liste des élèves par ordre de mérite:\n" ;

   foreach $nom (reverse (sort by_value keys %classe)) {

       printf "    %s %10.2f\n",$nom,$classe{$nom} ;

   } ; # fin pour chaque

   sub by_value {

      local($test_num)=$classe{$a} <=> $classe{$b} ;

     # si $classe{$a}=$classe{$b} les deux moyennes sont identiques,
     # donc il faut trier par ordre alphabétique les noms

     # si les deux sont égaux, $test_num vaut 0, donc on trie selon la
     # clé. Sinon on ne fait rien.

      if ($test_num) {return $test_num ;}

      return $b cmp $a ;

   } ; # fin sub  by_value 

Vous pouvez utiliser le programme moynotes.pl correspondant.

Voici un exemple d'exécution (les entrées-clavier sont en bleu) :


   tuteurs>cat examen.notes
   BOBY        *         18 5  5
                                    <-- ici une ligne vide
   ZELYNOU     *         6 11 7
   ANTIN       *     8 4  10
   BOB         *    16 8 15
   IZEL        *     16 18 12

   tuteurs>perl moynotes.pl

      la syntaxe est moynotes nom_de_fichier.

   tuteurs>perl moynotes.pl exam.not

      impossible d'ouvrir le fichier nommé exam.not

   tuteurs>perl moynotes.pl examen.notes

      Il y a 5 élèves. Voici la liste des élèves par ordre alphabétique:

          ANTIN              7.33
          BOB               13.00
          BOBY               9.33
          IZEL              15.33
          ZELYNOU            8.00

      Voici la liste des élèves par ordre de mérite:

          IZEL              15.33
          BOB               13.00
          BOBY               9.33
          ZELYNOU            8.00
          ANTIN              7.33

EXEMPLES MOINS TRIVIAUX EN PERL

Conversion des noms de fichiers en minuscule

Ce programme met en minuscule le nom des fichiers passés en paramètre. On utilise tr pour la conversion majuscule/minuscule et la fonction rename qui "cause" au système d'exploitation.


 # minu.prl : met le nom du ou des  fichier(s) en minuscule

 $nbf = @ARGV ; # nombre de fichiers à traiter

 if ($nbf==0) {

     print " minu.pl : met le nom du ou des fichier(s) en minuscule \n"  ;
     print "     syntaxe  : minu nom(s)_de_fichier(s) \n"  ;
     print "     exemples : minu ESSAI   \n"  ;
     print "                minu A*      \n"  ;

 } else {

     foreach $oldfid (@ARGV) {
        $newfid = $oldfid  ;
        $newfid =~ tr/A-Z/a-z/ ;
        if ($newfid ne $oldfid) { rename($oldfid,$newfid) } ;
     } ; # fin de pour chaque
     print " $nbf fichier(s) converti(s)." ;

 } ; # fin de si nbf n'est pas nul

Vous pouvez utiliser le programme minu.pl correspondant.

Voici un exemple d'exécution (les entrées-clavier sont en bleu) :

demoPerl>perl minu.pl

minu.pl : met le nom du ou des fichier(s) en minuscule

  syntaxe  : minu nom(s)_de_fichier(s)
  exemples : minu ESSAI
             minu A*

demoPerl>ls

Essai.ALG  Essai_C.ALG  essai_c.cpp  essai_c.lvm  Essai_J.ALG
essai.c    essai_c.c    essai_c.lst  essai.cpp    essai_j.class

demoPerl>perl ~/public_html/tuteurs/minu.pl *.ALG
   3 fichier(s) converti(s).

demoPerl>ls

essai.alg  essai_c.alg  essai_c.cpp  essai_c.lvm  essai_j.alg
essai.c    essai_c.c    essai_c.lst  essai.cpp    essai_j.class

Lois probabilistes (cgi)

Ce programme effectue des calculs statistiques (on peut ignorer le détail des calculs) pour la page Web forge.info.univ-angers.fr/~gh/vitrine/Democgi/loisStatp.htm. Le formulaire utilise une méthode "POST". Nous n'en donnons pas tout le détail du programme ici car il est long. Nous n'en présentons que le début


   #! /usr/bin/perl

   print  "Content-type: text/html\n"  ;
   print  "\n" ;

   print  '<HTML>' ;
   print  '<HEAD>' ;
   print  "<TITLE> Lois statistiques usuelles discrètes </TITLE>" ;
   print  '</HEAD>' ;
   print  '<BODY bgcolor="#ffffff">' ;
   print  '<font size="6" color ="black"><b>
           Lois statistiques usuelles discrètes</b></font><p>' ;
   print  '<blockquote>' ;
   print  '<font size="5" color ="blue"><b>' ;
   print  '<pre>' ;

   # récupération de la variable d'environnement

   $qs = $ENV{"QUERY_STRING"} ;

   # décodage de la chaine

   $lig = "" ;
   for ($idc = 0 ; $idc < length($qs) ; $idc++) {
      $c = substr($qs,$idc,1) ;
      if ($c eq "=") { $lig = ""  ;  $c = " " }
      if ($c eq "+") { $c   = " "  ; } ;
      $lig = "$lig$c" ;
   } ; # fin pour

   # appel du sous-programme de calcul

   &lois(split(" ",$lig)) ;

   print  '</pre>' ;
   print  '</b>'   ;
   print  '</font>' ;
   print  '</blockquote>' ;
   print  '</BODY>' ;
   print  '</HTML>' ;
   exit(0) ;

   ##################################################

   #  (gH)   --  lois.pl  ;  TimeStamp (unix) : 09 Janvier 01 11:45
   

   sub syntaxe {

     $ligSyntax  = " [ b p | B n p | G p t | H n k s | P m t |  Q s p t \n" ;
     $ligSyntax .= (" "x18)."      | T a   | U a b | S m t   | Z ] T " ;

     print "\n" ;
     print " syntaxe  : lois $ligSyntax\n\n" ;
     print " exemples : \n" ;
     print "   lois  b   0.2       # loi de bernoulli     p=0.2\n" ;
     print "   lois  B   5 0.1     # loi binomiale        n=5, p=0.1\n" ;
     print "   lois  G   0.8 9     # loi géométrique      p=0.8 limitée à 9 termes\n" ;
     print "   lois  H   10 5 3    # loi hypergéométrique N=10, K=5, n=3\n" ;
     print "   lois  N   4 0.9 11  # loi de pascal        s=4, p=0.9 (11 termes)\n" ;
     print "   lois  P   1.2 9     # loi de poisson       m=1.2 limitée à 9 termes\n" ;
     print "   lois  S   0.3 9     # loi \"sans-nom\"     p=0.3 limitée à 9 termes\n" ;
     print "   lois  T   4         # loi triangulaire     a=4\n" ;
     print "   lois  U   2   7     # loi uniforme         a=2, b=7\n" ;
     print "   lois  Z             # loi de zipf-benford           \n" ;
     print "\n T est la taille de l'échantillon correspondant (100 par défaut)." ;
     print "\n" ;

   } ; # fin sub syntaxe

   sub lois {

   
   ##########################################################################
   ##                                                                      ##
   ##   sous-programme principal                                           ##
   ##                                                                      ##
   ##########################################################################
   

   print "\n" ;
   print " (gH) ; lois.pl v1.2 : lois statistiques discrètes usuelles \n" ;

   @gARGV = @_ ;

   if ($#gARGV==-1) { &syntaxe() ; exit 0 ; }  ;

   $nomLoi{"b"} = "de bernoulli" ;
   $nomLoi{"B"} = "binomiale (compte-avec)" ;
   $nomLoi{"G"} = "géométrique (bernoulli négative)" ;
   $nomLoi{"H"} = "hypergéométrique (compte-sans)" ;
   $nomLoi{"N"} = "de pascal (binomiale négative ou première-avec)" ;
   $nomLoi{"P"} = "de poisson" ;
   $nomLoi{"S"} = "sans-nom (première-sans)" ;
   $nomLoi{"U"} = "uniforme discrète" ;
   $nomLoi{"T"} = "triangulaire" ;
   $nomLoi{"Z"} = "de zipf-benford" ;

   if ($gARGV[0] eq "b") { &bernoulli($gARGV[1],$gARGV[2])             ; exit 0 ; }  ;
   if ($gARGV[0] eq "B") { &binomiale($gARGV[1],$gARGV[2],$gARGV[3])   ; exit 0 ; }  ;
   if ($gARGV[0] eq "G") { &geometrique($gARGV[1],$gARGV[2],$gARGV[3]) ; exit 0 ; }  ;
   if ($gARGV[0] eq "T") { &triangulaire($gARGV[1],$gARGV[2])          ; exit 0 ; }  ;
   if ($gARGV[0] eq "U") { &uniforme($gARGV[1],$gARGV[2],$gARGV[3])    ; exit 0 ; }  ;
   if ($gARGV[0] eq "Z") { &zipfbenford($gARGV[1])                     ; exit 0 ; }  ;

   print "\n loi $ARGV[0] : pas encore implémentée\n
         ou faute de frappe sur l'initiale de la loi !\n" ;
   exit 0 ;

   #########################################################################

   sub log10 { return log($_[0])/log(10) ; } ;

   #########################################################################

   sub cnk { # coefficients du binome

     my ($n,$p) = ($_[0],$_[1]) ;
     if ($p>$n) { return 0 ; } ;
     if ($n<0)  { return 0 ; } ;
     if ($p<0)  { return 0 ; } ;

     $k = $p ;
     if ($k>$n-$k) { $k = $n-$k ; } ;
     if    ($k==0) { $res = 1  ; }
     elsif ($k==1) { $res = $n ; }
     elsif ($k==2) { $res = $n*($n-1)/2 ; }
     else  {
       $i    = 0.0 ;
       $frac = 1.0 ;
       while ($i<$p) {
         $i++ ;
         $frac = $frac * ($n+1-$i)/$i ;
       } ; # fin tant que
       $res = $frac ;
     } ; # fin de si

     return $res ;
   } ; # fin sub cnk

   #########################################################################

   sub bernoulli {

     $proba     = $_[0] ;
     $taille    = $_[1] ;
     $nbVal     = 2 ;
     $paramLoi  = "p=$proba" ;
     ($tabVal[1],$tabVal[2]) = (0,1) ;
     ($tabPro[1],$tabPro[2]) = (1-$proba,$proba) ;

     &decritLoi("b") ;

   } ; # fin sub bernoulli


     ... ICI Il MANQUE (volontairement) LA FIN DU PROGRAMME

   
   #####################################
   #####################################
   

Vous pouvez utiliser le programme lois.pl correspondant. Pour l'exécution, allez sur la page forge.info.univ-angers.fr/~gh/vitrine/Democgi/loisStatp.htm.

Expressions régulières : analyse de fichiers-logs

On s'intéresse ici au fichier authlog.txt dont voici le début :


Jul 26 20:06:34 deneb PAM_unix[15771]: (system-auth) session opened for user brejeon by (uid=0)
Jul 26 20:06:34 deneb  -- brejeon[15771]: LOGIN ON pts/5 BY brejeon FROM sirius
Jul 26 20:43:32 deneb PAM_unix[15771]: (system-auth) session closed for user brejeon
Jul 27 01:24:53 deneb PAM_unix[15960]: (system-auth) session opened for user guilleme by (uid=0)
Jul 27 01:24:53 deneb  -- guilleme[15960]: LOGIN ON pts/5 BY guilleme FROM sirius
Jul 27 01:29:29 deneb PAM_unix[15960]: (system-auth) session closed for user guilleme
Jul 27 01:30:33 deneb PAM_unix[15996]: check pass; user unknown
Jul 27 01:30:33 deneb PAM_unix[15996]: authentication failure; (uid=0) -> etudinfo for system-auth service
Jul 27 01:30:33 deneb login[15996]: FAILED LOGIN 1 FROM sirius FOR etudinfo, Authentication failure
...

On profite des expressions régulières et des tableaux généraux de perl pour compter rapidement le nombre de sessions ouvertes et fermées, le nombre d'utilisateurs. Il est conseillé de lire et de relire expresreg.htm avant de tenter la compréhension du script prl :


   #  (gH)   --  analog.pl  ;  TimeStamp (unix) : 11 Février 2005 vers 16:56  

   print "\n (gH) Exemple d'analyse de logs\n\n" ;

   # on met tout dans la variable src 

   while (<>) { $src .= $_ } ;

   # transfert dans la variable "bien connue de perl" 

   $_ = $src ;
   # pour vérifier qu'on a tout lu : print "\n\n$src\n\n" ; 

   ###################################################################  

   # on cherche les ouvertures : le ? sert à modérer l'expression régulière 

   $so = 0 ;
   while (m| session opened for user (.*?) by |gs) {
     $so++;
     if    ($so<5)   { print "     " .sprintf("%4d",$so)."  $1\n"; }
     elsif ($so==5)  { print "     ...\n\n" ; } ;
   } ; # fin de tant que 
   print "   ".sprintf("%4d",$so)." sessions ouvertes\n" ;

   # on cherche les fermetures : le ? sert à modérer 
   # pas besoin de $sc = 0 ; car perl s'en charge. 

   while (m| session closed for (.*?) by |gs) {
     $sc++;
   } ; # fin de tant que 
   print "   ".sprintf("%4d",$sc)." sessions fermées\n" ;

   ################################################################### 

   # on recommence en plus aggressif avec les deux chaines  
   # à la fois dans une liste 

   print "\n Rebelote : \n\n" ;

   @ach = ("session opened for user","session closed for") ;
   foreach $mac (@ach) {
     while (m|$mac (.*?) by |gs) { $nbs{$mac}++ ; }  ;
   } ; # fin de pour chaque 

   foreach $mac (reverse sort @ach) {
     print "  ".sprintf("%-30s %6d",$mac, $nbs{$mac})."\n" ;
   } ; # fin de pour chaque 

   ################################################################### 

   print "\nRécupération des utilisateurs\n" ;

   $nu = 0 ;
   foreach $mac (@ach) {
     while (m|$mac (.*?) by |gs) {
       $nu++ ;
       $usr{$1}++ ;
       # pour debug :  
       if    ($nu<5)  { print "  ".sprintf("   %5d   %-15s %-25s",
                                                  $nu,  $1,   $mac)."\n" ; }
       elsif ($nu==5) { print "  ...\n" ; } ;
     }  ; # fin de tant que 
   } ; # fin de pour chaque 

   print "\n       Num   Utilisateurs  Nb Sessions (o/c) \n" ;
   $nu = 0 ;
   foreach $uti (sort keys %usr) {
       $nu++ ;
       if    ($nu<10)  { print "  ".sprintf("   %5d   %-30s %6d",
                                                   $nu,  $uti, $usr{$uti})."\n" ; }
       elsif ($nu==10) { print "  ...\n" ; } ;
   } ; # fin de pour chaque 

   # fin de l'exemple 

   print "\n (gH) -- fin d'analyse de logs\n\n" ;

Voici les résultats fournis par le perl nommé analog.pl:




    (gH) Exemple d'analyse de logs

           1  brejeon
           2  guilleme
           3  guilleme
           4  roynette
        ...

       152 sessions ouvertes
        74 sessions fermées

    Rebelote :

     session opened for user           152
     session closed for                 74

   Récupération des utilisateurs
            1   brejeon         session opened for user
            2   guilleme        session opened for user
            3   guilleme        session opened for user
            4   roynette        session opened for user
     ...

          Num   Utilisateurs  Nb Sessions (o/c)
            1   alaing                              3
            2   alexp                               1
            3   anthonyp                            3
            4   antier                              1
            5   blouin                              1
            6   bodi                                1
            7   brault                              1
            8   brejeon                             6
            9   buraud                              1
     ...

    (gH) -- fin d'analyse de logs


Extractions d'adresses dans les pages Web

On veut extraire (sans doublon) tous les liens de la page afine.html. Pour cela on utilise le programme anapw.pl que voici :


   #  (gH)   --  anapw.pl  ;  TimeStamp (unix) : 11 Février 2005 vers 18:24 

   while (<>) { $src .= $_ } ;
   $_ = $src ;
   # question pour les étudiants et pour EJ
   #      pourquoi le troisième .* a -t-il un ? mais pas de ()
   while (m|<a href="(.*?)".*?>(.*?)</a>|gs) {
     if (++$nom{$2}==1) { print "  ".sprintf("%-30s %-30s",$2, $1)."\n" ; } ;
   } ; # fin tant que  
   # que voit-on avec : if ($nom{$2}++==1) { print ... 

Voici un extrait de ce qu'il affiche :



...
  Bacillus alcalophilus          http://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?name=Bacillus+alcalophilus
  1BKS                           http://www.rcsb.org/pdb/cgi/explore.cgi?pdbId=1BKS
  Salmonella typhimurium         http://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?name=Salmonella+typhimurium
  1RNH                           http://www.rcsb.org/pdb/cgi/explore.cgi?pdbId=1RNH
  1RHD                           http://www.rcsb.org/pdb/cgi/explore.cgi?pdbId=1RHD
  1PRC                           http://www.rcsb.org/pdb/cgi/explore.cgi?pdbId=1PRC
  Blastochloris viridis          http://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?name=Blastochloris+viridis
  1PHH                           http://www.rcsb.org/pdb/cgi/explore.cgi?pdbId=1PHH
  Pseudomonas fluorescens        http://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?name=Pseudomonas+fluorescens
  1HIP                           http://www.rcsb.org/pdb/cgi/explore.cgi?pdbId=1HIP
  Chromatium vinosum             http://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?name=Chromatium+vinosum
  1GP1                           http://www.rcsb.org/pdb/cgi/explore.cgi?pdbId=1GP1
  4GCR                           http://www.rcsb.org/pdb/cgi/explore.cgi?pdbId=4GCR
...


Dans le même genre d'idées, on pourra consulter adf.pl qui affiche tous les <font .... d'une page Web.

Formulaire perl-cgi

Dans la mesure où il existe des modules perl pour écrire des formulaires, afficher un panneau de saisie et tester la réponse utilisateur est un jeu d'enfant. Voici par exemple un exemple de script cgi nommé gereform.pl qui utilise le module CGI et qui demand un nom et un prénom.

Cet exemple, minimal, est typique d'un script "tout-en-un" qui selon la valeur de ses variables, affiche le formulaire, le teste ou l'exécute après l'avoir validé.


    #!/usr/bin/perl -w 

    use CGI ;

    $mp = new CGI ;

    print $mp->header(),
          $mp->start_html(-title=>"Essai de Formulaire") ;

    if ($mp->param()) { &traitement() ; }
               else   { &saisie() ; } ;

    print $mp->end_html() ;

    ############ fin du programme principal

    sub saisie {
      print "<table>" ;
      print $mp->startform() ;
      print "<tr><td>Nom </td>" ;
      print "<td>".$mp->textfield(-name=>"Nom")."</td></tr>" ;
      print "<tr><td>Prenom </td>" ;
      print "<td>".$mp->textfield(-name=>"PreNom")."</td></tr>" ;
      print "<tr><td></td><td>".$mp->submit(-value=>"Ok")."</td></tr>"  ;
      print "</table>" ;
      print $mp->endform() ;
    } ; # fin saisie

    ###########################

    sub traitement {
      print "<h1> Traitement des infos</h1>" ;
      print "Votre nom est <font size=\"+2\" color=\"blue\">".$mp->param("Nom")."</font>";
    } ; # fin traitement

EXERCICES D'ENTRAÎNEMENT (solution)

E1. numéroter les lignes d'un fichier (solution)

On veut ici numéroter proprement les lignes d'un fichier avec un numéro de ligne sur 4 caractères avec des 0 non significatifs éventuels. Par exemple, pour le fichier fic.xmp qui contient

   Ligne 1
   (vide)
   ceci est la fin (ligne 3 ?).

on voudrait obtenir

   0001 Ligne 1
   0002 (vide)
   0003 ceci est la fin (ligne 3 ?).

Ecrire une solution classique puis une solution concise "à la perl".

E2. variables d'environnement (solution)

Les variables d'environnement (commande set sous Dos comme sous Unix) sont des couples (variable, valeur). On voudrait les afficher en tableau avec deux colonnes bien séparées, comme par exemple

   Variable         Valeur

     OPTERR          1
     SHELL           /bin/bash
     TERM            Xterm

Ecrire une solution avec des tableaux classiques puis avec des tables de hachage. Reprendre ensuite sous forme de cgi en rajoutant de la couleur dans l'affichage classique de set, comme le fait la page

http://forge.info.univ-angers.fr/scripts/env.pl

E3. dictionnaires d'un texte (solution)

Ecrire un programme Perl qui lit un texte passé en paramètre et en fait les dictionnaires alphabétiques et par occurence. Voir la page

forge.info.univ-angers.fr/~gh/Wanalexies/f_dicos.php

comme exemples de texte et de résultats.

On pourra utiliser le fichier debcand.txt qui contient le début du texte de Candide de Voltaire pour tester le programme. On devrait obtenir :


Analyse du fichier debcand.txt :

    204 ligne(s), 1602 mot(s) dont 666 mot(s) différent(s).

 Vous pouvez consulter les fichiers  dic_debcand.txt.mot et dic_debcand.txt.occ
 dont voici le début :

fichier dic_debcand.txt.mot issu de dico.pl debcand.txt
   Abares                 1
   Ah                     2
   BEAU                   1
   BULGARES               1
   Bulgares               4
   C                      1
   CANDIDE                2
   CE                     1
   CHAPITRE               2
   CHASSé                 1
   CHâTEAU                1
   COMMENT                2
   Camarade               1
   Candide               20
   Comme                  2
   Comment                1
   Cunégonde              9
   D                      1
   DANS                   1
fichier dic_debcand.txt.occ issu de dico.pl debcand.txt
   de                    55
   le                    52
   et                    46
   la                    39
   les                   28
   il                    25
   des                   23
   un                    22
   Candide               20

E4. calcul de Chi2 (solution)

Un utilisateur me demande d'installer un module perl pour afficher les valeurs qu'on trouve dans une table de chi2. Il sait que ce module est Distributions.pm et me dit qu'on doit utiliser la fonction chisqrdistr. Pour m'aider il me dit qu'avec les deux paramètres 4 et 5 on doit trouver 9.4877 alors qu'avec les valeurs 17 et 5 on doit obtenir 27.587.

Expliquer comment on installe ce module en tant que root pour tout le monde et en tant que simple utilisateur dans un répertoire personnel.

E5. fichiers DBF (solution)

Un utilisateur qui utilise beaucoup de petites bases de données (en fait des tableaux rectangulaires avec des colonnes typées et avec des lignes qui ont toutes le même format) a besoin de lire en perl des fichiers Dbase, c'est à dire des fichiers de type DBF.

Justifier le choix de Dbase (et plus généralement Xbase) par rapport au choix d'Excel ou d'un tableur quelconque pour de tels tableaux. Sachant que le module perl correspondant est XBase.pm (et ses fichiers), essayer d'afficher le nombre de lignes du tableau et les données du tableau vins.dbf (on séparera les colonnes par un espace sans se préoccuper du formatage) ; on trouvera plus de renseignements sur le dossier dans la page vins.htm.

Modifier le programme pour qu'il affiche les données dans une page Web.

E6. extractions d'adresses (solution)

Reprendre le programme d'extractions d'adresses et répondre aux questions du texte du programme mises en commentaire.

Modifier le programme pour qu'il affiche les adresses par ordre alphabétique de référence puis par ordre alphabétique de site.

E7. que fait ce programme ? (solution)

Après avoir lu soigneusement le programme ldphp.pl essayer de l'utiliser, par exemple en lui passant comme paramètre le fichier std.php (il vous faudra sans doute aussi le fichier strfun.php).

Cela peut-il vous être utile ?

 

 


Retour à la table des matières