re模块
本节内容:
1.正则表达式
2.练习题
3.re模块
4.练习题
一.正则表达式
- 字符组:[字符组](对每一个字符进行匹配)
在同一位置可能出现的各种字符组成了一个字符组,在正则表达式中[]表示.假如你现在要求一个位置’只能出现数字’,那么这个位置上的字符只能是0,1,,9这是十个数之一
正则 |
待匹配字符 |
匹配结果 |
说明 |
[0-9] |
878xghg |
878xghg |
匹配数字 |
[a-z] |
2afdf47 |
2afdf47 |
匹配小写字母 |
[A-Z] |
78xFFT |
78xFFT |
匹配大写字母 |
[a-zA-Z] |
8Ta |
8Ta |
匹配大小写字母 |
[a-zA-Z0-9] |
78Ta |
78Ta |
匹配大小写字母数字 |
[a-zA-Z0-9_] |
78Ta_ |
78Ta_ |
匹配字母数字下划线 |
A ascii码65 |
Z 90 |
a 97 |
z 122 |
2.元字符
元字符 |
待匹配字符 |
匹配结果 |
匹配内容 |
.(李.) |
李杰和李连杰和李二棍 |
李杰和李连杰和李二棍 |
匹配除换行符以外的其他字符 |
\w |
78Ta_你好 |
78Ta_你好 |
匹配字母数字下划线 |
\s |
78T a_ 你 |
78T a_ 你 |
匹配任意空白字符 |
\t |
78T a_ 你 |
78T a_ 你 |
匹配任意制表符 |
\n |
78T a_ 你
|
匹配到 1 条结果 |
匹配任意换行符 |
\d |
78T a_ 你 |
78T a_ 你 |
匹配任意数字 |
\d(lo\b) |
hello world |
hello world |
匹配一个单词结尾 |
^(^李.) |
李杰和李连杰和李二棍 |
李杰和李连杰和李二棍 |
匹配字符串的开头 |
^ |
|
匹配到 1 条结果 |
什么都不打也有 |
$ |
|
匹配到 1 条结果 |
什么也不打 |
$(李.{2}$) |
李杰和李连杰和李二棍 |
李杰和李连杰和李二棍 |
匹配字符串的结尾 |
|
|
|
|
字符串的开头结尾相当于有一个东西占位虽然什么都不显示 |
|||
\W |
|
|
匹配非字母数字下划线 |
\D |
|
|
匹配非数字 |
\S |
|
|
匹配非空白符 |
[\s\S] [\d\D] [\w\W] 匹配所有字符 |
|||
a|b |
|
|
匹配字符a或b |
\d+\.\d+|\d+ 1455.45456 \d+|\d+\.\d+ 1455.45456或前面的执行为真后面就不执行了() |
|||
如果b规则是a规则的一部分,且a规则比b规则要苛刻,就把a规则放前面 |
|||
() |
表示给几个字符加上量词的约束,就给这些字符加上() |
匹配括号内的表达式 |
|
[......]([\d]) |
1455.45456 |
|
匹配字符组中的字符 |
[^.....](\s) |
1455.45456 |
|
匹配非字符组中的字符 |
3.量词
量词 |
用法说明 |
待匹配字符 |
匹配结果 |
*(\d*) |
重复零次或更多次 |
m|85fj545 |
m|85fj545 |
+(\d+.\d+|\d) |
重复一次或更多次 |
1.26564 |
1.26564 |
?(李.?) |
重复一次或零次 |
李杰和李连杰和李二棍 |
李杰和李连杰和李二棍 |
{n}(李.{2}) |
重复n次 |
李杰和李连杰和李二棍 |
李杰和李连杰和李二棍 |
{n,}(李.{2, }) |
重复至少n次 |
李杰和李连杰和李二棍 |
李杰和李连杰和李二棍 |
{n,m}李.{1,2} |
重复n到m次 |
李杰和李连杰和李二棍 |
李杰和李连杰和李二棍 |
注意:前面的*+?等都是贪婪的的匹配,也就是尽可能匹配,后面加?号使其变成惰性机制
李.?? 李杰和李连杰和李二棍
4.字符集[ ],[^ ]
李[杰和李连杰和李二棍] |
李杰和李连杰和李二棍 |
表示匹配’李’后面[杰和李连杰和李二棍]的字符 |
李[^杰和李连杰和李二棍] |
李杰和李连杰和李二棍李哈 |
表示匹配李后面除了[杰和李连杰和李二棍] |
李[^和]* |
李杰和李连杰和李二棍李哈 |
表示匹配一个不是和的字符的任意次 |
5.贪婪匹配机制
例子一
1 2 |
var pattern=/8[a-zA-Z0-9]*7/;贪婪模式 var string="abc8defghij7klngon8qrstwxy7"; |
这时使用了贪婪模式*,表示8与8之间可有有任意多个字母,那这个正则先匹配第一个8,如果匹配到了后,就无限制的匹配后面的内容,只要后面的内容都满足[a-zA-Z0-9]就可以。一直匹配,匹配到不能再匹配为止,看紧接着后面的一个是不是7,如果不是那他就往前进一个(吐出一个看是不是7),如果不是再继续吐直到吐出7为止,然后匹配到的就是这之间的内容。所以结果匹配到的内容就是整条字符串。
1 2 |
var pattern=/8[a-zA-Z0-9]*?7/ig;惰性模式 var string="abc8defghij7klngon8qrstwxy7"; |
上面正则使用了惰性模式*?,此时匹配方式是这样的,先匹配一个8,然后在往后匹配一个字符看是不是符合[a-zA-Z0-9],如果符合,再去看紧接着后面的一个字符是不是7,如果是7就结束,如果不是就再往后匹配一个字符,看是不是符合[a-zA-Z0-9],如果符合,就再看紧接着后面的一个字符是不是7,如果是7就结束,否则,按照上面的方式依次循环下去,指导符合为止
6.转义字符
在正则表达式中如果要匹配正常的"\d"而不是数字就需要对'\'进行转义,变成'\\',在python中,无论是正则表达式还是带匹配的内容都是以字符串的形式出现的,所以如果要匹配一次''\d',字符串中要写成'\\d',那么正则里就写成'\\\\d',第一个\是使\d变成正常字符
正则 |
待匹配字符 |
匹配结果 |
说明 |
\d |
\d |
False |
因为在正则表达式中\是有特殊意义的字符所以要匹配\d本身用表达式\d无法匹配 |
\\d |
\d |
True |
转义\之后变成\\,即可匹配 |
‘’\\\\d” |
‘\\d’ |
True |
如果在python中,字符串中的’python’也需要转义,所以每一字符串’\’又需要转义一次 |
r'\\d' |
r’\d’ |
True |
在字符串之前加r,让整个字符串不转义 |
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import re ret=re.sub('\\d','sb','hdhsbkdfjid154',1)#将数字换成sb,替换一次 print(ret) #hdhsbkdfjidsb54
二.练习题
1.匹配整数或者小数(包括正数和负数)
-?\d+(\.\d+)? 与split的尽量用第二种 -?(\d+\.\d+|\d+)
2.匹配年月日日期 格式2018-12-6
[1-9]\d{0,3}-(1[0-2]|0?[1-9])-(3[01]|[12]\d|0?[1-9])
3.1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2)) # 1)从上面算式中匹配出内层没有其他小括号的表达式
\([^()]+\)
4.匹配邮箱地址
[0-9a-zA-Z][\w\-.]+@[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)*\.[A-Za-z0-9]{2,6}
三.re模块的方法
1.findall()找到所有匹配项,返回一个列表,如果没有则返回一个空列表[],不用和group(函数一起)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import re
ret=re.findall("alex?",'hello alexxxxxxxxx')
print(ret) #['alex']表示x出现一次或零次(不是惰性匹配也不是贪婪匹配)
ret=re.findall("alex*",'hello alexxxxxxxxx')
print(ret) #['alexxxxxxxxx']
ret=re.findall("alex*?",'hello alexxxxxxxxx')
print(ret) #['ale']
ret=re.findall("alex+?",'hello alexxxxxxxxx')
print(ret) #['alex']
ret=re.findall("ale\w+8",'hello alexxxxxxxxx8xxx8alex')
print(ret) #['alexxxxxxxxx8xxx8']贪婪匹配
ret=re.findall("ale\w+?8",'hello alexxxxxxxxx8xxx8alex')
print(ret)
2.search()
函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,如果没有返回None,如果匹配到了该对象可以 通过调用group()方法得到匹配的字符串,如果没有匹配到直接调用group()则会报错.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import re
ret=re.search('\d+','5464821 cvdhgyfusg 7877')
print(ret) #<_sre.SRE_Match object; span=(0, 7), match='5464821'>
print(ret.group()) #5464821
ret=re.search('[<>]','5464821 cvdhgyfusg 7877')
print(ret) #None
print(ret.group()) #'NoneType' object has no attribute 'group'
解决方案
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
ret=re.search('[\d]','5464821 cvdhgyfusg 7877')
if ret:
print(ret.group()) #5
ret=re.search('[<>]','5464821 cvdhgyfusg 7877')
if ret:
print(ret.group()) #什么都不输出
3.match()同search()不过尽在字符串开始处进行
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import re
ret=re.match('abh','abh哈哈哈哈1548')
print(ret) #<_sre.SRE_Match object; span=(0, 3), match='abh'>
print(ret.group()) #abh
4.split(''要以什么分割的东西','字符串','分割的次数) #分割,如果分割在两端则会产生空白
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import re
ret=re.split('\d+','dufhuf15486ndgfyhd14',1)
print(ret)
#['dufhuf', 'ndgfyhd', '']
5. sub('想要替换掉的','想要替换成的','替换的大对象',替换次数),返回字符串
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import re
ret=re.sub('\d','sb','hdhsbkdfjid154',1)#将数字换成sb,替换一次
print(ret)
#hdhsbkdfjidsbsbsb
subn('想要替换掉的','想要替换成的','替换的大对象') 返回元组(替换的结果,替换了多少次)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
ret=re.subn('\d','sb','hdhsbkdfjid154')#将数字换成sb, print(ret) #('hdhsbkdfjidsbsbsb', 3)
6.compile()可与findall(), search(),match()调用对象需要如果要输出匹配内容需要与group()连用(请使用if语句,否则会报错)
语法
import re obj=re.compile('要匹配的内容'') ret=obj.findall('带匹配内容') print(ret)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import re obj=re.compile('\d{1,3}') ret1=obj.search('156478756ndjhgsfy4578') print(ret1.group()) #156
7.findinter()
# it = re.finditer(r"\w+", "meirenyao, meichaofeng, meixingfu, meiqian")
# for i in it:
# print(i.group())