正则引擎的分类
Regex Engine Types
正则引擎主要可以分为基本不同的两大类:一种是DFA(相当于之前说的电动机),另一种是NFA(相当于前面的汽油机)。我们很快就会知道DFA和NFA的具体含义,但是现在读者只需要知道这两个名字,就像“Bill”和“Ted”,“汽油机”和“电动机”一样。
DFA和NFA都有很长的历史,不过,正如汽油机一样,NFA的历史更长一些。使用NFA的工具包括.NET、PHP、Ruby、Perl、Python、GNU Emacs、ed、sec、vi、grep的多数版本,甚至还有某些版本的egrep和awk。而采用DFA的工具主要有egrep、awk、lex和flex。也有些系统采用了混合引擎,它们会根据任务的不同选择合适的引擎(甚至对同一表达式中的不同部分采用不同的引擎,以求得功能与速度之间的最佳平衡)。表4-1列出了少量常用的工具及其大多数版本使用的引擎。如果你最喜欢的工具没有名列其中,可以参考下一页的“测试引擎的类型”来找到答案。
表4-1:部分程序及其所使用的正则引擎
|
引擎类型 |
程 序 |
|
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 |
第3章已经讲过,NFA和DFA都发展了二十多年,产生了许多不必要的变体,结果,现在的情况比较复杂。POSIX标准的出台,就是为了规范这种现象,POSIX标准不但清楚地规定了前一章中提到的引擎应该支持的元字符和特性,还明确规定了使用者期望由表达式获得的准确结果。除开表面细节不谈,DFA(也就是电动机)显然已经符合新的标准,但是NFA风格的结果却与此不一,所以NFA需要修改才能符合标准。这样一来,正则引擎可以粗略地分为3类:
DFA(符合或不符合POSIX标准的都属此类)。
传统型NFA。
POSIX NFA。
这里提到的POSIX是匹配意义上的,也就是说,POSIX标准规定的某个正则表达式的应有行为(本章稍后部分将讨论);而不是指POSIX标准引入的匹配特性。许多程序支持这些特性,但结果与POSIX规范不完全一致。
老式(功能极少的)程序,比如egrep、awk、lex之类,一般都是使用DFA引擎(电动机),所以,新的标准只是肯定了既有的情况,而没有大的改变。但是也存在一些汽油机版本的此类程序,如果它们需要达到POSIX标准,就需要做些修改。通过了加州排放标准测试(POSIX NFA)的汽油机能够产生符合标准的结果,但是这些必要的修改会增加保养的难度。以前,错位的火花塞也能应付着使用,但现在根本就点不着火。以前还能“凑合”的汽油,现在会弄得发动机砰砰乱响。不过,一旦掌握其中的门道,发动机就能平稳安静地运转了。
几句题外话
From the Department of Redundancy Department
现在,我请读者回过头去,重新思考关于引擎的故事。其中的每句话都涉及某些与正则表达式相关的事实。读第二遍会引起许多思考。尤其是,为什么说电动机(DFA引擎)只是“能够运行”。什么影响了汽油机(NFA)?使用NFA引擎时,应该如何调整才能获得期望的结果?通过(排放)测试的POSIX DFA有什么特别之处?现实中“熄火的引擎”又是什么?
【责任编辑:
雪花 TEL:(010)68476606】