Perl脚本从两个日期范围之间的日志文件中提取数据,文件中不存在必要的输入日期

时间:2014-02-24 17:49:53

标签: perl date

我有一个日志文件,每行都有一个时间戳,如下所示。我需要在两个日期之间获取数据。例如,在8月9日16:24:23到8月9日16:28:00之间获取数据,即使它们不在文件中。

Aug  9 16:24:21 linux-447z dbus-daemon[685]: 
Aug  9 16:24:21 linux-447z dbus[685]: [system] Activating service 
Aug  9 16:24:21 linux-447z dbus-daemon[685]: 
Aug  9 16:24:21 linux-447z dbus-daemon[685]: dbus[685]: [system] 
Aug  9 16:24:21 linux-447z dbus[685]: [system] Successfully activated 
Aug  9 16:27:46 linux-447z dhcpcd[3422]: eth0: renewing lease of 192.168.37.128
Aug  9 16:27:46 linux-447z dhcpcd[3422]: eth0: leased 192.168.37.128 for 1800 seconds
Aug  9 16:27:46 linux-447z dhcpcd[3422]: eth0: adding IP address 192.168.37.128/24
Aug  9 16:27:46 linux-447z dhcpcd[3422]: eth0: adding 
Aug  9 16:27:47 linux-447z dhcpcd[3422]: eth0: Failed to lookup
Aug  9 16:27:47 linux-447z ifup:     eth0      
Aug  9 16:27:48 linux-447z SuSEfirewall2:   
Aug  9 16:29:03 linux-447z dbus[685]: [system] Activating service 

3 个答案:

答案 0 :(得分:4)

您可以使用Time::Piece(自Perl 5.10以来的核心模块)进行日期解析和比较:

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;

use Time::Piece;

my $format = '%b %e %T';
my $start = Time::Piece->strptime('Aug  9 16:24:23', $format);
my $end   = Time::Piece->strptime('Aug  9 16:28:00', $format);

while (<DATA>) {
    my ($timestamp) = /(^\w+\s+\d+\s+\d\d:\d\d:\d\d)/;
    my $t = Time::Piece->strptime($timestamp, $format);

    print if $t >= $start && $t <= $end;
}

__DATA__
Aug  9 16:24:21 linux-447z dbus-daemon[685]:
Aug  9 16:24:21 linux-447z dbus[685]: [system] Activating service
Aug  9 16:24:21 linux-447z dbus-daemon[685]:
Aug  9 16:24:21 linux-447z dbus-daemon[685]: dbus[685]: [system]
Aug  9 16:24:21 linux-447z dbus[685]: [system] Successfully activated
Aug  9 16:27:46 linux-447z dhcpcd[3422]: eth0: renewing lease of 192.168.37.128
Aug  9 16:27:46 linux-447z dhcpcd[3422]: eth0: leased 192.168.37.128 for 1800 seconds
Aug  9 16:27:46 linux-447z dhcpcd[3422]: eth0: adding IP address 192.168.37.128/24
Aug  9 16:27:46 linux-447z dhcpcd[3422]: eth0: adding
Aug  9 16:27:47 linux-447z dhcpcd[3422]: eth0: Failed to lookup
Aug  9 16:27:47 linux-447z ifup:     eth0
Aug  9 16:27:48 linux-447z SuSEfirewall2:
Aug  9 16:29:03 linux-447z dbus[685]: [system] Activating service

输出:

Aug  9 16:27:46 linux-447z dhcpcd[3422]: eth0: renewing lease of 192.168.37.128
Aug  9 16:27:46 linux-447z dhcpcd[3422]: eth0: leased 192.168.37.128 for 1800 seconds
Aug  9 16:27:46 linux-447z dhcpcd[3422]: eth0: adding IP address 192.168.37.128/24
Aug  9 16:27:46 linux-447z dhcpcd[3422]: eth0: adding 
Aug  9 16:27:47 linux-447z dhcpcd[3422]: eth0: Failed to lookup
Aug  9 16:27:47 linux-447z ifup:     eth0      
Aug  9 16:27:48 linux-447z SuSEfirewall2:  

答案 1 :(得分:0)

您可以解析以散列形式存储数据的每一行:将日期转换为int(只为数据样本删除':')并将其用作键,值应为数组,因为您同时拥有多个数据。将边框值转换为数字将帮助您限制结果输出。

答案 2 :(得分:0)

如果您的日志文件中的时间戳具有已知或明确标记的时区,则应该很简单,例如:使用Time :: Piece(以此问题的其他答案为例)或更简单的要求(例如文件中的时间戳和grep在同一时区)Time :: Local。

但是,使用您的示例文件(例如典型的系统日志文件),它会变得毛茸茸,因为您既没有时区信息,也没有年份,如果这些是syslog文件,它们通常使用(但不记录)当前时区,这些时区可以在记录时更改,特别是如果你有夏令时。

我曾经参与过一个项目,其中旧的系统日志格式(例如当前时间既没有时区也没有年份)是必需的。为了确定日志开始的时区和年份,我们在每次旋转后在新文件的顶部放置一个特殊的日志条目。我们还确保每小时至少写一次日志条目,以便我们可以检测到夏令时和返回时间的变化。打破时间戳的大量解决方法:(