Perl에서 대괄호로 묶인 텍스트를 일치시키고 싶습니다. 어떻게해야합니까?Perl 정규 표현식을 사용하여 균형 잡힌 텍스트를 일치시킬 수 있습니까?
이것은 official perlfaq의 질문입니다. 우리는 importing the perlfaq to Stack Overflow입니다.
Perl에서 대괄호로 묶인 텍스트를 일치시키고 싶습니다. 어떻게해야합니까?Perl 정규 표현식을 사용하여 균형 잡힌 텍스트를 일치시킬 수 있습니까?
이것은 official perlfaq의 질문입니다. 우리는 importing the perlfaq to Stack Overflow입니다.
이는 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>