我正在处理文本文件以提取包含时间戳的行,然后对这些时间戳执行计算。该行包含一个时间戳,后跟一条消息,我正在执行正则表达式以提取。
TIME | MESSAGE
20:48:27.159 | FOO
20:48:47.353 | BAR
20:48:49.227 | SPAM
20:48:52.192 | FOO
下面是我在文件
上执行的正则表达式的sudo代码... .... ...
open (my $FH, "<", $file) or die "Cannot open <$file>: $!";
for my $line (<$FH>) {
if ($line =~ /bar/) {
my $ts1 = ExtractTimestamp($line);
} elsif ($line =~ /FOO/) {
my $ts2 = ExtractTimestamp($line);
}
}
my $diff = $ts2 - $ts1;
这里的问题是正则表达式找到第一次出现的行并提取它,这给我留下了负时间戳。我想知道在perl中是否有任何模块或任何技术我可以在BAR之后提取文件中出现的FOO事件?
感谢您的帮助!
答案 0 :(得分:5)
此解决方案使用范围运算符查找第一个BAR
行,后面跟着第一个FOO
行。如果记录中的时间是范围中的第一行或最后一行,则将记录中的时间推送到数组@ts
use strict;
use warnings;
my @ts;
while ( <DATA> ) {
next unless my $state = /BAR/ .. /FOO/;
push @ts, /([\d:.]+)/ if $state == 1 or $state =~ /E/;
}
print join(' ... ', @ts), "\n";
__DATA__
TIME | MESSAGE
20:48:27.159 | FOO
20:48:47.353 | BAR
20:48:49.227 | SPAM
20:48:52.192 | FOO
20:48:47.353 ... 20:48:52.192
答案 1 :(得分:2)
open (my $FH, "<", $file) or die "Cannot open <$file>: $!";
# define $ts1 and $ts2 OUTSIDE "for" loop
my( $ts1, $ts2);
for my $line (<$FH>) {
if ($line =~ /bar/) {
$ts1 = ExtractTimestamp($line);
}
# ignore FOO before first BAR sets $ts1
elsif ( defined($ts1) and $line =~ /FOO/) {
$ts2 = ExtractTimestamp($line);
# stop searching after first FOO and "BAR after FOO" pair
last;
}
}
# if both FOO and "BAR after FOO" has set their variables
if( defined($ts1) and defined($ts2)) {
my $diff = $ts2 - $ts1;
...
}
答案 2 :(得分:0)
有几种方法可以在perl中执行此操作,具体取决于您要完成的任务。如果我正确地读你,你正在寻找FOO
和BAR
时间戳,并且可能试图提取delta?
关键问题是 - FOO
和BAR
完全匹配吗?
我的意思是,你可以通过多行正则表达式来实现:
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
local $/;
my ( $bar, $foo ) = <DATA> =~ m/^(\d\S+) \| BAR.*?(\d\S+) \| FOO$/ms;
print "BAR: $bar\nFOO: $foo\n";
__DATA__
TIME | MESSAGE
20:48:27.159 | FOO
20:48:47.353 | BAR
20:48:49.227 | SPAM
20:48:52.192 | FOO
这将匹配配对的'BAR'和'FOO'的第一个实例。 (如果在正则表达式上使用g
标志,则可以多次捕获)。
或者 - 您可以将记录分隔符设置为FOO
:
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
local $/ = "FOO\n";
while ( <DATA> ) {
my ( $foo ) = m/(\S+) \| FOO/;
my ( $bar ) = m/(\S+) \| BAR/;
print "$foo $bar\n";
}
__DATA__
TIME | MESSAGE
20:48:27.159 | FOO
20:48:47.353 | BAR
20:48:49.227 | SPAM
20:48:52.192 | FOO
或者你在做什么 - 逐行迭代:
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
my $last_bar;
while (<DATA>) {
if (m/^(\d\S+) \| BAR/) {
$last_bar = $1;
}
if ( my ($foo) = m/^(\d\S+) \| FOO/ ) {
if ($last_bar) {
print "$foo $last_bar\n";
}
else {
print "Unmatched:\n";
print;
}
$last_bar = undef;
}
}
__DATA__
TIME | MESSAGE
20:48:27.159 | FOO
20:48:47.353 | BAR
20:48:49.227 | SPAM
20:48:52.192 | FOO