2010-06-01 5 views
3

J'ai un fichier journal dont les premiers caractères de chaque ligne sont horodatés.Problème de plage de dates

2010-06-01 04: 56: 02802 DEBUG {thread-27} Certains messages texte

2010-06-01 04: 56: 02802 DEBUG {thread-27} Certains messages texte

2010-06-01 04: 56: 02802 DEBUG {thread-27} Certains messages texte

2010-06-01 04: 56: 02802 DEBUG {thread-27} Certains messages texte

2010-06-01 05: 22: 02802 DEBUG {thread-27} Certains messages texte

2010-06-01 05: 22: 02802 DEBUG {Discussion-27} Certains message texte

2010-06-01 05: 22: 02802 DEBUG {thread-27} Certains messages texte

2010-06-01 05: 22: 02802 DEBUG {discussion-27} Certains message texte

2010- 06-01 06: 43: 02,802 INFO {Thread-27} Un message texte

2010-06-01 06: 43: 02803 INFO {Discussion-27} Certains messages texte

2010-06-01 06: 43: 02804 INFO {Discussion-27} Certains messages texte

2010-06-01 06: 43: 02804 INFO {discussion-27} Certains messages texte

2010-06-01 06: 43: 02809 DEBUG {discussion-27} Certains message texte

2010-06-01 06: 43: 02,809 DEBUG {thread-27} Certains messages texte

2010-06-01 06: 43: 02809 DEBUG {thread-27} Certains messages texte

2010-06-01 07: 08: 02809 DEBUG { discussion-27} Certains des messages texte

2010-06-01 07: 08: 02809 DEBUG {} thread-27 Certains messages texte

Mon but de trouver toutes ces lignes qui ont l'horodatage de 1 hr avant l'heure actuelle.

Comment cela peut-il être réalisé?

+1

Est-ce une heure avant l'heure, la minute et la seconde en cours? Ou êtes-vous simplement intéressé par toutes les entrées enregistrées dans l'heure de 6 heures si l'heure actuelle est 7 heures? – Zaid

Répondre

1

Depuis que les horodatages vont être triés, vous pouvez essayer une sorte de Binary Search avec une torsion. Comme la plupart des lignes ne seront pas de même longueur, vous pouvez simplement chercher un décalage, recherchez les nouvelles lignes (ou n'importe quel terminateur de ligne) qui apparaissent avant et après (OU après et après que), vous obtenez une ligne de candidats.Maintenant, comparez la date sur la ligne à celle que vous recherchez et décidez si vous devez chercher à nouveau, ou simplement regarder autour de cette ligne. Pour déterminer le décalage à rechercher, vous pouvez essayer d'utiliser quelque chose de similaire à ce que fait Interpolation Search, c'est-à-dire décider du décalage en fonction de la différence entre l'heure de la ligne et l'heure recherchée.

Cela devrait être beaucoup plus rapide que la recherche linéaire.

Pour un exemple de faire des recherches binaires dans des fichiers en utilisant perl: http://perl.plover.com/yak/lightweight-db/materials/slides/slide024.html

+0

Les solutions Perl ont tendance à se concentrer davantage sur le traitement de texte. Voyant que l'OP est seulement après avoir enregistré quelques lignes, la recherche binaire en vaut-elle la peine? – Zaid

+0

@Zaid: Est-il vraiment important que OP essaie d'utiliser perl pour le faire? L'OP n'a jamais dit que le fichier journal était petit, donc je ne sais pas d'où vous venez. Bien sûr, je suis d'accord avec le fait que le problème d'OP pourrait avoir été de tenter de déterminer l'heure du journal d'une ligne particulière, mais cela n'est pas clair d'après la question. –

+0

Je n'ai pas dit que le fichier journal était petit. Ce que j'ai dit, c'est que le PO est seulement après quelques lignes. Le besoin OP est clair: Déterminez ces lignes avec des horodateurs qui se trouvent dans l'heure qui suit l'heure actuelle. La question est étiquetée 'perl', donc je suppose qu'elle veut une réponse en Perl ... Je ne dis pas que votre réponse est fausse, mais je n'ai jamais vu un tel problème abordé avec une approche de recherche binaire, probablement parce que il faudrait charger le fichier entier en mémoire. – Zaid

4

Le module DateTime est bien adapté aux besoins de ce problème:

use strict; 
use warnings; 
use DateTime; 

my $oneHourAgo = DateTime->now()->subtract(hours => 1); 
my $threshold = join ' ', $oneHourAgo->ymd, $oneHourAgo->hms; # Time as string 

open my $logFile, '<', 'logfile.txt'; 

while (my $log = <$logFile>) { 

    chomp $log; 
    my ($time) = split /,/, $log;  # Gets current log's time 

    print $log if $time ge $threshold; # String-compares log's time to threshold 
} 

close $logFile; 
+0

+1 pour utiliser 'ge' plutôt que de convertir (plus cher) chaque horodatage pour calculer un objet' DateTime :: Duration' ... – pilcrow

0

Est-ce que l'ordre dans lequel les lignes sont sorties matière? Si cela ne vous dérange pas de les avoir avec le plus récent en premier, vous pourriez envisager d'utiliser File::ReadBackwards. Continuez à lire vers l'arrière jusqu'à ce qu'une ligne ait plus d'une heure, puis arrêtez-vous. Si vous les voulez dans un ordre particulier, vous pouvez les stocker dans un tableau et les imprimer comme vous le souhaitez. (Cela suppose qu'il s'agit d'un fichier journal plus ou moins standard avec les entrées les plus récentes à la fin du fichier.)