[Perl] parcourir un fichier à partir d'une certaine ligne

parcourir un fichier à partir d'une certaine ligne [Perl] - Perl - Programmation

Marsh Posté le 17-03-2004 à 10:47:07    

Salut,
 
j'utilise awstats, un magnifique outil d'analyse de logs tout écrit en perl et qui accepte des plugins.
 
Il existe un plugin (rawlog) qui permet d'afficher et de filtrer les logs, mais celui-ci ne fonctionne pas d'une façon très pratique je trouve, il permet de travailler sur les n premières lignes du fichier de log, et moi je travaille en général plutôt sur les n dernières lignes (ça me parait logique, m'enfin bref) :D
 
je cherche donc à le customiser légèrement pour qu'il ne renvoi pas les n premières lignes mais les n dernières.
 
 
voici le code original :
 

Code :
  1. # Precompiled regex Filter to speed up scan
  2.         if ($Filter) { $Filter=qr/$Filter/i; }
  3.         print "<hr />\n";
  4.         # Show raws
  5.         open(LOG,"$LogFile" ) || error("Couldn't open server log file \"$LogFile\" : $!" );
  6.         binmode LOG;    # Avoid premature EOF due to log files corrupted with \cZ or bin chars
  7.         my $i=0;
  8.         while (<LOG> ) {
  9.                 chomp $_; $_ =~ s/\r//;
  10.                 if ($Filter && $_ !~ /$Filter/o) { next; }
  11.                 print "$_<br />\n";
  12.                 if (++$i > $MAXLINE) { last; }
  13.         }
  14.         print "<br>\n<b>$i lines.</b><br />";
  15.         return 1;


 
 
et voici mon code modifié :
 

Code :
  1. # Precompiled regex Filter to speed up scan
  2.         if ($Filter) { $Filter=qr/$Filter/i; }
  3.         print "<hr />\n";
  4.         # Show raws
  5.         open(LOG,"$LogFile" ) || error("Couldn't open server log file \"$LogFile\" : $!" );
  6.         binmode LOG;    # Avoid premature EOF due to log files corrupted with \cZ or bin chars
  7.         my $i=0;
  8.         seek(LOG,-$MAXLINE,2);
  9.         while (<LOG> ) {
  10.                 chomp $_; $_ =~ s/\r//;
  11.                 if ($Filter && $_ !~ /$Filter/o) { next; }
  12.                 print "$_<br />\n";
  13.                 if (++$i > $MAXLINE) { last; }
  14.         }
  15.         print "<br>\n<b>$i lines.</b><br />";
  16.         return 1;


 
 
 
dans les deux cas, $MAXLINE vaut 5000, mais avec ma modif (j'ai juste ajouté un seek), ça ne renvoi que 30 lignes :(
 
pourquoi?


Message édité par duch le 17-03-2004 à 10:48:03
Reply

Marsh Posté le 17-03-2004 à 10:47:07   

Reply

Marsh Posté le 17-03-2004 à 10:58:19    

je viens de constater que la première ligne de ma sortie était tronquée. Voici mes 2 premières lignes :
 

/xxx.html HTTP/1.0" 200 8 "http://www.xxx.com/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
218.113.208.97 - - [17/Mar/2004:10:28:03 +0100] "GET /_media/img_1189_300x300_95.jpg HTTP/1.1" 200 76304 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"


 
 
comme vous pouvez le constater la première ligne ne commence pas par l'IP mais par l'URL. Pire, ce n'est pas systématique, elle est parfois tronquée à un autre endroit...
 
 
et puis ça n'affiche pas toujours 30 lignes, c'est selon, en ce moment il affiche 27 lignes...


Message édité par duch le 17-03-2004 à 11:02:13
Reply

Marsh Posté le 17-03-2004 à 11:05:17    

maxline = octects

Reply

Marsh Posté le 17-03-2004 à 11:06:52    

merci de ta réponse, je venais de constater que ma sortie faisait exactement 5000 caractères
 
comment faire donc pour sélectionner les 5000 dernières lignes (au lieu des 5000 derniers octets)?


Message édité par duch le 17-03-2004 à 11:07:16
Reply

Marsh Posté le 17-03-2004 à 11:08:12    

seek va reculer dans ton fichier du nombre de caractere que tu va lui indiquer, mais la ce qui t'interesse ce sont des lignes. Et comme les lignes ne font pas toute la meme taille tu ne peux pas proceder comme ca.
 
Voila ce qu'il te faut:
http://search.cpan.org/~uri/File-R [...] ckwards.pm

Reply

Marsh Posté le 17-03-2004 à 11:11:24    

merci pospos, mais ça va lire le fichier à l'envers ce truc, non?

Reply

Marsh Posté le 17-03-2004 à 11:14:14    

tu veux lire un certain nombre de ligne depuis al fin du fichier non?
apres si tu les veux dans l'ordre de la plus ancienne à la plus recente, tu n'aura qu'a retourner la liste que ce module te renverra:
@lignes = reverse @lignes;

Reply

Marsh Posté le 17-03-2004 à 11:15:45    

bon sinon, j'ai une solution (pas clean, mais light :D)
 
mes lignes faisant toujours environ 200 octets, il me suffit de faire un seek(LOG,-$MAXLINE*200,2); :D
 
 
la soluce du plugin me semble bonne, mais dans mon cas, celle-ci sera ss doute plus light je pense.


Message édité par duch le 17-03-2004 à 11:16:42
Reply

Marsh Posté le 17-03-2004 à 11:18:30    

ouai c'est tres porc en effet
essai au moins d'avancer jusqu'au "\n" suivant pour par commencer par une demie ligne, en faisant un <LOG> dans le vide

Reply

Marsh Posté le 17-03-2004 à 11:20:10    

oui c'est ce que je me disais.
 
J'vais qd même essayer le coup du ReadBackwards, si c'est pas lourd ça va le faire

Reply

Marsh Posté le 17-03-2004 à 11:20:10   

Reply

Marsh Posté le 17-03-2004 à 11:22:43    

il me semble tout de meme que si tu remplacait simplement ton

Code :
  1. open(LOG, '<', $LogFile) || error("Couldn't open server log file \"$LogFile\" : $!" );

du premier script par un

Code :
  1. tie(*LOG, 'File::ReadBackwards', $LogFile) || error("Couldn't open server log file \"$LogFile\" : $!" );

ce serait vachement plus propre! Dan ce cas effectivement ca te lirait les lignes à l'envers mais c'est encore mieux je trouve, plus logique

Reply

Marsh Posté le 17-03-2004 à 11:25:13    

attends laisse moi le temps d'installer le truc et de l'essayer :D

Reply

Marsh Posté le 17-03-2004 à 11:32:32    

Reply

Marsh Posté le 17-03-2004 à 11:35:55    

je suppose que tu veux parler de : comment écrire un tail en perl?
 
 
à vrai dire après avoir essayer le ReadBackwards, je dois dire que je trouve ça plutôt rapide (donc ok pour moi) et effectivement logique d'avoir les lignes dans cet ordre.


Message édité par duch le 17-03-2004 à 11:37:43
Reply

Sujets relatifs:

Leave a Replay

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