我有一个日志文件,其中每行的前几个字符都作为时间戳。
2010-06-01 04:56:02,802 DEBUG {Thread-27}一些短信
2010-06-01 04:56:02,802 DEBUG {Thread-27}一些短信
2010-06-01 04:56:02,802 DEBUG {Thread-27}一些短信
2010-06-01 04:56:02,802 DEBUG {Thread-27}一些短信
2010-06-01 05:22:02,802调试 {Thread-27}一些短信
2010-06-01 05:22:02,802调试 {Thread-27}一些短信
2010-06-01 05:22:02,802调试 {Thread-27}一些短信
2010-06-01 05:22:02,802调试 {Thread-27}一些短信
2010-06-01 06:43:02,802 INFO {Thread-27}一些短信
2010-06-01 06:43:02,803 INFO {Thread-27}一些短信
2010-06-01 06:43:02,804 INFO {Thread-27}一些短信
2010-06-01 06:43:02,804 INFO {Thread-27}一些短信
2010-06-01 06:43:02,809 DEBUG {Thread-27}一些短信
2010-06-01 06:43:02,809 DEBUG {Thread-27}一些短信
2010-06-01 06:43:02,809 DEBUG {Thread-27}一些短信
2010-06-01 07:08:02,809 DEBUG {Thread-27}一些短信
2010-06-01 07:08:02,809 DEBUG {Thread-27}一些短信
我的目标是找到时间戳在当前时间之前1小时的所有这些行。
如何实现这一目标?
答案 0 :(得分:4)
DateTime
模块非常适合此问题的需要:
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;
答案 1 :(得分:1)
由于时间戳将被排序,您可以尝试一种扭曲的Binary Search。
由于大多数线条的长度不一样,你可以寻找一定的偏移量,寻找前后出现的换行符(或者你所拥有的任何行终止符)(或者之后的在之后),你得到一个候选线。现在将线上的日期与您要查找的日期进行比较,并决定是再次寻找,还是只是环顾这条线。
在确定接下来要寻找的偏移量时,您可以尝试使用与Interpolation Search类似的内容,即根据您获得的线的时间与您搜索的时间之间的差异来确定偏移量。
这应该比线性搜索快得多。
有关使用perl进行二进制搜索的示例:http://perl.plover.com/yak/lightweight-db/materials/slides/slide024.html
答案 2 :(得分:0)
线路输出的顺序是否重要?如果您不介意使用最新的第一个,可以考虑使用File::ReadBackwards。继续向后读,直到一条线超过一个小时,然后停止。如果您希望按特定顺序使用它们,则可以将它们存储在数组中并根据需要进行打印。 (这假定它是一个或多或少的标准日志文件,文件末尾有最新的条目。)