• Python中正则表达式讲解


    正则表达式是匹配字符串的强大武器,它的核心思想是给字符串定义规则,凡是符合规则的字符串就是匹配了,否则就是不合法的。在介绍Python的用法之前,我们先讲解一下正则表达式的规则,然后再介绍在Python中如何运用。

    如果直接给出字符,那么就是精确的匹配,例如‘abc’当然是匹配’abc’了。

    • d可以匹配数字(0-9)
    • D和d相反,就是说只要不是0-9,都可以匹配
    • w可以匹配字母或者数字(0-9|a-z|A-Z)
    • W和w相反,就是说只要不是字母和数字,都可以匹配
    • s可以匹配空格, , , ,f
    • S和s相反
    • . 可以匹配除了 以外的任意字符

    第一步先说这些内容,Python提供re模块,包含所有正则表达式的功能,看下面的程序演示:

    #如何判断正则表达式是否匹配,使用re.match()
    import re
    a=re.match('d','1')
    b=re.match('d','s')
    print(a)
    print(b)
    
    输出:
    <_sre.SRE_Match object at 0x000000000065A510>
    None

    这里说一下,如果match()方法匹配的话,返回一个Match对象,否则返回None
    为了方便观察程序运行结果,我们使用if判断来输出结果,下面再看一个例子

    import re
    def is_match(a):
        if a!=None:
            print('yes!')
        else:
            print('no!')
    a=re.match('d','123abc')
    b=re.match('dd','123abc')
    c=re.match('ddd','123abc')
    d=re.match('dddd','123abc')
    is_match(a)
    is_match(b)
    is_match(c)
    is_match(d)
    
    输出:
    yes!
    yes!
    yes!
    no!

    现在来讲解上面的代码,我们知道d可以匹配一个0-9的数字,所以re.match(‘d’,’123abc’)中的d匹配的是字符串‘123abc’中的1,至于后面的’23abc’不用管它。一个d我只用匹配一个数字就可以了。re.match(‘dd’,’123abc’)中的两个d分别匹配的是字符串’123abc’中的‘1’和‘2’,后面的‘3abc’不用管。re.match(‘dddd’,’123abc’)中前3个d分别匹配的是‘1’,‘2’,‘3’,当第4个d去匹配‘a’的时候发现不能匹配,所以最后一个不能匹配上,输出None。再看几个例子体会下吧

    为了减少代码量,下面的代码我会直接写主要的代码部分,输出结果用注释代替

    a=re.match('w','123abc') #yes
    b=re.match('w','abc123') #yes
    c=re.match('w','Abc123') #yes
    a=re.match('.','abc') #yes
    b=re.match('.','Abc') #yes
    c=re.match('.','12bc') #yes
    d=re.match('.','*2bc') #yes
    e=re.match('.','
    2bc') #no

    如果我们要匹配变长的字符,可以在d,w,s, . 的后面使用下面的符号
    * 表示任意个字符(包括0个)
    +表示至少一个字符
    ?表示0个或1个字符
    {n}表示n个字符
    {n,m}表示n-m个字符

    a=re.match('d*','123') #yes
    # *表示任意个字符,包括0个,所以d*可以匹配0个数字,所以match('d*','abc')可以匹配
    b=re.match('d*','abc') #yes
    c=re.match('d+','1abc') #yes
    # +表示至少1个字符,d+表示至少1个数字,所以匹配不成功
    d=re.match('d+','abc') #no
    a=re.match('d?','123') #yes
    b=re.match('d?','abc') #yes
    c=re.match('d{3}','1234') #yes
    #d{3}代表3个数字,而'12'只有2个,所以不匹配
    d=re.match('d{3}','12') #no
    #'12abc'前3个'12a'不全是数字
    e=re.match('d{3}','12abc') #no
    a=re.match('d{0,3}','abc') #yes
    b=re.match('d{0,3}','12abc') #yes
    c=re.match('d{0,3}','1234bc') #yes

    还有更加精确的匹配,用[ ]表示范围,例如:
    [0-9]匹配1个数字,和d一样
    [a-z]匹配1个小写字母
    [A-Z]匹配1个大写字母
    _匹配下划线
    [0-9a-zA-Z]可以匹配1个数字或者字母,等价于w
    [0-9a-zA-Z _]可以匹配1个数字或者字母或者下划线,一般是变量的命名规则
    [0-9] | [a-z]匹配1个数字或者小写字母,使用的是 | 符号
    ^表示以什么开头,例如^[0-9]就是以数字开头
    $表示以什么结尾

    a1=re.match('[0-9]','123') #yes
    a2=re.match('[a-z]','abc') #yes
    a3=re.match('[A-Z]','Abc') #yes
    a4=re.match('[0-9a-zA-Z]','Abc') #yes
    b1=re.match('[0-9a-zA-Z]','12bc') #yes
    b2=re.match('[0-9a-zA-Z]','abc') #yes
    b3=re.match('[0-9a-zA-Z]','张康abc') #no
    b4=re.match('[0-9a-zA-Z\_]','_abc') #yes
    a=re.match('^[0-9a-zA-Z\_][0-9]','a1bc') #yes
    b=re.match('^[0-9a-zA-Z\_][a-z]','Abc') #yes
    c=re.match('^[0-9a-zA-Z\_][A-Z]','1Bbc') #yes
    d=re.match('^[0-9a-zA-Z\_][0-9]','1abc') #no
    e=re.match('^[0-9a-zA-Z_]','_1bc') #yes
    a=re.match('^[0-9a-z]+[A-Z]$','1234A') #yes
    b=re.match('^[0-9a-z]+[A-Z]$','1234a') #no

    正则表达式还可以用来切分字符串(切分字符串)

    import re
    a=re.split('s+','a  b c')
    print(a)
    
    输出:
    ['a', 'b', 'c']

    关于字符串中的split()函数,不明白的请参考我的另一篇博文。上面的代码的意思是以空格为切分符,把字符串分成n段,并以list的形式返回。
    如果还想把逗号加进去,让空格和逗号都变成分隔符,看下面的代码:

    import re
    a=re.split('[s\,]+','a  b c     ,d,f    e')
    print(a)
    
    输出:
    ['a', 'b', 'c', 'd', 'f', 'e']
    

    正则表达式还可以用来提取子串(分组)

    用( )表示的就是要提取的分组(Group),把想要提取的子串在正则表达式中用( )括起来,例如我要提取带区号的固定电话号的每一部分,看代码演示:

    import re
    a=re.match('(d{4})-(d{7})','0370-5163700')
    g0=a.group(0)
    g1=a.group(1)
    g2=a.group(2)
    print(g0)
    print(g1)
    print(g2)
    
    输出:
    0370-5163700
    0370
    5163700

    d{4}匹配的是0370,因为我要提取它,所以用()括起来,代表一个分组
    - 匹配的是 - ,因为这里 - 是特殊字符,需要转义,就像下划线需要转义 _,这里我不需要提取这个 - ,所以不用加括号。
    d{7}匹配的是5163700,这是需要提取的第二个分组,所以需要括起来。
    还有一点需要注意,无论什么时候,group(0)提取的都是原来的字符串,你要提取的分组从group(1)开始。

    正则表达式的贪婪匹配

    正则表达式匹配默认是贪婪匹配,也就是匹配尽可能多的字符,看个例子吧!

    import re
    a=re.match('^(d+)(1*)$','12345611111')
    print('第一组:'+a.group(1))
    print('第二组:'+a.group(2))
    
    输出:
    第一组:12345611111
    第二组:

    按照正常的理解d+应该匹配123456,1*匹配11111,但是由于正则表达式是默认贪婪匹配,d+匹配了全部数字。怎么才能不让它贪婪匹配呢,很简单,在后面加个问号?就可以了

    import re
    a=re.match('^(d+?)(1*)$','12345611111')
    print('第一组:'+a.group(1))
    print('第二组:'+a.group(2))
    
    输出:
    第一组:123456
    第二组:11111

    编译

    在Python中使用正则表达式时,re模块内部会干两件事情:

    1. 编译正则表达式,如果正则表达式的字符串本身不合法,会报错;
    2. 用编译后的正则表达式去匹配字符串。

    在编写网站的时候,有可能我们会对用户注册时输入的用户名或者邮箱等进行正则验证,那么一个正则表达式可能会匹配成千上万个用户名或者邮箱,每次都需要先编译后匹配,那么效率显得很低。那么为了提高效率,我们可以先编译正则表达式,只需要编译一次,然后用的时候再匹配。

    import re
    #由字母或者下划线开头,由数字,字母,下划线组成长度为6-20的字符串
    re_c=re.compile('^[a-zA-Z\_][w\_]{5,19}$')
    print(re_c.match('a123456789a123456789'))
    
    输出:
    <_sre.SRE_Match object at 0x000000000065A510>

    编译后生成Regular Expression对象,由于该对象自己包含了正则表达式,所以调用对应的方法时不用再次给出正则串。

    以上的内容只是正则表达式的九牛一毛,关于其他的正则表达式用法请读者自己查阅,如读者发现错误,欢迎指正。

  • 相关阅读:
    [Mac] 获取cpu信息
    [gcc warnings] -Wtrigraph warnings
    查看SSD寿命
    [linux] 查看SATA速度和具体设备
    [raspberry p3] [suse] 安装maven
    文本处理例子
    容器中用shell脚本启动如何优雅关闭(传送kill SIGTERM信号)
    kubernetes deployment 使用镜像摘要发布新版本
    Yearning sql工单系统 自动执行工单python脚本
    Kubernetes 企业发行版、容器Pass平台 OpenShift4.3 规划裸机部署
  • 原文地址:https://www.cnblogs.com/neuzk/p/9476429.html
Copyright © 2020-2023  润新知