正则表达式是一个特殊的字符序列,它能帮助我们方便的检查一个字符串是否与某种模式匹配。Python提供Perl 风格的正则表达式模式。
re 模块使 Python 语言拥有全部的正则表达式功能。
一、正则表达式
1、字符元素(可跳过)
字符的匹配元素,比较琐碎,简单了解后即可,后期边用边查就记住了。
^ 匹配字符串的开头
$ 匹配字符串的末尾。
. 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。
[...] 用来表示一组字符,单独列出:[amk] 匹配 a,m或k
[^...] 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。
re* 匹配0个或多个的表达式。
re+ 匹配1个或多个的表达式。
re? 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
re{ n} 匹配n个前面表达式。例如,"o{2}"不能匹配"god"中的"o",但是能匹配"good"中的两个o。
re{ n,} 精确匹配n个前面表达式。例如,"o{2,}"不能匹配"god"中的"o",但能匹配"gooood"中的所有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 匹配一个单词边界,也就是指单词和空格间的位置。
\B 匹配非单词边界。
\n, \t, 等。 匹配一个换行符。匹配一个制表符, 等
\1...\9 匹配第n个分组的内容。
\10 匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。
2、flags标志位
用于控制正则表达式的匹配方式,其常用枚举类型解析如下:
re.I:使匹配对大小写不敏感
re.M:多行匹配,影响 ^ 和 $
re.S:使 . 匹配包括换行在内的所有字符
re.U:根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
二、re.match
re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回None。
def match(pattern, string, flags=0)
参数说明:
pattern->匹配的正则表达式
string->要匹配的字符串
flags标志位,上文有对应说明
示例:
import re
print(在起始位置匹配,re.match(hello, hello world,re.I))
print(不在起始位置匹配,re.match(world, hello world,re.I))
输出:
在起始位置匹配 <re.Match object; span=(0, 5), match=hello>
不在起始位置匹配 None
re.Match对象的span(),group(),groups()方法
#平台不允许一篇文章有相同的行,所以行尾加上了很多#,下同
import re#
print("在hello在母串的起止位置索引",re.match(hello, hello world,re.I).span())
print("在hello在母串的起位置索引",re.match(hello, hello world,re.I).start())
print("在hello在母串的止位置索引",re.match(hello, hello world,re.I).end())
line = "dog eat my homework"
# .* 表示任意匹配除换行符(\n、\r)之外的任何单个或多个字符
# 多个flags可以用|链接
matchobj = re.match( r(.*) eat (.*), line, re.M|re.I)
print ("默认group(num=0)全部,matchobj.group() : ", matchobj.group())
print ("小组1,matchobj.group(1) : ", matchobj.group(1))
print ("小组2,matchobj.group(2) : ", matchobj.group(2))
print ("小组1,2的tuple,matchobj.group(1,2) : ", matchobj.group(1,2))
print ("全部分组的tuple,matchobj.groups() : ", matchobj.groups())
在hello在母串的起止位置索引 (0, 5)
在hello在母串的起位置索引 0
在hello在母串的止位置索引 5
默认group(num=0)全部,matchobj.group() : dog eat my homework
小组1,matchobj.group(1) : dog
小组2,matchobj.group(2) : my homework
小组1,2的tuple,matchobj.group(1,2) : (dog, my homework)
全部分组的tuple,matchobj.groups() : (dog, my homework)
三、re.search方法
re.search 扫描整个字符串并返回第一个成功的匹配。
def search(pattern, string, flags=0)
search和match的区别主要在于是否第一个匹配
import re############
print(在起始位置匹配,re.search(hello, hello world,re.I).span())
print(不在起始位置匹配,re.search(world, hello world,re.I).span())matchobj=re.search((world), hello world,re.I)
print(matchobj对象,matchobj)
print(matchobj对象的groups方法,matchobj.groups())
print(不存在,re.search(dog, hello world,re.I))
在起始位置匹配 (0, 5)
不在起始位置匹配 (6, 11)
matchobj对象 <re.Match object; span=(6, 11), match=world>
matchobj对象的groups方法 (world,)
不存在 None
四、re.sub函数
Python 的re模块提供了re.sub用于替换字符串中的匹配项。
def sub(pattern, repl, string, count=0, flags=0)
参数解析:
pattern : 正则中的模式字符串。repl : 替换的字符串,也可为一个函数。string : 要被查找替换的原始字符串。count : 模式匹配后替换的最大次数,0 表示替换所有的匹配。flags : 编译时用的匹配模式,上文已做说明。
代码举例:
#####import re
lie = "2 dogs eat my homework ;说谎"
# 删除注释
text = re.sub(r;.*$, "", lie)
print ("正文 : ", text)
# 移除空格
text = re.sub(r\ , "", text)
print ("移除空格 : ", text)
正文 : 2 dogs eat my homework
移除空格 : 2dogseatmyhomework
repl参数是一个函数的情况:
####import re
lie = "2 dogs eat my homework ;说谎"#
#匹配数量乘以100
def multi(matched):
value = int(matched.group(1))
return str(value * 100)
text = re.sub(r(\d), multi, lie)
print ("匹配数量乘以100 : ", text)
匹配数量乘以100 : 200 dogs eat my homework ;说谎
五、re.findall函数
match 和 search 是匹配一次 ,而findall 匹配所有并返回一个列表list,如果没有找到匹配的,则返回空列表。
def findall(pattern, string, flags=0)
import re##########
lie = "OMG,2 dogs eat my homework ;说谎"
#取非空字符串
text = re.findall(r\S+, lie,re.I)
print ("正文1 : ", text)
#取cat字符串
text = re.findall(rcat, lie,re.I)
print ("正文2 : ", text)
正文1 : [OMG,2, dogs, eat, my, homework, ;说谎]
正文2 : []
六、re.finditer函数
与findall 类似,但它返回的是一个迭代器。
def finditer(pattern, string, flags=0)
import re#########
nums = re.finditer(r"\d+","OMG,2 dogs eat my homework in 1 day ;说谎")
for match in nums:
print (match,match.group() )
<re.Match object; span=(4, 5), match=2> 2
<re.Match object; span=(30, 31), match=1> 1
七、re.split函数
split 按照能够匹配的子串将母串分割后返回列表
import re####
li=re.split(\ , OMG,2 dogs eat my homework in 1 day ;说谎)
print("返回成功的list",li)
li=re.split(cat, OMG,2 dogs eat my homework in 1 day ;说谎)
print("没有分割的list",li)
返回成功的list [OMG,2, dogs, eat, my, homework, in, 1, day, ;说谎]
没有分割的list [OMG,2 dogs eat my homework in 1 day ;说谎]
八、pile函数
compile可以理解为正则的编译函数,生成一个表达式对象,供上述函数使用。
def compile(pattern, flags=0) #pattern : 一个字符串形式的正则表达式
pattern=pile(pattern, flags=0),返回编译对象
常用具体方法:
matchobj=pattern.match(母串,开始位置索引,结束位置索引)
matchobj=pattern.search(母串,开始位置索引,结束位置索引)
# match 和 search 是匹配一次,而 findall 匹配所有,返回list,若没有发现则返回[]list=pattern.findall(母串,开始位置索引,结束位置索引)
# findall 和 finditer都是匹配所有,但finditer返回的是一个迭代器iter=pattern.finditer(母串,开始位置索引,结束位置索引)
# 使用正则分割字符串list=pattern.split(母串)
由于match和search类似,这里只用match示例:
import re#############################
lie = "OMG,2 dogs eat my homework ;说谎"###
pattern = pile(r\d+)
print(pattern,pattern)
print(查找头部,没有匹配,pattern.match(lie))
print(从G,没有匹配,pattern.match(lie,2,5))
matchobj=pattern.match(lie,4,10)
print(从2,匹配,matchobj)
print(matchobj的span方法,matchobj.span())
pattern pile(\\d+)
查找头部,没有匹配 None
从G,没有匹配 None
从2,匹配 <re.Match object; span=(4, 5), match=2>
matchobj的span方法 (4, 5)
pattern.match返回为Match的对象,后续可以使用其span,group,groups,start,end等方法。
findall的示例
import re#######################
lie = "OMG,2 dogs eat my homework ;说谎"######
pattern = pile(r\d+)####
patternno = pile(rcat)
print(pattern,pattern)##
print(全局有匹配,pattern.findall(lie))
print(全局无匹配,patternno.findall(lie))
pattern pile(\\d+)##
全局有匹配 [2]
全局无匹配 []
finditer示例
import re#################################################
lie = "OMG,2 dogs eat my homework ;说谎"#####
pattern = pile(r\d+)##########
patternno = pile(rcat)##
print(全局有匹配,[a.group() for a in pattern.finditer(lie)])
print(全局无匹配,[a.group() for a in patternno.finditer(lie)])
全局有匹配 [2]#
全局无匹配 []#
split示例
import re################
lie = "OMG,2 dogs eat my homework ;说谎"####
pattern = pile(r\ )
patternno = pile(rcat)#####
print(pattern,pattern)###############
print(匹配分割,pattern.split(lie))
print(无匹配分割时,原样返回,patternno.split(lie))
pattern pile(\\ )
匹配分割 [OMG,2, dogs, eat, my, homework, ;说谎]
无匹配分割时,原样返回 [OMG,2 dogs eat my homework ;说谎]