本文共 4513 字,大约阅读时间需要 15 分钟。
继上篇文章说了正则表达式的基础用法,那今天我们就继续说一下正则表达式的复杂的用法。好了,废话不多说,直接进入正题。
情景:当你想要匹配一个qq号,qq号码长度为5-10位,那根据上篇文章的说法,很容易就可以想到该正则:
[0-9]{ 5,10}
这样是可以的,但是当你匹配一个长度大于10的号码时就会出错,这时就会去该字符串的前10个数字出来,如下:
import rea='1234567890'r=re.findall('[0-9]{5,10}',a)#明显当查找的字符串长度大于8位时就会出错,只会截取前一部分长度print(r)
结果:
['1234567890']
这样的话你就会得到一个错误的qq号码。
这时就需要引入边界匹配了:
现在再写个匹配qq号码的正则:
r=re.findall('^[0-9]{5,10}$',a)#这个表示从左边起为5-10的数字长度,右边也是一样print('第一个匹配结果:',r)a = '1234567890'r=re.findall('^[0-9]{5,10}$',a)print('第二个匹配结果:',r)
结果:
第一个匹配结果: []第二个匹配结果: ['1234567890']
这样就可以匹配到了,是不是很神奇?
组:前面我们有用 [ ] 来匹配,中括号里面表示的是或关系,而这里的组表示的是并关系,并且用小括号括起来 ( )。
比如:重复 python 字样三次import rea='pythonpythonpythonjakjpythonpythonsdjjpythonpythonpythonsd'r=re.findall('(python){3}',a)print(r)
结果:
['python', 'python']
这里的结果不是返回三个python,而是返回这个组,当符合一次就会将此组添加到返回列表中一次。
这个组还挺好用的,再看下这个需求:获取下列英文中的life和python之间的内容。
a='life is short,i use python'r=re.findall('life(.*)python',a,re.S)print(r) # 这样获取的就是组内的内容
结果:
[' is short,i use ']
这个组还常用,因为在我们经常在用正则来解析html元素时,经常需要获取两个标签之间的内容,标签是确定的,标签内容不确定,就可以用这个了。如下这个html元素:
python进阶 python入门 vce解决方法 百度 反馈意见 下载图片
这样就可以用组来获取a标签的内容了:<a .*?>(.*?)</a>
。?表示非贪婪哦!
当需要写多个匹配模式时,可以用 | 分隔每个模式
代码如下:a='Java12Python89'r=re.findall('python',a,re.I)print(r)a='hsjhj h123jfkksf hajkGH\nkj fjfk'r=re.findall('.',a,re.I|re.S)print(r)
结果:
['Python']['h', 's', 'j', 'h', 'j', ' ', 'h', '1', '2', '3', 'j', 'f', 'k', 'k', 's', 'f', ' ', 'h', 'a', 'j', 'k', 'G', 'H', '\n', 'k', 'j', ' ', 'f', 'j', 'f', 'k']
正则除了可以用来检索字符串,还可以用来替换字符串,常见的可以用来替换那些文本中的空格,制表符和回车等,这些都是用一个正则就可以搞定的了。
python中用这个方法来进行正则替换
re.sub(pattern, repl, string, count=0, flags=0)代码如下:
import rea='skjC#ksjfc#jkdsc#'r=re.sub('c#','gg',a)#返回值是替换后的字符串print(r)print(a)r=re.sub('c#','gg',a,1) # 这个加了替换次数print(r)r=re.sub('c#','gg',a,1,re.I) # 加了匹配模式,忽视大小写print(r)
结果
skjC#ksjfggjkdsggskjC#ksjfggjkdsc#skjggksjfc#jkdsc#
我们试试第二个参数为函数的情况
def convert(value):#他是把对象传进去这个参数 print(value) #可以通过group()方法来获取内容 return '!!'+value.group()+"!!"r=re.sub('c#',convert,a,flags=re.I)#接收个参数后,更改后的内容为他的返回值print(r)
结果
<_sre.SRE_Match object; span=(3, 5), match='C#'><_sre.SRE_Match object; span=(9, 11), match='c#'><_sre.SRE_Match object; span=(15, 17), match='c#'>skj!!C#!!ksjf!!c#!!jkds!!c#!!
这个第二个参数为convert函数,里面的.group() 方法是获取匹配后的字符串的值,所以我们就可以根据匹配后的字符串来进行相对应的替换内容,比如这个简单的小需求:
把字符串中的数字大于50的改为99,小于的就改为11。a='ds+45sd78asd12568asd45asd74ew+9ddf12sd45'def func(value): if int(value.group())>50: return '99' else: return '11'r=re.sub('\d{1,2}',func,a)print(r)
结果
ds+11sd99asd119911asd11asd99ew+11ddf11sd11
另谈两个函数
代码:
import rea='pythonphpjavacphp'r=re.match('php',a)#这个一开始没有就返回Noneprint(r)r=re.search('php',a)#这个搜索到之后就返回一个对象#返回的对象可以通过group()方法来获取他的内容print(r)# 获取匹配内容print(r.group())
结果
None<_sre.SRE_Match object; span=(6, 9), match='php'>php
这两个函数返回的内容的几个属性:
前面提到组的概念,试下这两个方法的组的用法:
import re#获取life和python之间的内容a='life is short,i use python'r=re.search('life(.*)python',a,re.S)#用小括号的就是一组print(r.group(1))#这个下标1就是对应的中间部分#也可以获取中间的两部分a='javawoshipythonjunephp'r=re.search('java(.*)python(.*)php',a)#两个小括号就是分成了两组print(r.group(1),r.group(2))#分别打印第一第二组print(r.groups())#这个获取所有分组信息
结果:
is short,i use woshi june('woshi', 'june')
上面的代码注释已经很清楚了,还有个group()方法是获取整个正则匹配的内容,不按分组。match()方法也一样,就不演示了。
最后一个问题:怎样拆分含有多种分隔符的字符串?
比如:kfs;hsji’fhsikf*bhsfk=jsf/shj。要将不属于字母的都去掉,你是不是会想到用字符串的循环,然后再一个一个分割出来?我告诉你,学了正则之后,再也不用这么麻烦了。re库里面有个split()方法,如下:re.split(pattern, string, maxsplit=0),参数看名字应该就能知道。直接一行代码进行分割:
a = 'kfs;hsjifhsikf*bhsfk=jsf/shj'r = re.split('[;*=/]', a)print(r)
结果:
['kfs', 'hsjifhsikf', 'bhsfk', 'jsf', 'shj']
是不是很完美?所以说正则必须得学!
这个正则复杂点的已经说完了,还有些进阶的,不过暂时没有用到,就先不写了,有需要的可以百度。
正则表达式相关的jupyter的笔记已经上传的到我的GitHub上,有需要的可以下载下来看看,给个star也是可以的。
GitHub:转载地址:http://oeren.baihongyu.com/