2010-12-15 2 views

답변

22

이는 official FAQ answer을 뺀 이후의 편집이다.

첫 번째 시도는 아마 펄 5.8 이후 펄 표준 라이브러리에있는 Text::Balanced 모듈해야한다. 그것은 까다로운 텍스트를 다루는 다양한 기능을 가지고 있습니다. Regexp::Common 모듈은 사용할 수있는 통조림 패턴을 제공하여 도움을받을 수도 있습니다.

펄 5.10, 당신은 재귀 패턴을 사용하여 정규 표현식 균형 텍스트를 일치시킬 수 있습니다. Perl 5.10 이전에는 (??{}) 시퀀스의 Perl 코드 사용과 같은 다양한 트릭에 의지해야했습니다.

여기에 재귀 정규 표현식을 사용하는 예입니다. 목표는 중첩 된 꺾쇠 괄호 안에있는 텍스트를 포함하여 꺾쇠 괄호 안에있는 모든 텍스트를 캡처하는 것입니다. 이 샘플 텍스트에는 하나의 중첩 수준이있는 그룹과 두 개의 중첩 수준이있는 그룹이라는 두 개의 "주요"그룹이 있습니다.

I have some <brackets in <nested brackets> > and 
<another group <nested once <nested twice> > > 
and that's it. 

균형 텍스트와 일치하는 정규 표현식은 두 개의 새로운 (펄 5.10) 정규 표현식 기능을 사용 꺾쇠 괄호 다섯 개 전체 그룹이 있습니다. 이 내용은 perlre에 있으며이 예제는 해당 설명서에서 수정 된 버전입니다. 어떤 정량에 새 소유 +을 추가하는 첫 번째

는 가장 긴 일치를 발견하고 역 추적하지 않습니다. 이것은 역 추적이 아닌 재귀를 통해 꺾쇠 괄호를 처리하기 때문에 중요합니다. 그룹 [^<>]++은 역 추적없이 하나 이상의 앵글 괄호를 찾습니다.

둘째, 새로운 (?PARNO)PARNO에 의해 주어진 특정 캡처 그룹의 하위 패턴을 참조합니다. 다음 정규 표현식에서 첫 번째 캡처 그룹은 균형 잡힌 텍스트를 찾고 기억합니다. 중첩 된 텍스트를 지나치려면 첫 번째 버퍼 내에서 동일한 패턴이 필요합니다. 그것은 재귀적인 부분입니다. (?1)은 외부 캡처 그룹의 패턴을 정규 표현식의 독립적 인 부분으로 사용합니다.

모두 함께 퍼팅, 당신이 :

#!/usr/local/bin/perl5.10.0 

my $string =<<"HERE"; 
I have some <brackets in <nested brackets> > and 
<another group <nested once <nested twice> > > 
and that's it. 
HERE 

my @groups = $string =~ m/ 
     (     # start of capture group 1 
     <     # match an opening angle bracket 
      (?: 
       [^<>]++  # one or more non angle brackets, non backtracking 
        | 
       (?1)  # found <or>, so recurse to capture group 1 
      )* 
     >     # match a closing angle bracket 
     )     # end of capture group 1 
     /xg; 

$" = "\n\t"; 
print "Found:\n\[email protected]\n"; 

출력은 펄이 두 가지 주요 그룹이 발견 보여줍니다 약간의 추가 작업으로

Found: 
    <brackets in <nested brackets> > 
    <another group <nested once <nested twice> > > 

을, 당신은의 모두를 얻을 수 있습니다 그룹은 다른 꺾쇠 괄호에도 있지만 꺽쇠 괄호 안에 있습니다. 균형 잡힌 일치가 생길 때마다 바깥 쪽 구분 기호 (방금 찾은 것과 일치하므로 다시 일치하지 않음)를 제거하고이를 처리 할 문자열 큐에 추가하십시오. 일치 항목이 없을 때까지 계속하십시오.

#!/usr/local/bin/perl5.10.0 

my @queue =<<"HERE"; 
I have some <brackets in <nested brackets> > and 
<another group <nested once <nested twice> > > 
and that's it. 
HERE 

my $regex = qr/ 
     (     # start of bracket 1 
     <     # match an opening angle bracket 
      (?: 
       [^<>]++  # one or more non angle brackets, non backtracking 
        | 
       (?1)  # recurse to bracket 1 
      )* 
     >     # match a closing angle bracket 
     )     # end of bracket 1 
     /x; 

$" = "\n\t"; 

while(@queue) 
    { 
    my $string = shift @queue; 

    my @groups = $string =~ m/$regex/g; 
    print "Found:\n\[email protected]\n\n" if @groups; 

    unshift @queue, map { s/^<//; s/>$//; $_ } @groups; 
    } 

출력에 모든 그룹이 표시됩니다. 가장 바깥 쪽 일치하는 첫 번째 표시 등 최대 나중에 중첩 경기 :

Found: 
    <brackets in <nested brackets> > 
    <another group <nested once <nested twice> > > 

Found: 
    <nested brackets> 

Found: 
    <nested once <nested twice> > 

Found: 
    <nested twice> 
관련 문제