2013-04-15 4 views
0

초보자 용 질문입니다. 코드에서 :Perl에서 겹쳐지는 패턴 일치

$a = 'aaagggaaa'; 

(@b) = ($a =~ /(a.+)(g.+)/); 

print "$b[0]\n"; 

aaagg하지 aaa 동일 $b[0]입니까? 즉, 두 번째 그룹 인 (g.+)이 마지막으로 만 일치하는 이유는 g입니까?

+0

Perl 정규 표현식 엔진이 실제로 작동하는지 보려면 [Regexp :: Debugger] (https://metacpan.org/pod/Regexp::Debugger) 모듈에서 'rxrx' 유틸리티를 사용해보십시오. 매우 시원하고 교육적입니다. – jreisinger

답변

3

첫 번째 .+은 "greedy"이므로 가능하면 많은 문자를 일치 시키려고합니다.
이 "욕심 많은"동작을 끄려면 .+.+?으로 바꿀 수 있으므로 /(a.+?)(g.+)/은 ('aaa', 'gggaaa')를 반환합니다.

어쩌면 /(a+)(g+)/ (첫 번째 그룹에만 'a', 두 번째 그룹에는 'g'만 쓸 수 있습니다.

1

펄 정규 표현식은 일반적으로 가능한 가장 긴 문자열과 일치합니다.

코드에서이 코드는 마지막 g과 일치하고 aaagg을 반환합니다. aaa으로 결과를 얻으려면 비 탐욕적인 행동을 사용해야합니다.

aaa 

분명히, question mark의 사용이 경기 ungreedy한다 : 출력 그것은 것

$a = 'aaagggaaa'; 
(@b) = ($a =~ /(a.+?)(g.+)/); 
print "$b[0]\n"; 

:이 코드를 사용합니다.

1

정규 표현식 당신이 쓴 :

($a =~ /(a.+)(g.+)/); 

이 더 많은 문자 다음에 한 "g"을 마무리 "a" 어떤 단어가 할 수있는 한을이나 저전압. 그래서 첫 번째 (a.+)는 정규 표현식의 두 번째 부분의 경기까지 "aaagg" 일치 : (g.+) =>"gaaa"

@b 배열이 두 경기를 "aaagg""gaaa"를받습니다. 따라서 $b[0]"aaagg"만을 인쇄합니다.

0

보통 정규 표현식은 욕심이 있습니다. 당신은 ? 문자를 사용하여 해제 할 수 있습니다

$a = 'aaagggaaa'; 
my @b = ($a =~ /(a.+)(g.+)/); 
my @c = ($a =~ /(a.+?)(g.+)/); 
print "@b\n"; 
print "@c\n"; 

출력 :

aaagg gaaa 
aaa gggaaa 

그러나 나는 이것이 당신이 원하는 확실하지 않다! abagggbb은 어떨까요? aba이 필요합니까?

1

첫 번째 .+g이되도록 오른쪽으로 매치되는 것이 문제입니다.
실제로 무엇이 일어나고 있는지 보여주기 위해 코드를 수정하여 debug 정보를 더 자세히 보여 주도록 수정했습니다.

Compiling REx "a.+[g ]" 
Final program: 
    1: EXACT <a> (3) 
    3: PLUS (5) 
    4: REG_ANY (0) 
    5: ANYOF[ g][] (16) 
    16: END (0) 
anchored "a" at 0 (checking anchored) minlen 3 
.+이 함께 시작하는이 할 수있는 모든 것을 캡처하는 것을
Guessing start of match in sv for REx "a.+[g ]" against "aaagggaaa" 
Found anchored substr "a" at offset 0... 
Guessed: match at offset 0 
Matching REx "a.+[g ]" against "aaagggaaa" 
    0 <> <aaagggaaa>   | 1:EXACT <a>(3) 
    1 <a> <aagggaaa>   | 3:PLUS(5) 
            REG_ANY can match 8 times out of 2147483647... 
    9 <aaagggaaa> <>   | 5: ANYOF[ g][](16) 
            failed... 
    8 <aaagggaa> <a>   | 5: ANYOF[ g][](16) 
            failed... 
    7 <aaaggga> <aa>   | 5: ANYOF[ g][](16) 
            failed... 
    6 <aaaggg> <aaa>   | 5: ANYOF[ g][](16) 
            failed... 
    5 <aaagg> <gaaa>   | 5: ANYOF[ g][](16) 
    6 <aaaggg> <aaa>   | 16: END(0) 
Match successful! 
Freeing REx: "a.+[g ]" 

공지 사항

$ perl -Mre=debug -e'q[aaagggaaa] =~ /a.+[g ]/' 
.
그런 다음 g이 일치 할 때까지 역 추적해야합니다. 당신이 원하는 정규식 알고하는 것은 불가능합니다, 당신에서 더 많은 정보가 없으면

/(a+ )(g+ )/x; 
/(a.+? )(g.+)/x; 
/(a+ )(g.+)/x; 
/(a[^g]+)(g.+)/x; 
/(a[^g]+)(g+ )/x; 
# etc. 

: 당신은 아마 원하는 것은


중 하나입니다.

정말 정규 표현식은 그 자체만으로도 Perl의 나머지 부분보다 복잡한 언어입니다.