文档章节

浅谈正则表达式背后的原理

这里好像没有人
 这里好像没有人
发布于 2017/01/07 14:54
字数 1597
阅读 15
收藏 0

一、写在前面

搞编程的都知道正则表达式是什么东西,这里就不多啰嗦了,需要强调的是,这篇文章并不是教你怎么去使用用正则表达式,正则表达式的语法并不是本文的重点,这篇文章的目的就是剥开正则表达式的语法糖,来看一看正则表达式最本质的原理,如果文章中有错误或者纰漏,欢迎批评指正。

二、什么是语法糖

在上面我提到了语法糖的概念,也许有人还不清楚语法糖是什么东西,这里简单的说一下。

语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会。——摘自 百度百科

可以这么说吧,像C、C++、Java等等这些编程语言都可以看做成语法糖,因为最终还是得将这些高级程序语言翻译成机器代码,也就是10101……这样的形式,要知道所有的可执行程序最终都可以只需要赋值跳转两种结构即可,而高级语言都是对这两种结构的封装,来适应不同的应用场景,除了机器代码,汇编和这些高级语言都是语法糖,一层一层的包装,达到简化开发的目的,大家想想,如果没有这些语法糖,那我们岂不是得天天用机器代码写程序?

三、算数表达式

这里先引入一个小小的例子,我想在阅读这篇文章的人都知道什么是算数表达式,最基本的算数表达式:

1,2,3,4,5,6,7,8,9,0,……
+,-,*,/,……

这些都是最基本的算数表达式,而由这些最基本的算数表达式可以构造出更加复杂的复合表达式比如1+1,3*5等等,无论是基本的还是复合的,它们都是算数表达式,通过这个例子,来自然的过渡到下面正则表达式的内容,其实本质上算数表达式和正则表达式的道理是差不多的。

四、正则表达式

构成正则表达式最基本的就是给定的字符集∑={c1,c2,c3,……,cn},这就相当于算数表达式中的0,1,2,3……这些基本算数表达式。
接下来呢,就是他的归纳定义,来告诉我们如何通过最基本的字符集构造出复杂的正则表达式:

  1. 空串ε是正则表达式。
  2. 对于任意字符c∈∑,c是正则表达式
  3. 如果M,N是正则表达式,则以下也是正则表达式:

    选择 M|N = {M,N}
    连接 MN = {mn | m∈M, n∈N}
    闭包 M* = {ε,M,MM,MMM,……}

不难看出,以上的归纳定义给出了正则表达式最基本的的形式,无论多么复杂的正则表达式都是在这个基础上构成的。

现在我们通过一个小例子来加深对上面概念的理解:

给定一个字符集∑={a,b},可以写出那些正则表达式呢?
1.  ε
2.  a,b
3.  ε|ε,ε| a , ε| b ,……
4.  εa , εb , ab , εε , ……
5.  a(ε| a) , b(ε|b),……
6.  ε* , (a(ε| a))*,……
7.  ……

也就是说,单个的字符都是正则表达式,它们按照上面的定义组合起来依然是正则表达式,正则表达式与正则表达式相互组合又可以生成新的正则表达式,在复杂的正则表达式都是由这些基本的正则表达式构成,当然了上面这些只是该字符集的正则表达式的一小部分,因为这个字符集的正则表达式集合是一个无限集,到这里,我想大家应该有所体会。

我们再来看一个例子:

我们用上面的正则表达式的概念来构造出用来描述C语言标识符的正则表达式:
首先给定字符集,我们都知道C语言的字符集有ASCII码构成。
C语言标识符的格式:以字母或下划线开头,后面跟零个或多个字母、数字或下划线。

该怎么用正则表达式来描述呢?

(a|b|c|……|z|A|B|C|……|Z|_)(a|b|c|……|z|A|B|C|……|Z|0|1|2|3|……|9|_))*

首先来看,这个正则表达式是由两个子表达式连接而成,每个子表达式都是用选择符|构成,又因为第二个子表达式可以出现零或多次,所以加上闭包,是不是看的脑袋都大了,是不是觉得平时什么时候这么写过正则表达式,下面就得说说语法糖的作用啦。

五、正则表达式中的语法糖

大家接触到的正则表达式的语法似乎是有差异的,比如POSIX风格正则表达式和Perl风格正则表达式,要知道无论什么风格的正则表达式它们背后的原理都是一样的,只是在上层提供的语法糖不一样而已,实际应用的过程中都是根据上面的原理演变过来的,语法糖可以大大简化正则表达式的形式,变得更容易阅读和理解,就像下面的对应关系一样。

[c1-cn] == c1|c2|c3|……|cn

e? == ε|e

e+ == (e*)\ε

e{i,j} == i到j个e连接

这里就不一一举例了,无论上面的对应关系中左边的语法如何变化,它所对应的右边的基本原理都是一样的。

六、小结

正则表达式可以写的非常复杂,复杂到除了作者外很少有人看的懂的,曾经我也是一度不能自拔,但随着学习的深入,慢慢的发现,剥开正则表达式表面的东西,去看背后的原理,才有一种恍然大悟的感觉。

本文转载自:http://blog.csdn.net/mybc724/article/details/45956057

这里好像没有人
粉丝 0
博文 12
码字总数 6316
作品 0
浦东
程序员
私信 提问
浅谈我对grep跟egrep的简单认识

㈠首先我们要明白grep和egrep的干什么用的 grep:global search regular RE ) and print out the line,全面搜索正则表达式并把行打印出来,是一种强大的文本搜索工具,它只能用基本的正则表达...

chinahaike
2014/02/24
0
0
react-router原理之路径匹配

首先看一下react-router官网示例 上面代码的运行效果点击这里 本文的目的是讲清楚react-router如何根据浏览器中的url来渲染不同的组件的,至于url是如何改变的(Link组件)后面会有专文讨论。...

Randal
2018/05/23
0
0
正则表达式产生器--Regexgen.js

RegexGen.js 是开发给 JavaScript 使用的正则表达式产生器,可以使用浅显易懂的语法来表现复杂的正则表达式。 RegexGen.js 基本上是为那些已经了解正则表达式引擎运作原理,但是不常使用正则...

amobiz
2016/04/19
878
0
【正则表达式】JavaScript的exec()和search()方法

本文简单介绍了正则表达式的元字符,和 JavaScript 提供的两个和正则表达式有关的方法: 和 。 正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。 正则表达式为了描述一个规则,...

Fstar
06/08
0
0
007零基础学Python:Python 正则表达式--学习笔记

Python 正则表达式 正则表达式基础 基本概念: 执行原理: 基本语法: 模式 描述 ^ 匹配字符串的开头 $ 匹配字符串的末尾。 . 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹...

weir_will
2017/07/02
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Mybatis Plus删除

/** @author beth @data 2019-10-17 00:30 */ @RunWith(SpringRunner.class) @SpringBootTest public class DeleteTest { @Autowired private UserInfoMapper userInfoMapper; /** 根据id删除......

一个yuanbeth
今天
4
0
总结

一、设计模式 简单工厂:一个简单而且比较杂的工厂,可以创建任何对象给你 复杂工厂:先创建一种基础类型的工厂接口,然后各自集成实现这个接口,但是每个工厂都是这个基础类的扩展分类,spr...

BobwithB
今天
5
0
java内存模型

前言 Java作为一种面向对象的,跨平台语言,其对象、内存等一直是比较难的知识点。而且很多概念的名称看起来又那么相似,很多人会傻傻分不清楚。比如本文我们要讨论的JVM内存结构、Java内存模...

ls_cherish
今天
4
0
友元函数强制转换

友元函数强制转换 p522

天王盖地虎626
昨天
5
0
js中实现页面跳转(返回前一页、后一页)

本文转载于:专业的前端网站➸js中实现页面跳转(返回前一页、后一页) 一:JS 重载页面,本地刷新,返回上一页 复制代码代码如下: <a href="javascript:history.go(-1)">返回上一页</a> <a h...

前端老手
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部