zoukankan      html  css  js  c++  java
  • Python正则表达式 re模块

    Python正则表达式re模块

    参考:https://www.cnblogs.com/cute/p/9186208.html

    老男孩苑昊老师: http://www.cnblogs.com/yuanchenqi/articles/5732581.html

    廖雪峰老师: https://www.liaoxuefeng.com/wiki/1016959663602400/1017639890281664

    https://www.cnblogs.com/hanmk/p/9143514.html

    爬虫部分的re模块使用:https://www.cnblogs.com/XJT2018/p/10312830.html

    re模块(* * * * *)

    就其本质而言,正则表达式(或 RE)是一种小型的、高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。

    正则 就是对字符串进行模糊匹配

    字符匹配(普通字符,元字符):

    1、普通字符:大多数字符和字母都会和自身匹配
                  >>> re.findall('alvin','yuanaleSxalexwupeiqi')
                          ['alvin'] 

    2、元字符: .  ^  $  *  +  ?  { }  [ ]  |  ( )       的详细解释:

    ^

    匹配行首,以 xxx为开头

    $

    匹配行尾,以xxx结尾。

    转义字符,如果要匹配本身,需要使用再次转义:\

    一些特殊字符:

    d:匹配:[0-9]
    
    D:匹配:[^0-9]
    
    s:匹配:任何空白符,即:[	
    
    fv]
    
    S:匹配:任何非空白符,即:[^	
    
    fv]
    
    w:匹配:[a-zA-Z0-9_ ]
    
    W:匹配:[^a-zA-Z0-9_ ]

    *

    匹配前一个字符或子表达式出现 0次或多次。

    +

    匹配前一个字符或子表达式出现 1次或多次。

    ?

    (1) 匹配前一个字符或子表达式出现 0次或1次。

    (2) 跟在 * 或 + 后面表示非贪婪匹配

    *? 匹配0个
    +? 匹配1个
    import re
    # 贪婪模式,会尽量多地去匹配
    r1 = re.compile(r'ab+')
    s1 = 'abbb'
    print(re.findall(r1,s1))    #['abbb']
    
    # 非贪婪模式,会尽量少地去匹配
    r2 = re.compile(r'ab+?')
    s2 = 'abbb'
    print(re.findall(r2,s2))    #['ab']

    {}

    匹配前一个字符或子表达式出现指定次数:

    • {0,}:0次或多次,相当于 *

    • {1,}:1次或多次,相当于 +

    • {0,1}:0次或1次,相当于 ?

    • {m,n}:m次到n次(m <= n)

    import re
     
    ret=re.findall('a..in','helloalvin')
    print(ret)#['alvin']
     
    ret=re.findall('^a...n','alvinhelloawwwn')
    print(ret)#['alvin']
     
    ret=re.findall('a...n$','alvinhelloawwwn')
    print(ret)#['awwwn']
     
    ret=re.findall('a...n$','alvinhelloawwwn')
    print(ret)#['awwwn']
     
    ret=re.findall('abc*','abcccc')#贪婪匹配[0,+oo]  
    print(ret)#['abcccc']
     
    ret=re.findall('abc+','abccc')#[1,+oo]
    print(ret)#['abccc']
     
    ret=re.findall('abc?','abccc')#[0,1]
    print(ret)#['abc']
     
    ret=re.findall('abc{1,4}','abccc')
    print(ret)#['abccc'] 贪婪匹配

    注意:前面的 *,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配(非贪婪匹配)

    ret=re.findall('abc*?','abcccccc')
    print(ret)#['ab']

    跟着教程敲代码练习:

    """ 第一类元字符 . ^ $ * + ? {}"""
    import re
    
    """ . 匹配除了 
     之外的任意字符,一个 . 只能匹配一个字符 """
    re.findall("alex","djkalfjioealexieou")        ##['alex']
    
    re.findall("a..x",'jowutojoauixuoero')      #['auix']
    
    re.findall("a...x",'jowutojoauixuoero')      #[]
    
    """ ^ 开头匹配 """
    re.findall("^a...x",'jowutojoauixuoero')      #[]
    
    re.findall("^j..u",'jowutojowuixuoero')      #['jowu']
    
    re.findall("j..u",'jowutojowuixuoero')  #['jowu', 'jowu']
    
    """ $ 结尾匹配 """
    re.findall("j..u$",'jowutojowuixuoejrou')       #['jrou']
    
    re.findall("j..u$",'jowutojowuixuoejrou$')       #[]
    
    """ * 紧挨着的字符 匹配0~无穷次 """
    """ + 紧挨着的字符 匹配1~无穷次 """
    re.findall("alex*","uoghkalexxx")   #['alexxx']
    re.findall("alex+","uoghkalexxx")   #['alexxx']
    re.findall("alex*","uoghkale")  #['ale']
    re.findall("alex+","uoghkale")  #[]
    
    """ ? 紧挨着的字符 匹配0~1 """
    re.findall("alex?","uoghkale")      #['ale']
    
    re.findall("alex?","uoghkalex")     #['alex']
    
    re.findall("alex?","uoghkalexxxx")      #['alex']
    
    """ {} 是上面 * + ? 的集合,并且可自定义
    {0,}  <===> *
    {1,}  <===> +
    {0,1}  <===> ?
    {1,6}      1 2 3 4 5 6 都可以
    """
    re.findall("alex{6}","uoghkalexxxxxx")      #['alexxxxxx']
    
    re.findall("alex{0,6}","uoghkalexxx")       #['alexxx']
    
    re.findall("alex{0,6}","uoghkale")      #['ale']
    
    re.findall("alex{0,1}","uoghkale")      #['ale']
    
    re.findall("alex{0,1}","uoghkalex")     #['alex']
    
    # 惰性匹配 在元字符后面加上 ?
    re.findall("alex*?","uoghkalexxxx")     #['ale']
    
    re.findall("alex+?","uoghkalexxxx")     #['alex']
    
    re.findall("alex+","uoghkalexxxx")      #['alexxxx']
    我的理解

    元字符之字符集[]:

    (1) 常用来指定一个字符集,如[abc]匹配:a或b或c

    (2) 元字符. * ? + ^ $ 在[]中不起所用,比如:[a+]匹配:a或+

    但注意:在方括号中:要匹配转义符“”本身,要用:\;要匹配方括号开头的^符本身,要用:^;要匹配-字符,需要用:-

    (3) 补集匹配:[^a],匹配非a的一个字符,^在[ ]中表示取非

    (4) 匹配连续字符:[a-zA-Z0-9],匹配大小写英文字母和数字

    #--------------------------------------------字符集[]
    ret=re.findall('a[bc]d','acd')
    print(ret)#['acd']
     
    ret=re.findall('[a-z]','acd')
    print(ret)#['a', 'c', 'd']
     
    ret=re.findall('[.*+]','a.cd+')
    print(ret)#['.', '+']
     
    #在字符集里有功能的符号: - ^ 
     
    ret=re.findall('[1-9]','45dha3')
    print(ret)#['4', '5', '3']
     
    ret=re.findall('[^ab]','45bdha3')
    print(ret)#['4', '5', 'd', 'h', '3']
     
    ret=re.findall('[d]','45bdha3')
    print(ret)#['4', '5', '3']

    跟着教程敲代码练习:

    """ [] 中:^ 非 ,- 表示从。。到。。  a-z 所有小写字母, 转义  (  就表示左括号。
    其他的元字符失去意义,如 * 不表示(0-无穷),()就只是表示括号
    """
    ret = re.findall('a[bc]d', 'acd')       # 匹配 abd 或 acd
    print(ret)  # ['acd']
    
    ret = re.findall('[a-z]', 'acd')   #一个字符 从a到z
    print(ret)  # ['a', 'c', 'd']
    
    ret = re.findall('[.*+]', 'a.cd+')  #* 失去特殊意义 就表示一个 *
    print(ret)  # ['.', '+']
    
    # 在字符集里有功能的符号: - ^ 
    
    ret = re.findall('[1-9]', '45dha3')
    print(ret)  # ['4', '5', '3']
    
    ret = re.findall('[^ab]', '45bdha3')
    print(ret)  # ['4', '5', 'd', 'h', '3']
    
    ret = re.findall('[d]', '45bdha3')
    print(ret)  # ['4', '5', '3']
    我的理解
    # 一个特殊案例:匹配表达式里面 最内层括号(13-6)
    
    re.findall("([^()]*)","12+(34*6+2-5*(13-6))")    #['(13-6)']

    元字符之转义符

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

    • d  匹配任何十进制数;它相当于类 [0-9]。
    • D 匹配任何非数字字符;它相当于类 [^0-9]。
    • s  匹配任何空白字符;它相当于类 [ fv]。
    • S 匹配任何非空白字符;它相当于类 [^ fv]。
    • w 匹配任何字母数字字符;它相当于类 [a-zA-Z0-9_]。
    • W 匹配任何非字母数字字符;它相当于类 [^a-zA-Z0-9_]
    •   匹配一个特殊字符边界,比如空格 ,&,#等
    ret=re.findall('I','I am LIST')
    print(ret)#[]
    ret=re.findall(r'I','I am LIST')
    print(ret)#['I']
    
    r'I'   其中 r=raw 表示原始的 未经处理的
    re.findall(r'I','I am LIST')   #r'I'  要先经过Python解释器编译 然后传递给re模块,re模块处理  匹配到 空格

    现在我们聊一聊 ,先看下面两个匹配:

    #-----------------------------eg1:
    import re
    ret=re.findall('cl','abcle')
    print(ret)#[]
    ret=re.findall('c\l','abcle')
    print(ret)#[]
    ret=re.findall('c\\l','abcle')
    print(ret)#['c\l']
    ret=re.findall(r'c\l','abcle')
    print(ret)#['c\l']
     
    #-----------------------------eg2:
    #之所以选择是因为在ASCII表中是有意义的
    m = re.findall('blow', 'blow')
    print(m)
    m = re.findall(r'blow', 'blow')
    print(m)

                      

    由于Python的字符串本身也用 转义,所以要特别注意:

    s = 'ABC\-001' # Python的字符串
    # 对应的正则表达式字符串变成:
    # 'ABC-001'

    因此我们强烈建议使用Python的 r前缀,就不用考虑转义的问题了:

    s = r'ABC-001' # Python的字符串
    # 对应的正则表达式字符串不变:
    # 'ABC-001'

    元字符之分组 ()

    (?P<分组名>d+)      有名分组 可以通过ret.group('分组名') 取得匹配结果

    m = re.findall(r'(ad)+', 'add')
    print(m)        #ad
     
    ret=re.search('(?P<id>d{2})/(?P<name>w{3})','23/com')
    print(ret.group())        #23/com
    print(ret.group('id'))    #23
    
    ##'(?P<id>d{2})/(?P<name>w{3})'  ?P<id> 分组 组名为ip, d{2} 匹配后面两位整数
    #(?P<name>w{3})  ?P<id> 分组 组名为name,w{3}  匹配3位 大小写字母 数字 下划线
    >>> re.search(r'<a.*>(.*)</a>.*<p>(.*)</p>',s).group(1)
    '更多'
    >>> re.search(r'<a.*>(.*)</a>.*<p>(.*)</p>',s).group(2)
    'dfsl'
    >>> ss = re.search(r'<a.*>(?P<txt>.*)</a>.*<p>(?P<txt2>.*)</p>',s)
    >>> ss.group('txt')
    '更多'
    >>> ss.group('txt2')

    练习:

    >>> re.findall(r'(abc)+','adklnvkaj45d6kasdfeabcwoibcfabcabcabcdf')
    ['abc', 'abc']
    >>> re.findall(r'abc+','adklnvkaj45d6kasdfeabcwoibcfabcabcabcdf')
    ['abc', 'abc', 'abc', 'abc']
    >>> re.findall(r'(abc)+','abcabcabcabc')
    ['abc']
    >>> re.findall(r'(abc)*','abcabcabcabc')
    ['abc', '']
    >>> re.findall(r'(ab)+','abcabcabcabc')
    ['ab', 'ab', 'ab', 'ab']
    >>> re.findall(r'(abc)+','abcabcabcabc')
    ['abc']
    >>> re.findall(r'(abc)+','abcccccc')
    ['abc']
    >>> re.findall(r'(?P<name>[a-z]+)d+','xiong26wang33zhang23sun56')
    ['xiong', 'wang', 'zhang', 'sun']
    >>> re.search(r'(?P<name>[a-z]+)d+','xiong26wang33zhang23sun56')
    <_sre.SRE_Match object; span=(0, 7), match='xiong26'>
    >>> re.search(r'(?P<name>[a-z]+)d+','xiong26wang33zhang23sun56').group()
    'xiong26'
    >>> re.search(r'(?P<name>[a-z]+)d+','xiong26wang33zhang23sun56').group("name")
    'xiong'
    >>> re.search(r'(?P<name>[a-z]+)(?P<age>d+)','xiong26wang33zhang23sun56').group("name")
    'xiong'
    >>> re.search(r'(?P<name>[a-z]+)(?P<age>d+)','xiong26wang33zhang23sun56').group("age")
    '26'
    cmd执行

    元字符之|

    ret=re.search('(ab)|d','rabhdg8sd')
    print(ret.group())#ab

    re模块下的常用方法

    # 1
    re.findall('a', 'alvin yuan')  # 返回所有满足匹配条件的结果,放在列表里
    # 2
    re.search('a', 'alvin yuan').group()  # 函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以
    # 通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。
    
    # 3
    re.match('a', 'abc').group()  # 同search,不过要在字符串开始处进行匹配,相当于re.search('^','')
    
    # 4
    ret = re.split('[ab]', 'abcd')  # 先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割
    print(ret)  # ['', '', 'cd']
    
    # 5
    ret = re.sub('d', 'A', 'alvin5yuan6', 1)     ## 替换 数字 替换为 A , 只替换第一个
    print(ret)  # alvinAyuan6
    ret = re.subn('d', 'A', 'alvin5yuan6')     #将替换结果 和 替换个数 返回为一个元组
    print(ret)  # ('alvinAyuanA', 2)
    
    # 6
    obj = re.compile('d{3}')           ## 编译,如果使用多次匹配规则 效率就体现出来了
    ret = obj.search('abc123eeee')
    print(ret.group())  # 123

    处理大量数据,匹配结果返回一个迭代器

    import re
    ret=re.finditer('d','ds3sy4784a')
    print(ret)        #<callable_iterator object at 0x10195f940>
     
    print(next(ret).group())
    print(next(ret).group())

    注意:

    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']

    补充练习题:

    >>> import re
    >>> re.findall('d+','nka15640-8dasgwe-96dagv-6')
    ['15640', '8', '96', '6']
    >>> re.findall('^d+','nka15640-8dasgwe-96dagv-6')
    []
    >>> re.findall('[^-]d+','nka15640-8dasgwe-96dagv-6')
    ['a15640', '96']
    >>> re.findall('d{3}s+d{3,8}','sdfag123  7845agewgv')
    ['123  7845']
    >>> re.findall('d+@$','1351655382@qq.com')
    []
    >>> re.findall('d+','1351655382@qq.com')
    ['1351655382']
    >>> re.findall(r'ka|b','adklnvkj45d6kaewoib')
    ['ka', 'b']
    >>> re.findall(r'ka|b','adklnvkj45d6ksdfewoibfadf')
    ['b']
    >>> re.findall(r'ka|bc','adklnvkaj45d6kasdfewoibcfadf')
    ['ka', 'ka', 'bc']
    >>> re.findall(r'(abc)+','adklnvkaj45d6kasdfeabcwoibcfabcabcabcdf')
    ['abc', 'abc']
    >>> re.findall(r'abc+','adklnvkaj45d6kasdfeabcwoibcfabcabcabcdf')
    ['abc', 'abc', 'abc', 'abc']
    >>> re.findall(r'(abc)+','abcabcabcabc')
    ['abc']
    >>> re.findall(r'(abc)*','abcabcabcabc')
    ['abc', '']
    >>> re.findall(r'(ab)+','abcabcabcabc')
    ['ab', 'ab', 'ab', 'ab']
    >>> re.findall(r'(abc)+','abcabcabcabc')
    ['abc']
    >>> re.findall(r'(abc)+','abcccccc')
    ['abc']
    >>> re.findall(r'(?P<name>[a-z]+)d+','xiong26wang33zhang23sun56')
    ['xiong', 'wang', 'zhang', 'sun']
    >>> re.search(r'(?P<name>[a-z]+)d+','xiong26wang33zhang23sun56')
    <_sre.SRE_Match object; span=(0, 7), match='xiong26'>
    >>> re.search(r'(?P<name>[a-z]+)d+','xiong26wang33zhang23sun56').group()
    'xiong26'
    >>> re.search(r'(?P<name>[a-z]+)d+','xiong26wang33zhang23sun56').group("name")
    'xiong'
    >>> re.search(r'(?P<name>[a-z]+)(?P<age>d+)','xiong26wang33zhang23sun56').group("name")
    'xiong'
    >>> re.search(r'(?P<name>[a-z]+)(?P<age>d+)','xiong26wang33zhang23sun56').group("age")
    '26'
    >>> re.findall('(ab)|d','rabhdg8sd')
    ['ab', '']
    >>> re.findall('(ab)|d+','rabhdg8sd')
    ['ab', '']
    >>> re.findall('(ab)|d+','rab632hdg8sd')
    ['ab', '', '']
    >>> re.findall('(ab)|d','rab632hdg8sd')
    ['ab', '', '', '', '']
    >>> re.findall('(ab)|d+','rab632hdg8sd')
    ['ab', '', '']
    >>> re.findall('(ab).*d+','rab632hdg8sd')
    ['ab']
    >>> re.match('a', 'abc').group()
    'a'
    >>> re.match('a', 'abcadfa').group()
    'a'
    >>>
    ####################split分割
    >>> re.split(' ','hello world xiong')
    ['hello', 'world', 'xiong']
    >>> re.split('[ |]','hello world|xiong')
    ['hello', 'world', 'xiong']
    >>> re.split('[ab]','vnklaouojbouhg')
    ['vnkl', 'ouoj', 'ouhg']
    >>> re.split('[ab]','auouabuobuo')
    ['', 'uou', '', 'uo', 'uo']
    >>> re.split('[ab]','asdabcd')
    ['', 'sd', '', 'cd']
    >>> re.split('[ab]','abc')
    ['', '', 'c']
    >>>
    >>>############# '替换'
    
    >>> re.sub('d+','A','as451da23bc23d5dae')
    'asAdaAbcAdAdae'
    >>> re.sub('d','A','as451da23bc23d5dae')
    'asAAAdaAAbcAAdAdae'
    >>> re.sub('d','A','as451da23bc23d5dae',3)
    'asAAAda23bc23d5dae'
    >>> re.sub('d','A','as451da23bc23d5dae',2)
    'asAA1da23bc23d5dae'
    >>> re.subn('d','A','as451da23bc23d5dae')
    ('asAAAdaAAbcAAdAdae', 8)
    >>>
    ###########compile编译
    >>> com = re.compile("d+")
    >>> com.findall("uoihja37jdaogj230ldaoje")
    ['37', '230']
    >>>
    >>> re.findall("d","af7nka89wejojk03oajag")
    ['7', '8', '9', '0', '3']
    >>> re.finditer("d","af7nka89wejojk03oajag")
    <callable_iterator object at 0x000001E1D2836BE0>
    >>> ret = re.finditer("d","af7nka89wejojk03oajag")
    >>> ret.__next__()
    <_sre.SRE_Match object; span=(2, 3), match='7'>
    >>> ret.__next__().group()
    '8'
    
    >>>#############结果返回为一个迭代器
    >>> ret = re.finditer("www.(baidu|163).com","af7nkawww.baidu.com89wejojk03oajag")
    >>> re.finditer("www.(baidu|163).com","af7nkawww.baidu.com89wejojk03oajag")
    <callable_iterator object at 0x000001E1D2836B00>
    
    ###################匹配结果优先返回为匹配到的分组内容
    >>> re.findall("www.(baidu|163).com","af7nkawww.baidu.com89wejojk03oajag")
    ['baidu']
    >>> re.findall("www.(?:baidu|163).com","af7nkawww.baidu.com89wejojk03oajag")
    ['www.baidu.com']
    练习

    补充1:

    import re
    
    print(re.findall("<(?P<tag_name>w+)>w+</(?P=tag_name)>","<h1>hello</h1>"))
    print(re.search("<(?P<tag_name>w+)>w+</(?P=tag_name)>","<h1>hello</h1>"))
    print(re.search(r"<(w+)>w+</1>","<h1>hello</h1>"))
    View Code

    补充2:

    #匹配出所有的整数
    import re
    
    #ret=re.findall(r"d+{0}]","1-2*(60+(-40.35/5)-(-4*3))")
    ret=re.findall(r"-?d+.d*|(-?d+)","1-2*(60+(-40.35/5)-(-4*3))")
    ret.remove("")
    
    print(ret)
    View Code

     

  • 相关阅读:
    java
    JAVA的String 类
    JAVA的StringBuffer类
    TestLink 的使用详解
    Vertrigo Serv + testlink 环境搭建
    自动化测试全聚合
    selenium -文件上传的实现 -对于含有input element的上传
    chrome启动参数设置
    selenium
    java
  • 原文地址:https://www.cnblogs.com/XJT2018/p/10872274.html
Copyright © 2011-2022 走看看