Introduction à Perl … en trois heures
Plan Syntaxe variables scalaires listes tables de hachages spécial… Plus de syntaxe fonctions définies par l’utilisateur modules structures de contrôles idiomatiques entrées/sorties expressions régulières
Plan Syntaxe variables scalaires listes tables de hachages spécial… Plus de syntaxe fonctions définies par l’utilisateur modules structures de contrôles idiomatiques entrées/sorties expressions régulières
Généralités Perl ressemble beaucoup au C et au shell C : bas-niveau/ Perl : haut-niveau il y a des différences importantes ; par ex : parenthèses pas obligatoires (sauf si nécessaire) ! déclaration de variables pas obligatoire pas de pointeur manipulation de chaînes et de tableaux plus facile un script Perl = un fichier.pl un exemple ?
Généralités : exemple #!/usr/bin/perl use strict; use warnings; print "Quel est ton nom ?"; $nom = ; chomp( $nom ); print "Bonjour $nom !\n"; bonjour.pl $./bonjour.pl $ perl bonjour.pl ou exécution :
Plan Syntaxe variables scalaires listes tables de hachages spécial… Plus de syntaxe fonctions définies par l’utilisateur modules structures de contrôles idiomatiques entrées/sorties expressions régulières
Variables variables préfixées par une lettre $ pour les scalaires $n pour % pour les tables de hachage %config il faudrait toujours déclarer ses variables : my $n; my ($i, $j) = (2, 3); données non initialisées : undef my $n; # n est non initialisé : il « vaut » undef if( defined $n ) # pour savoir si n est initialisé
Plan Syntaxe variables scalaires listes tables de hachages spécial… Plus de syntaxe fonctions définies par l’utilisateur modules structures de contrôles idiomatiques entrées/sorties expressions régulières
Scalaires scalaires nombres (=double) chaînes opérateurs nombres : les mêmes qu’en C chaînes concaténation avec. comparaison de chaînes avec eq (égalité) ne (différence) lt (inférieur) gt (supérieur) le (inférieur ou égal) ge (supérieur ou égal) conversion nombres chaînes automatiques
Scalaires Exemple : (print)
Plan Syntaxe variables scalaires listes tables de hachages spécial… Plus de syntaxe fonctions définies par l’utilisateur modules structures de contrôles idiomatiques entrées/sorties expressions régulières
Listes liste = ensemble ordonné de scalaires ("pin", "chêne, "arbousier")# liste de 3 éléments ( )# liste vide tableau = variable qui contient une liste = ("pin", "chêne, "arbousier"); accès aux éléments avec […] : $arbres[0] = "pin sylvestre"; $arbres[4] = "érable";# création d'un 5 ème élément affectation tableau liste possible : ($arbre1, $arbre2)
Listes : fonctions utiles qw (quoted words) = qw( pin chêne arbousier ); # identique à… = ("pin", "chêne", "arbousier"); push/pop (empiler/dépiler) : accès "à droite" "acacia"; # ajoute "acacia" en bout de tableau $arbre = # retire le dernier élément # et le stocke dans $arbre shift/unshift (défiler/enfiler) : accès "à gauche" "acacia"; # ajoute "acacia" en tête de tableau $arbre = # retire le premier élément # et le stocke dans $arbre
Listes : itération (1) à la C for( $i=0; $i<=$#arbres; $i++ ){ print $arbres[$i], "\n"; } à la Perl foreach $arbre print $arbre, "\n"; } # attention ! # $arbre n'est pas une copie de chaque élément # $arbre est chaque élément successivement !
Listes : itération (2) encore plus à la Perl : foreach print $_, "\n";# $_ = variable par défaut } autre version : foreach print ;# $_ est implicite pour print }
Listes : contextes Très important : contexte de scalaire / contexte de liste Perl attend l'un ou l'autre lorsqu'il analyse une expression Exemples : 42 + chose# Perl attend que chose soit un scalaire pop chose# Perl attend que chose soit une liste dans un contexte de liste # à cause de pop dans un contexte scalaire # à cause de $n =
Plan Syntaxe variables scalaires listes tables de hachages spécial… Plus de syntaxe fonctions définies par l’utilisateur modules structures de contrôles idiomatiques entrées/sorties expressions régulières
Tables de hachage table de hachage : tableau de scalaires indices = chaînes uniques (au lieu de nombres) %jours = ( "lundi"=> "monday", "mardi"=>"tuesday", "mercredi"=>"wednesday" ); accès aux éléments avec {…} $jours{'lundi'} = "monday"; $jours{'jeudi'} = "thursday";
Tables de hachage : fonctions keys/values = keys %jours; vaut ('lundi', 'mardi', 'mercredi') = values %jours; vaut ('monday', 'tuesday', 'wednesday') exists/delete if( exists $jours{'lundi'} ){ # si lundi est une clé de %jours delete $jours{'lundi'}; # suppression de l'élément }
Tables de hachage : itération avec foreach foreach $cle (keys %jours){ print "cle=$cle, valeur=$jours{$cle}\n"; } avec each while( ($cle,$valeur) = each %jours ){ print "cle=$cle, valeur=$valeur\n"; } # à chaque appel de each, # la paire clé/valeur suivante est renvoyée # jusqu'à ce qu'il n'y en ait plus
Plan Syntaxe variables scalaires listes tables de hachages spécial… Plus de syntaxe fonctions définies par l’utilisateur modules structures de contrôles idiomatiques entrées/sorties expressions régulières
Spécial : les booléens pas de type booléen en Perl dans un test (if ou while ou autre) : fauxvrai nombre0 0 0 chaîne chaîne vide '0' '' '0' undef listeliste videliste non vide table de hachage table videtable non vide
Spécial : les quotes pour délimiter les chaînes 'des apostrophes' "des guillemets" interpolationséquences d'échappement '... 'non \' signifie ' \\ signifie \ "... "oui \" signifie " \\ signifie \ \$ signifie $ \n signifie « retour à la ligne » \r signifie « retour chariot » \t signifie « tabulation »...
Spécial : interpolation Dans une chaîne délimitée par des guillemets doubles : les chaînes sont remplacées par leur valeur les nombres sont remplacés par leur valeur (en utilisant un format par défaut) les tableaux (indexés) sont remplacés par la liste de leurs éléments, séparés par un espace les variables non initialisées ( undef ) sont remplacées par une chaîne vide les tables de hachage ne sont pas interpolées !
Spécial : interpolation Exemples : = ("pin", "chêne", "arbousier"); my $n print "J'ai $n arbres :\n"; print "Voici leurs noms print "Mon arbre préféré est le $arbre[1]\n";
Plan Syntaxe variables scalaires listes tables de hachages spécial… Plus de syntaxe fonctions définies par l’utilisateur modules structures de contrôles idiomatiques entrées/sorties expressions régulières
Fonctions définies par l'utilisateur Définition sub ma_fonction { # corps de la fonction print "je suis dans ma fonction"; } Appel &ma_fonction; # parenthèses non obligatoires &ma_fonction(); # si vous préférez
Fonctions définies par l'utilisateur Valeur de retour à indiquer avec return Arguments accessibles via le Exemple : sub max { if( $_[0]>$_[1] ){ return $_[0]; # renvoyer le 1 er argument }else{ return $_[1]; # sinon renvoyer le 2 ème } } $m = &max( 5, 7 ); # exemple d'appel
Fonctions définies par l'utilisateur à la Perl (version 1) : sub max { my( $a, $b ) if( $a>$b ){ return $a; }else{ return $b; } }
Fonctions définies par l'utilisateur à la Perl (version 2) : sub max { my($max_actuel) = # ou shift; tout seul ){ if( $_>$max_actuel ){ $max_actuel = $_; } } return $max_actuel; }
Plan Syntaxe variables scalaires listes tables de hachages spécial… Plus de syntaxe fonctions définies par l’utilisateur modules structures de contrôles idiomatiques entrées/sorties expressions régulières
Modules : concepts et installation module = des fonctions + de la documentation "packagé" dans un certain format (typiquement un fichier.pm) certains sont livrés avec Perl (par ex. CGI.pm) d'autres sont disponibles sur CPAN (par ex. XML::Simple) Lire la documentation d'un module $ perldoc nom_du_module Installer un module manuellement (téléchargement, extration, compilation) ou gestionnaire CPAN ( yum) : $ perl -MCPAN -e shell
Modules : utilisation utilisation : ajouter en tête du script use nom_du_module; permet l'utilisation des fonctions et variables mises à disposition par le module si on veut uniquement certaines fonctions : use nom_du_module qw/ fonction1 fonction2 /;
Modules : un exemple #!/usr/bin/perl use strict; use warnings; use File::Basename qw/ basename dirname/; my $nom = "/usr/bin/perl"; my $file = basename $nom; # donne 'perl' my $dir = dirname $nom; # donne '/usr/bin‘ print "répertoire=$dir\n"; print "fichier=$file\n";
Plan Syntaxe variables scalaires listes tables de hachages spécial… Plus de syntaxe fonctions définies par l’utilisateur modules structures de contrôles idiomatiques entrées/sorties expressions régulières
Structures de contrôles idiomatiques Perl introduit de "nouveaux" opérateurs : nouvelle structurestructure équivalente unless( $n==0 ){ print "n 0"; } if( $n!=0 ){ print "n 0"; } $n = 5; until( $n==0 ){ print "n vaut $n\n"; $n--; } $n = 5; while( $n!=0 ){ print "n vaut $n\n"; $n--; }
Structures de contrôles idiomatiques Il n'existe pas de switch en Perl. On utilise : if( !defined $n ){ print "n n'est pas défini\n"; } elsif( $n==0 ){ print "n vaut 0\n"; } elsif( $n>0 ){ print "n est positif\n"; } else { print "n est négatif\n"; }
Structures de contrôles idiomatiques Perl aime les formulations naturelles : nouvelle structurestructure équivalente print "$n est négat\n" if( $n<0 ); if( $n<0 ){ print "$n est nég\n"; } $n = 5; print "n vaut $n\n“ while( $n-- >= 0); $n = 5; while( $n>=0 ){ print "n vaut $n\n"; $n--; }
Structures de contrôles idiomatiques Hérités du shell, les opérateurs logiques sont à évaluation partielle : si, à partir du côté gauche, on peut prédire la valeur de l'expression logique, alors le côté droit n'est pas évalué. Certains utilisent cela comme une structure de contrôle : $jour = "lindi"; $day = $jours{ $jour } || 'unknown day'; On utilise très souvent quelque chose comme : open FICHIER, $nom_fichier or die "Imposs d'ouvrir le fichier !\n";
Plan Syntaxe variables scalaires listes tables de hachages spécial… Plus de syntaxe fonctions définies par l’utilisateur modules structures de contrôles idiomatiques entrées/sorties expressions régulières
Entrées/sorties sur STDIN et STDOUT STDIN : entrée standard / STDOUT : sortie standard écriture sur STDOUT avec print : print "j'écris sur STDOUT !\n"; lecture sur STDIN avec : $ligne = ;# lecture d'une ligne chomp( $ligne );# nettoyage
Entrées/sorties sur fichiers … comme sur STDIN/STDOUT mais on utilise en plus un descripteur de fichier (handle) On obtient ce descripteur en ouvrant le fichier avec open open CONFIG, " fichier.tmp";# en écriture (crée le #fichier ou écrase l'ancien) open JOURNAL,">> /var/log/monappli.log"; # en ajout (crée le fichier # s'il n'existe pas) open DONNEES,"+< appli-data";# en lecture/écriture (s'il # existe déjà) Typiquement, on vérifie que ça a marché : open CONFIG, "< /etc/yum.conf" or die "Impossible d'ouvrir yum.conf : $!\n";
Entrées/sorties sur fichiers écriture dans fichier avec print : print DESCR "écriture dans fichier\n"; ou bien avec printf : printf JOURNAL "le %s à %s : MAJ terminée.\n", $date, $heure; descripteur de fichier obtenu avec open pas de virgule !
Entrées/sorties sur fichiers lecture dans fichier avec : $ligne = ;# lecture d'une ligne chomp( $ligne );# nettoyage lecture d'un fichier entier : renvoie undef à la fin du fichier on peut donc utiliser while( … ) exemple : while( $ligne = ){ # traitement de la ligne lue chomp( $ligne ); print "je viens de lire $ligne\n"; }
Tests sur les fichiers On peut obtenir des infos sur les fichiers sans les ouvrir Perl fournit des opérateurs permettant de tester : si un fichier/répertoire existe, si on peut lire/écrire/exécuter un fichier/répertoire, sa taille, …… Ces opérateurs s'appliquent : soit sur un nom de fichier (absolu ou relatif) soit sur un descripteur de fichier déjà ouvert
Tests sur les fichiers opérateurmnémoniquevrai si -r read le fichier ou répertoire est accessible en lecture (pour l'utilisateur courant) -w write le fichier ou répertoire est accessible en écriture (pour l'utilisateur courant) -x execute le fichier est exécutable (pour l'utilisateur courant) -e existsle fichier ou répertoire existe -z zerole fichier existe mais est vide -s size le fichier ou répertoire est non vide (la valeur retournée est la taille en octets) -f file le fichier est « normal » (ce n'est ni un répertoire et ni un fichier spécial) -d directoryle fichier est un répertoire (!!)
Tests sur les fichiers Exemple : if( -e "/etc/passwd" ){ my $taille = -s "/etc/passwd"; print "/etc/passwd : $taille o\n"; }
Plan Syntaxe variables scalaires listes tables de hachages spécial… Plus de syntaxe fonctions définies par l’utilisateur modules structures de contrôles idiomatiques entrées/sorties expressions régulières
Expressions régulières Expression régulière = motif (pattern) = suite de caractères utilisée pour identifier (match) une partie d'une chaîne de caractères Utilisation rechercher/remplacer des traitements de textes : savoir si une chaîne contient le motif (correspondance) extraire des sous-parties de ce motif remplacer le motif par autre chose (substitution) ……
Expressions régulières : correspondance Simple correspondance : if( "le sport est bon pour la santé" =~ /sport/ ){ print "correspondance réussie !"; } motif opérateur de liaison chaîne traitée Correspondance sur variable par défaut : $_ = "le sport est bon pour la santé"; if( /sport/ ){# omission du =~ dans ce cas print "correspondance réussie !"; }
Méta-caractères Méta-caractères : {}[]()^$.|*+?\ Ils ont une signification particulière : ^ ancre de début de chaîne $ ancre de fin de chaîne \b ancre de limite de mot d'autres à suivre… Exemples ?
Méta-caractères "mentalement" =~ /ment/# vrai "mentalement" =~ /^ment/# vrai "mentalement" =~ /ment$/# vrai "mentalement" =~ /^mental/# vrai "mentalement" =~ /mental$/# faux "mentalement" =~ /^mental$/# faux "mentalement" =~ /^mentalement$/# vrai "le sport c'est bien" =~ /\bsport/# vrai "le sport c'est bien" =~ /\bport/# faux "le sport c'est bien" =~ /bien\b/# vrai
Méta-caractères Classe de caractères = un caractère parmi plusieurs d'une liste Une classe de caractères correspond avec UN caractère Pour spécifier une classe, on utilise les crochets [ ] par exemple, [abc] désigne UN caractère parmi a, b ou c Exemple : print "Etes-vous d'accord ?"; chomp( $_ = ); if( /[Oo][Uu][Ii]/ ){ print "Il est d'accord !\n"; }
Méta-caractères Il existe des raccourcis : - permet de fabriquer une plage de caractères (par ex [a-z] égale [abcdefghijk…vwxyz] ) ^ permet d'inverser la classe de caractère (par ex [^a] désigne tout caractère sauf un a) . n'importe quel caractère (sauf \n) : égale [^\n] \w n'importe quel caractère alphanumérique \s n'importe quel caractère "blanc" \d n'importe quel chiffre : égale [0-9] Par exemple /\d\d:\d\d:\d\d/ correspond avec les chaînes au format d'heure hh:mm:ss.
Méta-caractères Alternative : | signifie que le côté gauche ou le côté droit peut correspondre Regroupement : () permettent de regrouper deux expressions en une seule entité Exemples ?
Méta-caractères /ch(ien|at)/; # 'chien' ou 'chat' /(a|b)b/; # 'ab' ou 'bb' /(^a|b)c/; # 'ac' en début de chaîne ou 'bc' n'importe où /planche (à voile|)/; # 'planche' ou 'planche à voile' /planche (à (voile|repasser)|)/; # 'planche' ou 'planche à voile' ou 'planche à repasser' "20" =~ /(19|20|)\d\d/; # correspond avec l'alternative '()\d\d' # parce que '20\d\d' ne peut pas correspondre
Méta-caractères Quantification : ?, *, +, et {} permettent de spécifier le nombre de répétitions qu'on attend quantificateursignification ? 0 ou 1 fois + 1 fois ou plus * 0 fois ou plus {n} exactement n fois {n,} au moins n fois {n,m} entre n fois et m fois Exemples ?
Méta-caractères Par exemple, pour identifier une année sur 4 chiffres : /\d{4}/ Pour identifier une année sur 2 ou 4 chiffres : /\d{2,4}/ # pas ok : 3 chiffres marche ! /\d{2}(\d{2}|)/ # ok /\d{4}|\d{2}/ # ok, mieux /\d\d(\d\d)?/ # ok, plus lisible
Modificateurs A la suite d'une regex, des options peuvent être précisées, appelées modificateurs : i rend la correspondance insensible à la casse, x autorise les caractères d'espacement dans le motif, s fait que. correspond à n'importe quel caractère, même un retour à la ligne, g permet de faire une recherche globale (itération possible à l'aide d'une boucle while() ) Exemple : if( /oui/i ){ print "Il est d'accord !\n"; }
Extraction de motifs S'il y a correspondance, chaque groupe de ( ) est enregistré dans une variable $1, $2, … Ces variables sont utilisables normalement après la correspondance : # extraction de heure, minute, seconde $time =~ /(\d\d):(\d\d):(\d\d)/; $h = $1; $min = $2; $sec = $3; print "heure : ${h}h${min}m${sec}s\n";
Substitution (rechercher/remplacer) S'il y a correspondance, le motif peut être remplacé par une chaîne. On utilise la syntaxe s/regex/remplacement : $_ = "le sport c'est bon pour la santé"; s/le sport/les jeux vidéo/; # maintenant "les jeux vidéo c'est bon …" s/bon/pô bon/; # maintenant "les jeux vidéo c'est pô bon …" s/^/je suis sûr que /; # maintenant "je suis sûr que les jeux vidéo…" s/(\s+)(\w)/$1f/g; # maintenant "fe fuis fûr fue fes feux fidéo…"
split/join split permet de décomposer (exploser) une chaîne de caractères à chaque apparition d'un motif split renvoie les "morceaux" dans un tableau Le motif est souvent, ; : ou \n Par exemple, si $_ contient une ligne lue dans /etc/passwd, l'instruction suivante renvoie les données de l'utilisateur dans le = split /:/; print "uid=$userdata[0]\n"; Autre exemple, pour détacher les mots d'une phrase = split /\s+/, 'tagada tsoin tsin';
split/join join permet de faire le travail inverse de split join retourne une chaîne en joignant les éléments d'une liste avec un délimiteur join n'a rien à voir avec les expressions régulières ! Par exemple : my $ligne = join ';', (2,4,6,8,10); # renvoie '2;4;6;8;10'
Introduction à Perl … en trois heures : FIN