Regex 正则表达式仅匹配有效行
我写了一个脚本,总结了很长的日志文件。我遇到的一个小问题是日志很容易有损坏的条目,因此我的摘要有时会包含一些不好的行。 我的脚本生成一个中间临时文件,我只需要从中选择有效的行 以下行有效,我需要匹配以下行: 21/05/14 09:17 134U 0993 EUser_Message 01 21/05/14 11:07 134UD 0994 User_Message B02 21/05/14 11:47 134P 0995 User_Message UOD1 21/05/14 12:41 134B18 0996 User_Message UOD2 21/05/14 14:00 134B 0997 User_Message T02 21/05/14 14:22 134NV 0998 User_Message D02 21/05/14 15:25 121U 0999 EUser_Message 03 21/05/14 16:38 121UD 1000 EUser_Message 04 22/05/14 07:39 134TP 1001 EUser_Message 08 22/05/14 09:55 134P 1002 EUser_Message 13 22/05/14 10:46 134B 1003 EUser_Message 14 22/05/14 12:00 134NonVac 1004 User_Message UOD3Regex 正则表达式仅匹配有效行,regex,perl,Regex,Perl,我写了一个脚本,总结了很长的日志文件。我遇到的一个小问题是日志很容易有损坏的条目,因此我的摘要有时会包含一些不好的行。 我的脚本生成一个中间临时文件,我只需要从中选择有效的行 以下行有效,我需要匹配以下行: 21/05/14 09:17 134U 0993 EUser_Message 01 21/05/14 11:07 134UD 0994 User_Message B02 21/05/14 11:47 134P 09
如果有人能告诉我如何正确构建一个只匹配上面显示的有效文本行的正则表达式,我将不胜感激。让我们准确地翻译一下: (2位)(正斜杠)(2位)(正斜杠)(2位)(3个空格)(2位)(冒号)(2位)(3个空格)(4到9个字母或数字)(1到6个空格)(4位)(4个空格)(“用户信息字符串”)(0或1个空格)(新行) 现在唯一匹配的一行,你说你不想
17/04/14 10:04 134TP 0869 EUser_Message 01
我不明白为什么不应该符合你描述的规则
我猜这是因为您希望(4到9个字母或数字)和(1到6个空格)的总和始终为10个字符。我们可以使用-(?=.{10}\b\d)
给我们最后的答案:
/^\d{2}\/\d{2}\/\d{2} {3}\d{2}:\d{2} {3}(?=.{10}\b\d)\w{4,9} {1,6}\d{4} {4}E?User_Message ?/
让我们准确地翻译一下: (2位)(正斜杠)(2位)(正斜杠)(2位)(3个空格)(2位)(冒号)(2位)(3个空格)(4到9个字母或数字)(1到6个空格)(4位)(4个空格)(“用户信息字符串”)(0或1个空格)(新行) 现在唯一匹配的一行,你说你不想
17/04/14 10:04 134TP 0869 EUser_Message 01
我不明白为什么不应该符合你描述的规则
我猜这是因为您希望(4到9个字母或数字)和(1到6个空格)的总和始终为10个字符。我们可以使用-(?=.{10}\b\d)
给我们最后的答案:
/^\d{2}\/\d{2}\/\d{2} {3}\d{2}:\d{2} {3}(?=.{10}\b\d)\w{4,9} {1,6}\d{4} {4}E?User_Message ?/
列之间的确切空格数可能相关,也可能无关。如果这应该是固定宽度字段数据,那么应该使用 有效的日志行必须有六个(或五个)字段,包括:
unpack'A11 A9 A11 A9 A20',$line
提取字段。您仍然可以单独验证这些字段
您应该提取每个字段并分别进行验证,而不是用一个正则表达式模式来管理它们
下面是一个独立的示例。它假定字段提取采用空间分隔的数据,但对于固定宽度的字段数据,它的工作方式几乎相同,只需将拆分
替换为解包
,并计算出字段的正确编号和名称
我留下了一些验证器供您填写我对您的问题描述的理解中给定的不确定性
有更多的方法来做这类事情,比如从组成部分构建一个大型正则表达式模式。但是,在我看来,你有空格分隔的列,有时六个单独的小检查的认知负担比一个正则表达式要轻
此外,这使得添加进一步的代码来检查日期是否真的是有效日期、是否在某些范围内等变得更容易,而不会挤出程序的实际流程
#!/usr/bin/env perl
use strict;
use warnings;
package My::LogEntry;
use Carp qw( croak );
use Moo;
my @fields = qw( date time field3 field4 msg_type field6 );
has $_ => (is => 'ro', trigger => 1) for @fields;
sub _trigger_date {
my $self = shift;
my $date = shift;
unless ($date =~ m{\A [0-9]{2} / [0-9]{2} / [0-9]{2} \z}x) {
croak "Invalid date '$date'";
}
return;
}
sub _trigger_time {
my $self = shift;
my $time = shift;
unless ($time =~ m{\A [0-9]{2} : [0-9]{2} \z}x) {
croak "Invalid time '$time'";
}
return;
}
sub _trigger_field3 {}
sub _trigger_field4 {}
sub _trigger_msg_type {
my $self = shift;
my $msg_type = shift;
unless ($msg_type =~ m{ \A E? User_Message \z }x) {
croak "Invalid message type '$msg_type'";
}
return;
}
sub _trigger_field6 {}
sub do_something { }
sub BUILDARGS {
my $class = shift;
unless (@fields == @_) {
croak sprintf(
'%s constructor called with %d args (%s), need %d',
$class,
scalar @_,
join(',', @_),
scalar @fields
);
}
my $ret = {
map +( $fields[$_] => $_[$_] ), 0 .. $#_
};
}
while (my $line = <DATA>) {
my @entry = split ' ', $line;
my $entry;
eval { $entry = My::LogEntry->new(@entry) };
if ( $entry ) {
$entry->do_something;
}
else {
warn "$.: $@";
}
}
__DATA__
21/05/14 09:17 134U 0993 EUser_Message 01
21/05/14 11:07 134UD 0994 User_Message B02
21/05/14 11:47 134P 0995 User_Message UOD1
21/05/14 12:41 134B18 0996 User_Message UOD2
21/05/14 14:00 134B 0997 User_Message T02
21/05/14 14:22 134NV 0998 User_Message D02
21/05/14 15:25 121U 0999 EUser_Message 03
21/05/14 16:38 121UD 1000 EUser_Message 04
22/05/14 07:39 134TP 1001 EUser_Message 08
22/05/14 09:55 134P 1002 EUser_Message 13
22/05/14 10:46 134B 1003 EUser_Message 14
22/05/14 12:00 134NonVac 1004 User_Message UOD3
User_Message UOD1
19/08/14 11:46 1388 EUser_Message 01
03/07/13 0645 03/07/13 0646 03/07/13 0647 03/07/13 15:36 134U 0648
0862 17/04/14 0866 17/04/14 0867 17/04/14 0868 17/04/14
17/04/14 10:04 134TP 0869 EUser_Message 01
21/05/14 14:02 134B 0982
0983 22/05/14 22/05/14 12:48 134U 0984 User_Message UOD1
1015 03/06/14
11/07/13 08:12 134B 0011
11/07/13 12:39 134B 0012
11/07/13 13:53 134B 0013
12/07/13 08:01 134P 0014
12/07/13 08:29 134B 0015
#/usr/bin/env perl
严格使用;
使用警告;
包My::LogEntry;
使用鲤鱼qw(croak);
使用Moo;
my@fields=qw(日期时间字段3字段4消息类型字段6);
对于@fields,具有$979;=>(is=>'ro',触发器=>1);
子触发日期{
我的$self=shift;
我的$date=班次;
除非($date=~m{\A[0-9]{2}/[0-9]{2}/[0-9]{2}\z}x){
croak“无效日期'$date'”;
}
返回;
}
子触发时间{
我的$self=shift;
我的$time=shift;
除非($time=~m{\A[0-9]{2}:[0-9]{2}\z}x){
哼唱“无效时间'$time'”;
}
返回;
}
子触发器字段3{}
子触发器字段4{}
子触发器消息类型{
我的$self=shift;
my$msg_type=班次;
除非($msg_type=~m{\A E?User_Message\z}x){
croak“无效的消息类型'$msg_type'”;
}
返回;
}
子触发器字段6{}
sub do_something{}
子构建参数{
我的$class=shift;
除非(@fields==@){
呱呱(
用%d个参数(%s)调用了“%s”构造函数,需要%d个参数,
$class,
标量,,
连接(',',@)),
标量@字段
);
}
我的$ret={
映射+($fields[$\u]=>$\u[$\ u]),0$#_
};
}
while(我的$line=){
my@entry=拆分“”,$line;
我的$entry;
eval{$entry=My::LogEntry->new(@entry)};
如果($分录){
$entry->dou_某事;
}
否则{
警告“$:$@”;
}
}
__资料__
2014年5月21日09:17 134U 0993 EUser_信息01
2014年5月21日11:07 134UD 0994用户信息B02
2014年5月21日11:47 134P 0995用户信息UOD1
2014年5月21日12:41 134B18 0996用户信息UOD2
2014年5月21日14:00 134B 0997用户信息T02
2014年5月21日14:22 134NV 0998用户信息D02
2014年5月21日15:25 121U 0999 EUser_信息03
2014年5月21日16:38 121UD 1000 EUser_信息04
2014年5月22日07:39 134TP 1001 EUser_信息08
2014年5月22日09:55 134P 1002 EUser_信息13
2014年5月22日10:46 134B 1003 EUser_信息14
2014年5月22日12:00 1344 AC 1004用户信息UOD3
用户信息UOD1
14年8月19日11:46 1388 EUser_信息01
03/07/13 0645 03/07/13 0646 03/07/13 0647 03/07/13 15:36 134U 0648
0862 17/04/14 0866 17/04/14 0867 17/04/14 0868 17/04/14
2014年4月17日10:04 134TP 0869 EUser_信息01
2014年5月21日14:02 134B 0982
0983 22/05/14 22/05/14 12:48 134U 0984用户信息UOD1
1015 03/06/14
11/07/13 08:12 134B 0011
11/07/13 12:39 134B 0012
11/07/13 13:53 134B
#!/usr/bin/env perl
use strict;
use warnings;
package My::LogEntry;
use Carp qw( croak );
use Moo;
my @fields = qw( date time field3 field4 msg_type field6 );
has $_ => (is => 'ro', trigger => 1) for @fields;
sub _trigger_date {
my $self = shift;
my $date = shift;
unless ($date =~ m{\A [0-9]{2} / [0-9]{2} / [0-9]{2} \z}x) {
croak "Invalid date '$date'";
}
return;
}
sub _trigger_time {
my $self = shift;
my $time = shift;
unless ($time =~ m{\A [0-9]{2} : [0-9]{2} \z}x) {
croak "Invalid time '$time'";
}
return;
}
sub _trigger_field3 {}
sub _trigger_field4 {}
sub _trigger_msg_type {
my $self = shift;
my $msg_type = shift;
unless ($msg_type =~ m{ \A E? User_Message \z }x) {
croak "Invalid message type '$msg_type'";
}
return;
}
sub _trigger_field6 {}
sub do_something { }
sub BUILDARGS {
my $class = shift;
unless (@fields == @_) {
croak sprintf(
'%s constructor called with %d args (%s), need %d',
$class,
scalar @_,
join(',', @_),
scalar @fields
);
}
my $ret = {
map +( $fields[$_] => $_[$_] ), 0 .. $#_
};
}
while (my $line = <DATA>) {
my @entry = split ' ', $line;
my $entry;
eval { $entry = My::LogEntry->new(@entry) };
if ( $entry ) {
$entry->do_something;
}
else {
warn "$.: $@";
}
}
__DATA__
21/05/14 09:17 134U 0993 EUser_Message 01
21/05/14 11:07 134UD 0994 User_Message B02
21/05/14 11:47 134P 0995 User_Message UOD1
21/05/14 12:41 134B18 0996 User_Message UOD2
21/05/14 14:00 134B 0997 User_Message T02
21/05/14 14:22 134NV 0998 User_Message D02
21/05/14 15:25 121U 0999 EUser_Message 03
21/05/14 16:38 121UD 1000 EUser_Message 04
22/05/14 07:39 134TP 1001 EUser_Message 08
22/05/14 09:55 134P 1002 EUser_Message 13
22/05/14 10:46 134B 1003 EUser_Message 14
22/05/14 12:00 134NonVac 1004 User_Message UOD3
User_Message UOD1
19/08/14 11:46 1388 EUser_Message 01
03/07/13 0645 03/07/13 0646 03/07/13 0647 03/07/13 15:36 134U 0648
0862 17/04/14 0866 17/04/14 0867 17/04/14 0868 17/04/14
17/04/14 10:04 134TP 0869 EUser_Message 01
21/05/14 14:02 134B 0982
0983 22/05/14 22/05/14 12:48 134U 0984 User_Message UOD1
1015 03/06/14
11/07/13 08:12 134B 0011
11/07/13 12:39 134B 0012
11/07/13 13:53 134B 0013
12/07/13 08:01 134P 0014
12/07/13 08:29 134B 0015
#!/usr/bin/perl
use strict;
use warnings;
use Time::Piece;
while ( <DATA> ) {
my ( $date, $time, $somecode, $othercode, $msgtype, $msgcode ) = split;
if ( $date =~ m,^\d+/\d+/\d+$,
and $time =~ m,^\d+:\d+$,
and eval { Time::Piece->strptime("$date $time", "%d/%m/%y %H:%M") } ) {
print "Date is ok\n";
}
else { print "$date $time is invalid\n"; next; }
if ( $somecode =~ m/^\w+\d+$/ ) {
print "somecode is ok\n";
}
else {
print "Error with somecode $somecode\n";
}
if ( $othercode =~ m,^\d{4}$, ) {
print "othercode is ok\n";
}
else {
print "Error with $othercode \n";
next;
}
if ( $msgtype =~ m/User_Message/
and $msgcode =~ m/\w+/ ) {
print "$msgtype $msgcode ok\n";
}
else {
print "Error with $msgtype $msgcode\n";
next;
}
print "Line: $. is ok\n$_";
}
__DATA__
21/05/14 09:17 134U 0993 EUser_Message 01
21/05/14 11:07 134UD 0994 User_Message B02
21/05/14 11:47 134P 0995 User_Message UOD1
21/05/14 12:41 134B18 0996 User_Message UOD2
21/05/14 14:00 134B 0997 User_Message T02
21/05/14 14:22 134NV 0998 User_Message D02
21/05/14 15:25 121U 0999 EUser_Message 03
21/05/14 16:38 121UD 1000 EUser_Message 04
22/05/14 07:39 134TP 1001 EUser_Message 08
22/05/14 09:55 134P 1002 EUser_Message 13
22/05/14 10:46 134B 1003 EUser_Message 14
22/05/14 12:00 134NonVac 1004 User_Message UOD3
User_Message UOD1
19/08/14 11:46 1388 EUser_Message 01
03/07/13 0645 03/07/13 0646 03/07/13 0647 03/07/13 15:36 134U 0648
0862 17/04/14 0866 17/04/14 0867 17/04/14 0868 17/04/14
17/04/14 10:04 134TP 0869 EUser_Message 01
21/05/14 14:02 134B 0982
0983 22/05/14 22/05/14 12:48 134U 0984 User_Message UOD1
1015 03/06/14
11/07/13 08:12 134B 0011
11/07/13 12:39 134B 0012
11/07/13 13:53 134B 0013
12/07/13 08:01 134P 0014
12/07/13 08:29 134B 0015
use strict;
use warnings;
use v5.14; # For regex /a modifier
use re '/a'; # Regex patterns match only ASCII characters
my $template = 'A11 A8 A10 A8 A*';
my @validation = (
qr{^\d\d/\d\d/\d\d$},
qr{^\d\d:\d\d$},
qr{^[0-9A-Z]+$}i,
qr{^\d+$},
qr{^E?User_Message\s+\w+$},
);
my ($total, $n) = (0, 0);
while ( <DATA> ) {
++$total;
my @fields = unpack $template, $_;
my $valid = 1;
for my $i ( 0 .. $#fields ) {
$valid = $fields[$i] =~ $validation[$i];
last if not $valid;
}
if ( $valid ) {
++$n;
print;
}
}
print "\n$n valid records of $total\n";
__DATA__
21/05/14 09:17 134U 0993 EUser_Message 01
21/05/14 11:07 134UD 0994 User_Message B02
21/05/14 11:47 134P 0995 User_Message UOD1
21/05/14 12:41 134B18 0996 User_Message UOD2
21/05/14 14:00 134B 0997 User_Message T02
21/05/14 14:22 134NV 0998 User_Message D02
21/05/14 15:25 121U 0999 EUser_Message 03
21/05/14 16:38 121UD 1000 EUser_Message 04
22/05/14 07:39 134TP 1001 EUser_Message 08
22/05/14 09:55 134P 1002 EUser_Message 13
22/05/14 10:46 134B 1003 EUser_Message 14
22/05/14 12:00 134NonVac 1004 User_Message UOD3
User_Message UOD1
19/08/14 11:46 1388 EUser_Message 01
03/07/13 0645 03/07/13 0646 03/07/13 0647 03/07/13 15:36 134U 0648
0862 17/04/14 0866 17/04/14 0867 17/04/14 0868 17/04/14
17/04/14 10:04 134TP 0869 EUser_Message 01
21/05/14 14:02 134B 0982
0983 22/05/14 22/05/14 12:48 134U 0984 User_Message UOD1
1015 03/06/14
11/07/13 08:12 134B 0011
11/07/13 12:39 134B 0012
11/07/13 13:53 134B 0013
12/07/13 08:01 134P 0014
12/07/13 08:29 134B 0015
21/05/14 09:17 134U 0993 EUser_Message 01
21/05/14 11:07 134UD 0994 User_Message B02
21/05/14 11:47 134P 0995 User_Message UOD1
21/05/14 12:41 134B18 0996 User_Message UOD2
21/05/14 14:00 134B 0997 User_Message T02
21/05/14 14:22 134NV 0998 User_Message D02
21/05/14 15:25 121U 0999 EUser_Message 03
21/05/14 16:38 121UD 1000 EUser_Message 04
22/05/14 07:39 134TP 1001 EUser_Message 08
22/05/14 09:55 134P 1002 EUser_Message 13
22/05/14 10:46 134B 1003 EUser_Message 14
22/05/14 12:00 134NonVac 1004 User_Message UOD3
12 valid records of 25
my @validation = (
qr{^$RE{time}{tf}{ -pat => 'd/m/yy' }$},
qr{^$RE{time}{tf}{ -pat => 'h:m' }$},
qr{^[0-9A-Z]+$}i,
qr{^\d+$},
qr{^E?User_Message\s+\w+$},
);