【正则表达式介绍篇】

不打扰是莪最后的温柔 提交于 2019-11-27 20:24:06

原文: http://blog.gqylpy.com/gqy/381

"    正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为Regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。

    许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。正则表达式这个概念最初是由Unix中工具软件(例如sedgrep)普及开的。正则表达式通常缩写称“regex”,单数有regexp、regex,复数regexps、regexes、regexen。
***

概念

    正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特殊字符、及这个特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。

简介

    正则表达式是对字符串(包括普通字符(例如,a到z之间的字母)和特殊字符(称为“元字符”))操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。正则表达式是一种文本模式,模式描述在搜索文本时要匹配的一个或多个字符串。

起源

    正则表达式的“鼻祖”或许可一直追溯到科学家对人类神经系统工作原理的早期研究。美国新泽西州的Warren McCulloch和出生在美国底特律的Walter Pitts这两位神经生理方面的科学家,研究出了一种用数学方式来描述神经网络的新方法,他们创造性地将神经系统中的神经元描述成了小而简单的自动控制元,从而做出了一项伟大的工作革新。

    在1951年,一位名叫Stephen Kleene的数学科学家,他在Warren McCulloch和Walter Pitts早期工作的基础之上,发表了一篇题目是《神经网事件的表示法》的论文,利用称之为正则集合的数学符号来描述此模型,引入了正则表达式的概念。正则表达式被作为用来描述其称之为“正则集的代数”的一种表达式,因而采用了“正则表达式”这个术语。

    之后的一段时间,人们发现可以将这一工作成果应用于其它方面。Ken Thompson就把这一成果应用于计算搜索算法的一些早期研究,Ken Thompson是Unix的主要发明人,也就是大名鼎鼎的Unix之父。Unix之父将此符号系统引入编辑器QED,然后是Unix上的编辑器ed,并最终引入grep。Jeffrey Friedl在其著作《Mastering Regular Expressions (2nd edition)》(中文版译作:精通正则表达式,已出到第三版)中对此作了进一步阐述讲解,如果你希望更多了解正则表达式理论和历史,推荐你看看这本书。

    自此以后,正则表达式被广泛地应用到各种UNIX或类似于UNIX的工具中,如大家熟知大的Perl。Perl的正则表达式源自于Henry Spencer编写的regex,之后已演化成了pcre(Perl兼容正则表达式Perl Compatible Regular Expressions),pcre是一个由Philip Hazel开发的、为很多现代化工具所使用的库。正则表达式的第一个实用应用程序即为Unix中的qed编辑器。

    然后,正则表达式在各种计算机语言或各种应用领域得到了广大的应用和发展,演变称为计算机技术森林中的一只形神美丽且声音动听的百灵鸟。

    以上是关于正则表达式的起源和发展的历史描述,如今正则表达式在基于文本的编辑器和搜索工具中依据占据着一个非常重要的地位。

    在最近的六十年里,正则表达式逐渐从模糊而深奥的数学概念,发展成为计算机各类工具和软件包应用中的主要功能。不仅仅众多UNIX工具支持正则表达式,近二十年来,在WINDOWS的阵营下,正则表达式的思想和应用在大部分Windows开发者工具包中得到支持和嵌入应用!从正则式在Microsoft Visual Basic 6或Microsoft VBScript到.NET Framework中的探索和发展,WINDOWS系列产品对正则表达式的支持发展到无与伦比的高度,几乎所有Microsoft开发者和所有.NET语言都可以使用正则表达式。如果你是一位接触计算机语言的工作者,那么你会在主流操作系统(*nix[Linux, Unix等]、Windows、HP、BeOS等)、主流的开发语言(delphi、Scala、PHP、C#、Java、C++、Objective-c、Swift、VB、Javascript、Ruby以及Python等)、数以亿万计的各种应用软件中,都可以看到正则表达式优美的舞姿。

目的

给定一个正则表达式和另一个字符串,我们可以达到如下的目的:

  1. 给定的字符串是否符合正则表达式的过滤逻辑(称作“匹配”)。
  2. 可以通过正则表达式,从字符串中获取我们想要的特定部分。

特点

正则表达式的特点是:

  1. 灵活性、逻辑性和功能性非常强。
  2. 可以迅速地用极简单的方式达到字符串的复杂控制。
  3. 对于刚接触的人来说,比较晦涩难懂。

由于正则表达式主要应用对象是文本,因此它在各种文本编辑器场合都有应用,小到著名编辑器EditPlus,大到Microsoft Word、Visual Studio等大型编辑器,都可以使用正则表达式来处理文本内容。

引擎

    正则引擎主要可以分为两大类:一种是DFA,一种是NFA。这两种引擎都有很久的历史(至今二十多年),当中也由这两种引擎产生了很多变体!于是POSIX的出台规避了不必要变体的继续产生。这样一来,主流的正则引擎又分为三类:一是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不符合要求淘汰。nsen和nsem符合要求,然后DFA依次检查字符串,检测到sen中的n时只有nsen分支符合,则匹配成功!

    由此可以看出来,两种引擎的工作方式完全不同,一个(NFA)以表达式为主导,一个(DFA)以文本为主导!一般而论,DFA引擎则搜索更快一些!但是NFA以表达式为主导,反而更容易操纵,因此一般程序员更偏爱NFA引擎! 两种引擎各有所长,而真正的引用则取决与你的需要以及所使用的语言!


"

原文: http://blog.gqylpy.com/gqy/381

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!