在日常工作中,经常会用到正则操作。但是对于大多数人来说,操作正则表达式简直就是抓瞎。

本篇文章主要整理了正则表达式匹配的规则,使用中的一些要点,以及用图形化的方式列举出一些常见的正则表达式,希望能给大家带来一定的帮助,能在以后的工作中,用上正则,爱上正则。

PS:不同语言中的正则表达式的规则不完全相同,但是大部分都可以适用。

正则是什么

正则表达式是为了对字符串进行有效 数据提取 以及 匹配 的一种机制,字符串在匹配的过程中将会从第一个位置开始匹配,然后从左往右进行依次匹配,每尝试匹配一次,就会把控制权交由下一个位置,直到匹配结束。

正则表达式是由 普通字符(例如字符 a 到 z)以及 特殊字符(称为元字符)组成的文字模式。该模式描述在查找文字主体时待匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。

正则的诞生

正则表达式的“祖先”可以一直上溯至对人类神经系统如何工作的早期研究。Warren McCulloch 和 Walter Pitts 这两位神经生理学家研究出一种数学方式来描述这些神经网络。

1956 年, 一位叫 Stephen Kleene 的美国数学家在 McCulloch 和 Pitts 早期工作的基础上,发表了一篇标题为「神经网事件的表示法」的论文,引入了正则表达式的概念。

正则表达式就是用来描述他称为“正则集的代数”的表达式,因此采用“正则表达式”这个术语。

随后,人们发现可以将这一工作应用于使用Ken Thompson 的计算搜索算法的一些早期研究,Ken Thompson是Unix 的主要发明人。正则表达式的第一个实用应用程序就是 Unix 中的qed 编辑器。从那时起直至现在正则表达式都是基于文本的编辑器和搜索工具中的一个重要部分。具有完整语法的正则表达式使用在字符的格式匹配方面上,后来被应用到熔融信息技术领域。自从那时起,正则表达式经过几个时期的发展,现在的标准已经被ISO(国际标准组织)批准和被Open Group组织认定。

匹配规则

下面将正则中的一些基本的匹配规则列出来如下表所示:

要点

贪与不贪

举个例子,假设有以下这段html字符,我想拿到a标签中的内容:

<a>南京长江大桥</a>哈哈<a>南京市长江大桥</a>

然后我写了这样一个正则: <a>(.)*</a>

在线测试的结果如下:

这个结果与我们的预期不符,正常我应该得到两个匹配的结果才对,但是现在却只匹配到一个结果。

现在把刚刚的正则改成这样: <a>(.)*?</a>

在线测试的结果如下:

说的是正则在不约束的情况下会继续自动向右进行匹配,直到匹配结束,只要匹配的数据与正则的最后一个值匹配就算是匹配到了。

不贪 说的是只要匹配到就结束,不继续向右进行匹配了。

问号 ? 就解决了贪婪的问题,使得问号前面的字符匹配到之后就结束,但是并不是把 ? 放在哪里都可以解决贪婪的,在正则里,有一些属于贪婪模式量词,比如以下这些:

{m,n}
{m,}
?
*
+

断言与零宽

在java中我们知道 断言 可以用来声明一个应该为 true 的事实,只有当断言为真时才会继续进行后续的操作。

在正则中也有 断言 的概念,但是在正则中除了 断言 还有 零宽 的概念。

  • 断言

通俗点将断言就是 “我断定某某情况是真的” ,而正则中的断言,就是说正则可以断定在 指定的内容前面后面 会出现满足指定规则的内容。比如 "aa1bb2cc3",正则可以用断言找出 bb2 前面有 aa1,也可以找出 bb2 后面有 cc3。

  • 零宽:

零宽就是没有宽度,在正则中,断言只是匹配位置,不占字符,也就是说,匹配结果里是不会返回断言本身的。

断言一共有四种情况:

让我们来举个例子来说明吧,假设我们现在拿到了某个网页的html,里面有个阅读数的标签:

span class="read-cnt">阅读数:1024</span>

现在我们要获取到这个阅读数,该怎么办呢?

如果用正向先行断言来匹配的话,可以这样来写:

\d+(?=</span>)

上述的表达式就是说明,我现在断言整数 \d+后面 匹配表达式: </span>

让我们来验证下结果:

相应的正向后行断言可以这样写表达式:

(?<=阅读数:)\d+

上述的表达式就是说明,我现在断言整数 \d+前面 匹配表达式: 阅读数:

验证下结果如下:

分组

正则表达式中用小括号 () 来做分组,也就是括号中的内容作为一个整体。

因此当我们要匹配分组 he 的时候,可以用下面这个表达式 :

(he)

我们看到正则表达式用小括号来做分组,那么问题来了:

如果要匹配的字符串中本身就包含小括号,那应该怎么办?

针对这种情况,正则提供了转义的方式,也就是要把这些元字符、限定符或者关键字转义成普通的字符,做法很简单,就是在要转义的字符前面加个斜杠(\)即可。

因此当我们要匹配分组 (he) 的时候,可以用下面这个表达式 :

(\(he\))

下面我们用一个正则表达式的图形生成工具,做一个对比的实验,让我们对分组和定位有个了解。

1:匹配 he 分组一次 ;

2:匹配 he 分组零或多次;

3:匹配以 he 开头的分组一次;

4:匹配以 he 开头的分组零或多次

捕获与反向引用

单纯说到捕获,他的意思是匹配表达式,但捕获通常和分组联系在一起,也就是“捕获组”。

捕获组:

匹配子表达式的内容,把匹配结果保存到内存中以数字编号或显示命名的组里(可以把它想象为java中的array和map),以深度优先进行编号,之后可以通过序号或名称来使用这些匹配结果。

捕获组的表达式为: (exp) ,这个语法跟上面讲到的分组的概念是一样的,只是捕获将匹配到的分组,保存在了内存中,留待后面使用。具体怎么时候他不管,他只需要把匹配到的分组保存在内存中就可以了。

有一种情况当在匹配的过程中,需要与已经捕获到的分组进行匹配,这时就需要使用到保存在内存中的捕获组了,这种使用方式就被称为: 反向引用

假设我有这样一段文字:

aa12bb23cc34

现在我想拿到成对的字符,该怎么做呢?这种情况下通过断言或者其他方式是办不到的,那我们能否在匹配的过程中将匹配到的一个字符先保存在内存中,然后匹配下一个字符时再与上一个字符相比较,如果相等,就说明匹配成了,拿到了成对的字符了。

那首先我们先要写一个匹配单个字符分组的表达式:

(\w)

那当匹配时捕获到一个字符分组时,我们需要将该字符引用出来,与下一个字符想比较,我们期望匹配的下一个字符也与我当前保存的字符相等,那么表达式就变成了这样:

(\w)\1

这里的 \1 表示的是,当前正则表达式匹配到的 第1个 分组,那就意味着, \2 表示 第2个分组。

做个测试,结果如下:

那如果我想再匹配复杂一点的结果,比如:XYY 这种的结果,又该怎么写呢?

其实有了上面的基础之后就很简单了,我们需要做的就是 对捕获到的第2个分组进行反向引用就可以了!

具体的表达式为:

(\w)(\w)\2

测试结果如下:

表示成图形就是这样:

常见正则

为了更加形象的了解正则表达式,我们最后通过图形的方式来了解一些常见的正则表达式,使用图形的目的是希望能对冷冰冰的表达式有个更深刻的认识。

以下是一些常见正则的表达式与图片,可能有些过时了,如电话号码出现了新的号段,但是大体上应该没有问题。

整数

[0-9]+

逗号分隔的整数

\b[0-9]{1,3}(,[0-9]{3})*\b

浮点数

(\+?(\d+|\.\d+|\d+\.\d+)|-?(\d+|\d+\.\d+))

0-255之间的数字

^([0-9]|[0-9]{2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])$

身份证

^[1-9]\d{14}(\d{2}[0-9x])?$

邮箱

^[-\w.]{0,64}@([a-zA-Z0-9]{1,63}\.)*[-a-zA-Z0-9]{1,63}$

固定电话

(\(?0[1-9]{2,3}\)?-?)?[1-9][0-9]\{6,7}(-[0-9]{1,6})?

邮编

[1-9][0-9]{5}

ISBN

((ISBN(-13)?:?\s)?97[89][-\s]?[0-9][-\s]?[0-9]{3}[-\s]?[0-9]{5}[-\s]?[0-9]|(ISBN(-10)?:?\s)?[0-9][-\s]?[0-9]{3}[-\s]?[0-9]{5}[-\s]?[0-9x])

手机号

(0|\+86)?(13[0-9]|15[0-356]|18[025-9])\d{8}

成对的html标签

test

<([^>]+)>[\s\S]*?<\/\1>

a标签

<a\s+href\s*=\s*["']?([^"'\s]+)["']?>([^<]+)<\/a>

head标签

<head>([^>]+)<\/head>

image标签

<img\s[^>]*?src=['"]?([^"']+)["']?[^>]*>

正则思维导图

附常用工具:

在线正则测试:http://tool.oschina.net/regex/

生成正则图片:https://regexper.com

这样学习正则表达式就轻松了!相关推荐

  1. 正则匹配问号_跟BBEdit学正则表达式,轻松地学习晦涩难解的语法

    作为搜索替换文本的强大工具,正则表达式(通常被称为"Grep")可能会让初学者望而生畏--好在有<BBEdit>.这款 App 的"Pattern Playg ...

  2. 正则表达式学习日记_《学习正则表达式》笔记_Mr_Ouyang

    正则表达式学习日记_<学习正则表达式>笔记_Mr_Ouyang 所属分类: 正则表达式学习日记  书名:     学习正则表达式 作者:     Michael Fitzgerald 译者 ...

  3. java正则表达式课程_通过此免费课程学习正则表达式

    java正则表达式课程 by Beau Carnes 通过博卡恩斯 通过此免费课程学习正则表达式 (Learn Regular Expressions with this free course) & ...

  4. 【推荐】使用Ultrapico Expresso学习正则表达式

    推荐理由 Ultrapico Expresso是我工作中经常使用的一个非常强大的正则表达式构建.测试以及代码生成工具.它能够对你构建的正则表达式进行解析.验证,并输出解析结果,提供性能测试工具,支持C ...

  5. (正则表达式学习)正则表达式语法

    以前一直想好好的系统的学习正则表达式,都没有按照自己的意愿去做.这次一定要很抓一下正则的学习.先把MSDN的正则表达式语法帖出来,方便自己查找.呵呵. 字符 说明 \ 将下一字符标记为特殊字符.文本. ...

  6. 蜗牛学习正则表达式 教程 工具一网打尽

    蜗牛学习正则表达式系列教程,不可多得的资料...... 转载于:https://www.cnblogs.com/qnfng/archive/2009/06/19/1506391.html

  7. 手机号正则_一起刷题学习正则表达式

    在我最开始学习正则表达式的时候看到一堆符号简直头晕,所以很长一段时间我都是百度一下某某正则怎么写,比如:匹配所有手机号码的正则,但是有时候工作中碰到的一些问题网上搜不到,这就尴尬了,后面还是逼着自己花 ...

  8. 2016-8-4学习正则表达式

    2016-8-4学习正则表达式 编程 正则 第二章 简单的模式匹配 正则表达式唯一的用途就是在文本中匹配和寻找模式 匹配字符串字面值的方法就是使用普通的字符. 第三章 边界 断言标记边界,但是并不耗用 ...

  9. 一个在线学习正则表达式的网站

    今天发现了一个不错的网站regexr.com,可以在线学习正则表达式. 如图,网站左边包含了常用的正则表达式,我们可以随时参考,右边是一些示例文字,英文段落.电话号码.网址.电子邮箱地址等都有.网站上 ...

最新文章

  1. Java中date和calendar的用法
  2. oracle 删除数据 快慢,记录一下Drop表空间的速度
  3. u-tools图床便捷生成markdown图片
  4. C++中有关queue常用函数的用法及其注意要项
  5. 硕士毕业后去国外读法学博士_法学硕士的完整形式是什么?
  6. tmc4361 闭环_TMC4361A-LA
  7. python3的 pymysql把mysqldb库取代了,让python 3支持mysqldb的解决方法
  8. [转]最常用的15大Eclipse开发快捷键技巧
  9. c# mvvm模式获取当前窗口_【自学C#】I 书 12 异常处理
  10. 每日学习之 2016.07.27
  11. HALCON 20.11:学习笔记---一维测量(Measuring)
  12. SpringBoot 实现接口参数加密解密功能
  13. Python是个什么鬼,为什么机械设计都要用到他?
  14. 红外图像特点及识别方法
  15. windows实用键盘快捷键
  16. 文心一言的魔性作图,我愣住了……
  17. excel用图标表示数据增减
  18. uniapp (H5、小程序、app)地图导航
  19. helm3 使用国内原安装Weave Scope
  20. 基于Gate的ANNIE插件的中文信息抽取

热门文章

  1. AI搜索外星人 发现宇宙深处72神秘光
  2. 使用nodejs搭建HTTPS server
  3. Velocity介绍
  4. 三星 Nexus S刷MIUI ROM最新图文刷机教程
  5. asp.net 页面之间跳转的几种方法及区别(转)
  6. Matlab自定义函数的几种方法
  7. Intellij Idea导出可执行的jar包
  8. Python获取当前工作目录
  9. TCP 通信过程中各步骤的状态
  10. 解决win下安装wordcloud出错问题