我经常使用以下正则表达式进行平衡匹配
my $np;
$np = qr{
\{
(?:
(?> [^\{\}]+ )
|
(??{ $np })
)*
\}
}x;
例如,,
my $text = "{string{string1}{string2}}";
$text =~ /($np)/;
问题是它是否可以扩展,以便在string
等包含}
或{
前面加上反斜杠时也匹配。这意味着在执行平衡匹配时,应忽略转义的大括号(与任何其他字符一样对待)。
答案 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;