2012-10-04 139 views
7

我試圖匹配像sp { ...{...}... }這樣的文本,允許在其中嵌套大括號。這是我到目前爲止有:正則表達式與遞歸表達式匹配嵌套大括號?

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; 

我只是無法得到它下面的文本匹配:sp { { word } }。任何人都可以看到我的正則表達式有什麼問題嗎?

回答

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,它真的是補充正則表達式,特別是正則表達式'gc'(解析器)功能。這就是爲什麼它使用字符串的「pos」,因爲預計你會將'text_balanced'調用與'// gc'混合在一起 –