增强Perl正则表达式以实现平衡匹配

时间:2014-10-03 07:06:56

标签: regex perl

我经常使用以下正则表达式进行平衡匹配

my $np;
$np = qr{
                \{
                (?:
                        (?> [^\{\}]+ )
                    |
                        (??{ $np })
                )*
                \}
            }x;
例如,

my $text = "{string{string1}{string2}}";
$text =~ /($np)/;

问题是它是否可以扩展,以便在string等包含}{前面加上反斜杠时也匹配。这意味着在执行平衡匹配时,应忽略转义的大括号(与任何其他字符一样对待)。

1 个答案:

答案 0 :(得分:3)

不确定。您所要做的就是将“任何其他字符”表达式更改为将接受转义大括号以及“除括号之外的任何内容”的

(?>  (?: \\[()] | [^{}] )+  )

另请注意,(??{ $np })构造早已被取代,如果您拥有Perl 5的10或更高版本,则可以使用内置的递归机制,从而{{1将从一开始就递归整个表达式。

(?R)

<强>输出

use strict;
use warnings;
use 5.010;

my $np = qr{
  \{
    (?:
      (?>
        (?: \\\\ | \\} | \\} | [^{}] )*
      )
    |
      (?R)
    )*
  \}
}xs; 

my $text = '{string{string1 \} test}{string2}}';
$text =~ /($np)/;

say $1;

请注意,我不相信“no backtrack”构造{string{string1 \} test}{string2}} 在这里很有用。已指定中间字符串,以便之后的任何内容必须匹配下一个标记或字符串的结尾,并且没有非贪婪的通配符。但我确信它没有任何伤害,所以我把它留在了。


<强>更新

为了允许在第一个常规大括号之前转换大括号,最简单的方法是为“常规字符”编写一个单独的正则表达式,这只不过是一个开头或关闭支撑,或逃脱任何东西。

喜欢这个

(?> ... )

<强>输出

use strict;
use warnings;
use 5.010;

my $reg_char = qr/(?: \\. | [^{}] )/xs;  # Define what *isn't* a brace

my $np = qr{
  \{
    (?:
      (?> $reg_char* )
    |
      (?R)
    )*
  \}
}x; 

my $text = 'aaa \{ bbb {string{string1 \} test}{string2}}';
die unless $text =~ / $reg_char* ($np) /x;

say $1;