Pb perl

Pb perl - Perl - Programmation

Marsh Posté le 28-04-2004 à 12:23:11    

Bonjour a tous
 
je suis en stage et je doit créer un logiciel en perl.
Donc je me suis mis au perl.
Et j'ai un petit pb.
 
En effet je doit extraire des donné d'un fichier mais voila il faut que je  parcours le fichier bcp de fois.
je m'explique:
 
voici un bout du fichier a parcourir:
 
 
---------------------------------------------------------------------------------------
|               voici les mesures pour le switch switch-V1-1                     |
---------------------------------------------------------------------------------------
 
  Adresse Mac: 000xxxxxxxxx  ;  Switch: switch-V1-1  ;  Vlan: 1  ;  Port: 48  ;  Description:  lien giga<=> switch-C-1  
  Adresse Mac: 000xxxxxxxxx  ;  Switch: switch-V1-1  ;  Vlan: 1  ;  Port: 48  ;  Description:  lien giga<=> switch-C-1  
  Adresse Mac: 000xxxxxxxxx  ;  Switch: switch-V1-1  ;  Vlan: 1  ;  Port: 48  ;  Description:  lien giga<=> switch-C-1  
 
 
C un fichier qui regroupe par switch toutes les @mac et leur port de tous le parc informatique.~700 machines
 
moi il faut que fasse un petit prog qui compte le nombre de machine derriere chaque port de chaque switch.
 
Pour ce faire je creé deux boucle une pour les switch et l'autre pour les ports mais avec cette technique le tps est bcp trop long.
 
Quelqu'un aurai une idée?
 
 
merci
 

Reply

Marsh Posté le 28-04-2004 à 12:23:11   

Reply

Marsh Posté le 28-04-2004 à 12:59:58    

super titre
 
je comprens pas quand tu lis une ligne tu récupères l'adresse MAC et le port direct ..
 

Reply

Marsh Posté le 28-04-2004 à 13:08:01    

une bonne regex, tu récuperes tout dans un tableau, tu tries après...

Reply

Marsh Posté le 28-04-2004 à 13:49:35    

Le truc c que je lis chaque ligne du fichier.
Une fois la ligne ds une variable je regarde le nom du switch puis le port. Si cela correspond j'incrémente un compteur.
Je repete cette opération pour toutes les ligne du fichier et pour tous ports de tous les switchs.
 
Pour etre plus explicite je vous donne un bout de code que j'execute
 
open(ECRIRE,"$chemin_rapport_ecriture/machines_par_port_de_switch" );
 
 $machine_total_reseau=0; #permet de connaitre le nombre total de machine sur le réseau
   
 foreach $switch (@switches_trouve)  
 {  
  printf ECRIRE ("Switch $switch\n" );
   
  for ($j=1 ; $j<51 ; $j++)  
  {
   printf ECRIRE ("$j " );  
  }
  printf ECRIRE (" Total " );
  printf ECRIRE (" \n" );
  $Nb_machines=0;  #permet de connaitre le nombre de machines par switch
   
  $i=1;
  for($i=1 ; $i<51 ; $i++) #pour chaque port
  {
   $Nb_machine=0;
   open(LIRE,"$chemin_rapport_lecture/rapport_tous_Switchs.txt" );
   while(<LIRE> )  
   {
    @mots=split(";",$_);
     
    if ($mots[1] eq "  Switch: $switch  " && $mots[3] eq "  Port: $i  " )
    {
     $Nb_machine++;  
    }    
   }
   close LIRE;  
   printf ECRIRE ("$Nb_machine  " );  
   $Nb_machines = $Nb_machines + $Nb_machine;  
 
  }
  printf ECRIRE (" $Nb_machines " );
  printf ECRIRE (" \n\n" );
   
  $machine_total_reseau = $machine_total_reseau + $Nb_machines;
 }
 printf ECRIRE ("Le nombre de machines sur le réseau est de $machine_total_reseau" );
 close ECRIRE;
 
 
 
voila

Reply

Marsh Posté le 28-04-2004 à 14:09:05    

t'as combien de lignes dans ton fichier à peu près?

Reply

Marsh Posté le 28-04-2004 à 14:28:37    

sa varie suivant les switch qui peuvent etre connecté au réseaux. actuellement j'en ai 1000 (4switch) mais il plus tard il y aura encore 5 switch de plus.

Reply

Marsh Posté le 28-04-2004 à 14:36:47    

Si je comprend bien, tu as une ligne sous cette forme :

Code :
  1. Adresse Mac: 000xxxxxxxxx  ;  Switch: switch-V1-1  ;  Vlan: 1  ;  Port: 48  ;  Description:  lien giga<=> switch-C-1


 
Et tu veux récupérer "switch-V1-1" et "48" ?
 
A tester :

Code :
  1. use strict;
  2. my %liste;
  3. ... ... ...
  4. while(<MON_FICHIER> )
  5. {
  6.     if (/.+Switch: (.+) +; +Vlan.+Port: (\d+).+/)
  7.     {
  8.         ++$liste{$1}{SWITCH};
  9.         ++$liste{$1}{PORT$2};
  10.     }
  11.     else
  12.     {
  13.         print "ligne $. non topée\n";
  14.     }
  15. }


Je précise tout de suite : ma RegExp est à affiner !
 
Dans %liste, chaque switch est une clé, laquelle est un hash de hash qui contient une clé "SWITCH" qui compte le nombre de fois où une ligne a été topée concernant le-dit switch, et d'autres clés "PORTn°" où n° est le n° du port trouvé (les clés comptent le nbre de fois que le port en question est rattaché au switch).
 
Je m'explique pas super bien  :D mais pour faire un peu plus clair :
 

Code :
  1. $liste{switch-V1-1}{SWITCH} vaut 1 après avoir lu la 1ère ligne
  2. $liste{switch-V1-1}{PORT48} vaut également 1


 
Désolé si je ne suis pas assez clair :whistle:


---------------
Samsung Galaxy S1 -> Samsung Galaxy S2 -> Samsung Note 2 -> Huawei Ascend Mate 7 -> ZTE Axon 7 -> OnePlus 6T -> Oppo Find X2 PRO -> Google Pixel 9 PRO XL
Reply

Marsh Posté le 28-04-2004 à 14:47:18    

essaye un truc comme ça:

Code :
  1. #!/usr/bin/perl -w
  2. use strict;
  3.     my $key;
  4.     my %nbComp;
  5.     my $filename = "test.txt";
  6.     open(SOURCE, $filename) || die "Impossible d'ouvrir le fichier $filename" ;
  7.     my $content = join "", <SOURCE>;
  8.     close(SOURCE);
  9.     ### looking for each switch
  10.     my @switch = ( $content =~ /Adresse Mac:(.*?);  Switch:(.*?);  Vlan:(.*?);  Port:(.*?);/gs );
  11.     for ( my $i=0; $i<=$#switch-3; $i+=4)
  12.     {
  13.        ### building key as : Switch name|Adresse Mac|port
  14.        $key = $switch[$i+1]."|".$switch[$i]."|".$switch[$i+3];
  15.        ### removing useless space
  16.        $key =~ s/\s//g;
  17.        ### starting or increasing count of line with this key
  18.        if ( !exists $nbComp{$key}){ $nbComp{$key}=1;}
  19.         else{$nbComp{$key}++;}
  20.     }
  21. exit;


 
[edit] grillé de 11 minutes je trouve ça bogosse, en meme temps ma fenetre était passée en arriere plan :p
alors par rapport à la solution de aricoh avec la mienne tu as une hash avec le nombre de lignes trouvées pour chaque triplet switch|mac|port
[/edit]


Message édité par anapajari le 28-04-2004 à 14:50:10
Reply

Marsh Posté le 28-04-2004 à 14:53:01    

Pouurais -tu m'expliquer cette ligne stp:
 
 if (/.+Switch: (.+) +; +Vlan.+Port: (\d+).+/);
 
 
Que vien faire le Vlan ici que signifie ces + ce .+/ et ce /. ?
Mer'ci beaucoup

Reply

Marsh Posté le 28-04-2004 à 14:59:49    

loothoof a écrit :

Pouurais -tu m'expliquer cette ligne stp:
 
 if (/.+Switch: (.+) +; +Vlan.+Port: (\d+).+/);
 
Que vien faire le Vlan ici que signifie ces + ce .+/ et ce /. ?
Mer'ci beaucoup

Ceci est une expression régulière.
 
Pour résumer rapidos : ".+" signifie "tout caractère autre que \n, au moins 1 fois"
 
Exemple : " +" signifie "1 ou plusieurs espaces"
 
Ce que j'ai indiqué entre parenthèses, c'est ce que mon expression régulière doit mémoriser et retourner dans $1 et $2 qui sont des variables dédiées aux expressions régulières ($1, $2, $3 et toutes celles dont tu as besoin en fait).


---------------
Samsung Galaxy S1 -> Samsung Galaxy S2 -> Samsung Note 2 -> Huawei Ascend Mate 7 -> ZTE Axon 7 -> OnePlus 6T -> Oppo Find X2 PRO -> Google Pixel 9 PRO XL
Reply

Marsh Posté le 28-04-2004 à 14:59:49   

Reply

Marsh Posté le 28-04-2004 à 15:01:51    

oups pardon, pour "\d+", ça signifie "1 ou plusieurs nombres"


---------------
Samsung Galaxy S1 -> Samsung Galaxy S2 -> Samsung Note 2 -> Huawei Ascend Mate 7 -> ZTE Axon 7 -> OnePlus 6T -> Oppo Find X2 PRO -> Google Pixel 9 PRO XL
Reply

Marsh Posté le 28-04-2004 à 15:04:18    

Excuse moi anapajari mais peut tu me commenter ton programme stp car je ne comprend pas grand chose.
Putain plus je découvre le perl et plus je me dit qu'il y en a  a découvrir.

Reply

Marsh Posté le 28-04-2004 à 15:09:08    

des commentaire il en a mis partout!!!

Reply

Marsh Posté le 28-04-2004 à 15:10:19    

pour les expression reguliere tappe ca dans un shell:
"perdoc perlre"

Reply

Marsh Posté le 28-04-2004 à 15:12:06    

Je reprend mon bout de code pour en faire un truc + simple (à toi de voir)  :)  
 

Code :
  1. while(<MON_FICHIER> )
  2.   {
  3.         s/ //g;        # je vire tous les espaces de la ligne
  4.         if (/Switch:(.+);Vlan.+Port:(\d+);/i)
  5.         {
  6.               ++$liste{$1}{SWITCH};
  7.               ++$liste{$1}{PORT$2};
  8.         }
  9.         else
  10.         {
  11.               print "ligne $. non topée\n";
  12.         }
  13.   }


Voilà. A moins que tu aies besoin de conserver chaque ligne du fichier intacte en mémoire pour un autre traitement, sinon je supprime tous les espaces de la ligne.


Message édité par Aricoh le 28-04-2004 à 15:12:35

---------------
Samsung Galaxy S1 -> Samsung Galaxy S2 -> Samsung Note 2 -> Huawei Ascend Mate 7 -> ZTE Axon 7 -> OnePlus 6T -> Oppo Find X2 PRO -> Google Pixel 9 PRO XL
Reply

Marsh Posté le 28-04-2004 à 16:48:13    

qd j'utilise une variable du type hachage voila l'erreur:
Can't use subscript on private hash at Recup_Nb_machines_par_port.pl line 40, near "$1}"
(Did you mean $ or @ instead of %?)
 
qui connait?

Reply

Marsh Posté le 28-04-2004 à 17:13:03    

ça te dit pas de montrer ton code ... au moins la ligne 40 ...

Reply

Marsh Posté le 29-04-2004 à 10:03:26    

Voici mon code  
 
 
#!/bin/perl        
use Tk;
require "mesure_parc.pl";
require "mesure.pl";
require "chemins.pl";
 
 
# Recuperation du nombre de machines par port de switch
#-------------------------------------------------------
sub Recup_Nb_machines_par_port
{  
 # récupération des switchs présent sur le réseaux
 system("ypcat hosts | grep switch > liste_switch.txt" );
 open (SNMP, "<liste_switch.txt" )  || die "Impossible d'ouvrir liste_switch.txt";
 while (<SNMP> )
 {
  # permet de ne recuperer que les noms des switch
  @champ=split(/fr/,$_);
  @champ2=split(/ /,$champ[1]);
  @champ3=split(/\t/,$champ2[1]);
  @champ4=split(/\n/,$champ3[0]);
  push(@switches_trouve,$champ4[0]);  
 }
 close SNMP;
 system("rm liste_switch.txt" );
 
 
 open(LIRE,"$chemin_rapport_lecture/rapport_tous_Switchs.txt" );
 use strict;
 
   
  while(<LIRE> )
   {
         if (/.+Switch: (.+) +; +Port: (\d+).+/)
         {
          %liste{$1}[$2]++;   #ligne ou se trouve le pb
         }
         else
         {
   print "ligne $. non topée\n";
         }
   }  
 
 printf %liste;
}
 
Le pb se trouve a la ligne 36  
et voici l'erreur:


Reply

Marsh Posté le 29-04-2004 à 10:06:15    

Global symbol "%liste" requires explicit package name at Recup_Nb_machines_par_port.pl line 36.
Can't use subscript on hash deref at Recup_Nb_machines_par_port.pl line 36, near "$1}"
(Did you mean $ or @ instead of %?)
 
 
Si je rajoute use strict alors j'ai un pb pour toute les variables du type scalaire($)
 
qui peut m'éclaircir l'esprit?
merci.

Reply

Marsh Posté le 29-04-2004 à 10:13:08    

les balises cpp c'est bien!!!!
 
ensuite  

Code :
  1. ### tu as écrit
  2.   %liste{$1}[$2]++;
  3. ### Aricoh avait écrit
  4.   ++$liste{$1}{SWITCH};


Tu vois la différence?
 
par ailleurs toute cette partie ne sert plus à rien:

Code :
  1. # récupération des switchs présent sur le réseaux
  2. system("ypcat hosts | grep switch > liste_switch.txt" );
  3. open (SNMP, "<liste_switch.txt" )  || die "Impossible d'ouvrir liste_switch.txt";
  4. while (<SNMP> )
  5. {
  6.   # permet de ne recuperer que les noms des switch
  7.   @champ=split(/fr/,$_);
  8.   @champ2=split(/ /,$champ[1]);
  9.   @champ3=split(/\t/,$champ2[1]);
  10.   @champ4=split(/\n/,$champ3[0]);
  11.   push(@switches_trouve,$champ4[0]); 
  12. }
  13. close SNMP;
  14. system("rm liste_switch.txt


tu peux l'enlever.
 
enfin tu as modifié la regex et c'est n'imp:

Code :
  1. /.+Switch: (.+) +; +Port: (\d+).+/
  2. ### doit etre remplacee par celle la qui suffit amplement
  3. /Switch: (.+);.*Port: (\d+);/


 
edit: et pour le use strict, il va falloir apprendre à déclarer tes variables.


Message édité par anapajari le 29-04-2004 à 10:14:35
Reply

Marsh Posté le 29-04-2004 à 12:09:18    

Merci les gars sa marche a présent. il me reste plus qu'a exposer mes données pour que ce soit plus convivial
merci bcp

Reply

Marsh Posté le 29-04-2004 à 14:20:18    

Une dernière chose, remplace :

Code :
  1. system("rm liste_switch.txt" );


par  

Code :
  1. unlink("liste_switch.txt" ) or warn("pb suppression fichier : $!\n" );


Eh oui, la commande rm a sa copine en Perl qui fait aussi la même chose, c'est la fonction unlink  :)


---------------
Samsung Galaxy S1 -> Samsung Galaxy S2 -> Samsung Note 2 -> Huawei Ascend Mate 7 -> ZTE Axon 7 -> OnePlus 6T -> Oppo Find X2 PRO -> Google Pixel 9 PRO XL
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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