什么是正则?
正则表达式也称为正则,是一个特殊的字符序列,能帮助检查一个字符串是否与某种模式匹配。可以用来进行验证:邮箱、手机号、qq号、密码、url = 网站地址、ip等。正则不是python语言独有的技术,python语言直到1.5版本才将正则表达式完成的整理/纳入进re模块中,我们只需要导入re模块,然后就可以使用其中所有和正则相关的函数和属性了。
1. re模块中最常用的几个函数
1). re.match函数:
功能:将string数据从头开始尝试匹配 ;如果匹配成功,那么就会返回给程序一个match对象;如果开头就不匹配,那么直接返回None值;
语法格式:re.match(regex, string[, flags=0])
参数:regex:匹配的正则表达式(内部定义了一套验证规则)
string:需要被验证的字符串数据
flags:可选参,模式/标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。默认情况下(不显示定义) --> 不开启任何的模式
【注意】匹配成功re.match方法返回一个匹配的对象,否则返回None。我们可以使用group(num) 或 groups() 等匹配对象函数来获取匹配表达式。match对象有5个常用的函数:
(1). group():返回匹配成功的数据值(理解:原串中的某部分子串信息)
(2). start():返回匹配成功的数据的起始索引
(3). end(): 返回匹配成功的数据的结束索引
(4). span(): 返回一个元祖对象,有两个元素组成;第一个元素记录了匹配成功的数据的起始索引第二个元素记录了匹配成功的数据的结束索引
(5). groups():以元祖的形式返回所有子组的信息(一个包含所有小组字符串的元组,从1到所含的小组号);如果没有进行正则分组,则返回一个空元祖。
1 import re 2 3 mo = re.match(r'Www','www.baidu.com') 4 print(mo) # None 5 print(type(mo)) # <class 'NoneType'> 6 7 print(re.match(r'www','www.sina.com')) # <_sre.SRE_Match object; span=(0, 3), match='www'> 8 print(re.match(r'www','www.sina.com').group()) # www 9 print(re.match(r'www','www.sina.com').start()) # 0 10 print(re.match(r'www','www.sina.com').end()) # 3 11 print(re.match(r'www','www.sina.com').span()) # (0,3) 12 print(re.match(r'www','www.sina.com').groups()) # () 13 print(re.match(r'WWW','www.sina.com')) # None 14 print(re.match(r'WWW','www.sina.com',flags=re.I)) # <_sre.SRE_Match object; span=(0, 3), match='www'> 15 16 17 18 line = "Cats are smarter than dogs" 19 20 matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I) 21 22 if matchObj: 23 print(matchObj.group()) # "Cats are smarter than dogs" 24 print(matchObj.group(1)) # "Cats" 25 print(matchObj.group(2)) # "smarter"26 print(matchObj.groups()) # ("Cats","smarter")27 else:28 print("No match!!")
【补充】:第二种方式实现正则对数据的校验:re.compile函数
功能:compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。
语法格式为:re.compile(regex[, flags])
参数:和match一样理解
【注意】compile 函数执行完毕以后返回给程序一个Pattern对象(理解:对象的内部封装了一套regex和flags),可以再通过Pattern对象调用其match函数(此时的match函数只需要传递一个参数:string即可)
compile()配合match()使用演示:
1 import re 2 3 pat = re.compile(r'www',flags=re.I) 4 print(pat) # re.compile('www', re.IGNORECASE) 5 print(type(pat))) # <class '_sre.SRE_Pattern'> 6 print(pat.match('www.baidu.com')) # <_sre.SRE_Match object; span=(0, 3), match='www'> 7 8 # 相当于 re.compile.match(r'www','www.baidu.com',flags=re.I)
【注意事项】:
1).正则表达式返回的索引值需要满足含头不含尾的特点
2).正则表达式验证的数据内容严格区分大小写
3).之后在定义正则表达式的时候,在它的第一个引号前面,都显示的追加一个r,无脑行为...(转义字符)
2). re.search函数:
功能:从头开始尝试匹配,如果开头就匹配不成功,不会返回None值,会继续尝试往后匹配;一旦匹配成功了,就直接返回一个match对象,后续就算还存在可以匹配成功的子串数据,也不会再匹配了(直接无视);如果直到最后都匹配不成功,返回一个None值。
语法格式:re.search(regex,string[,flags=0])
参数:和match一样理解
【补充】:由于search函数调用返回的是match对象,所以仍然可以调用5个常用的函数
1 import re 2 3 print(re.match(r'www','hahawww.baidu.com!!www.qfedu.comhehe')) # None 4 print(re.search(r'www','hahawww.baidu.com!!www.qfedu.comhehe')) # <_sre.SRE_Match object; span=(4, 7), match='www'> 5 print(re.search(r'www','hahawww.baidu.com!!www.qfedu.comhehe').group()) # www 6 print(re.search(r'www','hahawww.baidu.com!!www.qfedu.comhehe').start()) # 4 7 print(re.search(r'www','hahawww.baidu.com!!www.qfedu.comhehe').end()) # 7 8 print(re.search(r'www','hahawww.baidu.com!!www.qfedu.comhehe').span()) # (4, 7) 9 print(re.search(r'www','hahawww.baidu.com!!www.qfedu.comhehe').groups()) # () 10 print(re.search(r'Www','hahawww.baidu.com!!www.qfedu.comhehe')) # None 11 print(re.search(r'Www','hahawww.baidu.com!!www.qfedu.comhehe',flags=re.I)) # <_sre.SRE_Match object; span=(4, 7), match='www'>
compile()配合search()使用演示:
1 import re 2 3 pat = re.compile(r'www') 4 mo = pat.search('Wwww.sina.com!!www.baidu.com!!www') 5 6 print(mo) # <_sre.SRE_Match object; span=(1, 4), match='www'>
3). re.findall函数:
功能:在字符串中找到所有匹配成功的子数据(子串),都存入到列表中返回;如果一个都匹配不成功,那么返回一个空列表。
语法格式:re.findall(regex,string[, pos[, endpos]][,flags=0])
参数:pos:可选参数,指定字符串的起始位置,默认为 0
endpos :可选参数,指定字符串的结束位置,默认为字符串的长度
其他参数和match、search一样理解
1 import re 2 3 lt = re.findall(r'www','www.sina.com!!www.baidu.com') 4 print(lt,type(lt)) # ['www', 'www'] <class 'list'> 5 6 lt1 = re.findall(r'WWW','www.sina.com!!www.baidu.com!!WWW',flags=re.I) 7 print(lt1,type(lt1)) # ['www', 'www', 'WWW'] <class 'list'> 8
compile()配合search()使用演示:
1 import re 2 3 pat = re.compile(r'www',flags=re.I) 4 lt = pat.findall('www.sina.com!!www.baidu.com!!WWW') 5 6 print(lt) # ['www', 'www', 'WWW'] 7 8 9 10 pattern = re.compile(r'\d+') # 查找数字 11 result1 = pattern.findall('runoob 123 google 456') # 不指定字符串的起始和结束位置 12 result2 = pattern.findall('run88oob123google456', 0, 10) # 指定字符串的起始和结束位置 13 14 print(result1) # ['123', '456'] 15 print(result2) # ['88', '12']
4). re.finditer函数:
功能:和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,但是将所有匹配成功的数据封装为一个一个的match对象, 然后以iterator(迭代器对象)返回
语法格式:finditer(regex,string[,flags=0])
参数:和match、search、findall一样理解
1 import re 2 3 it = re.finditer('apple', 'i hate apple apple apple so much') 4 5 # iterator(迭代器对象)不能直接使用内置函数len()执行查看其容量大小,会报错:TypeError; 但是可以先将其转换为容器对象(list、tuple...),就可以被len()所执行了; 6 print(len(it)) # TypeError 7 print(len(list(it))) # 3 8 9 # 使用遍历的思想去访问iterator中的元素 10 for i in it: 11 print(i) 12 print(type(i)) 13 print(i.group()) 14 15 # <_sre.SRE_Match object; span=(7, 12), match='japan'> 16 # <class '_sre.SRE_Match'> 17 # apple 18 19 # <_sre.SRE_Match object; span=(13, 18), match='japan'> 20 # <class '_sre.SRE_Match'> 21 # apple 22 23 # <_sre.SRE_Match object; span=(19, 24), match='japan'> 24 # <class '_sre.SRE_Match'> 25 # apple 26 27 #迭代器对象中的内容只能被使用一次,不可逆,否则报错:StopIteration 28 # print(next(it)) 29 30 # 使用while循环来遍历iterator对象,结果和for......in..一样 31 while 1: 32 try: 33 mo = next(it) 34 print(mo) 35 print(mo.group()) 36 except: 37 break
5). re.sub 函数:
功能:替换字符数据
语法格式:sub(regex,repl,string,[count],[flags=0]):返回字符串(已经被替换完成后的内容)
subn(regex,repl,string,[count],[flags=0]):返回元祖对象,此对象有两个元素;第一个元素记录了替换以后的字符串内容,第二个元素记录了被替换的次数(count)
参数:regex:正则规则(字符串)
repl:替换成的字符串内容,也可为一个函数
string:原串数据
count:次数,模式匹配后替换的最大次数,默认 为0 表示替换所有的匹配
1 import re 2 3 str1 = re.sub('beijing', 'shanghai', 'i love beijing beijing beijing so much') 4 print(str1,type(str1)) # i love shanghai shanghai shanghai so much <class 'str'> 5 6 tp = re.subn('beijing', 'shanghai', 'i love beijing beijing beijing so much', 2) # 2改成4也不会报错,就会全部替换 7 print(tp,type(tp)) # ('i love shanghai shanghai beijing so much', 2) <class 'tuple'> 8 9 10 # 示例:模拟让游戏世界变得和谐(使用正则) 11 regex = r'CNM|MB|SB|NC|WQNMLGB|TMD|NND' 12 game = 'WQNMLGB!!连装备都不会出...小学生!!SB...' 13 14 s = re.sub(regex,'***',game) 15 print(s) # ***!!连装备都不会出...小学生!!***... 16 17 18 # 示例:删除某些内容 19 phone = "2004-959-559 # 这是一个国外电话号码" 20 21 # 删除字符串中的Python注释 22 num = re.sub(r'#.*$', "", phone) 23 print("电话号码是: ", num) # 电话号码是: 2004-959-559 24 25 # 删除非数字(-)的字符串 26 num = re.sub(r'\D', "", phone) 27 print("电话号码是 : ", num) # 电话号码是 : 2004959559 28 29 30 # 示例:repl参数是一个函数时,将字符串中的匹配的数字乘以 2 31 # 将匹配的数字乘以 2 32 def double(matched): 33 value = int(matched.group('value')) 34 return str(value * 2) 35 36 s = 'A23G4HFD567' 37 print(re.sub('(?P<value>\d+)', double, s)) # A46G8HFD1134
【补充示例】:替换相关的操作
1 str5 = 'dsaf######32141asf#####dsafa#########()!,.___######21341##' 2 3 # 将一个#替换成为一个- 4 regex1 = r'#' 5 str6 = re.sub(regex1,'-',str5) 6 print(str6) # dsaf------32141asf-----dsafa---------()!,.___------21341-- 7 8 # 将一堆#替换成为一个- 9 regex2 = r'#+' 10 tp = re.subn(regex2,'-',str5) 11 print(tp) # ('dsaf-32141asf-dsafa-()!,.___-21341-', 5)
6). re.split 函数:
功能:按照能够匹配的子串将字符串分割后返回列表
语法格式:re.split(regex, string[, maxsplit=0, flags=0])
参数:maxsplit :分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数
1 import re 2 3 str1 = 'i love shanghai so much' 4 regex = r' +' # 切割空格,+表示一个到多个,有贪婪行为,把空格全切了 5 lt = re.split(regex,str1) 6 print(lt) # ['i', 'love', 'shanghai', 'so', 'much'] 7 8 str2 = 'i love shanghai so much' 9 regex = r' +?' # 切割空格 +表示一个到多个, ?取消贪婪行为,能少切就少切 10 lt = re.split(regex,str2) 11 print(lt) # ['i', '', '', '', '', '', '', 'love', '', '', '', '', '', '', '', 'shanghai', '', '', '', 'so', '', 'much'] 12 13 str3 = 'dasfas23141sfa123dsafas13dasdfa1231241____3241234^&*&(dsafa 14 214331asdfa' 15 regex = r'\d+?' 16 lt = re.split(regex,str3) 17 print(lt) # ['dasfas', '', '', '', '', 'sfa', '', '', 'dsafas', '', 'dasdfa', '', '', '', '', '', '', '____', '', '', '', '', '', '', '^&*&(dsafa', '', '', '', '', '', 'asdfa'] 18 19 regex1 = r'\d+' 20 lt1 = re.split(regex1,str3) 21 print(lt1) # ['dasfas', 'sfa', 'dsafas', 'dasdfa', '____', '^&*&(dsafa', 'asdfa']
2. 正则表达式修饰符 - 可选标志(flags)
正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志:
re.I:使匹配对大小写不敏感,忽略大小写
re.L:做本地化识别(locale-aware)匹配,表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境
re.M:多行匹配,影响 ^ 和 $,多行模式
re.S:使.匹配包括换行在内的所有字符
re.U:根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B
re.X:该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解,即为了增加可读性,忽略空格和 # 后面的注释
3. 正则中元字符的使用
正则表达式模式:模式字符串使用特殊的语法来表示一个正则表达式:字母和数字表示他们自身。一个正则表达式模式中的字母和数字匹配同样的字符串。多数字母和数字前加一个反斜杠时会拥有不同的含义。标点符号只有被转义时才匹配自身,否则它们表示特殊的含义。反斜杠本身需要使用反斜杠转义。由于正则表达式通常都包含反斜杠,所以你最好使用原始字符串来表示它们。模式元素(如 r'\t',等价于 '\\t')匹配相应的特殊字符。下表列出了正则表达式模式语法中的特殊元素。如果你使用模式的同时提供了可选的标志参数,某些模式元素的含义会改变。
匹配单个字符(数字、英文、其它...)符号位:
[ ]:表示一字符位
[9876123450]:表示一位,取值范围:[0,9]中间的任何一位值
[0-9]:表示一位,取值范围:[0,9]中间的任何一位值
\d:表示一位,取值范围:[0,9]中间的任何一位值
\D:对以上的\d进行取反,意味着:匹配除了数字字符以外的所有字符
[24680]:表示一位,取值范围:2、4、6、8、0中的任何一个值
[abcdefg]:表示一位,取值范围:a、b、c、d、e、f、g中的任何一个值
[a-z]:表示一位,取值范围:[a,z]中的任何一个值
[A-Z]:表示一位,取值范围:[A,Z]中的任何一个值
[0-9a-zA-Z_]:表示一位,取值范围:0~9、a~z、A~Z以及_中的任何一个值
\w:表示一位,取值范围:0~9、a~z、A~Z以及_中的任何一个值
\W:对\w进行取反操作,意味着:匹配除了0~9、a~z、A~Z以及_中的其它所有字符
.: 匹配除了换行符以外的所有字符
匹配锚字符(边界字符):
^:从字符串数据的头部开始匹配,在开启了多行模式的情况下(re.M),它可以尝试匹配每一行的头部数据
$:从字符串数据的尾部开始匹配,在开启了多行模式的情况下(re.M),它可以尝试匹配每一行的尾部数据
\A:从字符串数据的头部开始匹配,在开启了多行模式的情况下(re.M),它没有多行的概念,还是匹配第一行的头部数据
\Z:从字符串数据的尾部开始匹配,在开启了多行模式的情况下(re.M),它没有多行的概念,还是匹配最后一行的尾部数据
补充:
\b:尝试匹配边界(左侧、右侧)数据,如果一旦满足返回对象(match、list)
\B:先舍弃规定边界的数据,然后一定满足从左侧开始匹配数据,...
匹配多个字符:
以下的一些x,y,n等都是变量名
1).模糊匹配:
x?:表示0个或者1个 取值范围:[0,1]
x+:表示1个或者多个 取值范围:[1,无穷大)
x*:表示0个或者多个 取值范围:[0,无穷大)
2).精确匹配:
n{x}: 将n匹配x次
n{x,}: 将n最少有x次,最多无穷大 范围:[x,无穷多)
n{x,y}:将n最少有x次,最多有y次 范围:[x,y]
得到 None <class 'NoneType'>
来源:https://www.cnblogs.com/bonheur/p/12337416.html