[PERL] Lire un paragraphe

Lire un paragraphe [PERL] - Perl - Programmation

Marsh Posté le 29-06-2012 à 09:46:11    

Bonjour,
 
Je commence tout juste à programmer en perl et j'aurais besoin d'aide pour lire un fichier a partir d'un pattern jusqu'à la prochaine ligne vide.
Voici mon fichier  
 
HORCM_MON
#ip_address        service         poll(10ms)     timeout(10ms)
Servername            10000                 1000              3000
 
HORCM_CMD
#dev_name               dev_name                dev_name
/dev/rdisk/disk4
 
HORCM_LDEV
#dev_group        dev_name  Serial#     CU:LDEV(LDEV#)     MU#
#[REFRESH]
oradata3          oradata3_001  78741   ce:ec   0
oradata3          oradata3_002  78741   ce:ed   0
oradata3          oradata3_003  78741   ce:ee   0
oradata3          oradata3_004  78741   ce:ef   0
oralog3           oralog3_001   78741   ce:f0   0
 
 
 
HORCM_INST
#dev_group        ip_address      service
oradata3          servername 10000
oralog3           servername  10000
 
 
Le but du jeu c'est de commencer à remplir un tableau à partir du pattern #[REFRESH] jusqu'à la prochaine ligne vide. CAD, récupérer uniquement  ces infos :  
#[REFRESH]
oradata3          oradata3_001  78741   ce:ec   0
oradata3          oradata3_002  78741   ce:ed   0
oradata3          oradata3_003  78741   ce:ee   0
oradata3          oradata3_004  78741   ce:ef   0
oralog3           oralog3_001   78741   ce:f0   0
 
J'arrive bien a stocké mon fichier dans un tableau @lines() le parcourir et match mon pattern par contre apres je suis perdu.  
Le top aussi c'est de conserver dans un variable distinct chaque champ  
ie : $1 =  oradata3
$2 = oradata3_001  
etc etc et j'en passe et des meilleurs....  
     
 
foreach (@lines) {
  if ($_ =~ /#\[\w+\]/) {
         .......
         }
....
}
Merci pour votre aide.
Grulles
 
 
 
 
 
 
 
 

Reply

Marsh Posté le 29-06-2012 à 09:46:11   

Reply

Marsh Posté le 29-06-2012 à 11:13:51    

J'ai du mal à comprendre la nécessité d'avoir une variable par ligne trouvée :??: Pourquoi pas un tableau? C'est quand même plus facile à traiter par la suite, non?


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 29-06-2012 à 11:25:31    

Citation :

Le but du jeu c'est de commencer à remplir un tableau à partir du pattern #[REFRESH] jusqu'à la prochaine ligne vide.


C'est une technique de base:

Code :
  1. #!/usr/local/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. my $file = "pat.txt"; # Je l'ai nommé ainsi pour tester
  6. my $pattern = qr/^#\[REFRESH\]\s*$/;
  7. my $outputflag = 0;
  8.  
  9. open(my $fh, $file) or die "can't openfile $file: $!";
  10.  
  11. while (<$fh> ) {
  12.  $outputflag  = ($outputflag && (/\S/)) || (/$pattern/);
  13.  print if ($outputflag);
  14.  # ou if ($outputflag) {...} si on veut faire des
  15.  # choses plus complexes dans le bloc de lignes à traiter
  16. }
  17.  
  18. close $fh;


On positionne un flag qui indique si on doit imprimer la ligne lue en sortie ou non.
 
On met le flag a zéro au départ,  
on met le flag a 1 si on trouve le pattern $outputflag  = ... || (/$pattern/);
on remet le flag a 0 s'il est a 1 et qu'on trouve une ligne vide $outputflag  = ($outputflag && (/\S/)) ... ;
Et on met le tout sur une seule ligne pour avoir une évaluation relativement optimisée: $outputflag  = ($outputflag && (/\S/)) || (/$pattern/);
 
Note: on peut gagner un peu si l'on est certain de ne rencontrer qu'une seule fois une zone intéressante par fichier, en arrêtant la lecture du fichier après avoir rencontré la fin du bloc de lignes à traiter.  
 
A+,


Message édité par gilou le 29-06-2012 à 11:30:45

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

Marsh Posté le 29-06-2012 à 11:59:48    

rufo a écrit :

J'ai du mal à comprendre la nécessité d'avoir une variable par ligne trouvée :??: Pourquoi pas un tableau? C'est quand même plus facile à traiter par la suite, non?

C'est clair que ça devrait être un tableau de hashes.
A+,


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

Marsh Posté le 29-06-2012 à 12:23:46    

Messieurs,  
@Rafo : Je ne comprends pas ce qui te gène. Je récupére ce fichier, que je stock dans un tableau, je parcours et je veux juste récupérer les champs.  
 
@gilou : Merci pour ta réponse. Nickel chrome .  
 
Pour info j'ai 2 autres pattern mais bon avec ton exemple, je peux me débrouiller.  
Je pense créer deux autres boucles. tu en penses quoi ?  
un truc comme ça  
my $REFRESHpattern = qr/^#\[REFRESH\]/;
 my $ZDBpattern = qr/^#\[ZDB\]\s*$/;
 my $BCpattern = qr/^#\[BC\]\s*$/;
 
Puis ce bout de code répété 3 fois (je remplace pattern par la bonne variable ;-))
foreach (@lines){
   $outputflag  = ($outputflag && (/\S/)) || (/$pattern/);
  print  if ($outputflag);
 

Reply

Marsh Posté le 29-06-2012 à 12:57:46    

Tu peux aussi faire  
my $pattern = qr/^#\[(REFRESH|ZDB|BC)\]\s*$/;  
 
A+,


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

Marsh Posté le 29-06-2012 à 13:08:35    

grulles a écrit :

Messieurs,  
@Rafo : Je ne comprends pas ce qui te gène. Je récupére ce fichier, que je stock dans un tableau, je parcours et je veux juste récupérer les champs.  
 
[...]
 


En relisant ton 1er post, je m'aperçois que j'avais pas bien compris. Moi, j'avais compris que tu voulais une variable par ligne alors qu'en fait, tu voulais,  une variable pour chaque champ qui compose la ligne en cours de lecture. Cela dit, tu peux tout à fait rester sur un tableau associatif, une ligne dans le tableau = une ligne de ton fichier et tu associe à chaque ligne de ton tableau, un autre tableau dont les données correspondent à tes champs de la ligne
Ex :

Code :
  1. $Lignes = array(
  2.                      array("ch1" => "...", "ch2" => "....", ...),
  3.                      array("ch1" => "...", "ch2" => "....", ...),
  4.                      ...
  5.                    )


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 29-06-2012 à 13:59:26    

gilou a écrit :

C'est clair que ça devrait être un tableau de hashes.


Exemple:

Code :
  1. #!/usr/local/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. my $file = "pat.txt"; # Je l'ai nommé ainsi pour tester
  6. my $pattern = qr/^#\[REFRESH\]\s*$/;
  7. my $outputflag = 0;
  8. my @ligne = ();
  9. my @fields;
  10.  
  11. open(my $fh, $file) or die "can't openfile $file: $!";
  12.  
  13. while (<$fh> ) {
  14.  $outputflag  = ($outputflag && (/\S/)) || (/$pattern/);
  15.  if ($outputflag) {
  16.    print;
  17.    chop;
  18.    @fields = split /\s+/;
  19.    next if (@fields != 5);
  20.    push @ligne, { "dev_group"       => $fields[0],
  21.           "dev_name"        => $fields[1],
  22.           "Serial#"         => $fields[2],
  23.           "CU:LDEV(LDEV#)"  => $fields[3],
  24.           "MU#"             => $fields[4],
  25.         };
  26.  }
  27. }
  28.  
  29. close $fh;
  30.  
  31. # visualisons ce que @ligne contient maintenant
  32. print "\nDump Contenu Tableau ligne:\n";
  33. use Data::Dumper;
  34. print Dumper(@ligne);


C:\Perl>perl pat.pl
#[REFRESH]
oradata3          oradata3_001  78741   ce:ec   0
oradata3          oradata3_002  78741   ce:ed   0
oradata3          oradata3_003  78741   ce:ee   0
oradata3          oradata3_004  78741   ce:ef   0
oralog3           oralog3_001   78741   ce:f0   0
 
Dump Contenu Tableau ligne:
$VAR1 = {
          'dev_name' => 'oradata3_001',
          'Serial#' => '78741',
          'CU:LDEV(LDEV#)' => 'ce:ec',
          'dev_group' => 'oradata3',
          'MU#' => '0'
        };
$VAR2 = {
          'dev_name' => 'oradata3_002',
          'Serial#' => '78741',
          'CU:LDEV(LDEV#)' => 'ce:ed',
          'dev_group' => 'oradata3',
          'MU#' => '0'
        };
$VAR3 = {
          'dev_name' => 'oradata3_003',
          'Serial#' => '78741',
          'CU:LDEV(LDEV#)' => 'ce:ee',
          'dev_group' => 'oradata3',
          'MU#' => '0'
        };
$VAR4 = {
          'dev_name' => 'oradata3_004',
          'Serial#' => '78741',
          'CU:LDEV(LDEV#)' => 'ce:ef',
          'dev_group' => 'oradata3',
          'MU#' => '0'
        };
$VAR5 = {
          'dev_name' => 'oralog3_001',
          'Serial#' => '78741',
          'CU:LDEV(LDEV#)' => 'ce:f0',
          'dev_group' => 'oralog3',
          'MU#' => '0'
        };


ou $VAR1 est $ligne[0], etc.
A+,


Message édité par gilou le 29-06-2012 à 14:09:29

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

Marsh Posté le 29-06-2012 à 16:11:29    

@Gilou  : Magnifique!!!

Reply

Sujets relatifs:

Leave a Replay

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