Python正则表达式(regular expression)简介-re模块
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
就其本质而言,正则表达式(或RE模块)是一种小型的,高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过re模块实现。正则表达式模式被编译成一系列的字节码,然后由C编写的匹配引擎执行。
前言:
如果让你匹配一下以“13|14|15|17|18”开头的电话号码你会怎么写呢?可能你会说这个很简单啊,几行代码搞定,不信你看:
1 PhoneNumber = input("You telephone number is >>>") 2 if PhoneNumber.isdigit() and len(PhoneNumber) == 11 and PhoneNumber.startswith("13")\ 3 or PhoneNumber.startswith("15") or PhoneNumber.startswith("14") \ 4 or PhoneNumber.startswith("17") or PhoneNumber.startswith("18") : 5 print("电话号码合法") 6 else: 7 print("sorry,电话号码不合法!")
你这样写的话可以实现功能,但是看起来很low,如果让你匹配的字符串较多的话这种写法就不是很好了,我们可以用正则表达式来帮我们来解决这个问题,不信你看:
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 import re 8 9 PhoneNumber = input("You telephone number is >>>") 10 if re.match('^(13|14|15|17|18)[0-9]{9}$',PhoneNumber): 11 print("电话号码合法") 12 else: 13 print("sorry,电话号码不合法!")
写了三行的代码竟然用一行就可以搞定了,是不是绝对很高大上呢?其实,正则的功能我这个小案例只是展示了冰山一角。它的用处在每个语言都是有设计的,好了接下里让我们系统的学习一下正则表达式把。
一.re元字符
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 import re 8 9 """ 10 正则表达式功能: 11 进行字符串的模糊匹配查询。 12 普通字符: 13 大多数字符和字母都会和自身匹配。 14 元字符: 15 字符串的模糊匹配,是通过元字符实现的,如:“ .^$*+?{}[]|()\” 16 1>.“.”:除换行符以外的任意一个符号; 17 2>.“^”:匹配字符串的开始位置; 18 3>.“$”:匹配字符串的结束位置; 19 4>.“*+?{}”:匹配重复的次数,其中“*”重复的是(0,无穷次),“+”重复的是(1,无穷次),“?”重复的是(0,1),“{}”表示指定的次数; 20 5>.“\”: 21 6>.“”: 22 7>.“”: 23 24 """ 25 26 s1 = re.findall("尹..","尹正杰,尹正文,尹小倩,邓西,yinzhengjie") 27 print(s1) 28 29 s2 = re.findall("^尹","尹正杰,尹正文,尹小倩,邓西,yinzhengjie") 30 print(s2) 31 32 s3 = re.findall("jie$","尹正杰,尹正文,尹小倩,邓西,yinzhengjie") 33 print(s3) 34 35 s4 = re.findall("\d{18}","612401199105197586,110569874136547861") #匹配连续18位的数字 36 print(s4) 37 38 s4_1 = re.findall("6124\d*","612401199105197586,110569874136547861,61247474741,6124") 39 print(s4_1) 40 41 s4_2 = re.findall("6124\d+","612401199105197586,110569874136547861,61247474741,6124") 42 print(s4_2) 43 44 s4_3 = re.findall("-?\d+","6124,-21,18,-26,12,-6") #匹配整数和负数 45 print(s4_3) 46 47 48 49 50 51 #以上代码执行结果如下: 52 ['尹正杰', '尹正文', '尹小倩'] 53 ['尹'] 54 ['jie'] 55 ['612401199105197586', '110569874136547861'] 56 ['612401199105197586', '61247474741', '6124'] 57 ['612401199105197586', '61247474741'] 58 ['6124', '-21', '18', '-26', '12', '-6']
二.转义符
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 import re 8 9 10 """ 11 转义符“\”的功能: 12 1>.反斜线后面跟元字符取出特殊功能,比如"\."; 13 2>.反斜杠后面跟普通字符实现特殊更难,比如“\d”; 14 “\d”:匹配任何十进制数;相当于类[0-9]; 15 “\b”:匹配任何非数字字符:相当于类[^0-9]; 16 “\s”:匹配任何空白字符:相当于[\t\n\r\f\v]; 17 “\S”:匹配任何非空白字符:相当于[^ \t\n\r\f\v]; 18 “\w”:匹配任何字母数字字符:相当于[a-zA-Z0-9]; 19 “\W”:匹配任何非字母数字字符,它相当于[^ a-zA-Z0-9]; 20 “\b”:匹配一个特殊字符边界,比如:“空格”,“,”,“&”,“#”等等; 21 """ 22 23 s1 = re.findall("\.com","www.baidu.com") #表示将元字符“.”转义为普通字符“.”。 24 print(s1) 25 26 s2 = re.findall("\d+","yinzhengjie2018") 27 print(s2) 28 29 s3 = re.findall("\w+","yinzhengjie@2018") 30 print(s3) 31 32 s4 = re.findall(r"y\b","My@ name is y inzhengjie !") #注意,这个字母“r”表示后面的对象是原生字符串,并不包含任何特殊意义,会直接将这个原生字符串传递给re模块的findall方法。 33 print(s4) 34 35 s5 =re.findall(r"c\\l","abc\le") 36 print(s5) 37 38 39 40 41 #以上代码执行结果如下: 42 ['.com'] 43 ['2018'] 44 ['yinzhengjie', '2018'] 45 ['y', 'y'] 46 ['c\\l']
三.findall的分组方法
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 8 import re 9 10 s1 = re.findall("yin+","yinzhengjieyinnnnnnyinnihao") #“+”具有贪婪模式的匹配。 11 print(s1) 12 13 s2 = re.findall("(yin)+","yinzhengjieyinyinnihao") #分组概念,将“yin”加入一个分组。 14 print(s2) 15 16 s3 = re.findall("(尹.{1,3}),","尹正杰,尹正文,尹小倩,邓西,yinzhengjie,") #分组的举例,我们用分组的效果实现s4的方法。findall方法是会优先匹配分组的内容。 17 print(s3) 18 19 s4 = re.findall("尹\w+","尹正杰,尹正文,尹小倩,邓西,yinzhengjie,") 20 print(s4) 21 22 23 24 25 #以上代码执行结果如下: 26 ['yin', 'yinnnnnn', 'yinn'] 27 ['yin', 'yin'] 28 ['尹正杰', '尹正文', '尹小倩'] 29 ['尹正杰', '尹正文', '尹小倩']
四.search方法
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 8 import re 9 10 """ 11 search: 12 只匹配意向符合规则的元素。 13 """ 14 15 16 s1 = re.search("\d+","yinzhengjie2018@0520") 17 print(s1) 18 print(s1.group()) 19 20 21 22 s2 = re.search(r"-blog-aticles-(?P<year>20[01]\d)-(?P<month>\d+)","-blog-aticles-2015-04") #给分组命名 23 print(s2.group("year")) #表示只取分组的“year”名称。 24 print(s2.group("month")) 25 26 27 28 29 #以上代码执行结果如下: 30 <_sre.SRE_Match object; span=(11, 15), match='2018'> 31 2018 32 2015 33 04
五.match方法
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 import re 8 9 """ 10 match: 11 只匹配字符串的开始的位置。 12 """ 13 14 s1 = re.match("\d+","yinzhengjie2018") 15 print(s1) 16 17 18 s2 = re.match("\d+","20180520yinzhengjie") 19 print(s2) 20 print(s2.group()) 21 22 23 24 #以上代码执行结果如下: 25 None 26 <_sre.SRE_Match object; span=(0, 8), match='20180520'> 27 20180520
六.字符集
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 import re 8 9 s1 = re.findall(r"a[bc]d","abdacde") 10 print(s1) 11 12 s2=re.findall(r"a[b.*c]d","abddaslacda*d") #我们此处的特殊字字符“.”,“*”并没有实际意义,而是一个普通字符 13 print(s2) 14 15 """ 16 字符集中只有三个特殊符号: 17 1>.“-” 18 2>.“^” 19 3>.“\” 20 21 """ 22 s3=re.findall(r"[0-9]+","yinzhengjie2018@0331") #等效“\d” 23 print(s3) 24 25 s4=re.findall(r"[a-zA-Z0-9_]+","yinzhengjie2018@0331") #等效“\w” 26 print(s4) 27 28 s5=re.findall(r"a[\d]c","ads32421sdf32a3c4sdf") #等效“\d” 29 print(s5) 30 31 ret=re.findall(r"a[^\da-z]c","ads32421sdf32a3c4sa@cdf") #等效“\d” 32 print(ret) 33 34 35 36 37 38 #以上代码执行结果如下: 39 ['abd', 'acd'] 40 ['abd', 'acd', 'a*d'] 41 ['2018', '0331'] 42 ['yinzhengjie2018', '0331'] 43 ['a3c'] 44 ['a@c']
七.管道符
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 import re 8 9 s1 = re.findall("www\.(?:\w+)\.(?:com|cn)","www.yinzhengjie.com;www.yinzhengjie.cn,www.yinzhengjie.org.cn;") #注意这个时候“?:”是取消优先级的作用! 10 print(s1) 11 12 13 14 15 #以上代码执行结果如下: 16 ['www.yinzhengjie.com', 'www.yinzhengjie.cn']
八.贪婪匹配
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 import re 8 9 10 # 贪婪 模式 11 s1 = re.findall("abc+","dasasdabccccasd") 12 print(s1) 13 14 s2 = re.findall("abc{2,5}","dasasdabcccccccasd") 15 print(s2) 16 17 # 非贪婪模式:按着最小重复数 18 s3 = re.findall("abc+?","dasasdabccccasd") 19 print(s3) 20 21 s4 = re.findall("abc{2,5}?","dasasdabcccccccasd") 22 print(s4) 23 24 s = "<div>yin<img></div><a href=""></div>" 25 s5 = re.findall("<div>.*?</div>",s) 26 print(s5) 27 28 s6 = re.search("<div>.*?</div>",s) 29 print(s6) 30 31 """ 32 一.几个常用的非贪婪匹配: 33 1>."*?":重复任意次,但尽可能少重复; 34 2>.“+?”:重复1次或更多次,但尽可能少重复; 35 3>.“??”:重复0次或1次,但尽可能少重复; 36 4>.“{n,m}?”:重复n到m次,但尽可能少重复; 37 5>."{n}?":重复n次以上,但尽可能少重复; 38 39 二.".",“*”,“?”的用法 40 1>.“.”是任意字符; 41 2>.“*”是取“0”至无限长度; 42 3>."?"是非贪婪匹配; 43 “.*?x”表示取前面任意长度的字符,直到x出现。 44 45 """ 46 47 48 49 50 #以上代码执行结果如下: 51 ['abcccc'] 52 ['abccccc'] 53 ['abc'] 54 ['abcc'] 55 ['<div>yin<img></div>'] 56 <_sre.SRE_Match object; span=(0, 19), match='<div>yin<img></div>'>
九.split方法
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 import re 8 9 s = "yinzhengjie2018hello05ACE19world" 10 11 s1 = re.split("\d+",s,2) #后面的数字表示指定分割的次数,如果不加数字默认全部分割。 12 print(s1) 13 14 15 s2 = re.split("(\d+)",s) 16 print(s2) 17 18 19 20 21 #以上代码执行结果如下: 22 ['yinzhengjie', 'hello', 'ACE19world'] 23 ['yinzhengjie', '2018', 'hello', '05', 'ACE', '19', 'world']
十.sub方法
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 import re 8 9 s = "yinzhengjie2018hello05ACE19world" 10 11 12 s1 = re.sub("yinzhengjie","尹正杰",s) 13 print(s1) 14 15 s2 = re.sub("e","E",s,2) 16 print(s2) 17 18 19 20 21 #以上代码执行结果如下: 22 尹正杰2018hello05ACE19world 23 yinzhEngjiE2018hello05ACE19world
十一.complie方法
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 import re 8 9 s = "yinzhengjie2018hello05ACE19world" 10 11 obj = re.compile("\d+") #编译规则。 12 13 s1 = obj.findall(s) 14 print(s1) 15 16 17 18 19 #以上代码执行结果如下: 20 ['2018', '05', '19']
十二.finditer方法
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 import re 8 9 """ 10 finditer: 11 返回的是一个迭代器对象。 12 """ 13 14 s = "yinzhengjie2018hello05ACE19world" 15 16 s1 = re.finditer("\d+",s) 17 print(s1) 18 19 for i in next(s1).group(): 20 print(i) 21 22 23 24 25 #以上代码执行结果如下: 26 <callable_iterator object at 0x032005F0> 27 2 28 0 29 1 30 8
十三.爬虫练习
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 import requests 8 import re 9 10 11 def getPage(): 12 respnse_str = requests.get("https://movie.douban.com/top250?start=0&filter=") 13 # print(type(respnse_str.text)) 14 15 return respnse_str.text 16 17 18 def run(): 19 resonse = getPage() 20 21 obj = re.compile('<div class="item">.*?<em.*?>(?P<id>\d+)</em>.*?<span class="title">(.*?)</span>' 22 '.*?<span class="rating_num".*?>(.*?)</span>', re.S) 23 24 ret = obj.finditer(resonse) 25 26 # res = next(ret).group() 27 # print(res) 28 print(ret) 29 30 run() 31 32 33 34 35 #以上代码执行结果如下: 36 <callable_iterator object at 0x02F47AF0>
正在表达式主要是用于模糊匹配,Python中的正则用法比较简单,但是规则比较麻烦,你可以根据你的需求配置不同的规则,更多详情请参考:http://www.cnblogs.com/yinzhengjie/p/6428006.html