2012-10-04 107 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'混合在一起 –