python从入门到精通(八): python正则表达式

Python正则表达式

(一)re模块常量(模式)

re模块中有9个常量,常量的值都是int类型!

在这里插入图片描述

1.re.IGNORECASE 或 re.I 使匹配对大小写不敏感
2.re.MULTILINE 或 re.M 多行匹配,影响 ^ 和 $,使它们匹配字符串的每一行的开头和结尾。
3.re.DOTALL 或 re.S: 使 . 匹配包括换行符在内的任意字符。
4.re.ASCII 使 \w, \W, \b, \B, \d, \D, \s, \S 仅匹配 ASCII 字符。
5.re.VERBOSE 或 re.X 忽略空格和注释,可以更清晰地组织复杂的正则表达式。

1.1 模式的使用
import re
pattern = re.compile(r'([a-z]+) ([a-z]+)', re.I)   #使匹配对大小写不敏感
pattern = re.compile(r'([a-z]+) ([a-z]+)', re.S)   #匹配包括换行符在内的任意字符

在这里插入图片描述

(二)re模块函数

在这里插入图片描述
在这里插入图片描述

2.1 查找一个匹配项

  1. search: 查找任意位置的匹配项
  2. match: 必须从字符串开头匹配
  3. fullmatch: 整个字符串与正则完全匹配
re.search方法

re.search 扫描整个字符串并返回第一个成功的匹配

import re
# span用于返回字符串中指定字符的起始位置和结束位置
print(re.search('www', 'www.runoob.com').span())  # 在起始位置匹配
print(re.search('com', 'www.runoob.com').span())   # 不在起始位置匹配
re.match(pattern, string, flags=0)

re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match() 就返回 None

import re
print(re.match('www', 'www.runoob.com').span())  # 在起始位置匹配
print(re.match('com', 'www.runoob.com'))         # 不在起始位置匹配
(0, 3)
None

re.match 与 re.search的区别
re.match 只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回 None,而 re.search 匹配整个字符串,直到找到第一个匹配。

re.fullmatch(pattern, string, flags=0)

功能:必须完全匹配整个字符串,不可以匹配字符串的部分

import re
print(re.fullmatch('www.runoob.com', 'www.runoob.com'))  # 必须完全匹配整个字符串
print(re.fullmatch('com', 'www.runoob.com'))
<re.Match object; span=(0, 14), match='www.runoob.com'>
None

2.2 查找多个匹配项

  1. findall: 从字符串任意位置查找,返回一个列表
  2. finditer:从字符串任意位置查找,返回一个迭代器
re.findall(pattern, string, flags=0)

在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果有多个匹配模式,则返回元组列表,如果没有找到匹配的,则返回空列表。

import re
 
result1 = re.findall(r'\d+','runoob 123 google 456')
 
pattern = re.compile(r'\d+')   # 查找数字
result2 = pattern.findall('runoob 123 google 456')
result3 = pattern.findall('run88oob123google456', 0, 10)  #从字符串的0到10匹配
['123', '456']
['123', '456']
['88', '12']
re.finditer(pattern, string, flags=0)

和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。

import re
 
it = re.finditer(r"\d+","12a32bc43jf3") 
for match in it: 
    print (match.group() )

2.3 分割

re.split(pattern, string, maxsplit=0, flags=0) 函数:用 pattern 分开 string , maxsplit表示最多进行分割次数, flags表示模式,就是上面我们讲解的常量!

re.split(pattern, string, maxsplit=0, flags=0)

split 方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:

import re
print(re.split(r'\W+','runoob, runoob, runoob.'))
print(re.split(r':','runoob:runoob:runoob.'))
print(re.split(r'(\W+)',' runoob, runoob, runoob.'))
print(re.split(r'\W+',' runoob, runoob, runoob.', 1))
print(re.split(r'a*','hello world'))# 对于一个找不到匹配的字符串而言,split 不会对其作出分割
['runoob', 'runoob', 'runoob', '']
['runoob', 'runoob', 'runoob.']
['', ' ', 'runoob', ', ', 'runoob', ', ', 'runoob', '.', '']
['', 'runoob, runoob, runoob.']
['', 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '']

2.4 替换

  1. re.sub
  2. re.subn
re.sub(pattern, repl, string, count=0, flags=0)

re.sub(pattern, repl, string, count=0, flags=0) 函数参数讲解:repl替换掉string中被pattern匹配的字符, count表示最大替换次数,flags表示正则表达式的常量。

pattern : 正则中的模式字符串。
repl : 替换的字符串,也可为一个函数。
string : 要被查找替换的原始字符串。
count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
flags : 编译时用的匹配模式,数字形式。
import re
print(re.sub('[a]','x','abcdef'))   # 第1个参数:正则表达式;第2个参数:替代值;第3个参数:被替代字符串
phone = "2004-959-559 # 这是一个电话号码"
# 删除注释
num = re.sub(r'#.*$', "", phone)
print ("电话号码 : ", num)
# 移除非数字的内容
num = re.sub(r'\D', "", phone)
print ("电话号码 : ", num)

值得注意的是:sub函数中的入参:repl替换内容既可以是字符串,也可以是一个函数哦! 如果repl为函数时,只能有一个入参:Match匹配对象。

re.subn(pattern, repl, string, count=0, flags=0)

re.subn(pattern, repl, string, count=0, flags=0) 函数与 re.sub函数 功能一致,只不过返回一个元组 (字符串, 替换次数)。

print(re.sub('[ae]','x','abcdef'))   # 第1个参数:正则表达式;第2个参数:替代值;第3个参数:被替代字符串
('xbcdxf', 2)  #替换了2次

2.5 编译正则对象

re.compile(pattern, flags=0)

compile函数 与 template函数 将正则表达式的样式编译为一个 正则表达式对象 (正则对象Pattern),这个对象与re模块有同样的正则函数(后面我们会讲解Pattern正则对象)。

import re
pattern = re.compile(r'([a-z]+) ([a-z]+)', re.I)   # re.I 表示忽略大小写
m = pattern.match('Hello World Wide Web')
print(m)       # 匹配成功,返回一个 Match 对象

2.5 其他

1.re.escape(pattern) 可以转义正则表达式中具有特殊含义的字符,看似非常好用省去了我们自己加转义,但是使用它很容易出现转义错误的问题,所以并不建议使用它转义,而建议大家自己手动转义!

2.re.purge() 函数作用就是清除 正则表达式缓存,

正则表达式模式

在这里插入图片描述在这里插入图片描述

^	匹配字符串的开头
$	匹配字符串的末尾。
.	匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。
[...]	用来表示一组字符,单独列出:[amk] 匹配 'a''m''k'
[^...]	不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。
re*	匹配0个或多个的表达式。
re+	匹配1个或多个的表达式。
re?	匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
re{ n}	匹配n个前面表达式。例如,"o{2}"不能匹配"Bob"中的"o",但是能匹配"food"中的两个o。
re{ n,}	精确匹配n个前面表达式。例如,"o{2,}"不能匹配"Bob"中的"o",但能匹配"foooood"中的所有o。"o{1,}"等价于"o+""o{0,}"则等价于"o*"。
re{ n, m}	匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式
a| b	匹配a或b
(re)	匹配括号内的表达式,也表示一个组
(?imx)	正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。
(?-imx)	正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。
(?: re)	类似 (...), 但是不表示一个组
(?imx: re)	在括号中使用i, m, 或 x 可选标志
(?-imx: re)	在括号中不使用i, m, 或 x 可选标志
(?#...)	注释.
(?= re)	前向肯定界定符。如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。
(?! re)	前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功。
(?> re)	匹配的独立模式,省去回溯。
\w	匹配数字字母下划线
\W	匹配非数字字母下划线
\s	匹配任意空白字符,等价于 [\t\n\r\f]。
\S	匹配任意非空字符
\d	匹配任意数字,等价于 [0-9]。
\D	匹配任意非数字
\A	匹配字符串开始
\Z	匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。
\z	匹配字符串结束
\G	匹配最后匹配完成的位置。
\b	匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B	匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
\n, \t, 等。	匹配一个换行符。匹配一个制表符, 等
\1...\9	匹配第n个分组的内容。
\10	匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。

正则表达式字符集

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

在这里插入图片描述

字符集匹配模式

在这里插入图片描述

匹配具体数据

匹配包含2020的数据
输入 code就可以匹配所有包含code的数据
在这里插入图片描述
接下来,请你使用正则表达式匹配所有2020的数据。

2020

在这里插入图片描述

匹配字符组

字符组[] 匹配其中的任意字符即可。
在这里插入图片描述
接下来,请你使用字符组匹配Java和 java。

[Jj]ava

在这里插入图片描述

在这里插入图片描述

区间

如果要匹配从a-z的字母呢?我想你肯定不愿意从a写到z了!正则表达式引擎在字符组中使用连字符(-)代表区间,依照这个规则,我们可以总结出三点:

要匹配任意数字可以使用[0-9];
如果想要匹配所有小写字母,可以写成[a-z];
想要匹配所有大写字母可以写成[A-Z]。

[A-Za-z0-9]+    +号和*号的区别

在这里插入图片描述

匹配特殊字符

正则表达使用了 - 号代表了区间,但是我们有时候需要匹配的符号就是 -号,该怎么办呢?
这个时候我们需要对-号进行转义操作,即 -。
在正则中使用 \ 就可以进行对特殊符号进行转义,对 - 进行转义就可以表示为 -,即 - 就代表了 - 号本身。
偷偷告诉你,转义符 \ 也适用于其他的符号,例如匹配圆括号可以使用 (
在这里插入图片描述
接下来请你编写正则表达式匹配下列符号。

[\[\-\(][\]\-\)]{1,4}
[^\w]+

在这里插入图片描述

匹配字母

匹配字母[a-zA-F]
在这里插入图片描述
在这里插入图片描述

取反

到目前为止,我们定义的字符组都是由可能出现的字符定义,不过有时候我们可能希望根据不会出现的字符定义字符组。
例如:匹配不包含数字的字符组

在这里插入图片描述
可以通过在字符数组开头使用 ^ 字符实现取反操作,从而可以反转一个字符组(意味着会匹配任何指定字符之外的所有字符)。

再看一个例子:
这里的 n[^e] 的意思就是n后面的字母不能为 e。

[^]

在这里插入图片描述
不含小写字母的数据
在这里插入图片描述

快捷匹配

当我们想要匹配任意数字的时候也可以使用快捷方式\d,d即digit数字的意思,等价于[0-9]
在这里插入图片描述
在这里插入图片描述

匹配空白

\s快捷方式可以匹配空白字符,比如空格,tab、换行等。
在这里插入图片描述
匹配空白分隔的单词
在这里插入图片描述

单词边界

\b 匹配的是单词的边界,例如

\bmaster\b 就仅匹配有边界的master单词。
在这里插入图片描述在这里插入图片描述在这里插入图片描述

快捷方式取反

快捷方式也可以取反,例如对于\w的取反为\W,将小写改写成大写即可,其他快捷方式也遵循这个规则
在这里插入图片描述
请使用正则表达式匹配下列开头不以字母开头的单词。

在这里插入图片描述

开始和结束

正则表达式中 ^指定的是一个字符串的开始,$指定的是一个字符串的结束。在这里插入图片描述

在这里插入图片描述

任意字符

.字符代表匹配任何单个字符,它只能出现在方括号以外。
值得注意的是: .字符只有一个不能匹配的字符,也就是换行符(\n),不过要让.字符与换行符匹配也是可以的,以后会讨论。
在这里插入图片描述

可选字符

这个时候我们可以使用 ? 符号指定一个字符、字符组或其他基本单元可选,这意味着正则表达式引擎将会期望该字符出现零次或一次。
在这里 u? 表示u是可选的,即可以出现也可以不出现,可以匹配的是 honor 和 honour 。
在这里插入图片描述
在这里插入图片描述

可选任意字符

在这里插入图片描述

重复

在一个字符组后加上{N} 就可以表示在它之前的字符组出现N次。在这里插入图片描述
在这里插入图片描述

重复区间

里重复区间就可以出场了,语法:{M,N},M是下界而N是上界。
在这里插入图片描述
\d{3,4} 既可以匹配3个数字也可以匹配4个数字,不过当有4个数字的时候,优先匹配的是4个数字,这是因为正则表达式默认是贪婪模式,即尽可能的匹配更多字符,而要使用非贪婪模式,我们要在表达式后面加上 ?号。
在这里插入图片描述
在这里插入图片描述

开闭区间

有时候我们可能遇到字符组的重复次数没有边界,例如:
闭区间不写即可表示匹配一个或无数个
在这里插入图片描述
速写
还可以使用两个速写字符指定常见的重复情况,可以使用 + 匹配1个到无数个,使用 *代表0个到无数个。

即:+等价于{1,},*等价于{0,}。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

练习题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

分组提取数据

在正则表达式中还提供了一种将表达式分组的机制,当使用分组时,除了获得整个匹配。还能够在匹配中选择每一个分组。

要实现分组很简单,使用()即可。

 (\d{4}) -(\d{7})    0731-8825951

在这里插入图片描述
这段正则表达式将文本分成了两组,第一组为:0731,第二组为8825951。
在这里插入图片描述
分组有一个非常重要的功能——捕获数据。所以()被称为捕获分组,用来捕获数据,当我们想要从匹配好的数据中提取关键数据的时候可以使用分组。

(\d{4}) 和 (\d{7})就分别捕获了两段数据:

  • 0731
  • 8825951

接下来请你使用分组进行数据的提取。

  <div>.*?</div>  
  <div>(.*?)</div>  

正则只返回()里的内容就叫提取
在这里插入图片描述

<p>(.*?)</p>

在这里插入图片描述

\d{4}-?\d{4}-?\d{2}

在这里插入图片描述

(\d{4})-/-/
在这里插入图片描述

分组条件

要提取所有图片文件的后缀名,可以在各个后缀名之间加上一个 | 符号:.mp4 |.avi|.wmv|.rmvb

在这里插入图片描述

在这里插入图片描述

非捕获分组

有时候,我们并不需要捕获某个分组的内容,但是又想使用分组的特性。
这个时候就可以使用非捕获组(?:表达式),从而不捕获数据,还能使用分组的功能。
例如想要匹配两个字母组成的单词或者四个字母组成的单词就可以使用非捕获分组:
在这里插入图片描述

(?:\d{4}) -(\d{7}) ?:不要第一个 ()只要第二个
(?:\d{1,5}|\D{3})(?😐:)(\d{5})
(\d{1,5}|\D{3})(-|:)(\d{5})

在这里插入图片描述
分组使用技巧
在这里插入图片描述
通过(\d{4})[-./\s]?(\d{1,2})[-./\s]?(\d{1,2}) 就可以从文本中将年月日分别提取出来了。
虽然这段正则表达式看起来内容挺多,但是还是很容易理解的,[-./\s]表示匹配三个可能出现的分隔符-./和空白,?表示匹配它们0次或者1次,其他年月日的数据使用\d{N}与分组结合就可以提取到目标数据。

(\d{4}[-.\s/](\d{1,2})[-.\s/](\d{1,2})

在这里插入图片描述

在这里插入图片描述

分组的回溯引用

正则表达式还提供了一种引用之前匹配分组的机制,有些时候,我们或许会寻找到一个子匹配,该匹配接下来会再次出现。
例如,要匹配一段 HTML 代码,比如:0123提示abcd,可能会编写出这样一段正则表达式:
在这里插入图片描述
可以使用分组的回溯引用,使用\N可以引用编号为N的分组,因此上述例子的代码我们可以改为:
通过这个例子,可以发现 \1 表示的就是第一个分组,在这里第一个分组匹配的是 font 所以\1 就代表font。
在这里插入图片描述

回溯 <(\w+)>(.*?)</\1> \1代表第一个分组
0123提示abcd
在这里插入图片描述

先行断言和后行断言总共有四种:
正向先行断言
反向先行断言
正向后行断言
反向后行断言
正向先行断言:(?=表达式),指在某个位置向右看,表示所在位置右侧必须能匹配表达式
例如:
我喜欢你 我喜欢 我喜欢我 喜欢 喜欢你
如果要取出喜欢两个字,要求这个喜欢后面有你,这个时候就要这么写:喜欢(?=你),这就是正向先行断言。
在这里插入图片描述

提取包含大小写字母的字符串
先行断言可以用来判断字符串是否符合特定的规则,例如提取包含至少一个大小写字母的字符串:

(?=.*?[a-z])(?=.*?[A-Z]).+ 这段正则表达式规定了匹配的字符串中必须包含至少一个大写和小写的字母。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
反向先行断言(?!表达式)的作用是保证右边不能出现某字符。
例如: 我喜欢你 我喜欢 我喜欢我 喜欢 喜欢你
如果要取出喜欢两个字,要求这个喜欢后面没有你,这个时候就要这么写:喜欢(?!你),这就是反向先行断言。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
正向后行断言
只需要你记住一句话:先行断言和后行断言只有一个区别,即先行断言从左往右看,后行断言从右往左看。
正向后行断言:(?<=表达式),指在某个位置向左看,表示所在位置左侧必须能匹配表达式
例如:如果要取出喜欢两个字,要求喜欢的前面有我,后面有你,这个时候就要这么写:(?<=我)喜欢(?=你)。
在这里插入图片描述

反向后行断言

反向后行断言:(?<!表达式),指在某个位置向左看,表示所在位置左侧不能匹配表达式
例如:如果要取出喜欢两个字,要求喜欢的前面没有我,后面没有你,这个时候就要这么写:(?<!我)喜欢(?!你)。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  • 20
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HACKNOE

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值