捕获组的表达式问题

时间:2015-04-06 15:41:58

标签: regex perl expression capture

我有一些像这样的数据

Wed Mar 18 15:16:10 2015 eth0:1 109.224.232.219 up (not currently mapped)
Wed Mar 18 15:18:12 2015 eth0:1 109.224.232.219 down (not responding)
Wed Mar 18 15:20:46 2015 eth0:1 109.224.232.219 up (not currently mapped)
Wed Mar 18 15:22:52 2015 eth0:1 109.224.232.219 down (not responding)
Wed Mar 18 15:24:26 2015 eth0:1 109.224.232.219 up (not currently mapped)

我正在尝试捕获每行上的IP和日期字符串,我以为我可以在单词eth之前做任何事情然后我的IP检查,但这不起作用。我是否误解了捕获组的概念?

是否有一种合理的方法可以从1个正则表达式获取此数据?

(^(.*?)eth)(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})

任何帮助都将不胜感激。

这是当前正则表达式的图像

https://www.debuggex.com/i/BaXnqh2DzRhUCph8.png

2 个答案:

答案 0 :(得分:0)

你几乎就在那里。您只需在.*?之后添加eth,以便它与eth和ip-address之间的字符匹配。

^(.*?)eth.*?\b(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})

DEMO

如果您不希望第1组无法捕获eth之前的空格,那么您可以像这样更改正则表达式,

^(.*?)\s+eth.*?\b(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})

DEMO

答案 1 :(得分:-1)

有时,人们会忽略点分十进制IP表示的明确定义的字符序列。当我完全详细说明一个合适的IP八位字节时,我几乎没有没有问题来识别IP。

my $octet  = qr/\b(?:0|1\d{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?)\b/;
my ( $foctet = "$octet" ) =~ s/0[|]//;

然后,最重要的是,我指定一个IP地址是一组四个八位字节,用点分隔。

my $ip_regex = qr/($foctet(\.$octet){3})/;

这个小小的美女几乎总能从任何文件中获取任何有效IP。

除此之外,还可以使用更高的规格指定日期。再次,按照这个规范,你得到的将几乎不可避免地是一个日期:

my $dow            = qr/\b(?:Fri|Mon|Sat|Sun|Thu|Tue|Wed)\b/;
my $mon            = qr/\b(?:Apr|Aug|Dec|Feb|Jan|Jul|Jun|Mar|May|Nov|Oct|Sep)\b/;
my $day            = qr/\b(?:[012]\d?|3[01]?|[4-9])\b/;
my $hr24           = qr/\b(?:[01]\d?|2[0-3])\b/;
my $minsec         = qr/\b(?:[0-5]\d)\b/;
my $datetime_regex = qr/$dow\s+$mon\s+$day\s+$hr24:$minsec:$minsec\s+\d+/;

因此,只需对源代码行使用两个正则表达式,即可获得所需的内容,而无需进行大量的回溯。

my @date_parts = $line =~ /$datetime_regex/;
my ( $ip )     = $line =~ /$ip_regex/;

事实上,如果性能是一个问题,我看到单个正则表达式中有很多失败与非贪婪的匹配,而ip正则表达式首次尝试成功。正则表达式引擎找到了'。'在偏移35处并从位置32开始。

然而,以下情况并非一次都失败。只是表明它如何帮助您将表达式指定到预期的数据范围:

my ( $dt, $ip ) = m/($datetime_regex)\s+eth\d:\d+\s+($ip_regex)/;