zoukankan      html  css  js  c++  java
  • Python Revisited Day 13 (正则表达式)

    《Python 3 程序开发指南》 学习笔记

    13.1 Python的正则表达式语言

    13.1.1 字符与字符类

    特殊字符:.^$?+*{}|

    在一个字符类内部,除外,特殊字符不再具备特殊意义.
    当^ 为一个字符类的第一个字符时,表其特殊含义否定。
    -表示一个字符范围,如果作为字符类中的第一个字符,就表示一个字面意义上的连字符。

    字符类速记(表)

    符号 含义
    . 可以匹配除换行符之外的任意字符,或带re.DOTALL标记的任意字符,或匹配字符内部的字面意义的字符。
    d 匹配一个Unicode数字,或带(等价于的意思?)re.ASCII标记的[0-9]
    D 匹配一个Unicode非数字,或带re.ASCII标记的[0-9]
    s 匹配Unicode空白,或带re.ASCII标记的[ fv]
    S 匹配Unicode非空白,或带re.ASCII标记的[^ fv]
    w 匹配一个Unicode单词字符,或带re.ASCII标记的[a-zA-Z0-9]
    W 匹配一个Unicode非单词字符,或带re.ASCII标记的[^a-zA-Z0-9]

    13.1.2 量词 {m, n} ? + *

    {m, n}:m表示该量词必须匹配的最小次数,而n表示最多次数,如e{1,1}, e{2, 2}
    如果m, n相同,可以简写为{m}。而量词{0,1}有一种速记形式?.
    travell{0,1}ed == travell?ed

    正则表达式量词(表)

    语法 含义
    e? or e{0,1} 贪婪地匹配表达式e的0或1次出现
    e?? or e{0,1}? 非贪婪地匹配表达式e e+或{1,}的0次或1次出现,贪婪地匹配表达式e的1次或多次出现
    e+? or e{1,}? 非贪婪地匹配表达式e的一次或多次出现
    e* or e{0,} 贪婪地匹配表达式e的0次或1次出现
    e*? or e{0,}? 非贪婪地匹配表达式e地0次或1次出现
    e{m} 准确匹配表达式e的m次出现
    e{m,} 贪婪地匹配表达式e的至少m次出现
    e{m,}? 非贪婪地匹配表达式e的至少m次出现
    e{,n} 贪婪地匹配表达式e的至多n次出现
    e{,n}? 非贪婪地匹配表达式e的至多n次出现
    e{m,n} 贪婪地匹配表达式e的至少m次,至多n次出现
    e+ e{1,n}(至少一次),n是量词地可能地最大值,通常是32767
    e* e{0,n}(任意次),n同上
    e{m,n}? 非贪婪地匹配表达式e地至少m次,至多n次出现
    • 默认情况下,所有量词都是贪婪的,量词后面跟随?表示非贪婪。
    re.match(r"d+", "136") 
    #<re.Match object; span=(0, 3), match='136'>
    re.match(r"d+?", "136")
    #<re.Match object; span=(0, 1), match='1'>
    re.match(r"d??", "136")
    #<re.Match object; span=(0, 0), match=''>
    re.match(r"d{0,1}?", "136")
    #<re.Match object; span=(0, 0), match=''>
    re.match(r"d{0,1}?36", "136")
    #<re.Match object; span=(0, 3), match='136'>
    re.match(r"d*?", "136")
    #<re.Match object; span=(0, 0), match=''>
    re.match(r"d*?6", "136")
    #<re.Match object; span=(0, 3), match='136'>
    re.match(r"<imgs+[^>]*?src=w[^>]*?>", "<img   src=dd>")
    #<re.Match object; span=(0, 14), match='<img   src=dd>'>
    

    组与捕获 ?:可以关闭捕获

    ()可以进行分组,而交替字符|在多种方案中选取一个的情况下使用。

    re.match(r"aircraft|airplane|jet", "airplane")
    #<re.Match object; span=(0, 8), match='airplane'>
    re.match(r"air(craft|plane)|jet", "airplane")
    #<re.Match object; span=(0, 8), match='airplane'>
    

    ()在分组的同时进行捕获,以备后用。

    for i in range(3):
        print(re.match(r"(air(craft|plane)|jet)", "airplane")[i])
    #airplane #只要匹配成功,首项都是完整匹配项
    #airplane
    #plane
    
    try:
        for i in range(3):
            print(re.match(r"(air(?:craft|plane)|jet)", "airplane")[i]) #?:关闭捕获
    except IndexError as err:
        print("IndexError: {0}".format(err))
    #airplane
    #airplane
    #IndexError: no such group
    
    s = "eric1 = something
    "
        "eric2 = somewhere
    "
        "eric3 = somebody"
    try:
        for i in range(10):
            print(re.match(r"(w+ = .+
    ?)+", s)[i])
    except IndexError as err:
        print("IndexError: {0}".format(err))
    
    #eric1 = something
    #eric2 = somewhere
    #eric3 = somebody
    #eric3 = somebody
    #IndexError: no such group
    
    s = "eric1 = something
    "
        "eric2 = somewhere
    "
        "eric3 = somebody"
    try:
        for i in range(10):
            print(re.match(r"(?:(w+) = (.+)
    ?)+", s)[i])
    except IndexError as err:
        print("IndexError: {0}".format(err))
    
    
    #eric1 = something
    #eric2 = somewhere
    #eric3 = somebody
    #eric3
    #somebody
    #IndexError: no such group
    

    反向引用 i 反向引用不能用在字符类内部,即不能用在[]中

    re.match(r"(w+)s+1", "eric eric")
    #<re.Match object; span=(0, 9), match='eric eric'>
    re.match(r"(w+)(d?)s+12", "eric1 eric1")
    #<re.Match object; span=(0, 11), match='eric1 eric1'>
    re.match(r"(w+)(d?)s+12", "eric1 eric2") # None
    

    命名捕获 (?P…) 反向引用:(?P=name)

    • 注意, (?P=name)只是匹配,((?P=name))才能完成捕获
    for item in ('name', 'what'):
        print(re.match(r"(?P<name>w+)s+(?P<what>w+)", "Pikachu Pokemon")[item])
    #Pikachu
    #Pokemon
    re.match(r"(?P<name>w+)s+((?P=name))", "Pikachu Pikachu")[2]
    #'Pikachu'
    

    断言与标记

    符号 含义
    ^ 在起始处匹配,也可以在带MULTILINE标记的每个换行符后匹配
    $ 在结尾处匹配,也可以在MULTILINE标记的每个换行符前匹配
    A 在起始处匹配
     在单词边界匹配,受re.ASCII标记影响——在字符类内部,则是backspace字符的转义字符
    B 在非单词边界匹配,受re.ASCII标记影响
     在结尾处匹配
    (?=e) 如果表达式e在此断言处匹配,但没有超越此处——称为前瞻或正前瞻,则匹配
    (?!e) 如果表达式e在此前言处不匹配,也没有超越此处——称为负前瞻,则匹配
    (?<=e) 如果表达式e恰在本断言之前匹配——成为正回顾,则匹配
    (?<!e) 如果表达式e恰在本断言之前不匹配——称为负回顾,则匹配
    • 单词边界,顾名思义就是该位置为单词的边界,比如位置之前是一个单词,后面是非单词(比方空格),当然反过来也是可以的。
    re.match(r"eric", "eric1")
    #<re.Match object; span=(0, 4), match='eric'>
    re.match(r"eric", "eric1") #None
    re.match(r"deric", "deric1")
    #<re.Match object; span=(0, 5), match='deric'>
    re.match(r"deric", "deric1") #None
    s = "I'm sorry, my son.
     Actually, actually, she is my daughter, and your sister..."
    re.match(r".+(?<=son)", s)
    #<re.Match object; span=(0, 17), match="I'm sorry, my son">
    s = "I'm sorry, my son.
     Actually, actually, she is my daughter, and your sister..."
    re.match(r".+(?<!daugther)", s)
    #<re.Match object; span=(0, 18), match="I'm sorry, my son.">
    

    条件性匹配 (?(id)yes_exp) | (?(id)yes_exp|no_exp)

    s1 = "src="ddd.ddd""
    s2 = "src='ddd.ddd'"
    s3 = "src=ddd.ddd"
    re.match(r"src=(["'])([^"'>]+)1", s1) # ! s3
    #<re.Match object; span=(0, 13), match='src="ddd.ddd"'>
    re.match(r"src=(["'])?([^"'>]+)(?(1)1)", s3)
    #<re.Match object; span=(0, 11), match='src=ddd.ddd'>
    

    设置标记 (?flags) flags == a | i | m| s | x

    符号 含义
    a re.ASCII
    i re.IGNORECASE
    m re.MULTILINE
    s re.DOTALL
    x re.VERBOSE

    13.2 正则表达式模块

    正则表达式模块的函数(表)

    语法 描述
    re.compile(r, f) 返回编译后的正则表达式r,如果指定,就将其标记设置为f
    re.escape(s) 返回字符串s,其中所有非字母数字的字符都是用反斜线进行了转义处理,因此返回的字符串中没有特殊的正则表达式字符
    re.findall(r, s, f) 返回正则表达式r在字符串s中所有非交叠的匹配(如果给定f,就受其值约)。如果正则表达式中有捕获,那么每次匹配都作为一个捕获元组返回
    re.finditer(r, s, f) 对正则表达式r在字符串s中每个非交叠的匹配(如果给定f,就受其值约),都返回一个匹配对象
    re.match(r, s, f) 如果正则表达式r在字符串s的起始处匹配(如果给定f,就受其制约),就返回一个匹配对象,否则返回None
    re.search(r, s, f) 如果正则表达式r在字符串s的任意位置处匹配(如果给定f,就受其值约),就返回一个匹配对象,否则返回None
    re.split(r, s, m) 返回分割字符串s(在正则表达式r每次出现出进行分割)所产生的字符串的列表,至多分割m次(如果没有给定m,就分割尽可能多的次数),如果正则表达式中包含捕获,就被包含在分割的部分之间
    re.sub(r, x, s, m) 对正则表达式r的每次匹配(如果给定m,那么至多m次),返回字符串s的一个副本,并将其替换为x——这可以是一个字符串,也可以是一个函数
    re.subn(r, x, s, m) 与re.sub()函数相同,区别在于此函数返回一个二元组,其中一项为生成的字符串,一项为代入的次数
    import re
    re.escape("\") #'\\'
    s = "eric1 = something
    "
        "eric2 = somewhere
    "
        "eric3 = somebody"
    try:
        for i in range(10):
            print(re.findall(r"(?:(w+) = (.+)
    ?)+", s)[i])
    except IndexError as err:
        print("IndexError: {0}".format(err))
    #('eric3', 'somebody')
    #IndexError: list index out of range
    
    #从下面的例子可以明白什么是非交叠匹配
    s = "bigbigericbigbig
    "
        "smallsmallericsmallsmall
    "
        "hardharderichardhard"
    e = r"""(?x)(?i)
    ((?P<attr>big|small)(eric)2)
    """
    e = re.compile(e)
    re.findall(e, s) #[('bigericbig', 'big', 'eric'), ('smallericsmall', 'small', 'eric')]
    
    s = "eric1 = something
    "
        "eric2 = somewhere
    "
        "eric3 = somebody"
    re.split(r"
    ", s)
    #['eric1 = something', 'eric2 = somewhere', 'eric3 = somebody']
    
    

    正则表达式模块的标记(表)

    标记 含义
    re.A or re.ASCII 使,B,s,S,w,W都假定字符串为ASCII,默认为这些字符类的速记法,依赖于Unicode规范
    re.I or re.IGNORECASE 使正则表达式以大小写不敏感的方法进行匹配
    re.M or re.MULTILINE 使^在起始处并在每个换行符后匹配,使$在结尾处但在每个换行符之前匹配
    re.S or re.DOTALL 使.匹配每个字符,包括换行符
    re.X or re.VERBOSE 使空白和注释包含在匹配中
    s = "eric1=something
    "
        "eric2 = somewhere
    "
        "Eric3 = somebody"
    re.findall(r"eric", s, re.I)
    #['eric', 'eric', 'Eric']
    e = r"""(?x)
     (?P<eric>eric)
    """
    e = re.compile(e)
    e.findall(s)
    #['eric', 'eric']
    

    正则表达式对象方法(表)

    rx表正则表达式,下面的方法其实上面都有提到过。

    语法 描述
    rx.findall(s, start, end) 返回字符串s中(或s的start:end分片中)正则表达式的所有非交叠的匹配,如果正则表达式有捕获,那么每次匹配是返回一个捕获元组
    rx.finditer(sstart, end) 对字符串s中(或s的start:end分片中)的每个非交叠匹配,返回一个匹配对象
    rx.flags 正则表达式编译时设置的标记 readonly
    rx.groupindex 一个字典,其键位捕获组名,值为捕获组编号,如果没有使用名称就为空
    rx.match(s, start, end) 如果正则表达式在字符串s的起始处(或s的start:end分片起始处)匹配,就返回一个匹配对象,否则返回None
    rx.pattern 正则表达式被编译时使用的字符串
    rx.search(s, start, end) 如果正则表达式在字符串s的任意位置(或s的start:end分片中的任意位置)匹配,就返回一个匹配对象,否则返回None
    rx.split(s, m) 返回字符串列表,其中每个字符串都源自对字符串s的分割(在正则表达式的每次匹配处),但至多有m个分割(如果没有给定m,则可以有尽可能多的分割);如果正则表达式有捕获,就包含在列表中俩个分割之间
    rx.sub(x, s, m) 返回字符串s的副本,其中每个(或至多m个,如果给定)匹配出使用x(可以时字符串或函数)进行替换
    rx.subn(x, s, m) 与rx.sub()相同,区别在于返回的是二元组,其中一项时结果字符串,一项时所做替换的个数
    e.groupindex
    #mappingproxy({'eric': 1})
    e.pattern
    #'(?x)
     (?P<eric>eric)
    '
    

    匹配对象的属性与方法(表)

    m 匹配对象——finditer, match等方法可能返回匹配对象

    语法 描述
    m.end(g) 返回组g(如果给定)在文本中匹配的终点索引位置,对组0,则表示整体匹配;如果匹配中不包含改组,就返回-1
    m.endpos 搜索的终点索引位置(文本的重点,或赋予match()或search()的end
    m.expand(s) 返回字符串s,并将其中的捕获标志(1, 2, g等类似的标志)用相应的捕获替代 经测试如果s== r"…"上述可行,如果s是普通的字符串,应当用:1, 2, g,没错除了g外需要转义
    m.group(g, …) 返回编号的或命名的组g,如果给定的不止一个,就返回相应的捕获组成的元组(组0表示整体匹配)
    m.groupdict(default) 返回一个字典,其中存放所有命名的捕获组,组名作为键,捕获作为值;如果给定了default参数,就将其用作那些不参与匹配的捕获组的值
    m.groups(default) 返回包含所有捕获组的元组,从1开始;如果给定default,就将其用作那些不参与匹配的捕获组的值
    m.lastgroup 匹配的,编号最高的捕获组的名称,如果不存在或没使用名称,就返回None
    m.lastindex 匹配的,编号最高的捕获组的编号,如果没有就返回None
    m.pos 搜索的起始索引位置(文本的起始处,或赋予match()或search()的start)
    m.span(g) 如果给定g,就返回组g在文本中匹配的起始索引位置与结尾索引位置(对组0,则是整体匹配);如果改组不参加匹配,就返回(-1,-1)
    m.start(g) 如果给定g,就返回组g在文本中匹配的起始索引位置(对组0,则是整体匹配);如果改组不参加匹配,就返回01
    m.string 船体给match()或search()的字符串
    s = "bigbigericbigbig
    "
        "smallsmallericsmallsmall
    "
        "hardharderichardhard"
    e = r"""(?x)(?i)
    ((?P<attr>big|small)(eric)2)
    """
    e = re.compile(e)
    ms = re.finditer(e, s)
    for m in list(ms):
        print(m.end(2), m.endpos)
    #6 62
    #27 62
    s2 = "g<attr>pig"
    s3 = "\2cat"
    s4 = r"2cat"
    ms = re.finditer(e, s)
    print(next(ms).expand(s2))
    m = next(ms)
    print(m.expand(s3), m.expand(s4))
    #bigpig
    #smallcat smallcat
    m.group(), m.group(1), m.group(1, 2, 3)
    #('smallericsmall', 'smallericsmall', ('smallericsmall', 'small', 'eric'))
    m.groupdict()
    #{'attr': 'small'}
    m.groups()
    #('smallericsmall', 'small', 'eric')
    m.lastgroup #None
    m.lastindex #1
    m.span(), m.span(1), m.span(2), m.span(3)
    #((22, 36), (22, 36), (22, 27), (27, 31))
    m.string
    #'bigbigericbigbig
    smallsmallericsmallsmall
    hardharderichardhard'
    
  • 相关阅读:
    CF85E Guard Towers(二分答案+二分图)
    CF732F Tourist Reform(边双联通)
    CF949C Data Center Maintenance(建图+强联通分量)
    CF402E Strictly Positive Matrix(矩阵,强联通分量)
    CF209C Trails and Glades(欧拉路)
    POJ1201Intervals(差分约束)
    NOIP2016 天天爱跑步(树上差分)
    CF19E Fairy(树上差分)
    NOIP 2017 小凯的疑惑(同余类)
    POJ 3539 Elevator(同余类BFS)
  • 原文地址:https://www.cnblogs.com/MTandHJ/p/10526755.html
Copyright © 2011-2022 走看看