python正则表达式
❝Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式。re 模块使 Python 语言拥有全部的正则表达式功能。
❞
常用匹配方法
findall(正则, 待匹配的字符串, flag)
返回所有匹配项的列表。 search(正则, 待匹配的字符串, flag)
返回一个变量,通过group(num) 或 groups() 匹配对象函数来获取匹配表达式(只匹配第一个)。 match
从头开始找第一个,其他和search一样。 示例
match('手机号正则$','Jon123123ZJ456456') 规定这个字符串必须是什么样的。多用于验证输入的合法性 search('^手机号正则$','Jon123123ZJ456456') 用来寻找这个字符串中是不是含有满足条件的子内容 用户输入的内容匹配的时候,要求用户输入11位手机号码
>>> import re
>>> ret = re.match('\d+', 'Jon123123ZJ456456')
>>> print(ret)
None
>>> ret = re.match('\d+', '123123Jon321ZJ456456')
>>> print(ret)
<_sre.SRE_Match object; span=(0, 6), match='123123'>
>>> print(ret.group())
123123
>>> ret = re.search('^\d+', '123123Jon321ZJ456456')
>>> print(ret)
<_sre.SRE_Match object; span=(0, 6), match='123123'>
>>> print(ret.group())
123123
>>>
匹配结果处理函数
split 「通过正则表达式匹配的内容进行分割」
>>> import re
>>> ret = re.split('\d+', 'Jon123123ZJ')
>>> print(ret)
['Jon', 'ZJ']
>>> ret = re.split('(\d+)', 'Jon123123ZJ')
>>> print(ret)
['Jon', '123123', 'ZJ']
>>>
❝字符串中用split以后,分割的字符不会保留,这里会保留,因为这里只知道是一个规则,但是不知道具体的分割字符,保留就可以知道具体的字符。
❞
sub 「替换,通过正则表达式匹配的内容来进行替换」
>>> import re
>>> ret =re.sub('\d+', 'H', 'Jon123123ZJ456456')
>>> print(ret)
JonHZJH
>>> ret =re.sub('\d', 'H', 'Jon123123ZJ456456')
>>> print(ret)
JonHHHHHHZJHHHHHH
>>> ret =re.sub('\d+', 'H', 'Jon123123ZJ456456', 1)
>>> print(ret)
JonHZJ456456
>>> ret =re.sub('\d', 'H', 'Jon123123ZJ456456', 1)
>>> print(ret)
JonH23123ZJ456456
>>>
subn 「替换,在sub的基础上,返回一个元组,元组第一个内容是替换的结果,第二个是替换的次数」
>>> import re
>>> ret =re.subn('\d+', 'H', 'Jon123123ZJ456456')
>>> print(ret)
('JonHZJH', 2)
>>> ret =re.subn('\d', 'H', 'Jon123123ZJ456456')
>>> print(ret)
('JonHHHHHHZJHHHHHH', 12)
>>>
compile(正则) 「节省代码时间的工具 如果没有重复使用同一个正则,不能节省时间」
❝假如同一个正则表达式要被使用多次,可以通过re.compile('正则表达式')先编译解析,节省了多次解析同一个正则表达式的时间
❞
>>> import re
>>> ret = re.compile('\d+')
>>> res1 = ret.search('123123Jon321ZJ456456')
>>> res2 = ret.findall('123123Jon321ZJ456456')
>>> print(res1)
<_sre.SRE_Match object; span=(0, 6), match='123123'>
>>> print(res2)
['123123', '321', '456456']
finditer ** 节省空间 结果集较多的时候才能节省空间**
❝返回一个迭代器,通过迭代取到的是一个变量,通过group取值。
❞
>>> import re
>>> ret = re.finditer('\d+', '123123Jon321ZJ456456')
>>> for i in ret:
... print(i)
... print(i.group())
...
<_sre.SRE_Match object; span=(0, 6), match='123123'>
123123
<_sre.SRE_Match object; span=(9, 12), match='321'>
321
<_sre.SRE_Match object; span=(14, 20), match='456456'>
456456
>>>
>>>
# 先compile,再finditer
>>> ret = re.compile('\d+')
>>> res = ret.finditer('123123Jon321ZJ456456')
>>> for i in res:
... print(i.group())
...
123123
321
456456
>>>
分组命名
格式 : (?P<名字>正则表达式) ret.group('名字')
>>> ret = re.search('\d(\d)\d(\w+?)(\d)(\w)\d(\d)\d(?P<name1>\w+?)(\d)(\w)\d(\d)\d(?P<name2>\w+?)(\d)(\w)\d(\d)\d(?P<name3>\w+?)(\d)(\w)', '123Jon3ZJ456456123Jon3ZJ456456123Jon3ZJ456456123Jon3ZJ456456123Jon3ZJ456456')
>>> print(ret.group('name1'))
6123Jon3ZJ
>>> print(ret.group('name2'))
6123Jon3ZJ
>>> print(ret.group('name3'))
6
>>>
分组命名的引用 格式 :(?P<名字>正则表达式) (?P=tag)
>>> exp = '<abc>asdfawef78976698&<abb>^&*</abb>(^&*^*&YKJBKJQBEER</abc>'
>>> ret1 = re.search('<\w+>.*?</\w+>', exp)
>>> ret2 = re.search('<(?P<tag>\w+)>.*?</(?P=tag)>', exp)
>>> ret3 = re.search(r'<(\w+)>.*?</\1>', exp)
>>> # 采用分组索引,但是需要再整个正则表达式字符串前加上r进行转义,
... # 让‘\1’直接显示为‘\1’以满足要求,默认python在print时 \1 有特殊含义,输出结果是空白
... # (有点模糊,如果转义 \w 也会转义,可以确定python在print时 \w 无特殊含义,可以深入了解一下)
... print(ret1.group())
<abc>asdfawef78976698&<abb>^&*</abb>
>>> print(ret2.group())
<abc>asdfawef78976698&<abb>^&*</abb>(^&*^*&YKJBKJQBEER</abc>
>>> print(ret3.group())
<abc>asdfawef78976698&<abb>^&*</abb>(^&*^*&YKJBKJQBEER</abc>
>>>
>>>
# 有时候我们要匹配的内容时包含在不想要的内容之中的,
# 只能先把不要的内容匹配出来,然后再想办法从结果中去除
示例
输出所有的整数,注意去除小数
>>> ret = re.findall(r"\d+\.\d+|(\d+)", "1-2*(60+(-40.35/5)-(-4*3))")
>>> print(ret)
['1', '2', '60', '', '5', '4', '3']
输出所有的整数,注意去除小数,并通过 filter 过滤非真,顺序也不变
>>> ret = re.findall(r"\d+\.\d+|(\d+)", "1-2*(60+(-40.35/5)-(-4*3))")
>>> ret = filter(lambda n:n, ret)
>>> print(list(ret))
['1', '2', '60', '5', '4', '3']
匹配链家房源信息 lianjia.html
<span class="divide">/</span>2室1厅<span class="divide">/</span>94.14平米<span class="divide">/</span>
par = '<div class="title">.*?<a class=.*?>(?P<name>.*?)</a>.*?<span class="divide">/</span>(?P<room>.*?)<span class="divide">/</span>(?P<area>.*?)<span class="divide">/</span>'
with open('lianjia.html',encoding='utf-8') as f:
context = f.read()
ret = re.finditer(par, context, flags=re.S)
for i in ret:
print(i.group('name'), i.group('room'), i.group('area'))
补充
列表的特殊性 列表不能用insert 列表不能用pop(n)
❝因为列表在存储时是连续的,所以插入或者中途删除后,后续的所有值需要全部移位,代价过大
❞
写代码的三个考虑方向
时间 : 空间 : 你完成一个代码所需要执行的代码行数 你在执行代码的过程中,底层程序是如何工作的 占用的内存资源 影响程序的执行效率 功能 性能 用户体验
文章转载自我们不秃头,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




