正则表达式顿悟之后,查找如探囊取物

什么是正则表达式

正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。也就是查找字符串中是否包含满足要求的字符串,譬如我想知道射雕英雄传这本书中“郭靖”出现过多少次,就可以用正则表达式来解决。
正则的发展历史,详情参见1

从正则的发展历史中可以看出,技术的鲜明特性,就是功能导向,而功能之所以有价值是因为有需求,正则之所以被开发和不断发展,是因为有搜素字符串的需求,从需求出发,来理解什么是正则,以及怎样使用正则表达式可能会更好入手。
需求就是解决问题,下面在解决10个问题的过程中说明正则的语法。

问题1: 如何匹配 “abc1de” 中的数字 ?

1 元字符

元字符就可以,元字符是构造正则表达式的最基本元素。常用的元字符如下:

元字符说明
.匹配除换行符以外的任意字符
\w匹配任意字母、数字、汉字、下划线
\s匹配任意的空白符
\d匹配数字
\b匹配单词的开始或者结束
^匹配字符串的开始
$匹配字符串的结束

匹配 “abc1de” 中的数字

\d

问题2 :如何匹配" Years may wrinkle the skin, but to give up enthusiasm wrinkles the soul." 中 “w” 开头的单词?

\bw

这就是元字符的使用,有了元字符就可以写一些简单的正则了。
比如: 匹配以 "A"开头的字符串

^A

匹配十一位的手机号码

\d\d\d\d\d\d\d\d\d\d\d 

很明显这样的语法并不简洁,匹配一个长度为100的数字序列,难道写100个\d吗 ?
当然不需要,长度限定符可以解决这个问题。

2 长度限定符

为了解决匹配模式的长度问题,正则中有一些定符可以控制模式的长度, 如下:

字符说明
*匹配零次或者任意次
+匹配重复一次或者更多次
匹配零次或者一次
{n}匹配重复n次
{n,}匹配重复n次或多于n次
{n,m}匹配重复n次到m次
{,m}匹配重复m次或少于m次

那么, 匹配十一位的手机号码记可以改写成

\d{11}

问题3 :{n,m}匹配n次到m次, 那么具体是匹配多少次呢?
这取决于贪婪还是偷懒

3 贪婪与偷懒

贪婪匹配:(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符,默认是贪婪匹配的,也就是说{n, m} 是在整个表达式得到满足时匹配的尽可能大长度。
偷懒匹配(非贪婪):(在使整个表达式能得到匹配的前提下)匹配尽可能少的字符。懒惰量词是在贪婪量词后面加个"?"

字符说明
*?重复任意次,但尽可能少
+?重复1或更多次 ,但尽可能少
??重复0次或1次,但尽可能少
{n,m} ?重复n,m次,但尽可能少

贪婪与非贪婪的比较
在这里插入图片描述
问题4:上诉可以匹配重复的1或2,那么如果我需要12作为整体重复匹配怎么办?

4 分组

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

\12{2}

问题5:\d可以匹配任意数字,那如果我只想匹配1到5之间的数字怎么办呢 ?

5 区间

正则表达式提供一个元字符中括号 [ ] 来表示区间条件。如下:

符号说明
[0-9]0到9之间的数字
[a-z]a到z之间的字母
[A-Z]A到Z之间的字母

比如, 匹配" 大于1小于5的数字?

[1-5]

问题6 :如果我现在需要匹配的是离散的 1,5,7,8呢 ?
集合可以用来匹配集合中的任意一个

6 集合

正则表达式中,符号[xy]也可以表示一个集合,匹配其中的任意字符。

[1578]

或者匹配 a, g, k的其中一个

[agk]

也可以使用条件或

7 条件或

正则用符号 | 来表示或,也叫做分支条件,当满足正则里的分支条件的任何一种条件时,都会当成是匹配成功,就是并的逻辑。
匹配a,g,k的其中一个也可以写成,

a|g|k

匹配 130/166/186/三个号段的号码

(130|166|186)\d{8}

既然有逻辑条件或,当我们不想匹配某个字符时,非也是并不可少的需求

8 条件非

正则表达式提供一些否定的元字符如下 :

字符说明
\W匹配任意不是字母,数字,下划线,汉字的字符
\S匹配任意不是空白符的字符
\D匹配任意不是数字的字符
\B匹配不是单词开头或结束的位置
[^xyz]匹配任意不是xyz的字符

注意: ^在[ ]中出现表示否定,^单独出现表示字符串开始位置

问题 7:上述出现的(),[ ] ,{ } ,都有特殊用法 , 如果我匹配的就是这些符号本身怎么办呢?

9 转义

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

\(\)

所以普通字符加一个转义字符变成特殊符号,如\d , 特殊符号加一个转义字符变成了普通字符,如\ ^表示 ^ 本身。

问题8 : 爬虫时常会有这样的需求,比如在爬取网页中图片的地址时,需要从"< id=“bigImg” src=“https://b.zol-img.com.cn/desk/bizhi/image/10/960x600/98319721647.jpg” " 提取图片的url 。
观察发现,我们需要的是 src= 之后的字符串,零宽断言很好满足您的需求。

10 零宽断言

零宽就是没有宽度,不占字符,只是匹配一个位置。断言就是断定有字符或者没有什么字符 。
正则表达式提供零宽断言有四种,如下

语法名称说明
(?=x)正向前行断言匹配任意x之前的位置
(?<=x)正向后行断言匹配任意x之后的位置
(?!x)负向前行断言匹配任意不是x之前的位置
(?<!x)负向后行断言匹配意不是x之前的位置

零宽断言的字符比较好记,特殊字符(?)表示零宽断言, = 表示正向断言,!表示否定,<表示在x后面的位置, 没有<则是前面的位置。

在这里插入图片描述

上图为很实用的正则化练习网站 https://regex101.com/

匹配图片地址,

(?<=src=)\".*\"

问题9:现在需要将字符串" location: China, date : 2020-06-01,weather : cloudy "中的日期匹配出,并且分别调用其中的年月日 。
这就不仅仅要匹配所需字符串而且要将匹配的结果分组。

11 捕获组

捕获组就是把正则表达式中子表达式匹配的内容,保存到以数字编号或者命名的组里,方便后面引用。
捕获组的只需要括号就可以(x), 也可以将捕获的组命名,语法为(?<name>x) ,不命名就自动编号。
比如捕获日期(数字编号),
在这里插入图片描述

捕获组并且命名,

在这里插入图片描述
python中groups方法可以调用捕获组。 python正则函数详细用法,参见2

捕获组不仅可以在外部调用,也可以在正则表达式中调用,比如解决下面的问题。
问题10 : 查找一串字母"5443114994002568856643"里连续相同的数字。

12 反向引用

捕获组捕获到的内容,不仅可以在正则表达式外部通过程序进行引用,也可以在正则表达式内部进行引用,这种引用方式就是反向引用。
对于普通捕获组和命名捕获组的引用,语法如下:
普通捕获组反向引用:\k,通常简写为\number
命名捕获组反向引用:\k或者\k’name’
在这里插入图片描述
解释一下就是,捕获组(\d)捕获的是一个数字,第一组就是这个数字, 引用第一组,就和第一组一样,所以匹配的是两个相同的数字。
以上就是正则的基本语法,实战中往往组合起来使用,熟练掌握还是得多练习多使用。

本文是正则表达式的语法梳理,不涉及正则表达式的原理,正则原理是优化正则的前提,也是我们必须了解的部分,原理参照1


  1. 正则表达式发展历史以及原理(https://mp.weixin.qq.com/s/YWgLfb7xvrqNpcdFdFaksQ) ↩︎ ↩︎

  2. python正则详细介绍 (https://mp.weixin.qq.com/s/iZk1CX9VjCcHiXVOEwyWGg) ↩︎

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值