根据this page(以及其他一些人),DFA正则表达式引擎可以很好地处理群组。我对原子团体(或占有量词)感到好奇,因为我最近使用它们很多,无法想象如何做到这一点。
我不同意答案的第一部分:
DFA不需要像原子分组那样处理构造......原子分组是一种帮助引擎完成匹配的方法,否则会导致无休止的回溯
原子组不仅对于NFA引擎的速度很重要,而且还允许编写更简单且不易出错的正则表达式。假设我需要在程序中找到所有C风格的多行注释。确切的正则表达式将是:
/*
*
*
后跟除/
*/
这听起来有点复杂,正则表达式
/\* ( [^*] | \*[^/] )+ \*/
复杂而错误(它无法正确处理/* foo **/
)。使用不情愿(懒惰)量词更好
/\* .*? \*/
但也错了,因为它可以吃掉整条线
/* foo */ @#$!!**@#$ /* bar */
当由于后来的子表达式失败而导致的回溯发生时。将上述内容放在一个原子组中很好地解决了这个问题:
(?> /\* .*? \*/ )
这总是(我希望)并且尽可能快(对于NFA)。所以我想知道DFA引擎是否能以某种方式处理它。
答案 0 :(得分:1)
DFA不需要处理像原子分组这样的结构。 DFA是“文本导向的”,与NFA不同,后者是“正则表达式”,换句话说: 原子分组是一种帮助引擎完成匹配的方法,否则会导致无休止的回溯,因为(NFA)引擎尝试在每个排列位置找到匹配,甚至不可能匹配。
简单地说,原子分组会抛弃后退位置。由于DFA不会回溯(要匹配的文本是针对正则表达式进行检查,而不是像NFA那样对文本进行正则表达式检查 - DFA会为每个决定打开一个分支),丢弃一些不存在的东西是毫无意义的。
我建议J.F.Friedl的掌握正则表达式(Google Books),他解释了DFA的一般概念:
DFA引擎:文字导向
将正则表达式导向的NFA引擎与引擎对比 扫描字符串,跟踪“当前在中的所有匹配” “在今晚的例子中,当发动机达到t时,它会增加 与其当前正在进行的列表的潜在匹配:
[...]
扫描的每个后续字符都会更新可能的列表 火柴。经过几个字符匹配后的情况 变
[...]
有两个可能的比赛正在进行中(还有一个替代,骑士, 排除)。随后的g,只有第三种选择 仍然可行。一旦h和t被扫描,发动机 意识到它完全匹配并且可以返回成功。
我将此称为“文本导向”匹配,因为每个字符都是扫描的 从文本控制引擎。如示例中所示,部分匹配 可能是任何数量的不同但可能的比赛的开始。 不再可行的匹配被修剪为后续字符 扫描。甚至有些情况下“部分匹配” 进步“也是完全匹配。如果正则表达式是⌈to(...)?⌋,那么 例如,带括号的表达式变为可选,但它仍然是 贪心,所以总是尝试。部分匹配的所有时间 在这些括号内进行,完全匹配('to') 已经确认并保留,以防较长的比赛不平息 进行。
关于捕获群组和DFA:就我能从您的链接中理解而言,这些方法不是纯粹的DFA引擎,而是DFA和NFA的混合。