上海 day15 -- 正则表达式和 re 模块
2019-07-17 17:39 在上海的日子里 阅读(272) 评论(0) 编辑 收藏 举报目 录
一、正则表达式
二、re 模块
一、正则表达式
re 模块与正则表达式的关系:
正则表达式是一门独立的技术,任何语言都可以运用,但是如果Python想要使用正则表达式的话就要借助 re 模块。
作用:正则表达式就是用来筛选字符串中特定的内容。
应用场景:爬虫、数据分析。只要有reg。。。一般都与正则有关
字符组:[ 字符组 ]
在同一个位置中可能出现的各种字符组成了一个字符组,在正则表达式中用[ ] 表示。
[0123456789] —— 带匹配数字与字符组里任意一个数字相同都是匹配成功
[ 0-9 ] —— [0123456789] 的简易写法,也是用来匹配数字,只要有一个与带匹配数字相同就匹配成功
[ a-z ] —— 匹配所有a到z 的小写字母
[ A-Z ] —— 匹配所有的大写字母
[ 0-9a-fA-F ] —— 字符组中不同形式的字符是“或”的意思,该字符组是用来匹配 0-9 a-f A-F 中的字符
一个字符串里的关系都是“或”的关系。
总结:字符组只能匹配一个位置上的字符内容。
元字符:只能匹配一个位置上的内容
1、点 . —— 匹配出换行符以外的所有字符;
2、\w \s \d
\w —— word 匹配任意的字母、数字和下划线
\s —— space 匹配空白符
\d —— digit 匹配数字
3、\W \S \D
\W —— 匹配非字母、数字或下划线
\S —— 匹配非空白符
\D —— 匹配非数字
4、\n \t
\n —— 匹配换行符
\t —— 匹配制表符(制表符就是 Tab键)
5、\b ^ $
\b —— 匹配一个单词的结尾
^ —— 匹配字符串的开始
$ —— 匹配字符串的结尾
^与$符连用 会精准限制匹配的内容
两者中间写什么 匹配的字符串就必须是什么
多一个也不行少一个也不行
6、[...] [^....]
[......] —— 匹配字符组中的任意字符
[^....] —— 匹配非字符组中的所有字符
^ 直接写在外面 限制字符串的开头
[^] 除了[]写的字符 其他都要
7、a | b ()
a|b —— 匹配a或b
abc|ab 一定要将长的放在前面
( ) —— 分组,匹配括号内的表达式,也表示分组。
分组:当多个正则符号需要重复多次的时候或者当做一个整体进行其他操作,那么可以分组的形式
分组在正则的语法中就是()
无论是字符组还是元字符都只能匹配一个位置上的字符,显然是不适应的,所以要引出“量词”!
量词:用在元字符后面,表示匹配数量的增加!
量词必须跟在正则符号的后面
量词只能能够限制紧挨着它的那一个正则符号
1、* + ?
* —— 重复 0次或更多次
+ —— 重复 1 次 或更多次
?—— 重复0次 或 1次
图解:
2、{n} {n,} {n,m}
{n} —— 重复 n次
{n,} —— 重复n 次 或更多次
{n,m} —— 重复n 到 m 次
正则表达式:
正则在匹配的时候默认都是贪婪匹配(尽量匹配多的)
你可以通过在量词后面加上一个?就可以将贪婪匹配变成非贪婪匹配(惰性匹配)
面试重点:
贪婪匹配:在满足匹配时尽可能匹配长的字符串,默认情况下采用贪婪匹配。
非贪婪匹配:通过在正则表达式量词后面加“?”,将贪婪匹配变成非贪婪匹配。
正则表达式常用方法:<.*> 和 <.*?>
<.*> —— 贪婪匹配,先将整个字符串取出,从后向前查找符号 > ,遇见该符号就停止
<.*?> —— 非贪婪匹配,从第一个字符开始,查找符号>,从前向后遇见该符号就停止
几个非贪婪匹配的模型:
*?: 重复0次或多次,尽可能少重复
+?: 重复1次或多次,尽可能少重复
??: 重复0次或1次,尽可能少重复
{n,}?: 重复n次或多次,尽可能少重复
{n,m}?: 重复n次到m次,尽可能少重复
.*? 的用法:
. 匹配除换行符之外的任意字符
* 重复 0 次或多次
? 非贪婪模式
综合在一起就是 取尽量少的任意字符,一般不会这么单独写,他大多用在:
.*?x
就是取前面任意长度的字符,直到一个x出现
二、re 模块
Python使用正则必须要借助re模块,或者是支持正则表达式书写的方法。
re 模块下的常用方法:findall() search() match() ****
import re """ findall search match """
findall() 用法:
# res = re.findall('[a-z]+','eva egon jason') # # findall('正则表达式','带匹配的字符串') # print(res) # 找出字符串中符合正则表达式全部内容 并且返回的是一个列表,列表中的元素就是正则匹配到的结果
search() 用法:
# res = re.search('a','eva egon jason') # print(res) # search不会给你直接返回匹配到的结果 而是给你返回一个对象 # print(res.group()) # 必须调用group才能看到匹配到的结果 """ 注意: 1.search只会依据正则查一次 只要查到了结果 就不会再往后查找 2.当查找的结果不存在的情况下 调用group直接报错 """ # res1 = re.search('a','eva egon jason') # # search('正则表达式','带匹配的字符串') # if res1: # print(res1.group())
match() 用法:
# res = re.match('a','eva egon jason') # print(res) # print(res.group()) """ 注意: 1.match只会匹配字符串的开头部分 2.当字符串的开头不符合匹配规则的情况下 返回的也是None 调用group也会报错 """
re 模块中的其他常用方法:
split() :
# ret = re.split('[ab]', 'abcd') # 先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割 # print(ret) # ['', '', 'cd'] 返回的还是列表
sub():
# ret = re.sub('\d', 'H', 'eva3egon4yuan4',1) # 将数字替换成'H',参数1表示只替换1个 # # sub('正则表达式','新的内容','待替换的字符串',n) # """ # 先按照正则表达式查找所有符合该表达式的内容 统一替换成'新的内容' 还可以通过n来控制替换的个数 # """ # print(ret) # evaHegon4yuan4
subn():
# ret = re.subn('\d', 'H', 'eva3egon4yuan4') # 将数字替换成'H',返回元组(替换的结果,替换了多少次) # ret1 = re.subn('\d', 'H', 'eva3egon4yuan4',1) # 将数字替换成'H',返回元组(替换的结果,替换了多少次) # print(ret) # 返回的是一个元组 元组的第二个元素代表的是替换的个数
compile():
# obj = re.compile('\d{3}') #将正则表达式编译成为一个 正则表达式对象,规则要匹配的是3个数字 # ret = obj.search('abc123eeee') #正则表达式对象调用search,参数为待匹配的字符串 # res1 = obj.findall('347982734729349827384') # print(ret.group()) #结果 : 123 # print(res1) #结果 : ['347', '982', '734', '729', '349', '827', '384']
finditer():
# import re # ret = re.finditer('\d', 'ds3sy4784a') #finditer返回一个存放匹配结果的迭代器 # print(ret) # <callable_iterator object at 0x10195f940> # print(next(ret).group()) # 等价于ret.__next__() # print(next(ret).group()) # 等价于ret.__next__() # print(next(ret).group()) # 等价于ret.__next__() # print(next(ret).group()) # 等价于ret.__next__() # print(next(ret).group()) # 等价于ret.__next__() # print(next(ret).group()) # 等价于ret.__next__() 超出迭代取值的范围 直接报错 # print(next(ret).group()) #查看第一个结果 # print(next(ret).group()) #查看第二个结果 # print([i.group() for i in ret]) #查看剩余的左右结果
给正则表达式起别名:--在表达式前加 “ ?P ”
import re # res = re.search('^[1-9](\d{14})(\d{2}[0-9x])?$','110105199812067023') # 还可以给某一个正则表达式起别名 # res = re.search('^[1-9](?P<password>\d{14})(?P<username>\d{2}[0-9x])?$','110105199812067023') # print(res.group()) # print(res.group('password')) # print(res.group(1)) # print(res.group('username')) # print(res.group(2)) # print(res.group(2)) # print(res.group(1))
给正则表达式的分组解除优先机制
# ret1 = re.findall('www.(baidu|oldboy).com', 'www.oldboy.com') # ret2 = re.findall('www.(?:baidu|oldboy).com', 'www.oldboy.com') # 忽略分组优先的机制 # print(ret1,ret2) # ['oldboy'] 这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可
split() 方法使用正则表达式分组 () 的不同效果
# ret=re.split("\d+","eva3egon4yuan") # print(ret) #结果 : ['eva', 'egon', 'yuan'] # # ret1=re.split("(\d+)","eva3egon4yuan") # print(ret1) #结果 : ['eva', '3', 'egon', '4', 'yuan']
最后更多用法可转此处