暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Python正则表达式

我们不秃头 2021-08-12
436

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=(06), match='123123'>
>>> print(ret.group())
123123
>>> ret = re.search('^\d+''123123Jon321ZJ456456')
>>> print(ret)
<_sre.SRE_Match object; span=(06), 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=(06), 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进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论