comment générer des tableaux en perl

comment générer des tableaux en perl - Perl - Programmation

Marsh Posté le 21-09-2009 à 16:20:11    

Bonjour,
 
Je fais pas mal de script en perl actuellement et j'ai, jusqu'à présent, toujours trouvé des réponses à mes problèmes sur le web. Mais là, je ne sais vraiment pas comment faire.
 
Voici le problème : je récupère une liste de nom de société dans un fichier que je place dans un tableau puis je récupère le nombre de société avec le nombre d'élément du tableau. Pour chaque société, je crée un tableau à 2 dimensions pour y stocker plusieurs informations (rapport d'incident : adresse ip, site ou à eu lieu l'attaque...) que je n'arrive pas à automatiser. Enfin, je crée une table de hachage de tableau avec pour clés, le nom des sociétés et pour valeurs, les tableaux de données associés.  
 
Le problème est de réussir à générer plusieurs tableaux à partir d'une variable. Imaginons que j'ai dans mon fichier 13 sociétés, il faut que je crée 13 tableaux différents. Est-il possible de réaliser cela au sein d'une boucle for en perl ?  
 
# récupération des noms de société dans le fichier (plusieurs information sur la ligne du fichier). Il y a, en général, plusieurs fois le même nom de société  
my @liste;
my $l = 0;
my $before = "";
while (defined($ligne = <FICHIER> ))
{
 my @tmp = split (/;/,$ligne);
 if ($before ne $tmp[3])
 {
 $liste[$l] = $tmp[3];  
 $before = $liste[$l];
 $l++;
 }
}
 
my $element = @liste;
 
 
Suite à ça, j'aimerai pouvoir créer un nombre de tableau équivalent à $element. Quelqu'un aurait-il une idée ?
 
Merci d'avance.

Reply

Marsh Posté le 21-09-2009 à 16:20:11   

Reply

Marsh Posté le 22-09-2009 à 13:40:18    

C'est bien sur tout a fait possible, mais bon, ce que tu fais la est assez douteux

Code :
  1. while (defined($ligne = <FICHIER> ))
  2. {
  3. my @tmp = split (/;/,$ligne);
  4. if ($before ne $tmp[3])
  5. {
  6. $liste[$l] = $tmp[3];  
  7. $before = $liste[$l];
  8. $l++;
  9. }
  10. }


a aucun moment, tu ne colles @tmp dans @liste, donc liste au mieux, ici, ca va etre un tableau des $tmp[3] successifs
Et d'autre part, en perl, on ne fait pas  
$liste[$l] = $tmp[3];  
...
$l++;
pour ajouter des éléments a une liste. On fait simplement
push @liste, $tmp[3];
 
Bon, essayes d'expliquer clairement ce que tu veux faire, en particulier pourquoi tu fais le test if ($before ne $tmp[3]) (il y a des lignes dupliquées dans tes données ou quoi?), et on pourra t'aider.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 22-09-2009 à 14:31:07    

Merci.
 
Cette partie là du programme fonctionne correctement. Ca marche très bien en faisant $liste[$l] = $tmp[3]; mais c'est vrai que ce n'est certainement pas la meilleure façon de l'écrire. J'ai donc opté pour la fonction push, je ne savais pas que ca pouvait s'écrire comme cela.
 
J'ai un fichier qui possède sur chaque ligne des informations spécifiques à une société (adresse ip, nom societe, AS number, ...). Le nom de société se trouve à la 3ème place dans mon fichier. C'est regroupé par société, par exemple, les trois premières lignes auront le même nom de société, la deuxième société aura les 5 prochaines lignes etc... Je récupère ce nom sur chaque ligne et je le veux qu'une seule fois d'où l'utilisation de $before ainsi que le test. par contre, je veux associé au nom de société les lignes du fichier correspondantes. J'insère ensuite chaque nom de société dans un hash avec un tableau en valeur.
 
ex de ligne du fichier :
  X.X.X.X;Belgium;ASXX;Société;http://www.siteinternet.com
  X.X.X.X;Belgium;ASXX;Société;http://www.siteinternet.com
  X.X.X.X;France;ASXX;Société;http://www.siteinternet.com
  ...
 
Je travaille toujours dans le même fichier, je l'ouvre une première fois pour récupérer les noms de sociétés que je mets dans un tableau (@liste) puis je le parcours à nouveau plusieurs fois pour faire les tests sur les sociétés afin d'associer dans le hash la societe avec les bonnes informations.
 
J'ai changé quelque truc et voilà une bonne partie du code :  
 
open(FICHIER, "$nom1.Geo" ) || die "Impossible d'ouvrir le fichier $nom1 :$!";
 
my $l = 0;
my $before = "";
while (defined($ligne = <FICHIER> ))
{
 my @tmp = split (/;/,$ligne);
 if ($before ne $tmp[3])
 {
 #$liste[$l] = $tmp[3];  
 push @liste, $tmp[3];  
 $before = $liste[$l];
 $l++;
 }
}
 
print "@liste";
 
close (FICHIER);
 
my $element = @liste;
print "Element = $element\n";
 
open(FICHIER, "$nom1.Geo" ) || die "Impossible d'ouvrir le fichier $nom1 :$!";
 
for ($l=0;$l<=$element;$l++)
{
while (defined($ligne = <FICHIER> ))
{
 @test= split (/;/,$ligne);
 my $nb_elt = @test;
   
 if ( $test[3] eq $liste[$l])
 {
 $tab[$i][$nb_elt+1]=$nb_elt;
 for ($j=0;$j<=$nb_elt;$j++){
  $tab[$i][$j] = $test[$j];
 }
 $i++;
 }
 
}
my $atab;
 
for $atab ( @tab ) {
      print "\n[ @$atab ],\n";      
  }
 
%h = (
 "$liste[$l]" => [@tab]
     );
 
@tab = ();
}
 
C'est un peu tordu certes, mais je n'ai pas trouvé plus simple pour être sur de créer un tableau avec les informations correspondant bien à une société (allant de 1 à plusieurs lignes dans le fichier, c'est pour ca que j'utilise un tableau à 2 dimensions). Mais ca fonctionne pas parfaitement, il ne fait la boucle for qu'une seule fois, il affiche le tableau résultant de l'analyse de la première société.
 
De plus, forcément je référence un tableau que je vide apres pour y mettre les nouvelles informations mais je ne sais pas comment envoyer mon tableau @tab de la structure conditionnelle dans le hash sans l'écraser ensuite... est ce possible avec des références ?
 
Et je me dis aussi que dans ma boucle for, je parcours le fichier mais je ne retourne pas en début de fichier à la fin du while. Est ce que ca se fait automatiquement ?
 
Ce que je veux au final, c'est associer dans un hash, chaque nom de société avec un tableau à 2 dimensions correspondant aux informations de la société.
 
J'espère que j'ai étais plus clair...


Message édité par manuche59 le 22-09-2009 à 14:59:10
Reply

Marsh Posté le 23-09-2009 à 01:42:07    

Bon, je ne suis pas sur que ça corresponde a 100% a vos besoins, mais vous pouvez vous inspirer d'une structure de données comme suit:

Code :
  1. #/usr/bin/perl
  2.  
  3. open(FICHIER, "sampledata.txt" ) || die "Impossible d'ouvrir le fichier $nom1 :$!";
  4.  
  5. my %h;
  6. while (defined($ligne = <FICHIER> )) {
  7.    chomp $ligne;
  8.    my @tmp = split (/;/, $ligne);
  9.    if (!defined($h{$tmp[3]})) {
  10.        $h{$tmp[3]} = [];
  11.    }
  12.    push @{$h{$tmp[3]}}, [@tmp];
  13. }
  14.  
  15. close (FICHIER);
  16.  
  17. my ($societe, $infos, $data);
  18. for $societe (keys %h) {
  19.    for $infos (@{$h{$societe}}) {
  20.        print "[ ";
  21.        for $data (@{$infos}) {
  22.            print $data, " ";
  23.        }
  24.        print "]\n";
  25.    }
  26. }


 
chomp $ligne; ##je vire le \n final
     
if (!defined($h{$tmp[3]})) { ## si on n'a pas encore le nom de la société comme clé du hash
        $h{$tmp[3]} = [];      ## on crée une entrée avec le nom de la société comme clé du hash
                                       ## et comme valeur, une référence a un tableau anonyme vide
    }
push @{$h{$tmp[3]}}, [@tmp]; ## on ajoute au tableau anonyme, référencée par la valeur de l'entrée du hash une reference au tableau @tmp
                                             ## on aurait pu écrire push @{$h{$tmp[3]}}, \@tmp;
 
donc ici, tu as une structure de hash, ou chaque entrée est de la forme:
 
"clé" => [ [..,..,..],
              ..........
              [..,..,..] ]
et chaque ligne du tableau correspond a une ligne lue en entrée.
 
après, pour exploiter, c'est juste une question d'écriture:
$h{$societe} est une référence a un tableau (dont les éléments sont des références a des tableaux). Le tableau référé est donc @{$h{$societe}}.
 
J'aurais pu écrire la partie qui imprime avec une syntaxe plus proche de celle des tableaux:

Code :
  1. for $societe (keys %h) {
  2.    for ($infos=0; $infos < scalar(@{$h{$societe}}); $infos++) {
  3.        print "[ ";
  4.        for ($data=0; $data < scalar(@{${$h{$societe}}[$infos]}) ; $data++) {
  5.            print ${${$h{$societe}}[$infos]}[$data], " ";
  6.        }
  7.        print "]\n";
  8.    }
  9. }


ou  

Code :
  1. for $societe (keys %h) {
  2.    for ($infos=0; $infos < scalar(@{$h{$societe}}); $infos++) {
  3.        print "[ ";
  4.        for ($data=0; $data < scalar(@{${$h{$societe}}[$infos]}) ; $data++) {
  5.            print ${$h{$societe}}[$infos][$data], " ";
  6.        }
  7.        print "]\n";
  8.    }
  9. }


Noter que ce code
1) marche avec un fichier de départ dont les lignes ne sont pas nécessairement triées par sociétés
2) marche avec un fichier de départ dont les lignes n'ont pas nécessairement le même nombre de champs après celui de la société
En hopant que ça helpe...
A+,


Message édité par gilou le 23-09-2009 à 02:12:06

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 23-09-2009 à 09:35:00    

Ok merci. J'ai testé et c'est parfait :) J'ai bien le nom de la société en clé du Hash ayant pour valeur un tableau qui contient les informations correspondantes :)
 
Merci beaucoup, ça faisait un moment que je coinçais dessus et je me mélangeais les pinceaux ! J'ai à peu près tout compris. J'ai encore un peu de mal avec les références. Je vais bien relire tout ça :)
 
C'est la première fois que je poste sur un forum et je ne regrette pas !
 
Encore une fois, merci !

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed