可以使用正则表达式来匹配嵌套模式吗?
是否可以编写匹配出现未知次数的嵌套模式的正则表达式?例如,当外部括号内嵌套的打开/关闭括号的数量未知时,正则表达式可以匹配打开和关闭括号吗?
例如:
public MyMethod() { if (test) { // More { } } // More { } } // End
应该匹配:
{ if (test) { // More { } } // More { } }
解决方案
不,那时候我们将进入上下文无关文法领域。
否。我们需要一个成熟的解析器来解决这种类型的问题。
不,就这么简单。有限自动机(即正则表达式基础的数据结构)除了处于其所在的状态外没有其他内存,并且如果我们具有任意深度的嵌套,则需要一个任意大的自动机,它会与有限自动机的概念相冲突。
我们可以将嵌套/配对的元素匹配到固定深度,该深度仅受内存限制,因为自动机变得非常大。但是实际上,我们应该使用下推式自动机,即用于上下文无关文法的解析器,例如LL(自上而下)或者LR(自下而上)。我们必须考虑更糟糕的运行时行为:O(n ^ 3)vs. O(n),其中n = length(input)。
有许多可用的解析器生成器,例如Java的ANTLR。查找Java(或者C)的现有语法也不难。
更多背景信息:Wikipedia上的自动机理论
如果字符串在一行上,则可能工作的Perl解决方案:
my $NesteD ; $NesteD = qr/ \{( [^{}] | (??{ $NesteD }) )* \} /x ; if ( $Stringy =~ m/\b( \w+$NesteD )/x ) { print "Found: \n" ; }
高温超导
编辑:检查:
- http://dev.perl.org/perl6/rfc/145.html
- 红宝石信息:http://www.ruby-forum.com/topic/112084
- 更多perl:http://www.perlmonks.org/?node_id=660316
- 甚至更多的perl:https://metacpan.org/pod/Text::Balanced
- perl,perl,perl:http://perl.plover.com/yak/regex/samples/slide083.html
还有Torsten Marek(正确指出,它不再是正则表达式)的另一件事:
- http://coding.derkeiler.com/Archive/Perl/comp.lang.perl.misc/2008-03/msg01047.html
常规语言的Pumping引理是我们无法做到这一点的原因。
生成的自动机将具有有限数量的状态,例如k,因此一串k + 1个大括号必然会在某处重复一个状态(因为自动机处理字符)。同一状态之间的字符串部分可以无限次重复,并且自动机将不知道区别。
特别是,如果它接受k + 1个开括号,然后接受k + 1个闭括号(它应该),那么它也将接受泵送数量的开括号,再加上不变的k + 1个闭括号(不应该)。
正确的正则表达式将无法做到这一点,因为我们将离开正则语言领域进入上下文无关语言领域。
但是,许多语言提供的"正则表达式"软件包严格更强大。
例如,Lua正则表达式具有匹配平衡括号的"%b()"识别器。在情况下,我们将使用"
%b {}`"
另一个与sed相似的高级工具是gema,我们可以在其中轻松地使用" {#}"来匹配平衡的花括号。
因此,根据可用的工具,"正则表达式"(广义上)可能可以匹配嵌套的括号。
正如zsolt所提到的,某些正则表达式引擎支持递归-当然,这些通常是使用回溯算法的引擎,因此它并不是特别有效。例如:/(?> [^ {}] *){(?> [^ {}] *)(?R)*(?> [^ {}] *)} / sm
是的,如果它是.NET RegEx引擎。 .Net引擎支持外部堆栈提供的有限状态机。查看具体信息
这似乎可行:/(\ {(?:\ {。* \} | [^ \ {])* \})/ m
使用正则表达式检查嵌套模式非常容易。
'/(\((?>[^()]+|(?1))*\))/'