SELFHTML/Aides à la navigation CGI/Perl Éléments de langage Perl |
Commandes de saut | |
La commande de saut goto
, qui permet de sauter à un autre endroit de son choix pouvant être déterminé dans le script au cours de son exécution, est marquée depuis longtemps au fer comme étant caractéristique d'une mauvaise programmation et de programmeurs de code décousu. Elle peut être aussi évitée en temps normal par des boucles programmées correctement ou bien par des instructions conditionnelles bien structurées.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body>\n"; print "<h1>Bonjour utilisateur</h1>\n"; goto MESSAGE; ENCOURAGEMENT: print "<p>Il fait si beau que l'on pourrait organiser quelque chose</p>"; goto FIN; MESSAGE: print "<p>Ce service n'est pas disponible pour l'instant</p>\n"; goto ENCOURAGEMENT; FIN: print "</body></html>\n"; |
Le script renvoie du code HTML au navigateur appelant. Pour trouver dans quel ordre les instructions print
sont sorties, vous devez suivre les instructions goto
. À chaque instruction goto
est mentionnée une marque de saut, ce qu'on appelle une étiquette. Ce sont dans l'exemple, les noms écrits en majuscules. Sous ce nom on doit retrouver l'étiquette quelque part dans le script et ce, seule sur une ligne et suivie de deux points. Au dessous se poursuit alors l'exécution du script quand l'étiquette est atteinte.
La commande de saut next
est conçue pour être employée dans des boucles. Le parcours actuel de la boucle est interrompu. La boucle suivante est lancée après une nouvelle évaluation de la condition de la boucle.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body>\n"; my $clef; my $valeur; while (($clef, $valeur) = each(%ENV)) { next unless $clef =~ /^HTTP_.*/; print "<b>$clef</b> a la valeur <b>$valeur</b><br>\n"; } print "</body></html>\n"; |
Le script en exemple sort dans le navigateur les variables d'environnement CGI , seulement celles cependant qui commencent par HTTP_
. Pour ce faire, le script lit le Hash prédéfini %ENV
dans une boucle pour les hashes. Avec next
et une condition placée après ainsi qu'une expression régulière correspondante /^HTTP_.*/
comme condition, qui est niée avec unless
, l'instruction obtient que la commande print
qui suit, ne soit pas interprétée, quand la variable d'environnement actuelle ne commence pas par HTTP_
. De cette façon, ne seront donc sorties que les variables pour lesquelles c'est le cas.
continue
- n'appartient pas aux commandes de saut au sens strict du terme, mais leur est étroitement apparenté étant donné que continue
est atteint par un saut. Le mot clé introduit un bloc d'instructions distinct. À l'intérieur de ce bloc d'instructions qui est marqué comme d'habitude avec des parenthèses accolades { et }, vous pouvez noter des instructions de votre choix. Quand un tel bloc continue
figure immédiatement derrière un bloc de boucle, il est exécuté à chaque exécution de la boucle et ensuite (excepté pour la toute première exécution de la boucle) exécuté directement avant la vérification de la condition de la boucle.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body>\n"; my $i = 1; while($i <= 100) { next if ($i % 7 != 0); print "$i est divisible par 7 <br>\n"; } continue { $i++; } print "</body></html>\n"; |
L'exemple sort dans le navigateur appelant tous les chiffres entre 1 et 100 qui sont divisibles par 7. Ici est utilisée une boucle while
dont la condition demande si $i
est plus petit ou égal à 100
. Étant donné que $i
est initialisé avec 1
, le bloc de la boucle est donc atteint. $i
n'est cependant pas incrémenté à l'intérieur du bloc de la boucle, cela conduirait à une désespérante boucle sans fin. Dans l'exemple le bloc continue
placé après la parenthèse accolade de fermeture du bloc de la boucle sert à cela . À l'intérieur du bloc continue
, $i
est incrémenté.
À l'intérieur de la boucle, il est demandé avec la condition $i % 7 != 0
, si la valeur actuelle de $i
divisée par 7 a un reste égal à 0 (voir division modulo dans les opérateurs de calcul). Par next
est aussitôt lancé le passage de boucle suivant, si le nombre n'est pas divisible par 7 sans donner de reste, toutefois l'instruction du bloc continue
est encore exécutée quelque soit le cas.
La commande de saut last
interrompt immédiatement une boucle.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body>\n"; while(1) { my $maintenant = time; print "$maintenant \n"; last if ($maintenant % 2 == 0); } print "</body></html>\n"; |
Le script en exemple recherche avec la fonction time, à l'intérieur d'une boucle sans fin classique formulée avec while(1)
("La condition est toujours vraie"), la valeur du temps actuelle en secondes et la sauvegarde dans la scalaire $maintenant
. Avec la condition $i % 2 == 0
il est demandé si la valeur actuelle de $maintenant
divisée a un reste égal à 0 (voir division modulo dans les opérateurs de calcul). Si la condition placée après l'instruction if
est remplie, la commande last
qui précède est exécutée. La boucle est alors interrompue. Au cas où le script est appelé à un moment où la valeur des secondes est impaire, la valeur actuelle des secondes est sortie jusqu'à ce que time
renvoie la valeur des secondes immédiatement supérieure.
La commande de saut redo
répète simplement encore une fois le parcours de la boucle actuelle. Pour cette répétition, la valeur de la boucle n'est pas évaluée encore une fois.
Ceci est \ un fichier avec une convention. une barre oblique inversée à la fin \ d'une ligne signifie: \ une nouvelle ligne! |
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); open(FH,"<texte.txt"); my @lignes; while(<FH>) { chomp; if(s/\\$//) { $_ .= <FH>; redo unless(eof(FH)); } push(@lignes,$_."\n"); } close(FH); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body><pre>\n"; print @lignes; print "</pre></body></html>\n"; |
L'exemple montre une utilisation classique de redo
. Il s'agit ici de regrouper plusieurs lignes sur la base d'une convention en une seule. Le fichier texte qui précède contient bien cinq lignes, mais à la fin doivent en résulter deux lignes seulement. Les lignes qui se terminent par une barre oblique inversée, doivent de poursuivre sur la ligne suivante.
Le script ouvre le fichier texte avec la fonction open. Dans une boucle while
il lit à chaque fois la ligne suivante du fichier. La condition de la boucle est ici <FH>
. Cela signifie: portion suivante du fichier lié au descripteur de fichier FH
et cela dans le contexte scalaire. Dans ce contexte la ligne suivante du fichier est alors livrée.
À l'intérieur de la boucle, le signe final de passage à la ligne de la ligne actuelle est retiré avec la fonction chomp . Ensuite on recherche et remplace avec l' expression régulière s/\\$//
une barre oblique inversée éventuellement présente à la fin de la ligne. Dans le cas où une barre oblique inversée a effectivement été trouvée et remplacée, la condition pour le if
est vraie, et le bloc d'instructions qui en dépend est exécuté. Dans ce bloc la ligne suivante est lue avec $_ .= <FH>;
et elle est accrochée à la ligne actuelle. Ici est utilisée la variable prédéfinie $_
et l' opérateur pour concaténer des chaînes de caractères (.
). Enfin, il est sauté à nouveau au début de la boucle avec redo
, dans la mesure où n'est pas (unless
) atteinte la fin du fichier ( eof).
redo
fait en sorte que la condition de la boucle ne soit pas réévaluée. Aucune ligne suivante n'est donc lue. La variable $_
, à laquelle se réfèrent tant l'instruction chomp;
que l'expression régulière, s'est déjà vu affecter une nouvelle valeur à l'intérieur du bloc if
. Pour la compréhension: avec chomp;
on veut dire quelque chose comme: chomp($_);
, et avec if(s/\\$//)
quelque chose comme: if($_ =~ s/\\$//)
. Aussi bien le retrait du passage à ligne que l'évaluation de la présence d'une barre oblique inversée qui la termine, se réfèrent donc implicitement à la variable prédéfinie $_
.
Quant dans l'exemple la condition if
n'est plus vraie, le script aboutit là où la ligne actuelle est ajoutée dans le tableau @lignes
avec la fonction push. N'y sont sauvegardées à la fin que les deux lignes du fichier qui doivent rester par convention. Le script sort le contenu de @lignes
à la fin, dans le navigateur appelant.
Opérateurs | |
Boucles | |
SELFHTML/Aides à la navigation CGI/Perl Éléments de langage Perl |
© 2001 Stefan Münz / © 2003 Traduction Serge François, 13405@free.fr
selfhtml@fr.selfhtml.org