我接受任何解释语言Perl,Python,Bash等。但我更喜欢Perl,因为它是我想要学习的东西。我有一个时间戳列表,如:
17:31:16
17:31:16
17:31:18
17:31:29
我想找到任意2个连续行之间的所有最大间隔(前5个),并返回时间戳和行号。基本上这是一个软件构建的日志文件,我试图确定哪些步骤花费的时间最长。我给出的例子实际上已经过滤了,行实际上看起来像: [15:57:42]:CC net / sunrpc / xprtsock.o 如果你能给我一个解析这种格式的程序,它会更容易一些,并返回最大时间差异发生的行号。
这是我用来隔离日志
的时间戳 perl -lane 'print $1 if $_ =~ /^\[(\d+:\d+:\d+)\]:*/'
我想要实现的输出类型如下:
line 574 20:04:54
line 575 20:24:55
Difference 00:20:01
如果您不想解决问题,我会很高兴看到一些伪代码或得到任何建议。我花了很多时间,没有有用的代码来展示它。
答案 0 :(得分:2)
我会稍微升级您的时间匹配正则表达式,以分别捕获时间的组件。我们是否必须担心在午夜之前开始并一直运行到第二天的清晨?
#!/usr/bin/env perl
use strict;
use warnings;
my $oldtime = ""; # hh:mm:ss for end of long interval
my $oldlineno = 0; # line number in the file of second line
my $oldoffset = 0; # offset in seconds from midnight of second command
my $olddiff = 0; # time taken for longest command
sub hhmmss
{
my($time) = @_;
my(@tm) = (int($time/3600), int($time/60)%60, $time%60);
return @tm;
}
while (<>)
{
chomp;
next unless m/^((\d\d):(\d\d):(\d\d))\s+/;
my $newoffset = (($2 * 60) + $3) * 60 + $4;
if ($oldoffset == 0)
{
$oldtime = $1;
$olddiff = 0;
$oldoffset = $newoffset;
$oldlineno = $.;
}
elsif (($newoffset - $oldoffset) > $olddiff)
{
$oldtime = $1;
$olddiff = $newoffset - $oldoffset;
$oldoffset = $newoffset;
$oldlineno = $.;
}
}
if ($oldoffset != 0)
{
my $prvlineno = $oldlineno - 1;
my $newoffset = $oldoffset - $olddiff;
my(@tm) = hhmmss($newoffset);
printf "line $prvlineno: %.2d:%.2d:%.2d\n", $tm[0], $tm[1], $tm[2];
print "line $oldlineno: $oldtime\n";
@tm = hhmmss($olddiff);
printf "diff: %.2d:%.2d:%.2d\n", $tm[0], $tm[1], $tm[2];
}
给定数据文件(data
)和上面的脚本(dt.pl
):
17:31:16 line1
17:31:18 line2
17:31:29 line3
17:33:59 line4
18:00:21 line5
18:21:03 line6
18:41:25 line7
19:51:54 line8
19:52:34 line9
下面的scriptlet产生了显示的输出:
$ for i in $(seq 1 9); do sed ${i}q data | perl dt.pl; done | so
line 0: 17:31:16
line 1: 17:31:16
diff: 00:00:00
line 1: 17:31:16
line 2: 17:31:18
diff: 00:00:02
line 2: 17:31:18
line 3: 17:31:29
diff: 00:00:11
line 3: 17:31:29
line 4: 17:33:59
diff: 00:02:30
line 4: 17:33:59
line 5: 18:00:21
diff: 00:26:22
line 4: 17:33:59
line 5: 18:00:21
diff: 00:26:22
line 6: 18:00:21
line 7: 18:41:25
diff: 00:41:04
line 7: 18:41:25
line 8: 19:51:54
diff: 01:10:29
line 7: 18:41:25
line 8: 19:51:54
diff: 01:10:29
$
在您编写任何代码之前,我很想听听您对此问题的看法。
这显然是一个问题,需要记录前一行信息的(相关部分)以计算它与当前行之间的差异。您还需要保持当前的最大差异,在您读取第二条匹配线之前,不能正式建立。这推动了设计。代码中的重复,通过无条件地分配3个值和第四个($olddiff
)有条件地减少为零。在那之后,主要是机械和战术问题。
像这样匹配多行是一个令人讨厌的过程;你必须处理保持适当的状态。部分地,这是一个经验问题;在你做了几十次这样的事情后,下次不会花那么长的时间。
答案 1 :(得分:1)
获得最大的差异
perl -l -n -e 'BEGIN {$m=0;$last=0;$am=$.;} /(\d+):(\d+):(\d+)/; $v=($1*3600)+($2*60)+$3; if ($last && $v-$last > $m) { $am=$.; $m=$v-$last;} $last=$v; END { print "max diff ",$m, " at line $am\n" }' d.txt
前5名
perl -l -n -e 'BEGIN {%h=();$last=0;} /(\d+):(\d+):(\d+)/; $v=($1*3600)+($2*60)+$3; if ($last) { $h{$v-$last}=$.;} $last=$v; END { for ((sort {$b <=> $a} keys %h)[0..4]) { print "line ",$h{$_}," $_"; }}' d.txt
在python中
last = 0
list = []
linenumber = 1
for t in (open("d.txt","r").readlines()):
q=3600
v=0
for x in t.split(":"):
v = v + q*int(x)
q = q / 60
if (last >0):
list.append([v-last, linenumber])
last = v
linenumber = linenumber + 1
top = sorted(list, key=lambda n: n[0], reverse=True)[0:5]
print top