Python 正则表达式完整示例教程

正则表达式一般用来在文本中查找和替换字符串,再简单的文本中我们可以直接使用字符串查找,但是在大量数据和复杂结构中查找指定字符串不方便并且效率低,因此学习正则表达式显得非常有必要。

正则表达式

元字符

正则表达式字符串是有普通字符和元字符组成。
· 普通字符,是指按照字面意义表示的字符,比如abcd。
· 元字符,是预先定义好的一些特定字符,比如下面正则表达式中的 \w 以及 . ,都属于元字符。

rep = r'\w+@mail2\.sysu\.edu\.cn' # 匹配域名为mail2.sysu.edu.cn的邮箱

元字符是用来描述其他字符的特殊字符,它是由基本元字符+普通元字符构成。

基本元字符:

字符 说明
\ 转义字符
. 表示任意一个字符
+ 表示重复一次或多次
* 表示出现零次或多次
| 表示或关系,比如A
{ } 定义量词
[ ] 定义字符类
( ) 定义分组
^ 表示取反,或匹配一行的开始
$ 匹配一行的结束
- 表示区间

\ 转义符: 比如上面的 \. ,实际上是为了匹配单个 . 符号,但是 . 本身又作为元字符表示任意一个字符,因此遇到这种情况需要转义。
^ 和 $: 这个时候不仅要求匹配字符串,而且要求字符串出现在文本的开始或者结尾,例如:

text = 'My email address is [email protected]'
rep1 = r'\w+@mail2\.sysu\.edu\.cn' # r表示原始字符,避免在正则表达式中输入转义
rep2 = r'^\w+@mail2\.sysu\.edu\.cn$' # 添加了^和$,对开头结尾有要求
# \w表示任意一个字母或数字  +表示出现一次或多次

像上面这段文本,需要将邮箱提取出来的话,只能使用rep1,因为rep2要求匹配的字符串是一行的开头和结尾,只有在邮箱是单独一行才能提取出来。
字符类:字符类用中括号括起来,只要其中一个字符满足条件即可,例如:

text1 = 'I like MATLAB and Python.'
text2 = 'I like MATLAB and python.'
rep = r'[Pp]ython'  # 等效于 python1|Python
# 上述两个文本中的python都可以用下面的正则表达式匹配出来。

^,取反符:有时候,就不需要某些字符出现,可以用取反符,例如我们需要找到非数字的字符:rep = r'^[0123456789]',这个正则表达式就可以匹配一个非数字的字符。
-,表示区间:比如上面的[0123456789],可以直接写成[0-9],这个区间可以是分段的,比如[0-35-9],这个就表示除4以外的数字。

预定义字符

字符 说明
\. 匹配 .
\ 匹配\
\n 匹配换行
\r 匹配回车
\f 匹配翻页符
\t 匹配水平制表符
\v 匹配垂直制表符
\s 匹配一个空格符,等价于[\t\n\r\f\v]
\S 匹配一个非空格符,等价于[^\s]
\d 匹配一个数字,等价于[0-9]
\D 匹配一个非数字,等价于[^\d]
\w 匹配任何语言单词字符、数字、下划线等,编码为ASCII的时候只能是英语
\W 等价于[^\w]

使用量词

字符 说明
出现零次或一次
* 出现零次或多次\
+ 出现一次或多次
{n} 出现n次
{n , } 至少出现n次
{n , m} 出现n次到m次之间

贪婪量词

默认情况都是匹配的字符串越多越好,有时候要尽可能少的匹配,就需要在后面加?,表示懒惰匹配,我们具体写一个例子:

import re
text = '123456789'
rep1 = r'\d{5,8}' # 匹配12345678
m = re.search(rep1,text)
print(m)
rep2 = r'\d{5,8}?' # 匹配12345
m = re.search(rep2,text)
print(m)

在这里插入图片描述

字符分组

字符分组就是将一个子字符串可看成一个整体,进行匹配,举个例子:

import re
text = '12312311aa'
rep = r'(123)+'  # 123出现一次或多次
rep1 = r'123+'  # 3出现一次或多次
m = re.search(rep1,text)
print(m)
m = re.search(rep2,text)
print(m)

在这里插入图片描述
这样有什么好处呢?我们举一个具体的例子,提取一个电话号码的区号和号码:

import re
tel = '0715-53566663'
rep = r'(\d{3,5})-(\d{6,9})'
m = re.search(rep,tel)
print(m)
print(m.group()) # 返回匹配的所有字符串
print(m.groups()) # 返回匹配所有字符串,用元组装起来

在这里插入图片描述
这样,可以将区号和电话号码有效分开,除此之外还可以给分组命名:

import re
tel = '0715-53566663'
rep = r'(?P<area_code>\d{3,5})-(?P<Phone_Number>\d{6,9})'
m = re.search(rep,tel)
print(m)
print(m.group()) # 返回匹配的所有字符串
print(m.groups()) # 返回匹配所有字符串,用元组装起来
print(m.group('area_code'))  # 通过分组名称来引用
print(m.group('Phone_Number'))

在这里插入图片描述

反向引用分组

我们在爬取网页的时候,常常会出现标签,标签的开始和结束应该是一致的,下面举例:

import re

text1 = '<title>Python Code</title>'
text2 = '<title>Python Code</text>'  # 这种情况是我们不想要的
rep1 = r'<(\w+)>.*</(\w+)>'
m = re.search(rep1,text1)
print(m)
m = re.search(rep1,text2) # 同样匹配了
print(m)

在这里插入图片描述
对上面的代码进行改进:

import re

text1 = '<title>Python Code</title>'
text2 = '<title>Python Code</text>'
rep1 = r'<(\w+)>.*</\1>' # 反向引用在这里,用 \1 代替了(\w+)这个分组,表示要和前面匹配的分组相同,1代表的是分组序号
m = re.search(rep1,text1)
print(m)
m = re.search(rep1,text2)
print(m)

在这里插入图片描述

非捕获分组

前面讲都是捕获分组,这些匹配的结果都被暂时存放在内存中,但是有时候我们只需要一些分组进行辅助匹配,但是不想保存,就可以使用非捕获分组,举一个例子,匹配.jpg文件名:

import re

text = 'im1.jpg,im2.jpg,im3.png'
rep = r'\w+(.jpg)'  (.jpg)为捕获分组
m = re.findall(rep,text)  # 找出所有匹配的结果
print(m)
rep = r'\w+(?:.jpg)'  (?:.jpg)为非捕获分组
m = re.findall(rep,text)  
print(m)

在这里插入图片描述
使用捕获分组的时候,只会讲捕获分组里面的打印出来,这并不是我们所希望的。

re模块介绍

re 模块是python提供的关于正则表达式的模块,可以直接使用,下面介绍里面的主要函数。

search()和match()函数

search()和match()函数在使用上非常相似,区别如下:

  • search从字符串中查找,返回第一个匹配对象
  • match从字符串开头开始匹配内容,返回匹配对象
import re

text = 'My email address is [email protected].'
rep = r'\w+@mail2\.sysu\.edu\.cn' # 匹配域名为mail2.sysu.edu.cn的邮箱
m = re.search(rep,text)
print(m)
m = re.match(rep,text)
print(m)

在这里插入图片描述
match与我们之前提到的 ^ 和 $ 的作用相似,一般用于验证结果。

match对象的方法

匹配结果返回的都是一个match对象,它常用的方法包括:group(),groups(),start(),end(),span().

import re

text = 'My email address is [email protected].'
rep = r'(\w+@mail2\.sysu\.edu\.cn)' # 匹配域名为mail2.sysu.edu.cn的邮箱
m = re.search(rep,text)
print(m)
print(m.groups())
print(m.group())
print(m.start())
print(m.end())
print(m.span())

在这里插入图片描述

findall()和finditer()

字符串分割和替换

分割 split()
re.split(pattern, string, count(可选) , flags (可选))
pattern是正则表达式 , string是字符串, count是最大分割次数, flags是编译标志

import re
p = r'\d+' # 表示至少一个数字
text = 'AB12CD23EF'
m = re.split(p,text)
print(m)

在这里插入图片描述
替换 sub()
re.sub(pattern, sym, text, count, flags)
pattern是正则表达式, sym是替换的字符串, text是查找的文本, count替换的次数, flags编译标志

import re
p = r'\d+' # 表示至少一个数字
text = 'AB12CD23EF'
m = re.sub(p, '#', text)
print(m)

在这里插入图片描述

编译正则表达式

为了能够重复使用正则表达式,并且提高程序运行速度,可以使用编译后正则表达式,返回一个regex对象。

import re
p = r'\d+' # 表示至少一个数字
rep = re.compile(p)  # 注意
text = 'AB12CD23EF'
m = rep.sub('#', text)  # 注意,虽然函数名一样,但是一个是rep对象的方法,一个是re模块中的函数
# 输入参数也变化了
print(m)

在这里插入图片描述
其使用方法都是一样的,效果也相同。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章