• Python--模块之re


    re模块

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

    字符串是编程时涉及到的最多的一种数据结构,对字符串进行操作的需求几乎无处不在。比如判断一个字符串是否是合法的Email地址,虽然可以编程提取@前后的子串,再分别判断是否是单词和域名,但这样做不但麻烦,而且代码难以复用。

    正则表达式是一种用来匹配字符串的强有力的武器。它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的。

    因为正则表达式也是用字符串表示的,所以,我们要首先了解如何用字符来描述字符。

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

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

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

    元字符之. ^ $

    元字符之* + ? { }

    要匹配变长的字符,在正则表达式中,用*表示任意个字符(包括0个),用+表示至少一个字符,用?表示0个或1个字符,用{n}表示n个字符,用{n,m}表示n-m个字符:

    # 匹配一个数字包括整型和浮点型
    ret=re.findall('d+.?d*','12.45,34,0.05,109')
    
    print(ret)
    运行结果:
    ['12.45', '34', '0.05', '109']

    贪婪匹配

    正则匹配默认是贪婪匹配,也就是匹配尽可能多的字符。

    非贪婪匹配

    在满足匹配时,匹配尽可能短的字符串,使用?来表示非贪婪匹配

    ret1=re.findall('131d+','1312312312') #-------------------------------------------------贪婪匹配
    print(ret1)  
    
    ret=re.findall('131d+?','1312312312') #-------------------------------------------------非贪婪匹配/惰性匹配
    print(ret)
    运行结果:
    ['1312312312']
    ['1312']

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

    几个常用的非贪婪匹配Pattern

    *? 重复任意次,但尽可能少重复
    +? 重复1次或更多次,但尽可能少重复
    ?? 重复0次或1次,但尽可能少重复
    {n,m}? 重复n到m次,但尽可能少重复
    {n,}? 重复n次以上,但尽可能少重复

    .*?的用法:

    . 是任意字符
    * 是取 0 至 无限长度
    ? 是非贪婪模式。
    何在一起就是 取尽量少的任意字符,一般不会这么单独写,他大多用在:
    .*?x
    
    就是取前面任意长度的字符,直到一个x出现

    元字符之转义符

    1、反斜杠后边跟元字符去除特殊功能,比如.

    2、反斜杠后边跟普通字符实现特殊功能,比如d

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

    让我们看一下的应用:

    ret=re.findall(r'I','I am LIST')
    print(ret)
    运行结果:
    ['I']
    ret=re.findall(r'c\b',r'abce')
    print(ret)
    运行结果:
    ['c\b']

    # 是特殊符号所以,'abce'前面需要加r

    接下来我们试着匹配下“abcle”中的‘cl’:

    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)
    # #
    # ret=re.findall(r'c\l','abcle')  #---------------------正确
    # print(ret)
    运行结果:
    报错
    报错
    ['c\l']
    ['c\l']

    元字符之分组 ()

    除了简单地判断是否匹配之外,正则表达式还有提取子串的强大功能。()表示的就是要提取的分组(Group)。

    m = re.findall(r'(ad)+', 'add')
    print(m)
    
    ret = re.search('(?P<id>d{2})/(?P<name>w{3})', '23/com')
    print(ret.group())
    print(ret.group('id')) 
    运行结果:
    ['ad']
    23/com
    23

    如果正则表达式中定义了组,就可以在Match对象上用group()方法提取出子串来。

    注意到group(0)永远是原始字符串,group(1)group(2)……表示第1、2、……个子串。

    元字符之|

    ret=re.search('(ab)|d','rabhdg8sd')
    print(ret)
    print(ret.group())
    运行结果:
    <_sre.SRE_Match object; span=(1, 3), match='ab'>
    ab

    元字符之字符集[]

    # --------------------------------------------字符集[]
    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']

    注意以上一点。

    re模块下的常用方法

    import re
    
    ret=re.findall('a', 'alvin yuan')  # 返回所有满足匹配条件的结果,放在列表里
    print(ret)  #['a', 'a']
    
    ret=re.search('a', 'alvin yuan').group()
    print(ret)  #a
    
    # 函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以
    # 通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。
    
    
    ret=re.match('a', 'abc').group()  # 同search,不过仅在字符串开始处进行匹配
    print(ret)  #a
    
    ret = re.split('[ab]', 'abcd')  # 先按'a'分割得到''和'bcd',再对''和'bcd'分别按'b'分割
    print(ret)  # ['', '', 'cd']
    
    ret = re.sub('d', 'abc', 'alvin5yuan6', 1)
    print(ret)  #alvinabcyuan6
    
    ret = re.subn('d', 'abc', 'alvin5yuan6')
    print(ret)  #('alvinabcyuanabc', 2)
    
    obj = re.compile('d{3}')   #编译 
    ret = obj.search('abc123eeee') print(ret.group()) # 123
    
    
    当我们在Python中使用正则表达式时,re模块内部会干两件事情

    1.
    编译正则表达式,如果正则表达式的字符串本身不合法,会报错;
    2.用编译后的正则表达式去匹配字符串。
      如果一个正则表达式要重复使用几千次,出于效率的考虑,我们可以预编译该正则表达式,接下来重复使用时就不需要编译这个步骤了,直接匹配:
    
    
    
    ret = re.finditer('d', 'ds3sy4784a')
    print(ret)  #<callable_iterator object at 0x0000000001DE5BE0>
    
    print(next(ret).group())  #3
    print(next(ret).group())  #4

    注意:

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

    2 split的优先级查询:

    ret=re.split("d+","yuan2egon56alex")
    print(ret)
    
    ret=re.split("(d+)","yuan2egon56alex")
    print(ret)
    结果:
    ['yuan', 'egon', 'alex']
    ['yuan', '2', 'egon', '56', 'alex']

     作业:

    1、 匹配一段文本中的每行的邮箱
    import re
    ret=re.findall("w+@w+.(?:com|cn|cc)",s)
    
    
    2、 匹配一段文本中的每行的时间字符串,比如:‘1990-07-12’;
    ret=re.findall('(?:[1-2]d{3})-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]d|3[0-1])',s)
    
    
    3、 匹配一段文本中所有的身份证数字。
    ret=re.findall('[1-9]d{16}[dx]',s)
    
    4、 匹配qq号。(腾讯QQ号从10000开始)
    ret=re.findall('[1-9]d{4,}',s)
    
    5、 匹配一个浮点数。
    ret=re.findall('d+.?d*',s)
    
    6、 匹配汉字。
    ret=re.findall('[u4e00-u9fa5]+',s)
    
    7、 匹配出所有整数
    ret=re.findall('-?d+.d*|(-?d+)',s)
  • 相关阅读:
    golang与vscode的安装与配置
    numpy学习之前的必要数学知识:线性代数
    分布式系统设计系列 -- 基本原理及高可用策略
    微服务的4个设计原则和19个解决方案
    JAVA8 十大新特性详解
    ConcurrentHashMap总结
    Java NIO理解与使用
    深入了解 Java-Netty高性能高并发理解
    java内存泄漏的定位与分析
    Netty高性能编程备忘录(下)
  • 原文地址:https://www.cnblogs.com/metianzing/p/7107851.html
Copyright © 2020-2023  润新知