这是Perl regular expression to match an IP address的后续行动。我想展示如何正确解决问题,但遇到了意想不到的行为。
use 5.010;
use strictures;
use Data::Munge qw(list2re);
use Regexp::IPv6 qw($IPv6_re);
use Regexp::Common qw(net);
our $port_re = list2re 0..65535;
sub ip_port_from_netloc {
my ($sentence) = @_;
return $sentence =~ /
( # capture either
(?<= \[ )
$IPv6_re # IPv6 address without brackets
(?= \] )
| # or
$RE{net}{IPv4} # IPv4 address
)
: # colon sep. host from port
($port_re) # capture port
/msx;
}
my ($ip, $port);
($ip, $port) = ip_port_from_netloc 'The netloc is 216.108.225.236:60099';
say $ip;
($ip, $port) = ip_port_from_netloc 'The netloc is [fe80::226:5eff:fe1e:dfbe]:60099';
say $ip;
第二场比赛失败。 use re 'debugcolor'
显示:($port_re)
已与IPv6地址中的:5
匹配。这让我感到惊讶,因为我没有用?
关闭贪婪。我预计它会吞噬到]
之前的所有内容,然后才会匹配分离的冒号以及之后的内容。
为什么会发生这种情况,以及解决方法是什么?
答案 0 :(得分:6)
只有当你的一个原子可以选择匹配多少(即使用*
,+
,?
或{{1}时,贪婪才会发挥作用})。这不是贪婪问题。
问题是正则表达式只会匹配一个IPv6地址,如果它紧跟着“{n,m}
”和“]
”。这不可能发生。
您可以使用两种不同的匹配,也可以使用以下内容:
:
也许这有点清洁?
my $port_re = list2re 0..65535;
my $IPv4_re = $RE{net}{IPv4};
sub ip_port_from_netloc {
my ($sentence) = @_;
return if $sentence !~ /
(?: \[ ( $IPv6_re ) \]
| ( $IPv4_re )
)
: ($port_re)
/msx;
return ($1 // $2, $3);
}
答案 1 :(得分:3)
零宽度断言不会被消耗,因此文字右括号仍然可以与第一个捕获组匹配。此调整似乎有效:
/
\[?( # capture either
(?<= \[ )
$IPv6_re # IPv6 address without brackets
(?= \] )
| # or
(?<! \[ )
$RE{net}{IPv4} # IPv4 address
(?! \] )
)\]?
: # colon sep. host from port
($port_re) # capture port
/msx;