2012-04-15 2 views
2

이것은 후속 조치입니다 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과 일치 함을 나타냅니다. ?으로 탐욕을 끄지 않았기 때문에 이것은 놀랍습니다. 나는 그것이 ]까지 모든 것을 중얼 거릴 것으로 예상하고, 그 다음에 분리 콜론 (colon)과 일치하며 그 다음은 뒤를 따릅니다.

왜 이런 일이 발생하며 어떻게 해결됩니까?

답변

6

탐욕은 놀이로 올 것 (즉 당신이 *, +, ? 또는 {n,m}를 사용하는 경우). 이것은 탐욕의 문제가 아닙니다.

문제는 "]"과 ":"바로 뒤에 정규식이 IPv6 주소와 일치한다는 것입니다. 그것은 일어날 수 없다.

당신은 두 개의 서로 다른 경기를 사용할 수 있습니다, 또는 당신은 같은 것을 사용할 수 있습니다 다음

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); 
} 

어쩌면이 조금 청소기입니다?

my $port_re = list2re 0..65535; 
my $IPv4_re = $RE{net}{IPv4}; 

sub ip_port_from_netloc { 
    my ($sentence) = @_; 
    return if $sentence !~/
     (?: \[ (?<addr> $IPv6_re) \] 
     |  (?<addr> $IPv4_re) 
     ) 
     : (?<port> $port_re) 
    /msx; 

    return ($+{addr}, $+{port}); 
} 
+0

또 다른 이상한 가능성 : 미리보기에서 대괄호를 캡처하고 캡처 후에'(? (2) \ 2)'를 사용하십시오. 하지만 ('(...) [0,2]') 매치 결과에리스트 슬라이스를 사용해야합니다. – ikegami

+0

아, 와우, 명명 된 캡처 그룹은 확실히 예쁘다! –

+0

@ 리차드 Simões, 5.10, IIRC에서 도입, 다른 것들의 무리와 함께. – ikegami

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; 
+0

그래, 거의 게시했지만 너무 복잡한 것으로 나타났습니다. 당신이 이미 무엇을하는지 알고 있다면,이 것이 무엇인지를 결정하기 위해 진지한 연구가 필요합니다. – ikegami