• Python的re模块


    什么是re模块,re模块有什么作用?

    re模块是Python提供的一个正则表达式相关的模块,主要是针对字符串进行模糊匹配,所以在字符串匹配这一功能上,re相当专业。

    什么是模糊匹配?

    之前的学习字符串内容的时候,也有进行匹配的一些方法,比如find()方法:

    S = 'adnsanpnqbciqwocb'
    ret = S.find('san')
    print(ret)
    >>> 3

    这样就可以获得"san"在S中的位置,这种方法称为精确匹配。但很多情况下我们提供的搜索条件并没有那么精确,比如“四条腿”,在大脑中检索出来的答案就有四条腿的桌子、四条腿的兔子等等,这种粗略的搜索就可以理解为模糊匹配

    在re中,匹配的参数可以是普通字符,也可以是元字符,这里用re中最常用的findall()函数举例,findall()函数就是找出目标字符串中所有的复合模板要求的字符串。

    import re
    
    ret = re.findall('pengfy','dainbqbfepengfyxMONDW434')
    print(ret)
    >>> ['pengfy']

    元字符主要有:. ^ $ * + ? {} [] () |

    我们在findall()函数中中演示这几个元字符的用法,先看元字符 . ^ $ * + ? {}

    .叫通配符能能够代表任意字符( 除外),需要代表几个就写几个.,举例如下:

    import re
    
    ret = re.findall('p..g','d123pengfyPENGFYpANgyq')
    print(ret)  #找出所有p开头g结尾的字符串,区分大小写
    >>>['peng', 'pANg']
    
    ret = re.findall('p..g','d123pe
    gfy')
    print(ret)  #不能代表
    
    >>>[]

    ^我们老师管它叫尖角符,只能从字符串的开头进行匹配,$刚好相反,只能从字符串的结尾进行匹配,举例如下:

    (注意^和$放的位置,也是一头一尾)

    import re
    
    ret = re.findall('^p..g','pengfyPENGFYpANgyq')
    print(ret)  #只能从头开始匹配
    >>> ['peng']
    
    ret = re.findall('p..g$','pengfyPENGFYpANgyqpang')
    print(ret)  #只能从尾部开始匹配
    >>>['pang']
    
    ret = re.findall('^p..g$','pengfyPengFYpANg')
    print(ret)  #一起使用不会报错,但也不会有结果,这不是一种有效的用法
    >>>[]

    如果有多个重复的字母,我们用.表示显然很麻烦,这种情况我们可以用* + {}

    *表示可以重复0或多次

    +表示可以重复1或多次

    {}可以指定重复的次数

    一定程度上,{}可以表示成* +

    分别举例如下:

    import re
    
    ret = re.findall('peng*','6ghpenggggggfwf')
    print(ret)
    >>>['pengggggg']
    
    ret = re.findall('peng*','6ghpenfwf')
    print(ret)
    >>>['pen']
    
    ret = re.findall('peng+','6ghpenggggggfwf')
    print(ret)
    >>>['pengggggg']
    
    ret = re.findall('peng+','6ghpenfwf')
    print(ret)   #和*的区别
    >>>[]
    
    ret = re.findall('peng{0,8}','6ghpenggggggfwf')
    print(ret)  
    >>>['pengggggg']
    
    ret = re.findall('peng{0}','6ghpenggggggfwf')
    print(ret)
    >>>['pen']
    
    ret = re.findall('peng{0,}','6ghpenggggggfwf')
    print(ret)   #不加逗号就只匹配0个g,加上就默认0到无穷,和*一样
    >>>['pengggggg']
    
    ret = re.findall('peng{8}','6ghpenggggggfwf')
    print(ret)
    >>>[]  #指定个数没达到,就没有匹配值
    
    ret = re.findall('peng{}','6ghpenggggggfwf')
    print(ret) #不指定区间,也没有匹配值
    >>> []

    通过以上实例,大家可以看到,只要匹配到的,我们都是返回重复最多的结果,这种匹配叫贪婪匹配,如何取消,那就是使用问号 ?,举例如下:

    import re
    ret = re.findall('peng*?','6ghpenggggggfwf')
    print(ret)   #最小重复0次
    >>>['pen']
    
    ret = re.findall('peng+?','6ghpenggggggfwf')
    print(ret)    #最小重复1次
    >>>['peng']
    
    ret = re.findall('peng{2,8}?','6ghpenggggggfwf')
    print(ret)    #最小重复指定次数,这里是2
    >>>['pengg']

    可以看到,加上?后,匹配的都变成了最小重复次数,这种匹配叫惰性匹配

    接下来看[],还是举例说明:

    import re
    
    ret = re.findall('www.[taobao,baidu].com','wwwww.baidu.commmm')
    print(ret)
    >>>[]
    
    ret = re.findall('www.[taobao,baidu].com','wwwww.b.commmm')
    print(ret)
    >>>['www.b.com']
    
    ret = re.findall('www.[taobao,baidu].com','wwwww.,.commmm')
    print(ret)
    >>>['www.,.com']

    通过上面的例子可以看到,[]里面,每个元素都独立存在,包括逗号,里面的关系可以理解成或的关系,但是在[]中的元素基本都没有自身的意义,

    但有三个符号是有意义的,分别是 - ^

    import re
    
    ret = re.findall('[a-z]','AJo;AHIcnwi1890jlk')
    print(ret)  #按ASSIC码表区范围
    >>>['o', 'c', 'n', 'w', 'i', 'j', 'l', 'k']
    
    ret = re.findall('[^a-z]','AJo;AHIcnwi1890jlk')
    print(ret)
    >>>['A', 'J', ';', 'A', 'H', 'I', '1', '8', '9', '0']
    
    ret = re.findall('[a-z]','AJo;AHIcnwz1890jlk')
    print(ret)   #取消了-的特殊功能,[]中就剩下a或-或z三个元素
    >>>['z']
    
    ret = re.findall('[^a-z]','AJo;AHIcnwi1890jlk')
    print(ret)   #取消了^的特殊功能,[]中就剩下^和a-z之间的字母
    >>>['o', 'c', 'n', 'w', 'i', 'j', 'l', 'k']
    
    ret = re.findall('[c.w]','AJo;AHIcnwi1890j.lk')
    print(ret)   #取消了.的特殊功能,[]中就剩下c或.或w三个元素
    >>>['c', 'w', '.']

    前面两个比较好理解,-就是一个范围,^就是非的意思,只要不是[]中的元素就可以匹配,的功能就是取消元字符的特殊功能,但还有一个功能,下面开始讲解

    1.反斜杠后边跟元字符去除特殊功能,比如.
    2.反斜杠后边跟普通字符实现特殊功能,比如d

    第一个上面已经演示过了,下面看第二个功能:

    d  匹配任何十进制数;它相当于类 [0-9]。
    D 匹配任何非数字字符;它相当于类 [^0-9]。
    s  匹配任何空白字符;它相当于类 [ fv]。
    S 匹配任何非空白字符;它相当于类 [^ fv]。
    w 匹配任何字母数字字符;它相当于类 [a-zA-Z0-9_]。
    W 匹配任何非字母数字字符;它相当于类 [^a-zA-Z0-9_]
      匹配一个特殊字符边界,比如空格 ,&,#等

    还是通过实例展示一下:

    import re
    
    ret = re.findall('d','AJo;AHIcnwi1890j.lk')
    print(ret)
    <<<['1', '8', '9', '0']
    
    ret = re.findall('D','AJo;.lk')
    print(ret)
    >>>['A', 'J', 'o', ';', '.', 'l', 'k']
    
    ret = re.findall('s','I am Pengfy')
    print(ret)
    >>>[' ', ' ']
    
    ret = re.findall('S','I am Pengfy')
    print(ret)
    >>>['I', 'a', 'm', 'P', 'e', 'n', 'g', 'f', 'y']
    
    ret = re.findall('w','I am,18YEARSOLD.')
    print(ret)
    >>>['I', 'a', 'm', '1', '8', 'Y', 'E', 'A', 'R', 'S', 'O', 'L', 'D']
    
    ret = re.findall('W','I am,18YEARSOLD.')
    print(ret)
    >>>' ', ',', '.']
    
    ret = re.findall('I','Y&I are boy')
    print(ret)
    >>>[]

    前面几个应该都能理解,看到最后一个,什么鬼,怎么没有返回数据啊?不要慌,这里要从Python运行机制去解释,先看下面几个例子:

    import re
    
    ret=re.findall('yz','penfgyze')
    print(ret)  #程序报错:bad escape z at position 1
    
    ret=re.findall('y\z','penfgyze')
    print(ret)  #程序报错:bad escape z at position 1
    
    ret=re.findall('y\\z','penfgyze')
    print(ret)
    >>>['y\z']
    
    ret=re.findall(r'y\z','penfgyze')
    print(ret)
    >>>['y\z']

    我们可以看到,需要传四个反斜杠才能输出正常结果,为什么呢?因为是给re模块识别的,但是在Python解释器中,又有别的意思,所以需要加一个r,至于为什么我们看到的结果为什么是两个反斜杠,这也是解释器的原因导致,其实在re中是一个。

    ret = re.findall(r'I','I am Iboy &I is')
    print(ret)
    >>>['I', 'I']

    加上r以后,就能正常匹配了,r是干什么的呢?r的作用就是告诉解释器,里面的东西不要编译,原封不动的给到re

    还剩下()和管道符 |,()是用于分组,比如:

    import re
    
    ret=re.findall(r'(ab)+','abbbbbbcd')
    print(ret)
    >>>['ab']  # 为什么只匹配到了一个?因为()的优先级比+高,使用?就可以取消他的优先级,这样写(?:ab)+
    
    import re
    ret=re.findall(r'(bcd)','abbbbbbcdbcdbcd')
    print(ret)
    >>>['bcd', 'bcd', 'bcd']
    
    ret=re.findall('(?P<id>d{2})/(?P<name>w{3})','23/com23com255/yyyy')
    print(ret)
    >>>[('23', 'com'), ('55', 'yyy')]
    
    ret=re.search('(?P<id>d{2})/(?P<name>w{3})','23/com23com255/yyyy')
    print(ret)  #返回的只是一个地址
    print(ret.group())
    print(ret.group('name')) #可以单独取一个
    >>>  <re.Match object; span=(0, 6), match='23/com'>
    >>>  23/com
    >>>  com

     上面(?P<id>)这种用法直接记住就好了,原理很难讲清楚。接下来看管道符的用法:

    import re
    
    ret=re.findall('www.baidu|google.com','www.baidu.com,www.google.com')
    print(ret)  #管道两边是或的关系
    >>> ['www.baidu', 'google.com']

    到这里,元字符的用法就讲完了,下面讲一下re模块中的其他函数用法,re模块主要有findall() search() match() split() sub() compile() finditer()几个函数:

    search()函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。

    import re
    ret = re.search('p..g','666pengfy888pangyq').group()
    print(ret)
    >>> peng

    match()函数和search()函数用法相同,但只能匹配字符串的开头

    ret = re.match('p..g','666pengfy888pangyq')
    print(ret)  #这里返回一个None,加上group()就报错了
    >>> None
    
    ret = re.match('p..g','pengfy888pangyq').group()
    print(ret)
    >>> peng

    split()看起来并不陌生,在字符串的处理中也有一样的方法,这个就可以选择按什么方法进行切割:

    ret = re.split('[bc]','abcde')
    print(ret)  #这里是先按b分割成a、cde,cde再按c分割成''、de
    >>> ['a', '', 'de']

     sub(),作用是替换,字符串中类似方法叫replace,直接看实例:

    import re
    
    set = re.sub('d','peng','haoren66haode546fwerwef',2)
    print(set)  #后面2这个参数,是替换的个数,本例中表示就替换前2个
    print(type(set))  #输出的会是一个字符串
    
    >>> haorenpengpenghaode546fwerwef
    >>> <class 'str'>

    compile()的目的就是将匹配的方法赋值,这样使用多次的时候回相对简单一些:

    func = re.compile('p..g*')
    ret = func.findall('penggggfy888panggyq')
    ret1 = func.search('penggggfy888panggyq').group()
    print(ret,ret1)
    >>>['pengggg', 'pangg'] pengggg

    finditer(),一看这个名字diter,其实就是iterator迭代器,用法和findall()差不多,然后使用next方法一个个取出来就好了:

    ret = re.finditer('p..g+','666penggggfy888panggyq')
    print(ret)
    print(next(ret).group())
    print(next(ret).group())

    >>><callable_iterator object at 0x000001F6CA11E908> >>>pengggg
    >>>pengg

    以上就是对re模块的总结。

  • 相关阅读:
    命令安装mongod作为服务启动
    npm命令
    win服务
    win进程操作
    【数据结构与算法之美】7.排序算法之冒泡、选择、插入
    【leetcode】23.合并K个排序链表
    【leetcode】141.环形链表
    【数据结构与算法之美】6.环形队列
    【数据结构与算法之美】5.基于链表实现队列
    【数据结构与算法之美】4.基于数组实现队列
  • 原文地址:https://www.cnblogs.com/pengfy/p/10544094.html
Copyright © 2020-2023  润新知