转载请注明出处 https://www.cnblogs.com/majianming/p/11823697.html
目前常见的正则表达引擎总体分为2种,DFA (确定型有穷状态自动机) 和 NFA (非确定型有穷状态自动机)
如果细分,NFA 可以分为传统NFA和POSIX NFA
那么如何区分3者
如果某种正则引擎如果他不能匹配能很快给出结果,那么他可能是DFA
如果只有在能够匹配的时候才能快速给出结果,那么就是传统NFA
如果无论能不能匹配,匹配的时间都基本一致,那么就是POSIX NFA
why ?
首先先看 DFA,DFA 是文本主导的表达式引擎,实际上,对于确定的DFA表达式,状态的个数是确定的,这个也是为什么是确定型有穷状态
通过DFA 表达式,可以分析出所有可能的匹配路径,也就是说,在匹配还没开始的时候,所有路径都已经确定了(如果遇到某个字符 就走某个指定的路径),接下来需要做的就是在匹配文本,然后删掉不符合的路径,如果中途存在没有的路径,那么匹配失败,如果到最后存在多条匹配成功的路径,那么取匹配最长的路径
另外DFA 不支持反向引用和环视
而NFA 是表达式主导的引擎,也就是说实际上是拿文本到表达式测试,如果成功就继续匹配,失败就回溯或者选择其他分支或者报告匹配失败
在NFA中分为两种引擎,传统NFA和POSIX NFA
传统NFA和POSIX NFA的区别是传统NFA 如果如果找到一个匹配,那么就会直接报告这个匹配,POSIX NFA会尝试所有可能的匹配,如果有多个匹配,返回最长最左的匹配
所以在能够匹配的时候NFA 只需要找到一个匹配就能返回了,相对速度会很快,因为POSIX NFA 需要尝试所有可能才会报告是否匹配成功,所以时间是一致的。
引擎类型 | 程序 | 忽略优先量词(懒惰) | 捕获型括号 | 回溯 |
---|---|---|---|---|
DFA | awk (大多数版本)、egrep (大多数版本)、flex 、lex 、MySQL、Procmail |
不支持 | 不支持 | 不支持 |
传统型 NFA | GNU Emacs、Java、grep (大多数版本)、less 、more 、.NET 语言、PCRE library、Perl、PHP(所有三套正则库)、Python、Ruby、sed(大多数版本)、vi |
支持 | 支持 | 支持,但性能差 |
POSIX NFA | mawk 、Mortice Kern Systems’utilities、GNU Emacs(明确指定时使用) |
不支持 | 支持 | 支持,但性能差 |
DFA/NFA 混合 | GNU awk 、GNU grep/egrep 、Tcl |
支持 | 支持 | DFA 支持 |