转载(正则表达式的分类) 规格严格

摘要:
正则引擎主要可以分为两大类:一种是DFA,一种是NFA。传统的NFA引擎运行所谓的“贪婪的”匹配回溯算法,以指定顺序测试正则表达式的所有可能的扩展并接受第一个匹配项。因为传统的NFA构造正则表达式的特定扩展以获得成功的匹配,所以它可以捕获子表达式匹配和匹配的反向引用。因为NFA工作方式是以正则表达式为标准,反复测试字符串,这样同样一个字符串有可能被反复测试了很多次!

正则引擎主要可以分为两大类:一种是DFA,一种是NFA。这两种引擎都有了很久的历史(至今二十多年),当中也由这两种引擎产生了很多变体!于是POSIX的出台产生规范了不必要变体的继续产生。这样一来,目前的主流正则引擎又分为3类:一、DFA,二、传统型NFA,三、POSIX NFA。

DFA 引擎在线性时状态下执行,因为它们不要求回溯(并因此它们永远不测试相同的字符两次)。DFA 引擎还可以确保匹配最长的可能的字符串。但是,因为 DFA 引擎只包含有限的状态,所以它不能匹配具有反向引用的模式;并且因为它不构造显示扩展,所以它不可以捕获子表达式。

传统的 NFA 引擎运行所谓的“贪婪的”匹配回溯算法,以指定顺序测试正则表达式的所有可能的扩展并接受第一个匹配项。因为传统的 NFA 构造正则表达式的特定扩展以获得成功的匹配,所以它可以捕获子表达式匹配和匹配的反向引用。但是,因为传统的 NFA 回溯,所以它可以访问完全相同的状态多次(如果通过不同的路径到达该状态)。因此,在最坏情况下,它的执行速度可能非常慢。因为传统的 NFA 接受它找到的第一个匹配,所以它还可能会导致其他(可能更长)匹配未被发现。

POSIX NFA 引擎与传统的 NFA 引擎类似,不同的一点在于:在它们可以确保已找到了可能的最长的匹配之前,它们将继续回溯。因此,POSIX NFA 引擎的速度慢于传统的 NFA 引擎;并且在使用 POSIX NFA 时,您恐怕不会愿意在更改回溯搜索的顺序的情况下来支持较短的匹配搜索,而非较长的匹配搜索。

目前使用DFA引擎的程序主要有:awk,egrep,flex,lex,MySQL,Procmail等;
使用传统型NFA引擎的程序主要有:GNU Emacs,Java,ergp,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

举例简单说明NFA与DFA工作的区别:
比如有字符串this is yansen’s blog,正则表达式为 /ya(msen|nsen|nsem)/ (不要在乎表达式怎么样,这里只是为了说明引擎间的工作区别)。
NFA工作方式如下,先在字符串中查找 y 然后匹配其后是否为 a ,如果是 a 则继续,查找其后是否为 m 如果不是则匹配其后是否为 n (此时淘汰msen选择支)。然后继续看其后是否依次为 s,e ,接着测试是否为 n ,是 n 则匹配成功,不是则测试是否为 m 。为什么是 m ?因为 NFA 工作方式是以正则表达式为标准,反复测试字符串,这样同样一个字符串有可能被反复测试了很多次!
而DFA则不是如此,DFA会从 this t 开始依次查找 y,定位到y ,已知其后为 a ,则查看表达式是否有 a ,此处正好有 a 。然后字符串 a 后为 n ,DFA依次测试表达式,此时 msen 不符合要求淘汰。nsennsem 符合要求,然后DFA依次检查字符串,检测到sen 中的n 时只有 nsen 分支符合,则匹配成功!

由此可以看出来,两种引擎的工作方式完全不同,一个(NFA)以表达式为主导,一个(DFA)以文本为主导!一般而论,DFA引擎则搜索更快一些!但是NFA以表达式为主导,反而更容易操纵,因此一般程序员更偏爱NFA引擎!

两种引擎各有所长,而真正的引用则取决与你的需要以及所使用的语言!

免责声明:文章转载自《转载(正则表达式的分类) 规格严格》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Golang协程与通道整理homebrew & brew cask使用技巧及Mac软件安装下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Notepad++正则表达式查找替换文本中文字符

测试需求 测试工具中xml配置文件中注释字段包含中文字符,在Win10系统下使用工具中偶尔会出现中文乱码导致配置文件失效。解决方法将配置文件中的中文注释换成英文注释或者直接替换删除。如何将配置文件中的中文字符查找删除? 操作步骤 在Notepad文本工具中使用正则表达式匹配中文字符并替换。当然你可以采用Python写个小工具也无不可。Notepad中使用正...

grep、egrep命令用法

何谓正则表达式 正则表达式,又称正规表示法、常规表示法(Regular Expression,在代码中常简写为regex、regexp或RE),是一类字符所书写的模式,其中许多字符不表示其字面意义,而是表达控制或通配等功能。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模...

python正则表达式匹配中文日期时间

今天分享一个Python正则表达式匹配日期与时间的方法,因为最近在做的项目需要从字符串里面把日期时间提取出来。 不多说,直接上代码: import re from datetime import datetime #python正则表达式匹配中文日期时间 test_date = '他的生日是2016-12-12 14:34,是个可爱的小宝贝.二宝的生日...

(20135213)信息安全系统设计基础第一周学习总结(共12课)课程(6~12)

【所有参考资料皆来源与实验楼,特此声明】 【第六课】 文件打包与压缩 实验介绍 Linux 上常用的 压缩/解压 工具,介绍了 zip,rar,tar 的使用。 一、文件打包和解压缩 在讲 Linux 上的解压缩工具之前,有必要先了解以下常见常用的压缩包文件格式。在 Windows 上我们最常见的不外乎这三种*.zip,*.rar,*.7z后缀的压缩文件,...

linux基础知识-24

一、正则表达式 正则表达式 (regular expression),简写(regex),用来描述一些表达复杂模式的方法。linux中的grep, vi, find, sed等命令都支持正则表达式。 linux@myccloves:~$ grep '^VER' /etc/os-release VERSION_ID="15.6" VERSION="15.6...

shell正则表达式

前言   正则表达式是一个字符串处理的标准依据。是使用单个字符串搜索、匹配一系列符合某个语法规则的字符串。通过特殊字符+普通字符来进行模式描述,从而达到文本匹配目的。 一、正则表达式分类 字符类 数量限定符 位置限定符 1.1 字符类 元字符 功能 举例 . 匹配除了换行符之外的任意一个字符 #egrep a.b 文件名;表示匹配文件中a跟b之...