2012-10-04 14 views
7

Kıvırcık parantezlerin yuvalanmasına izin verilen sp { ...{...}... } gibi metin eşleştirmeye çalışıyorum. sp { { word } }:İç içe geçmiş parantezleri eşleştirmek için özyinelemeli ifade ile regex?

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; 

Sadece aşağıdaki metni maç için alınamıyor: Bu defa ne var. Regex'imle neyin yanlış olduğunu gören var mı?

cevap

6

Çok sayıda sorun var. özyinelemeli bit olmalıdır: Hep birlikte

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

:

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

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

Sadece ihtiyacım olan şey. –

+0

Anlatabildiğim kadarıyla, normal ifade, parantez etrafındaki boşluklara (kafiye için özür) izin vermez, bu nedenle test durumu başarısız olur. Ne var ne yok? – tripleee

+0

Hmmm ... Bu, bazı kısmi eşleşmeler için sonsuza dek sürüyor, şöyle ki: "sp {word {(aaaaaaaaaaaaaaaaaaaaaaaaaaaaa)}". –

5

Bu kapatacağı Text::Balanced, bu tür şeyleri için çok kullanışlı çekirdek modülü için geçerlidir. İlk set/bulunmasıyla birlikte sınırlandırılmış dizisinin başlangıcının pos itimat yok, bu yüzden genellikle bu gibi çağırmak:

#!/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 değiştirici ile regex dize söyler

hatırlıyorum nerede son noktası eşleşme ve extract_bracketed, nereden başlayacağını bilmek için bu bilgileri kullanır.

+0

Bu modülü gerçekten okumam gerekiyor. Çok fazla geliyor ama her zaman düzenli ifadeyi tercih ediyorum çünkü öğrenmeye çok zaman harcadım, daha fazlasını öğrenmek eğlenceli ve daha kompakt görünüyor. Cevap için teşekkürler! –

+0

@NateGlenn, gerçekten regexp ve özellikle regexp 'gc' (ayrıştırıcı) işlevselliğini tamamlayıcıdır. Bu yüzden dizgenin 'pos'unu kullanır, çünkü '// gc' ile text_balanced' işlevlerini arayacağınız beklenir. –