2012-10-04 2 views
7

sp { ...{...}... }과 같은 텍스트를 찾으려고합니다. 중괄호는 중첩 할 수 있습니다. sp { { word } } :중첩 된 중괄호와 일치하는 재귀식이있는 정규식?

my $regex = qr/ 
(     #save $1 
    sp\s+   #start Soar production 
    (    #save $2 
     \{   #opening brace 
     [^{}]*  #anything but braces 
     \}   #closing brace 
     | (?1)  #or nested braces 
    )+    #0 or more 
) 
/x; 

내가 그냥 다음 텍스트와 일치하는 얻을 수 없다 : 이것은 내가 지금까지있는 것입니다. 누구든지 내 정규식에 어떤 문제가 있는지 확인할 수 있습니까?

답변

6

많은 문제가 있습니다. 재귀 비트는해야한다 : 모두 함께

(
    (?: \{ (?-1) \} 
    | [^{}]+ 
    )* 
) 

:

my $regex = qr/ 
    sp\s+ 
    \{ 
     (
     (?: \{ (?-1) \} 
     | [^{}]++ 
     )* 
    ) 
    \} 
/x; 

print "$1\n" if 'sp { { word } }' =~ /($regex)/; 
+0

내가 필요한 것. –

+0

거의 알 수 있듯이, 정규 표현식은 중괄호 주위에 공백을 허용하지 않으므로 (운율에 대해 유감 스럽습니다) 테스트 케이스가 실패해야합니다. 그게 뭐야? – tripleee

+0

흠 ... 이것은 다음과 같이 일부 부분 일치를 위해 영원히 끝납니다 :'sp {word {(aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)}'. –

5

이되지 않고있는 Text::Balanced, 이런 종류의 일을위한 매우 편리한 핵심 모듈에 대한 경우입니다. 그것은 먼저 설정/발견되는 구분 된 시퀀스의 시작의 pos에 의존 않는, 그래서 일반적으로이처럼 호출 :

#!/usr/bin/env perl 

use strict; 
use warnings; 

use Text::Balanced 'extract_bracketed'; 

sub get_bracketed { 
    my $str = shift; 

    # seek to beginning of bracket 
    return undef unless $str =~ /(sp\s+)(?={)/gc; 

    # store the prefix 
    my $prefix = $1; 

    # get everything from the start brace to the matching end brace 
    my ($bracketed) = extract_bracketed($str, '{}'); 

    # no closing brace found 
    return undef unless $bracketed; 

    # return the whole match 
    return $prefix . $bracketed; 
} 

my $str = 'sp { { word } }'; 

print get_bracketed $str; 

gc 수정과 정규식은 문자열을 알려줍니다

이 기억하는 곳의 끝점 경기는이고, extract_bracketed은 그 정보를 사용하여 어디에서 시작해야하는지 알 수 있습니다.

+0

정말이 모듈을 읽어야합니다. 그것은 많이 나오지만, 정규 표현식을 선호합니다. 왜냐하면 이미 그것을 배우는 데 너무 많은 시간을 투자했기 때문에, 더 배우기가 더 재미 있고 더 조밀 해 보입니다. 답변 해주셔서 감사합니다! –

+0

@NateGlenn, 그것은 regexp와 특히 regexp'gc' (파서) 기능을 보완합니다. 이것이 문자열의'pos'를 사용하는 이유입니다. 왜냐하면'text_balanced'에 대한 호출을'/ gc'와 혼합 할 것으로 예상되기 때문입니다. –