day22、模块-basedir、os、json模块、pickle和正则模块。

时间:2021-05-19 22:24:49

四、正则、

re模块:                                    

作用:针对的对象:字符串,

课前引入:

例子一、

s='dsdsadsadadsalexdsds'
s.find('alex')

  如何找到字符串内部的alex;?过去学习可使用方法:find、split、replace.但是字符串内置的方法很局限,只能实现完全匹配。

如果要找到:与a**开头的需求呢?就无法实现。要实现模糊匹配就得用到模糊匹配。

例子二、模糊匹配

#在文本里面存着一堆身份证
4504231989347382822
1104231989347382822
1104231992347382822
1104231995347382822
.....
#需求:找到北京市1990以后出身的人

^110......1990+*

找到一堆字符串里面的数字:

day22、模块-basedir、os、json模块、pickle和正则模块。

 

    正则本质上是一种小型的,高度专业化的编程语言。(python)中内嵌在python中,并通过re模块来实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。

 

字符匹配:(普通字符、元字符)

普通字符:大多数字符和字母都会和自身匹配

 import re
 print(re.findall('alex','dsfjdsfldsjfdalexdsds'))

>>>

['alex']

 

元字符:. ^ $ * + ?{} [] | () \

字符讲解:

1⃣️通配符 '.’

import re
print(re.findall('a..x','dsfjdsfldsjfdalexdsds'))

>>>
['alex']

2⃣️、尖角号:^ 以什么开头。在字符串的开头进行匹配。如果符合要求匹配成功。

import re
print(re.findall('^d..j','dsfjdsfldsjfdalexdsds'))
>>>
['dsfj']

3⃣️、$ 符号  以什么结尾,

import re
print(re.findall('d..s$','dsfjdsfldsjfdalexdsds'))

>>>>
['dsds']

重复符号:

4⃣️、*   (0,∞) D*按照紧挨着的字符进行无穷次→贪婪匹配,

import re
print(re.findall('d*','dsfjdsflddddddddddsjfdalexdsds'))

>>>
['d', '', '', '', 'd', '', '', '', 'dddddddddd', '', '', '', 'd', '', '', '', '', 'd', '', 'd', '', '']

 

import re
print(re.findall('^d*','dsfjdsflddddddddddsjfdalexdsds'))
>>
['d']

????️、+  匹配[1,∞)最少匹配一个字符尾部加一个?号就变成惰性匹配

import re
print(re.findall('alex*','dsfjdsfalesjfdsds'))
import re
print(re.findall('alex+','dsfjdsflalesjfdsds'))

>>>
['ale']
[]

6⃣️、?[0,1]

import re
print(re.findall('alex?','dsfjdsflalexxxsjfdsds'))

>>>
['alex']

7⃣️、{}  范围自己定{0,}=*:0到无穷次、{1,}=+:【1,+00】、{0,1}=?、{6}重复6次

import re
print(re.findall('alex{6}','dsfjdsflalexxxsjfdsds'))

>>>
[]

day22、模块-basedir、os、json模块、pickle和正则模块。

 

7⃣️.1:? [0,1] 就变成 惰性匹配,按照最小的来查找匹配。

import re
print(re.findall('alex+?','dsfjdsflalexxxsjfdsds'))

import re
print(re.findall('alex*?','dsfjdsflalexxxsjfdsds'))

>>>>
['alex']
['ale']

8⃣️、[]:字符集..任何符号放置在里面都是普通的符号,匹配里面的其中一个字符。里面的字符都是或的关系,之匹配其中的一个字符。


ret=re.findall('a[bc]d','acd') print(ret)#['acd'] ret=re.findall('[a-z]','acd') print(ret)#['a', 'c', 'd'] ret=re.findall('[.*+]','a.cd+') print(ret)#['.', '+']

除了一些特定功能:-、^、\

【a-z】范围,a到z

import re
print(re.findall('x[a-z]*','xypsssdsdsdsdssxzp'))
>>>
['xypsssdsdsdsdssxzp']

【^a-z】意义:非  匹配非a到z的字母

import re
print(re.findall('www.[oldboy baidu]','www.baid'))

import re
print(re.findall('x[yz]','xyssssxz'))

import re
print(re.findall('x[yz]p','xypssssxzp'))
>>>
['www.b']
['xy', 'xz']
['xyp', 'xzp']

   【\】 转义字符、让元字符变成普通字符,让普通字符变成有代表性的字符

反斜杠后边跟元字符去除特殊功能,比如\.
反斜杠后边跟普通字符实现特殊功能,比如\d


\d  匹配任何十进制数;它相当于类 [0-9]。 查找数字:\d+ 查找字符串里面所有数字。

 

import re
print(re.findall('\d+','asasa22jfdfddsd22jj23jk5jh55'))

>>>
['22', '22', '23', '5', '55']

 

 

\D 匹配任何非数字字符;它相当于类 [^0-9]。

 

import re
print(re.findall('\D+','asasa22jfdfddsd22jj23jk5jh55'))

>>>
['asasa', 'jfdfddsd', 'jj', 'jk', 'jh']

 

 

\s  匹配任何空白字符;它相当于类 [ \t\n\r\f\v]。


\S 匹配任何非空白字符;它相当于类 [^ \t\n\r\f\v]。


\w 匹配任何字母数字字符;它相当于类 [a-zA-Z0-9_]。


\W 匹配任何非字母数字字符;它相当于类 [^a-zA-Z0-9_]

 

 \b  匹配一个特殊字符边界,比如空格 ,&,#等

import re
print(re.findall('I\\b','I am LIST'))  #如何匹配出第一个。\\→、\
print(re.findall(r'I\b','I am LIST'))  #r代表pytho解释器完全把\b传入正则中
>>>
['I']
['I']

牛刀小试:a="12+(34*6+2-5*(2-1))"

思路:从最里层括号开始计算,:以括号开始中间没有括号。

import re a="12+(34*6+2-5*(2-1))" b=re.findall('\([^()]+\)',a) 元字符中有的符号,需要加上:\ 就变成普通括号 print(b) >>> ['(2-1)']

 

9⃣️、() 分组

day22、模块-basedir、os、json模块、pickle和正则模块。

import re
print(re.findall('(abc)+','abcabcabcabcabc'))

>>>
['abc']
ret=re.search('(?P<id>\d{2})/(?P<name>\w{3})','23/com')
print(ret.group())#23/com
print(ret.group('id'))#23

#有名匹配

 

????、\ 转义字符

        先看下面几个匹配例子:

import re ret=re.findall('c\l','abc\le') print(ret)#[]
ret=re.findall('c\\l','abc\le') print(ret)#[]
ret=re.findall('c\\\\l','abc\le') print(ret)#['c\\l']
ret=re.findall(r'c\\l','abc\le') print(ret)#['c\\l']

re.findall(r'I\b',"I am ooo")  加上r之后,python就不会转义特殊字符。or:\\b→转义为:\b

day22、模块-basedir、os、json模块、pickle和正则模块。

#-----------------------------eg2:
#之所以选择\b是因为\b在ASCII表中是有意义的
=  re.findall( '\bblow' 'blow' )
print (m)
=  re.findall(r '\bblow' 'blow' )
print (m)

day22、模块-basedir、os、json模块、pickle和正则模块。

解释:

  在re模块里面: \也是有特殊意义,所以对于普通的\ 也需要经过转义:\\=\    所以传到re里面需要是:a\\k才可以匹配到c\k

在python解释器中\也有特殊意义,所以要传入两个\\,就需要使用:\\\\→传入re变成:\\

 

11、

管道符:|  

import re
print(re.findall('ja|s','asasdds2j23jajs5jh55'))  #|左右两部分为整体

>>>>
['s', 's', 's', 'ja', 's']

五、re模块下的常用方法                                                                    

5.1、 re.search方法:

re.search('a','alvin yuan').group()  
#函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以                                     
# 通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。
import re
print(re.search('(?P<name>\w+)','alexalex')) #有名匹配
print(re.search('\d+','sndsakd332kkhjhl3h232jk'))
>>>>
<_sre.SRE_Match object; span=(0, 8), match='alexalex'>
<_sre.SRE_Match object; span=(7, 10), match='332'>

#要想打印出来,加个:.group

print(re.search('\d+','sndsakd332kkhjhl3h232jk').group())
332
import re print(re.search('(?P<name>[a-z]+)\d+','alex36+wupeiqi34yuanhao33')) print(re.search('(?P<name>[a-z]+)\d+','alex36+wupeiqi34yuanhao33').group()) print(re.search('(?P<name>[a-z]+)','alex36+wupeiqi34yuanhao33').group('name')) #有名匹配
print(re.search('(?P<name>[a-z]+)(?P<age>\d+)','alex36wupeiqi34yuanhao33').group('age')) print(re.search('(?P<name>[a-z]+)(?P<age>\d+)','alex36wupeiqi34yuanhao33').group('name','age')) >>>
<_sre.SRE_Match object; span=(0, 6), match='alex36'> alex36 alex 36 ('alex', '36')

 

应用:对于优先级差不多的情况下:优先处理第一个符合要求的字符。

    比如计算器应用:()+() 、 3+2-2

5.2、match。只能匹配开始的第一个。相当于用search匹配加了尖角号的字符

 

#3
re.match('a','abc').group()     #同search,不过尽在字符串开始处进行匹配.x
import re
print(re.match('a','abc').group())

>>>
a

 

5.3、re.split(),切割

简单例子:

 

import re
print(re.split('a','hello abc dea'))

>>>
['hello ', 'bc de', '']

split和字符集

 

ret=re.split('[ab]','abcd')     #先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割 划分的时候,对于两边没有内容的情况就会出现空格
print(ret)
>>>
['', '', 'cd']

 

import re
print(re.split('[ ae]','hello abc dea'))  #先按照' '划分,等到结果,再按照a划分,得到结果,在按照a划分:

['h', 'llo', '', 'bc', 'd', '', '']

5.4、re.findall 

re.findall('a','alvin yuan')    #返回所有满足匹配条件的结果,放在列表里

补充注意点:当在匹配规则里面做了分组之后,findall会优先把匹配成功分组的内容显示出来。分组内部优先级会高些。

import re print(re.findall('www\.(baidu|163)\.com','www.baidu.com')) >>> ['baidu']

如果要降低分组内的优先级的话:加上(?:):去优先级分组的目的在于提取重点内容,对于海量数据的解决方案是有好处的!

import re
print(re.findall('www\.(?:baidu|163)\.com','www.baidu.com163'))

>>>
['www.baidu.com']

 

 5.5、 替换:sub(pattern, repl, string, count=0, flags=0):count匹配前面的几次  

 

import re
print(re.sub('\d','A','hello12121ggii'))

>>>
helloAAAAAggii

 

5.6、 匹配替换:subn

#输出匹配结果和匹配次数,放置在一个元祖里面
ret=re.subn('\d','abc','alvin5yuan6')
print(ret)
>>>>
#('alvinabcyuanabc', 2)

 

5.7、事先定好规则如:obj.然后接下来直接调用就可以

obj=re.compile('\d{3}')
ret=obj.search('abc123eeee')
print(ret.group())
#123

 

 

 5.8、finditer。返回的结果是一个可迭代对象,可以用.next来输出下一个。用.group 来完整输出数字

实际用处:

对于匹配的数据结果是海量的时候!如果是使用findall会一下子放置在一个列表中,爆内存

如果封装到一个可迭代对象中。可以一个取一个,良好的控制!

 

import re
ret=re.finditer('\d','ds3sy4784a')
print(ret)
print(next(ret))
print(next(ret).group())
print(next(ret).group())

>>>
<callable_iterator object at 0x101979f60>
<_sre.SRE_Match object; span=(2, 3), match='3'>
4
7