Langage de Recherche d`Information
Transcription
Langage de Recherche d`Information
Langage de Recherche d’Information Travaux Pratiques Jérôme Farinas [email protected] Institut de Recherche en Informatique de Toulouse Université Paul Sabatier 13 janvier 2009 Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 1 / 29 Conseils généraux pour les TP Chaque exercice idéalement doit être testé, compris et parfois complété. Pour être sauvegardé comme fichier éventuellement modifié puis exécuté, chaque source fourni devra être saisi dans un éditeur de texte (nedit par exemple) Il est conseillé de ranger les exercices dans des sous-répertoires spécifiques au TP. Les noms des fichiers sont proposés avec l’extension .perl (qui ne joue aucun role, juste un signe de reconnaissance...) Sous Unix, les fichiers pour être exécutables doivent porter la permission x. Si nécessaire donner cette permission en passant la commande, comme : chmod a+x monfichier.perl Chaque script doit indiquer le chemin vers Perl avec cette 1ère ligne : #!/usr/bin/perl -w (vérifier le chemin sur la machine que vous utilisez en tapant dans le shell : which perl) Un dossier sera constitué à la fin des TPs : tous les exercices marqués avec une étoile devront etre présents. La notation prend en compte le fait que le programme marche, la présentation du programme (commentaires et indentation) ainsi que les méthodes utilisées. Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 2 / 29 Plan 1 TP2 : listes, tableaux et structures de contrôle Rappels listes et tableaux Exercices TP2 Exercices du cours Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 3 / 29 Plan 1 TP2 : listes, tableaux et structures de contrôle Rappels listes et tableaux Exercices TP2 Exercices du cours Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 4 / 29 Listes et tableaux : rappels I La liste est la principale structure de données en Perl. Il convient de bien en connaitre les possibilités. Une liste est un ensemble ordonné d’éléments scalaires, tandis qu’un tableau est un ensemble indicé de scalaires. Il s’agit en fait d’une même structure de données. La différence réside dans la vision qu’on en a et le type de manipulations effectuées. Les éléments d’une même liste peuvent être de types quelconques : nombres, chaines, variable, liste... Les identificateurs des listes sont précédés du symbole @, MAIS les éléments d’une liste sont notés avec $, car ce sont des valeurs scalaires Les listes sont dynamiquement allouées, donc de dimension variable. Les parenthèses (...), contenant une énumération avec des virgules, jouent le rôle de constructeur de listes. Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 5 / 29 Listes et tableaux : rappels II Exemple $ville = "Melun"; @mesamis=("jules","julie", "julot"); @liste= ("toto", 25 , $ville , @mesamis); # pour afficher la suite des éléments séparés par un espace print "@liste\n"; L’exemple précédent montre qu’il n’a pas de construction directe de liste de listes en Perl. print "$liste[3]\n" # affiche "jules" Création d’une liste par affectation directe de valeurs énumérées, ou indiquées par des intervalles avec l’opérateur .. (et non pas - ) Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 6 / 29 Listes et tableaux : rappels III #!/usr/bin/perl @chiffre = (0..9); @centaine =(@chiffre, 10..99); # va afficher la liste : 0 1 ...99 print "@centaine\n"; @alphabet = (a..z, A..Z); # extraction d’une sous-liste : @dix_premieres_lettres = @alphabet[0..9]; # La fonction qw() permet de s’affranchir # des virgules et des quotes ou guillemets : @mots= ("moi","toi","lui","nous","tous"); @mots= qw(moi toi lui nous tous); # Opérateurs de manipulations d’une liste @liste Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 7 / 29 Listes et tableaux : rappels IV En particulier push et pop permettent de traiter la liste comme une pile. I I I I ajout du coté droit (push) : push(@montableau,$nouvellevaleur) ; suppression du coté droit (pop) : $vieillevaleur = pop(@montableau) ; ajout du coté gauche (unshift) : unshift(@tab,$a) ; suppression du coté gauche (shift) : $x = shift(@tab) ; Utilisation d’une liste I I I I I I print ”@liste”; permet d’afficher l’ensemble des éléments $liste[1] est le second élément $#liste est le dernier indice de la liste $liste[$#liste] est donc son dernier élément $taille = @liste; pour connaitre le nombre d’éléments $der= $liste[-1] ..etc .. énumère les éléments à partir de la fin de la liste Parcourir une liste I La boucle foreach fait parcourir la variable $element dans la liste @liste, dans l’ordre de ses éléments. Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 8 / 29 Listes et tableaux : rappels V foreach $element (@liste) { print "$element\n"; } I façon classique avec une boucle for for ($i =0 ; $i < @liste ; $i++ ) { print "élément $i = $liste[$i]\n"; } Créations et manipulations de listes I affectation de listes Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 9 / 29 Listes et tableaux : rappels VI #!/usr/bin/perl @centaine =(1..99); @elements_cinq_a_sept = @centaine[4,5,6]; @elements_dix_a_vingt = @centaine[9..19]; print "@elements_cinq_a_sept\n@elements_dix_a_vingt\n"; I I I I $liste[@liste]=$n; ajoute un élément en fin de liste (pourquoi ?) push @liste,$n; on empile sur la liste un élément scalaire ou une liste (on l’ajoute ”à droite”) unshift @liste, $n; on ajoute en tête (ou à gauche) un scalaire ou une liste @liste = ($d,@liste,$f);, dans ce contexte, l’opérateur ”parenthèses” est un constructeur de liste Quelques façons d’accéder aux éléments I I $el = $liste[3] pour obtenir le 4ème élément $el = pop @liste dépile et donc modifie la liste (attention !) Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 10 / 29 Listes et tableaux : rappels VII I I I $el = shift @liste pour récupérer l’élément de tête, c’est-à-dire $liste[0], dépile donc la liste ($el) = @liste construit une liste contenant l’élément de tête de @liste ($a, $b, $c, @reste) = @liste affecte les 3 premiers éléments de la liste, puis la liste du reste. Quelques listes gérées par le système I I @ARGV contient la liste des arguments passé sur la ligne de commande après l’appel du script. (Le 1er argument passé est donc $ARGV[0]), ne pas confondre avec $0 qui est le nom du script) La variable système @ contient la liste des paramètres passés à une fonction Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 11 / 29 Opérateurs de tri Attention Le tri est effectué par sort, en ordre ASCII ascendant ! Testez le code suivant #!/usr/bin/perl print "TRIS\n"; @liste = (4, 11, 24, 2, 43, 21, 16, 6); print "Liste initiale : \n@liste\n"; @tri_alpha = sort @liste; print "Liste triée alphabétiquement : \n@tri_alpha\n"; @tri_num = sort { $a <=> $b} @liste; print "Liste triée numériquement (sens croissant) : \n@tri_num\n"; @tri_num = sort { $b <=> $a} @liste; print "Liste triée numériquement (sens décroissant) : \n@tri_num\n"; @envers = reverse @liste; print "Liste inversée : \n@envers\n\n"; Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 12 / 29 Transformations chaı̂ne/liste I split split permet de construire une liste dont les éléments proviennent du découpage d’une chaine suivant les occurrences d’un caractère choisi. join join effectue exactement l’opération inverse, en ”recollant” les éléments d’une liste à l’aide d’un caractère séparateur pour former une seule chaine. Exemple 1 $phrase = "Bonjour à toutes et à tous"; @mots = split " ",$phrase; print "@mots\n"; $phrase1 = join " ", @mots; print "$phrase1\n"; Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 13 / 29 Transformations chaı̂ne/liste II Cas particulier important Si on utilise ”” (caractère vide) comme séparateur, on agit (en séparant avec split ou en concaténant avec join) au niveau des caractères de la chaine. Exemple 2 $phrase = "Bonjour à toutes et à tous"; @caracteres = split "",$phrase; print "@caracteres\n"; $phrase1 = join "", @caracteres; print "$phrase1\n"; Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 14 / 29 Plan 1 TP2 : listes, tableaux et structures de contrôle Rappels listes et tableaux Exercices TP2 Exercices du cours Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 15 / 29 Exercice 10 * Exécutez et complétez le programme suivant : #!/usr/bin/perl -w @liste1 = qw(lundi mardi mercredi jeudi vendredi samedi dimanche); print "affichage global de la liste :\n"; print "- en dehors des guillemets :\n"; print @liste1,"\n"; print "- dans des guillemets :\n"; print "@liste1\n"; print "taille de \@liste1 = ... \n"; print "son premier élément est : ...\n"; print "son troisième élément est : ...\n"; print "son dernier élément est : ...\n"; Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 16 / 29 Exercice 11 Commentez les instructions suivantes, et prévoir très précisément les affichages avant d’expérimenter #!/usr/bin/perl -w @alpha = (’a’..’z’); @liste = (@alpha,0..9); $el = $liste[3]; print "$el\n"; ($a, $b, $c, @reste) = @liste ; print "\$a= $a, \$b= $b, \$c =$c , \@reste= @reste\n"; ($b, $a)= ($a, $b); print "\$a= $a, \$b= $b \n"; $el = pop @liste; print "\$el= $el, \@liste= @liste\n"; $el = shift @liste; print "\$el= $el, \@liste= @liste\n"; print "\@alpha est la liste \n@alpha\n"; for ($i=0; $i<26 ; $i++) { $el= pop @alpha; unshift @alpha, $el; } print "\@alpha est maintenant \n@alpha\n"; Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 17 / 29 Exercice 12 1 Commentez les instructions suivantes, prévoir les affichages #!/usr/bin/perl # pour placer la chaine saisie dans la variable $ligne # rappel : le descripteur STDIN lié à l’entrée standard peut etre omis $ligne = <STDIN> ; # pour l’afficher à l’écran, au lieu de print STDOUT $ligne; print "STDIN en contexte scalaire = " . $ligne ; # Pour lire une à une les lignes saisies, # on utilise une construction while # pour sortir de cette boucle : ctrl-D while ($ligne = <>) { chomp($ligne) ; @texte = (@texte, $ligne) ; # pour placer la ligne dans le tableau } print "STDIN en contexte liste = @texte\n" ; 2 Modifiez ce programme en utilisant <STDIN> dans un contexte de liste Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 18 / 29 Exercice 12 I Sur un système UNIX (qui n’utilise pas de système de répertoire centralisé), les comptes utilisateurs sont décrits dans un simple fichier texte /etc/passwd. On souhaite récupérer ce fichier dans une liste. Voici la structure des enregistrements de ce fichier : ############# extrait de /etc/passwd #################### jean:x:500:500::/home/jean:/bin/bash thierry:x:501:501::/home/thierry:/bin/bash admin:x:502:502::/home/admin:/bin/bash ######################################################### 1 Compléter et commenter l’exécution du script 2 Donner 2 façons de remettre le compte root en tête de la liste @comptes Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 19 / 29 Exercice 12 II #!/usr/bin/perl -w # ouvrir le fichier /etc/passwd en lecture open P,"/etc/passwd"; # lire la première ligne, puis tout le reste $root = .... print $root,"\n"; @comptes = <P>; print "\$root = $root\n"; print "2ème élément de \@comptes = ...\n"; # afficher le dernier compte : print "Dernier compte créé dans \@comptes = ...\n"; # pour placer $root en 1ère place dans @comptes ..... Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 20 / 29 Exercice 13 * I Il s’agit de rechercher les comptes utilisateurs sur un système Unix de numéros (3ème champ) supérieurs à 500 (en effet dans beaucoup de distributions les numéros internes de comptes (uid) commencent à 500 (ceci est réglable dans /etc/login.defs). On demande d’afficher les champs suivants : nom, uid, répertoire personnel en complétant le script ci-dessous) 1 Ouvrir le fichier /etc/passwd et extraire chaque ligne dans une boucle 2 Utiliser la fonction split() pour mettre les champs de chaque ligne dans une liste @champs 3 Comparer à 500 le champ entier contenant l’UID (c’est le 3ème champ). 4 Présenter une 2ème solution, en récupérant d’un coup le contenu du fichier 5 Prolongement : compléter en trouvant le groupe principal et la liste des groupes secondaires Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 21 / 29 Exercice 13 * II #!/usr/bin/perl -w $fichier="/etc/passwd"; print "Liste des comptes d’uid supérieur à 500\n"; open F, $fichier; while (<F>) { chomp(); @champs= .... if ( ... >= 500) { print " ....\n"; } } Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 22 / 29 Exercice 14 Il s’agit de récupérer et de placer dans une (seule) liste nommée @liste, toutes les lignes contenues dans 3 fichiers. Si on n’a pas de meilleure idée, utiliser /etc/passwd, /etc/group et /etc/fstab 1 Construire @fichiers, la liste de ces noms de fichiers 2 Construire une boucle de parcours de @fichiers, dans laquelle on ouvre chaque fichier en lecture et on empile dans @liste leur contenu 3 Afficher la liste @liste pour vérifier Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 23 / 29 Plan 1 TP2 : listes, tableaux et structures de contrôle Rappels listes et tableaux Exercices TP2 Exercices du cours Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 24 / 29 Exercices 15 à 17 : tableaux I Exercice 15 Écrire un programme lisant une liste de chaı̂nes dans des lignes individuelles et l’affichant en ordre inverse. Si vous lisez la liste sur le terminal, vous devrez probablement en délimiter la fin en produisant le caractère fin de fichier , certainement CTRL+D sous Unix, souvent CTRL+Z ailleurs. Exercice 16 * Écrire un programme lisant un nombre puis une liste de chaı̂nes (toutes dans des lignes individuelles), puis affichant la ligne de la liste selectionnée par le nombre. Exercice 17 Écrire un programme lisant une liste de chaı̂nes puis sélectionnant et affichant une chaı̂ne quelconque de la liste. Pour obtenir un élément quelconque de @untableau, indiquez : srand ; au début de votre programme (cela initialise le générateur de nombres aléatoires), puis utilisez : rand(@untableau) à l’endoit où vous avez besoin d’une valeur quelconque comprise entre zéro et la longueur moins un de @untableau. Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 25 / 29 Exercices 18 à 22 : structures de contrôle I Exercice 18 Écrire un programme demandant la température extérieure, et affichant trop chaud si elle est supérieure à 20°C, et trop froid autrement. Exercice 19 Modifiez le programme de l’exercice précedent pour qu’il affiche trop chaud si la température dépasse 22°C, trop froid si elle est inférieure à 18°C, et convenable entre. Exercice 20 Écrire un programme lisant une série de nombres (sur des lignes distinctes) jusqu’à la lecture de 999, puis affichant la somme de tous ces nombres (prenez soin de ne pas ajouter 999 !). Exercice 21 Écrire un programme lisant une liste de chaı̂nes dans des lignes distinctes, puis l’affichant en ordre inverse (sans utiliser reverse). Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 26 / 29 Exercices 18 à 22 : structures de contrôle II Exercice 22 * Écrire un programme affichant un tableau de nombres et leur carrés, de zéro à 32. Essayez de trouver une solution qui n’oblige pas à énumérer tous les nombres de 0 à 32 dans une liste, puis essayez-en un qui utilise ce type de liste. Pour une belle présentation, printf("%5g %8g\n",$a,$b)affiche le nombre $asur cinq colonnes et le nombre $bsur huit colonnes. Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 27 / 29 Remerciements Ces travaux pratiques sont largement inspirés des cours de programmation de Jean Gourdin : http://www.ac-creteil.fr/util/programmation/perl/ Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 28 / 29 Bibliographie 1 http://www.perl.org/ I 2 http://perso.univ-rennes1.fr/francois.dagorn/perl/ I 3 un site avec un cours synthétique sur Perl http://www.enstimac.fr/Perl/DocFr.html I 4 le site officiel documentation en français http://articles.mongueurs.net/planning.html I articles de revues Jérôme Farinas (IRIT) TP PERL 13 janvier 2009 29 / 29