Regex perl-如何根据行的位置从文件中提取行
我正在处理一个文本文件以提取包含时间戳的行,然后对这些时间戳执行计算。该行包含一个时间戳,后跟一条消息,我正在对其执行正则表达式以提取该消息Regex perl-如何根据行的位置从文件中提取行,regex,perl,Regex,Perl,我正在处理一个文本文件以提取包含时间戳的行,然后对这些时间戳执行计算。该行包含一个时间戳,后跟一条消息,我正在对其执行正则表达式以提取该消息 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 ope
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之后文件中出现的Let say FOO的OCcrure
非常感谢您的帮助 在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
或者你正在做什么-逐行迭代:
#!/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
此解决方案使用“范围”操作符查找第一条条形线,然后是其后的第一条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
我认为您的示例中的/bar/是一个输入错误,因为您的大量数据是bar,并且您的正则表达式不区分大小写?谢谢,没有想到定义的关键字!试一试,看看这是否有效。在标量上下文中,它不应该被称为触发器操作符吗?@paveljurca:不,因为当范围只有一个时,触发器是两个音节。同样的原因使得hash比可笑的七音节关联数组更可取。因为它对一系列的值返回true。好的,这是合理的。那么,我将继续使用range:
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;
...
}
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