FAQ PerlConsultez toutes les FAQ

Nombre d'auteurs : 18, nombre de questions : 250, dernière mise à jour : 29 octobre 2015  Ajouter une question

 

Bienvenue sur la FAQ Perl. Cette FAQ a pour vocation de vous enseigner ou de vous faire revoir les notions élémentaires de ce fantastique langage. Perl est très utilisé dans différents domaines depuis la gestion système, le réseaux, l'administration de bases de données, le web (CGI), la bureautique, la conception d'interfaces graphiques ou des contextes scientifiques telle la bioinformatique. Nous espérons que cette FAQ vous sera d'une grande utilité.

Vous souhaitez participer à l'amélioration de cette FAQ, n'hésitez pas !! Commentez

Bonne lecture !


SommairePerl avancéLes références (9)
précédent sommaire suivant
 

Les références Perl sont des variables qui permettent de référencer d'autres variables, tableaux, hashs, fonctions ou handles. La notion de référence peut être vue comme les pointeurs en C. Mais pas de panique :-(, c'est beaucoup plus simple que ce que vous croyez ! Vous allez me dire, oui, c'est bien beau, mais à quoi ça sert ? Voici donc un exemple...

Code perl : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
my @tab1 = (1, 2, 3); 
my @tab2 = ('a', 'b', 'c'); 
  
affiche(@tab1, @tab2); 
  
sub affiche { 
  my ( @recup1, @recup2 ) = @_; 
  print "Voici votre tableau tab1 récupéré dans ma fonction : @recup1\n"; 
  print "Voici votre tableau tab2 récupéré dans ma fonction : @recup2\n"; 
  
  return; 
}
Code : Sélectionner tout
1
2
Voici votre tableau tab1 récupére dans ma fonction : 1 2 3 a b c 
Voici votre tableau tab2 récupére dans ma fonction :
Bizarre le résultat non ? Dans notre exemple, deux tableaux @tab1 et @tab2 sont donnés en argument à notre fonction qui a pour unique but de les réafficher. Vous remarquez qu'il n'arrive pas à distinguer vos tableaux et à les récupérer correctement.
Il en aurait été de même avec des hashs.
Petite explication :

@_ récupère une liste des données (@tab1 et @tab2 concaténés). De ce fait, toutes les données récupérées se retrouvent dans @recup1, @recup2 reste vide. Comment doit-on faire pour que @recup1 et @recup2 soient corrects ? Facile ! Vous avez trouvé ? Les références !!! On passera en argument à la fonction les références de nos tableaux.

Mis à jour le 15 décembre 2005 djibril

Nous avons bien compris avec l'exemple ci-dessus l'utilité des références. La question est maintenant de savoir comment faire pour désigner (créer une référence) un tableau, un hash, une fonction…
Rien de plus simple, il suffit juste de placer un backslash ("\") devant la variable à référencer. Ainsi, la référence $ref_tab de notre tableau @tab s'écrit

Code perl : Sélectionner tout
$ref_tab = \@tab;
Exemples :

Code perl : Sélectionner tout
1
2
3
4
my $ref_tableau  = \@mon_tableau; 
my $ref_hash     = \%mon_hash; 
my $ref_fonction = \&ma_fonction; 
my $ref_handle   = \*FILE;
Voilà, c'est aussi simple que ça. Par curiosité, essayez cet exemple :

Code perl : Sélectionner tout
1
2
3
my @mon_tableau = ( 1, 2, 3 ); 
my $ref_tab = \@mon_tableau; 
print $ref_tab;
Vous obtenez ce genre de résultat : ARRAY(0x225da0).
C'est l'adresse, la référence du tableau @mon_tableau. D'ailleurs, aussi doué que vous soyez, vous avez déjà dû rencontrer des erreurs avec ce genre de caractère !! Généralement, sans le savoir, c'est dû au fait qu'on pense travailler sur un tableau ou une valeur de ce dernier alors que l'on travaille sur sa référence. Sinon, il existe une autre façon de créer des références, qu'on appelle références anonymes, voir ci-dessous.

Mis à jour le 15 décembre 2005 djibril

Excusez mon vocabulaire, mais c'est une façon un peu tordue de créer une référence ! En fait, on crée une référence sur une variable n'existant pas au préalable, ne possédant pas de nom. Je sais, ce n'est pas clair... Ce sont des références sur des structures anonymes en vue d'obtenir des structures de données plus complexes. Un petit exemple vous éclaira, du moins je l'espère !

Code perl : Sélectionner tout
1
2
3
4
5
6
7
my $ref_tab = [ 1, 2, 3 ]; 
my $ref_hash = { 
  "cle1" => "valeur1", 
  "cle2" => "valeur2", 
}; 
print $ref_tab; 
print $ref_hash;
Il vous affichera deux adresses. Eh oui, c'est tordu comme raisonnement ! La première pour le tableau (1,2,3) sans nom, la deuxième pour le hash ("cle1" => "valeur1", "cle2" => "valeur2") sans nom.
Vous remarquez les couleurs rouges pour que vous puissiez prêter attention à la façon d'écrire les références anonymes.
Petit résumé : un tableau s'écrit (1,2,3), une référence anonyme à un tableau [1,2,3].

Bon, c'est bien tout ce blabla, mais comment les utiliser ? On y arrive, on y arrive, allez voir ci-dessous (déférencement).

Mis à jour le 15 décembre 2005 djibril

Ah enfin !!! Après toutes ces explications, vous allez enfin savoir utiliser ces fameuses références !! Tout d'abord, sachez qu'il existe deux façons de les utiliser (eh oui, c'est Perl, avec sa grande capacité à pouvoir écrire du code de différentes façons) :

1) Première façon

  • @{$ref_tableau} est identique à @tableau.
  • ${$ref_tableau}[0] est identique à $tableau[0]
  • %{$ref_hash} est identique à %hash
  • ${$ref_hash}{"cle1"} est identique à $hash{"cle1"}


Voici encore plus simple si vous voulez, mais plus bizarre quand on tombe dessus pour la première fois.
Vous pouvez omettre les accolades si $ref a été déclaré : my $ref = \@tableau;
  • @{$ref_tableau} est identique à @$ref_tableau.
  • ${$ref_tableau}[0] est identique à $$ref_tableau[0]
  • %{$ref_hash} est identique à %$ref_hash
  • ${$ref_hash}{"cle1"} est identique à $$ref_hash{"cle1"}


Résumé:

@{$ref_tableau} est identique à @$ref_tableau, lui-même identique à @tableau ! En d'autres termes, un tableau est identique au tableau de sa référence ! C'est clair, non ?
Exemple :

  • $ref=\@tab => création d'une référence, c'est le référencement
  • @{$ref} => c'est le déférencement.

Code perl : Sélectionner tout
1
2
3
4
5
6
7
8
9
# Déclaration de mon tableau 
my @mon_tableau = ( 1, 2, 3 ); 
  
# Déclaration de la référence de mon tableau 
my $ref_tab = \@mon_tableau; 
  
print @{$ref_tab};    #ou print @$ref_tab; 
  
#  et vous obtiendrez : 123
En résumé, il faut juste mettre {$ref} à l'endroit où on met d'habitude le nom du tableau ou d'un hash.

2) Deuxième façon

C'est une écriture simplifiée (ressemblant à l'écriture objet pour les connaisseurs). Cette méthode s'utilise surtout lorsque l'on travaille sur un élément de tableau et de hash.
Exemple :

Code perl : Sélectionner tout
1
2
3
4
5
my @tableau = ( 1, 2, 3 ); 
my $ref_tableau = \@tableau; 
  
my %hash = ( "cle1" => "valeur1", "cle2" => "valeur2" ); 
my $ref_hash = \%hash;

  • $ref_tableau->[0] est identique à ${$ref_tableau}[0] identique à $tableau[0] égal à la valeur 1
  • $ref_hash->{"cle1"} est identique à ${$ref_hash}{"cle1"} identique à $hash{"cle1"} égal à la valeur valeur1


Voilà, est-ce compliqué ??
Va falloir relire la doc plusieurs fois au début !! C'est normal !!
Bon pour la route, reprenons notre tout premier exemple (dans la section Qu'est-ce qu'une référence, à quoi ça sert ?) :

Code perl : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
my @tab1 = ( 1,   2,   3 ); 
my @tab2 = ( 'a', 'b', 'c' ); 
  
# On donne en argument à la fonction affiche les références à nos tableaux. 
affiche( \@tab1, \@tab2 ); 
  
sub affiche { 
  
  # On récupère les références 
  my ( $ref1, $ref2 ) = @_; 
  
  # Affichage 
  print "Voici votre tableau tab1 récupéré dans ma fonction : @{$ref1}\n"; 
  print "Voici votre tableau tab2 récupéré dans ma fonction : @{$ref2}\n"; 
}
Code : Sélectionner tout
1
2
3
4
5
résultat : 
 
Voici votre tableau tab1 récupéré dans ma fonction : 1 2 3 
Voici votre tableau tab2 récupéré dans ma fonction : a b c 
Magique, non !!
Sachez tout de même qu'après l'appel de votre fonction, si celle-ci doit traiter et modifier le tableau, le tableau d'origine sera modifié !
Exemple :

Code perl : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
my @tab1 = ( 1,   2,   3 ); 
my @tab2 = ( 'a', 'b', 'c' ); 
  
# On donne en argument à la fonction affiche les références à nos tableaux. 
affiche( \@tab1, \@tab2 ); 
  
print "Voici votre tableau tab1 récupéré dans ma fonction : @tab1\n"; 
print "Voici votre tableau tab2 récupéré dans ma fonction : @tab2\n"; 
  
sub affiche { 
  
  # On récupère les références 
  my ( $ref1, $ref2 ) = @_; 
  
  push @{$ref1}, "dudu"; 
  push @{$ref2}, "dudu"; 
}
Code : Sélectionner tout
1
2
3
4
résultat : 
 
Voici votre tableau tab1 récupéré dans ma fonction : 1 2 3 dudu 
Voici votre tableau tab2 récupéré dans ma fonction : a b c dudu
Si vous ne souhaitez pas modifier les tableaux d'origine, à vous de créer vos tableaux dans vos fonctions :

Code perl : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
............ 
............ 
print "Voici votre tableau tab1 récupéré dans ma fonction : @tab1\n"; 
print "Voici votre tableau tab2 récupéré dans ma fonction : @tab2\n"; 
  
sub affiche { 
  
  # On récupère les références 
  my ( $ref1, $ref2 ) = @_; 
  
  # Copie de mes tableaux pour que la modification ne soit appliquée que dans la procédure. 
  my @tableau1_interne = @{$ref1}; 
  my @tableau2_interne = @{$ref2}; 
  push @tableau1_interne, "dudu"; 
  push @tableau2_interne, "dudu"; 
}
Code : Sélectionner tout
1
2
3
4
résultat : 
 
Voici votre tableau tab1 récupéré dans ma fonction : 1 2 3  
Voici votre tableau tab2 récupéré dans ma fonction : a b c
Voilà !!! Les tableaux @tab1 et @tab2 n'ont pas été modifiés !

Mis à jour le 15 décembre 2005 djibril stoyak

Prenons un exemple de hachage contenant des références, nous allons le parcourir.

Code perl : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/perl 
use strict; 
use Carp; 
use warnings; 
  
my %HashReferenceComplex = ( 
  'niv1' => 'valeur 1', 
  'niv2' => [ 'case0', 'case1', 'case2', 'case3' ], 
  'niv3' => { 
    'niv3-1_a' => 'valeur3-1', 
    'niv3-1_b' => [ 'case0-1', 'case1-1', 'case2-1', 'case3-1' ], 
    'niv3-1_c' => { 'niv3-2_a' => 'test', }, 
  }, 
  'niv4' => \&FonctionBonjour, 
); 
  
sub FonctionBonjour { 
  my $prenom = shift; 
  print "Bonjour $prenom\n"; 
}
Pour appeler la fonction FonctionBonjour via le hash, il faut écrire :

Code perl : Sélectionner tout
1
2
# Afficher bonjour via le hachage 
$HashReferenceComplex{'niv4'}->('djibril');
Code perl : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
# Afficher bonjour via le hachage 
$HashReferenceComplex{'niv4'}->('djibril'); 
  
# Afficher valeur3-1 
print $HashReferenceComplex{'niv3'}{'niv3-1_a'}, "\n"; 
  
# Afficher case0-1 
print $HashReferenceComplex{'niv3'}{'niv3-1_b'}->[0], "\n"; 
  
# Afficher case0 à case3 
foreach my $niveau ( @{ $HashReferenceComplex{'niv2'} } ) { 
  print "\t- $niveau\n"; 
}

Mis à jour le 13 juillet 2009 djibril

Voici un exemple de tableau à deux dimensions (tableaux de tableaux).

Code perl : Sélectionner tout
my @tab2tab = ([1,2], ["a","b"],["toto","tete"],["djibril","Stoyak","vous"]);
Chaque case du tableau @tab2tab contient une référence à un tableau anonyme, c'est-à-dire une référence anonyme.

  • 1re case du tableau @tab2tab => [1,2] ;
  • 2e case du tableau @tab2tab => ["a","b"] ;
  • 3e case du tableau @tab2tab => ["toto","tete"] ;
  • 4e case du tableau @tab2tab => ["djibril","Stoyak","vous"] ;
  • Petit rappel : un tableau normal s'écrit avec des parenthèses d'où @tab2tab = (...,...).

un tableau anonyme avec des crochets : [1,2]

@tab2tab contient quatre références anonymes, ainsi pour récupérer la première référence anonyme :

Code perl : Sélectionner tout
1
2
3
my $ref1 = $tab2tab[0]; # c'est-à-dire $ref1 = [1,2]; 
my $ref4 = $tab2tab[3]; # c'est-à-dire $ref4 = ["djibril","Stoyak","vous"]; 
# =>Rappel : la première case d'un tableau a pour indice 0.
Voici comment afficher la valeur "Stoyak", c'est-à-dire la deuxième case du 4e tableau anonyme de tab2tab :

Code perl : Sélectionner tout
1
2
my @tab2tab = ([1,2], ["a","b"],["toto","tete"],["djibril","Stoyak","vous"]); 
my $ref4 = $tab2tab[3];
Code perl : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
print ${$ref4}[1];      #=> "Stoyak" 
  
print $$ref4[1];        #=> "Stoyak" 
  
print ${$tab2tab[3]}[1];#=> "Stoyak" 
print $$tab2tab[3][1];  #=> ne fonctionnera pas (explication ci-dessous) 
  
# Cas particulier des tableaux à plusieurs dimensions, on peut écrire simplement ainsi 
print $tab2tab[3][1];   #=> "Stoyak" 
  
print $tab2tab[3]->[1]; #ou print $ref4->[1]; => "Stoyak"
Explication 3) :
Je vous avais expliqué plus haut qu'il était possible d'omettre les accolades et vous avez dû vous demander, pourquoi ${$tab2tab[3]}[1]; est correct et pas $$tab2tab[3][1]; ?
En fait, pour Perl, pour des raisons de priorité entre opérateurs, $tab2tab[3] sera considéré comme une référence, qui n'existe pas. Vous aurez un message d'erreur à l'exécution du script. Si vous utilisez use strict, vous aurez :

Code : Sélectionner tout
Global symbol "$tab2tab" requires explicit package name at .............
Pour Perl, $tab2tab[3] est une référence qui n'existe pas car n'a pas été déclarée. Le fait de mettre des accolades permet clairement d'indiquer que la référence est $tab2tab[3]. Donc soit vous tapez :

Code perl : Sélectionner tout
print ${$tab2tab[3]}[1]; #=> "Stoyak"
ou bien

Code perl : Sélectionner tout
1
2
my $ref4 = $tab2tab[3]; #on déclare bien la référence $ref4 
print $$ref4[1];        #=> "Stoyak" et c'est Ok.
J'espère avoir été clair !!!

Remarque : En général, dès que l'on parle de tableaux à deux dimensions ou plus, il faudra manipuler les références anonymes.

Code perl : Sélectionner tout
1
2
my @tab2tab = ([1,2], ["a","b"],["toto","tete"],["djibril","Stoyak","vous"]); 
print $tab2dimension[3][1];#=> Stoyak
Moyen mnémotechnique pour les tableaux à deux dimensions.

Code perl : Sélectionner tout
@tab2dimension => $tab2dimension[LIGNE][COLONNE]
Explication schématique de @tab2dimension

Code : Sélectionner tout
1
2
3
4
5
6
([1,2], ["a","b"],["toto","tete"],["djibril","Stoyak","vous"]) correspond à  
 
ligne0 -->   1      2      
ligne1 -->   a      b      
ligne2 -->   toto   tete      
ligne3 -->   djibril    Stoyak     vous
Exemple :

$tab2dimension[3][1] correspond à la ligne 3 et colonne 1, donc c'est Stoyak
première ligne => ligne0 et première colonne => colonne 0 (on est dans les tableaux !!!!!!)

Voilà, vous maîtrisez maintenant les références !!! Je vais vous faire un petit résumé ci-dessous avec les pièges à éviter.

Mis à jour le 15 décembre 2005 djibril

Si vous souhaitez savoir si $ref est une référence à un tableau ou un hash, voici une fonction Perl

Code perl : Sélectionner tout
1
2
3
4
my $ref_tableau = \@tableau; 
my $ref_hash    = \%hash; 
print ref $ref_tableau;    # ARRAY 
print ref $ref_hash;       # HASH
Erreurs à éviter : Ne confondez pas $ref{'toto'} et $ref->{'toto'}.

  • $ref{'toto'} correspond à la valeur de la toto d'un hash nommé ref ;
  • $ref->{'toto'} correspond à la valeur d'une référence nommée ref d'un hash.

Prenez pour habitude de donner des noms simples et clairs à vos variables, et de bien commenter vos scripts !

  • Ne pas confondre un tableau (1,2,3) et une référence anonyme à un tableau anonyme [1,2,3] ;
  • Ne pas confondre un hash ("cle" => "valeur") et une référence anonyme à un hash anonyme {"cle" => "valeur"}.


Attention :

Code perl : Sélectionner tout
1
2
3
ma_fonction(@tab1, @tab2); 
ou 
ma_fonction(%hash1, %hash2);
ne fonctionnera pas. Utilisez des références en argument :

Code perl : Sélectionner tout
1
2
3
ma_fonction(\@tab1, \@tab2);  
ou  
ma_fonction(\%hash1, \%hash2);
Si vous souhaitez une documentation plus complète, vous pouvez taper perldoc perlref sous Windows ou man perlref sous Unix/Linux.

Mis à jour le 15 décembre 2005 djibril

Une fermeture est une référence anonyme vers une fonction. Ces références ont des propriétés très intéressantes, comme celle de garder en mémoire des valeurs de variables lexicales devenues hors de portée. Ainsi, en plus de définir les valeurs d'une fonction lors de l'appel, on peut aussi le faire lors de la définition. Un petit exemple :

Code perl : Sélectionner tout
1
2
3
4
5
6
my $ref; 
{ 
	my $var = "Salut"; 
	$ref = sub {return "$var @_";}; 
} 
print $ref->("Larry"); # affiche Salut Larry, alors que $var n'existe plus !
Remarquez que l'on a défini une variable à la définition et une autre à l'appel.
On pourrait aussi passer $var à ferm et retourner $ref à la fin : à chaque appel de ferm on obtiendrait une fermeture (donc une référence vers un sous-programme) qui garderait la valeur de $var utilisée à l'appel de ferm. Cela donnerait ceci :

Code perl : Sélectionner tout
1
2
3
4
5
6
7
8
9
sub ferm { 
  my ($var) = @_; 
  my $ref = sub { return "$var @_"; }; 
  return $ref; 
} 
my $ref = ferm("Salut"); 
  
#plus tard 
print $ref->("Larry");    #affiche Salut Larry

Mis à jour le 22 juillet 2007 Woufeil

En bouclant autour d'une fermeture, on peut créer des fonctions ayant un code semblable mais des noms différents. Le problème est qu'une fermeture n'a pas de nom, mais on peut le contourner : il est en effet possible de lier une référence de code à un nom déjà existant en passant par les typeglobs.
Par exemple, on veut deux fonctions fic1 et fic2 qui écrivent leurs paramètres dans des fichiers qui ont respectivement pour handle FIC1 et FIC2. Les deux fonctions sont très proches, elles ne diffèrent que par le fichier dans lequel écrire. Voilà comment générer ces deux fonctions en bouclant autour d'une fermeture :

Code perl : Sélectionner tout
1
2
3
4
5
6
7
foreach my $champ (qw(fic1 fic2)) 
{ 
	my $handle = uc $champ; # met $champ en majuscule 
	no strict 'refs'; #Autorise les références symboliques 
	*$champ = sub {print $handle "@_";}; # affecte la fermeture en question au typeglob 
} 
fic1("Salut !"); #écrit salut dans FIC1

Mis à jour le 22 juillet 2007 Woufeil

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2017 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

 
Responsable bénévole de la rubrique Perl : djibril -