re模块

引入方式

import re

方法

  • findall():找所有的,返回所有的结果后放在列表中
ret = re.findall("[a-z]+","yangtuo tiancan shiye ")
print(ret)    # ['yangtuo', 'tiancan', 'shiye']

 

  • finditer()返回一个迭代器 ,更节省内存,一次一次返回
ret = re.finditer("\d","dahka5hdka4546465h")
print(ret)                      # <callable_iterator object at 0x0000000002061EF0>
print(next(ret).group())         # 5
print(next(ret).group())         # 4
print([i.group() for i in ret])  # ['5', '4', '6', '4', '6', '5']

 

  • search()从前往后找到一个就返回一个对象,调用group才可以拿到结果
ret = re.search("a","yangtuo is tiancai")
print(ret.group())        # a 

        找不到就返回None,此时无法调用group,会报错

ret = re.search("[0-9]+","yangtuo is tiancai")
print(ret)            # None
print(ret.group())    # AttributeError: 'NoneType' object has no attribute 'group'

        为了避免上面的这种报错,可以利用if判断,从而打断if循环不报错,非常常用的方式

ret = re.search("j","yangtuo is tiancai")
if ret:
     print(ret.group())  # 无结果但是不会报错了

 

  • match()必须从头开始匹配,比如下面的字符串,y、ya都能匹配上,但是a就不行。
        用法和search一样,返回对象,必须用group输出,空报错,可if避免
ret = re.match("[a-z]+","yangtuo is tiancai")
print(ret.group())    # yangtuo
ret = re.match("a","yangtuo is tiancai")
print(ret.group())    # AttributeError: 'NoneType' object has no attribute 'group'

 

  • split():按照正则关系分割,不是很常用
ret = re.split("[ab]","abcd")
# 先按a分割得到 " " 和"bcd",再按b分割得到 " "," ","cd"
print(ret) # ['', '', 'cd']

 

  • sub():按照正则关系对字符串替换
# 将数字替换成H  替换两次
ret = re.sub("\d","H","shah4546shdah123",2) print(ret) # shahHH46shdah123

 

  • subn():按照正则关系对字符串替换,并用元组的方式返回结果以及替换次数
ret = re.subn("\d","H","shah4546shdah123",2)
print(ret)    # ('shahHH46shdah123', 2)

 

  • compile():同一个正则规则需要被多次用到时可以使用此命令重复调用

         将正则表达式编译成一个对象,调用对象使用更简单

obj = re.compile("\d{3}")
ret = obj.search("hsdhabsh153lhslk86")
ret1 = obj.search("hsdh46897=lhslk86")
print(ret.group())    # 153
print(ret1.group())    # 468

 

特殊场景分析

  • findall的优先级查询
import re    
ret = re.findall('www.(baidu|oldboy).com', 'www.oldboy.com')
print(ret)     # ['oldboy']
# 这是因为findall会优先把匹配结果组里内容返回,如果想要匹配真实想要的结果,取消权限即可 
ret = re.findall('www.(?:baidu|oldboy).com', 'www.oldboy.com')
print(ret)    # ['www.oldboy.com']

 

  • split的优先级查询

    在匹配部分加上 () 之后所切出的结果是不同的,

    没有 () 的没有保留所匹配的项,但是有 () 的却能够保留匹配的项。

    这个在某些需要保留匹配部分的使用过程是非常重要的。

ret=re.split("\d+","eva3egon4yuan")
print(ret)    # ['eva', 'egon', 'yuan']
ret=re.split("(\d+)","eva3egon4yuan")
print(ret)    # ['eva', '3', 'egon', '4', 'yuan']

 

  • 分组的命名和引用

    组名的方式命名  (?P<组名>)

    组名的引用  (?P=组名)

ret = re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>")
print(ret.group("tag_name"))      # h1
print(ret.group())                 # <h1>hello</h1>

    也可以直接分组,然后用\1引用第一个组,组的索引是从1开始不是从0开始

ret = re.search(r"<(\w+)>\w+</\1>","<h1>hello</h1>")
print(ret.group(1))               # h1
print(ret.group())                # <h1>hello</h1>

 

  • 匹配小数整数(注意将 . 进行转义 \.
#40.35被当做40和35两个来取了
ret=re.findall(r"\d+","1-2*(60+(-40.35/5)-(-4*3))") 
print(ret)   #['1', '2', '60', '40', '35', '5', '4', '3']

 

  • 利用|的工作原理从左到右最长匹配,将长的匹配项先写

    注意将 . 进行转义 \.

    可以分组将分组的内容优先显示,但是无匹配的选项会用空表示出来

    可以使用remove进行空选项的移除,顺便这次稍微升级一下把负号一起取到了


ret=re.findall(r"-?\d+\.\d*|(-?\d+)","1-2*(60+(-40.35/5)-(-4*3))")
print(ret)   #['1', '-2', '60', '', '5', '-4', '3']
ret.remove("")
print(ret)   #['1', '-2', '60', '5', '-4', '3']

 

  • 获取手机号匹配方式对比
    # 普通的实现方式
    while True:
         phone_number = input('please input your phone number : ')
         if len(phone_number) == 11 \
                and phone_number.isdigit()\
                and (phone_number.startswith('13') \
                or phone_number.startswith('14') \
                or phone_number.startswith('15') \
                or phone_number.startswith('18')):
             print('是合法的手机号码')
         else:
             print('不是合法的手机号码')
    # re实现
    import re
    phone_number = input('please input your phone number : ')
    if re.match('^(13|14|15|18)[0-9]{9}$',phone_number):
             print('是合法的手机号码')
    else:
             print('不是合法的手机号码') 

     

posted @ 2019-03-29 19:04  雪儿来  阅读(147)  评论(0编辑  收藏  举报