• python学习笔记16:正则表达式


    import re
    

    1. re的method

    1.1. re.match(pattern,string,flags=0)

    说明:

    1. 从起始位置扫描string,返回match对象,match对象内容为第一个成功的匹配;(匹配不成功返回None)
    2. 与search的区别是,match要从开头扫描,search可以从任意位置开始扫描;
    3. 可能通过括号捕获内容,然后使用match对应.groups()/group()来访问捕获内容;
    >>> re.match(r’a’, ‘abc’) # 匹配,因为a出现在了str的起始位置  
    >>>  
    >>> test = ‘abcd’  
    >>> if re.match(r'bc', test):  
    ...     print('ok')  
    ... else:  
    ...     print('failed')  
    ...  
    failed # bc没出现在test开头,所以匹配不成功;如果需要从非开始位置匹配,需要使用re.search.  
    

    1.2. re.search(pattern, string, flags=0)

    说明:

    1. 扫描string,返回match对象,match对象内容为第一个成功的匹配;(匹配不成功返回None)
    2. 与match的区别是,match要从开头扫描,search可以从任意位置开始扫描;
    >>> re.search(r’cw+’, ‘abcde’) # 匹配,span=(2,5);即开始匹配的char idx为2,结束匹配的char idx为4;注意不包含char idx 5;  
    >>> re.search(r’c’, ‘abcdec’) # 匹配第一次出现的c,span=(2,3);注意:不会匹配第二次出现的c。  
    

    1.3. re.findall(pattern,string[, flags])

    说明:搜索string,返回列表,列表内容为全部能匹配的子串或捕获括号内的字符;

    没有捕获括号时,列表内容为匹配的子串

    >>> f0 = re.findall(r'd+', 'a00b01c02d03')  
    >>> f0 # 返回列表,注意:由于没有捕获括号,所以列表内容为匹配的子串  
    ['00', '01', '02', '03']  
    

    pattern中有捕获括号,则findall返回的列表中是括号捕获的内容

    >>> f0 = re.findall(r'12(3|4)?', 'a12b123c124d12') # pattern中有捕获括号;  
    >>> f0 # 返回列表,注意:由于pattern中有捕获括号,则findall返回的列表中是括号捕获的内容;  
    ['', '3', '4', '']  
    

    如果需要返回pattern匹配的内容,需要使用非捕获括号

    >>> f0 = re.findall(r'12(?:3|4)?', 'a12b123c124d12') # pattern中括号使用了?:,为非捕获括号;  
    >>> f0 #返回列表,注意:由于pattern中括号是非捕获模式,则findall返回的列表内容为匹配的子串;  
    ['12', '123', '124', '12']  
    

    1.4. re.finditer(pattern, string[, flags])

    说明:搜索string,返回迭代器,迭代器可以顺序访问每一个匹配结果(即一个match对象);

    >>> # f0是一个<callable_iterator object at 0x…>  
    >>> f0 = re.finditer(r'12(?:3|4)?', 'a12b123c124d12')  
    >>> for e in f0:  
    ...     print(e.group(0)) # 注意,e是一个match对象。  
    ...  
    12  
    123  
    124  
    12  
    

    1.5. re.split(pattern, sting[, maxsplit])

    用正则表达式切分字符串,返回切分后的列表;
    比使用固定字符(str.split(‘ ’))更灵活;

    re.split(r’[s\,;]+’, ‘a, b; ; cd’) # [‘a’,’b’,’c’,’d’]
    

    1.6. re.sub(pattern, repl, string[, count]) 替换

    1. 参数说明:
    参数 说明
    pattern 表示要匹配的pattern
    repl 表示要将pattern替换成的目标字符串
    string 原字符串
    count 替换的个数
    flags 是个什么东西?
    1. 基本替换:
    >>> s0 = ‘hello 123 world 456’  
    >>> s1 = re.sub(r‘d+’, ‘222’, s0) # 将s0字符串中的数字串替换为‘222’;  
    ‘hello 222 world 222’  
    
    1. 逆向引用(在pattern和repl中使用):
      例1:
    >>> s0 = 'come dog, go dog'  
    >>> s1 = re.sub(r'come (w+), go 1', 'g<1>', s0) # 返回‘dog’  
    'dog'  
    # 说明:1 是pattern中对group(1)的逆向引用;  
    # 说明:g<1>,是repl中对pattern group(1)的逆向引用;  
    

    例2:

    >>> s2 = re.sub(r’come (?P<name>w+), go (?P=name)’, ‘g<name>’, s0)  
    # 返回‘dog’,使用命名捕获,效果同s1  
    # 说明:(?P<name>xxx),是pattern中定义的命名组,name为组名,即原来的group(1)。  
    # 说明: (?P=name),是pattern中对命名组(name)的逆向引用。  
    # 说明:g<name>,是repl中对命名组的逆向引用。  
    
    1. repl是函数的情况:
    >>> def _add1(m0):# 函数的参数是match对象  
    ...     str_new = ''  
    ...     for char in m0.group(‘num’): # match对象匹配的命名组(num)是字串,对它做循环  
    ...         #字符转为整数,然后加1,再转回字串,取最低位  
    ...         str_new += str(int(char)+1)[-1]  
    ...     return str_new  
    ...    
    >>> s0 = ‘hello 123, world 456 696’  
    >>> s1 = re.sub(r’(?P<num>d+)’, _add1, s0)  
    'hello 234, world 567 707' # s0中的数字每一位都加1, 9+1后取0.  
    
    1. count,替换的次数
    >>> #接上一个例子,要求只替换两次,第三个匹配不替换:  
    >>> s1 = re.sub(r’(?P<num>d+)’, _add1, s0, 2)  
    'hello 234, world 567 696' # s0中的数字每一位都加1, 但第3个匹配不替换.  
    

    1.7. re.compile(pattern,flags=0)

    re.compile()用于编译正则表达式模式字符串,并生成Regular Expression Objects;
    如果正则表达式要重复使用几千次,可以预先编译该正则表达式,后续重复使用时就不需要编译了;
    Regular Expression Objects可以使用上述的re的方法(match、search、findall等)。

    >>> c0 = re.compile(r’(d+)-(d+)’) # 编译时不需要给匹配字符串;  
    >>> c0.match(‘010-123456’)          # 返回match对象。调用时不需要给正则串;  
    >>> c0.match(‘010-123456’).group(2) # ‘123456’ , 第二个括号截获的内容;  
    >>> c0.match(‘abc010-123456def’)    # None,使用match无法匹配,需要使用search。  
    >>>    
    >>> c0.search(‘abc010-123456def’)   # 返回search对象。  
    >>> c0.search(‘abc010-123456def’).span(2) # (7, 13),第2个括号截获的子串的索引;  
    

    2. flags的可选值:

    match、search等方法,有一个参数是flags,作用改变匹配的方式。
    可用flags如下:

    Flag值 作用
    0 默认值为0,不改变匹配方式
    re.I(IGNORECASE) 忽略大小写
    re.M(MULTILINE) 多行模式,改变^和$的行为
    re.S(DOTALL) 点可以匹配任意字符,包括换行符
    re.L(LOCALE) 做本地化识别的匹配,不推荐使用??
    re.U(UNICODE) 使用wWsSdD使用取决于unicode的定义的字符属性,
    python3默认使用该flag
    re.X(VERBOSE) 冗长模式,该模式下patter字符串中可以是多行的,忽略其中的空白字符,且可以在其中添加注释

    例子:

    >>> re.match(r’a’, ‘A’, flags=0) # 正常匹配方式,大小写不同,不匹配,返回None;
    >>> re.match(r’a’, ‘A’, flags=re.I)  # 忽略大小写匹配,返回match对象;
    >>> re.match(r’a B’, ‘AB’, flags=re.I) # patter中有空格,不匹配,返回None;
    >>> re.match(r’a B’, ‘AB’, flags=re.I|re.X) # 忽略patter中的空白,匹配,返回match对象;  
    

    3. match对象的method

    match对象通过调用这些方法,可以处理match匹配的内容。

    3.1. group([group1, …])

    作用:获取一个或多个分组截获的字符串;
    例:

    >>> m0 = re.match(r’^(d+)-(d+)’, ‘010-12345abc’) # 返回一个match对象  
    >>> m0.group(0) # ‘010-12345’,正则式匹配到的所有内容;  
    >>> m0.group(1) # ‘010’ ,第一个括号提取的内容;  
    >>> m0.group(2) # ‘12345’ ,第二个括号提取的内容;  
    >>> m0.group(1, 2) # (‘010’, ‘12345’) ,前2个括号提取的内容组成的元组;  
    >>> m0.group(3) # 报错:IndexError: no such group;  
    

    3.2. groups([default])

    作用:以元组形式返回分部分组截获的字符串,相当于调用group(1,2, … last); default表示没有截获字符串的组以这个值替代,默认为None。
    例:

    >>> m0 = re.match(r’^(d+)-(d+)’, ‘010-12345abc’) # 返回一个match对象  
    >>> m0.groups() # (‘010’, ‘12345’),group(1)和group(2)组成的元组  
    

    3.3. groupdict([default])

    作用:返回以有别名的组的别名为键、以该组截获的子串为值的字典,没有别名的组不包含在内。default含义同上;
    例:暂无

    3.4. start/end/span([group])

    作用:

    1. start([group]):返回指定的组截获的子串在string中的起始索引(子串第一个字符的索引)。group默认值为0;
    2. end([group)):返回指定的组截获的子串在string中的结束索引(子串最后一个字符的索引+1)。group默认值为0;
    3. span([group]):返回(start(group), end(group));
      例:
    >>> m0 = re.search(r’(d+)-(d+)’, ‘abc010-123456def’)  
    >>> m0.group(0) # ‘010-123456’,正则式匹配到的内容;  
    >>> m0.start() # 3,group0截获的子串的起始idx;  
    >>> m0.end() # 13,group0截获的子串的结束idx+1;  
    >>> m0.span() # (3, 13),即(m0.start(),m0.end());  
       
    >>> m0.group(1) # ‘010’,第一个括号截取到的内容;  
    >>> m0.start(1) # 3,group1截获的子串的起始idx;  
    >>> m0.end(1) # 6,group1截获的子串的结束idx+1;  
    >>> m0.span(1) # (3, 6),即(m0.start(1), m0.end(1));  
       
    >>> m0.group(2) # ‘123456’,第2个括号截取到的内容;  
    >>> m0.start(2) # 7,group1截获的子串的起始idx;  
    >>> m0.end(2) # 13,group1截获的子串的结束idx+1;  
    >>> m0.span(2) # (7, 13),即(m0.start(2), m0.end(2));  
       
    >>> m0.group(3) # 报错,IndexError: no such group;  
    >>> m0.start(3) # 报错,IndexError: no such group;  
    >>> m0.end(3) # 报错,IndexError: no such group;  
    >>> m0.span(3) # 报错,IndexError: no such group;  
    

    3.5. expand([group])

    作用:将匹配到的分组代入template中然后返回。template中可以使用id或g、g引用分组,但不能使用编号0。id与g是等价的;但10将被认为是第10个分组,如果你想表达1之后是字符'0',只能使用g<1>0。
    例:

    >>> m0 = re.search(r’(d+)-(d+)’, ‘abc010-123456def’)  
    >>> m0.expand(r’2:1’) # ‘123456:010’,将group()中的元素重新组合为:’grp2:grp1’  
    

    4. 字符

    字符 说明
    一般字符 匹配自身;
    点号(.) 匹配任意字符(换行符 除外,在DOTALL模式也能匹配换行符);
    反斜杠() 转义字符,改变字符原意,如匹配可以使用*或[],匹配可以使用;
    中括号([…]) 字符集,可以匹配字符集中列出的任意一个字符;

    中括号的用法:

    [abc]  # 可以逐个列出
    [a-c]  # 可以给出范围:
    [w]   # 可以使用预定义字符集:
    [^abc] #可以取反,不是abc的其它字符
    [^ - [ ] ] # 特殊字符在字符集中要转义
    

    5. 预定义字符集

    字符集 说明
    d 数字,等价于[0-9];
    D 非数字,等价于[^d];
    s 空白字符,等价于[<空格> fv];
    S 非空白字符,等价于[^s];
    w 单词字符,等价于[_A-Za-z0-9];
    W 非单词字符,等价于[^w];

    6. 数量词

    表示匹配字符重复的次数。

    数量词 说明
    * 匹配前一个字符0~∞次;
    + 匹配前一个字符1~∞次;
    ? 匹配前一个字符0~1次;
    {m} 匹配前一个字符m次;
    {m,n} 匹配前一个字符m~n次;

    注意:量词可以作用在多个字符上,如:

    >>> re.search(r’(123)+’, ‘a1123123123b’).group(0) # ‘123123123’,截取’123’重复多次;
    >>> re.search(r’(123){2}’, ‘a1123123123b’).group(0) # ‘123123’,截取’123’重复2次;
    

    7. 贪婪匹配、非贪婪匹配

    正则默认为贪婪匹配,进行非贪婪匹配需要使用?;

    1. *? 匹配前一个字符0次;
    2. +? 匹配前一个字符1次;
    3. ?? 匹配前一个字符0次;
    4. {m,n}? 匹配前一个字符m次;

    例1:

    >>> re.search(r’a(d*)’, ‘a1234b’).group(1) # ‘1234’,贪婪匹配,截取第一次出现的‘a+所有数字’;
    >>> re.search(r’a(d*?)’, ‘a1234b’).group(1) # ‘’,非贪婪匹配,截取第一次出现的‘a+第0个数字’;
    >>> re.search(r’(d*)’, ‘a1234b’).group(1) # ‘’,贪婪匹配,截取第一次出现的‘所有数字’;注意:这里用的d*,会在idx==0时匹配上0个数字,所以无法截取到后面的’1234’。
    

    例2

    >>> re.search(r’(d+)’, ‘a1234b’).group(1) # ‘1234’,贪婪匹配,截取第一次出现的所有数字;
    >>> re.search(r’(d+?)’, ‘a1234b’).group(1) # ‘1’,非贪婪匹配,截取第一次出现的第一个数字;
    

    例3

    >>> re.search(r’a(d?)’, ‘a1234b’).group(1) # ‘1’,贪婪匹配,截取第一次出现的1个数字;
    >>> re.search(r’(d??)’, ‘a1234b’).group(1) # ‘’,非贪婪匹配,截取第一次出现的0个数字;
    

    例4

    >>> re.search(r’a(d{1,3})’, ‘a1234b’).group(1) # ‘123’,贪婪匹配,截取第一次出现的n个数字;
    >>> re.search(r’(d{1,3}?)’, ‘a1234b’).group(1) # ‘1’,非贪婪匹配,截取第一次出现的1个数字;
    

    8. 边界匹配

    1. ^ 匹配字符串开头(多行模式时匹配每一行开头);
    2. $ 匹配字符串末尾(多行模式时匹配每一行末尾);
    3. A 仅匹配字符串开头;
    4.  仅匹配字符串末尾;
    5.  匹配单词字符串(w)边界;
    6. B 相当于[^],非单词字符串边界;

    9. 逻辑运算

    只有“或”逻辑,没有“与”逻辑;
    例1:不使用括号时,| 两边的字符做为整体来匹配,左边和右边出现任意一个即可。

    >>> re.search(r’abc|def’, ‘abc’).group(0) # ‘abc’
    >>> re.search(r’abc|def’, ‘def’).group(0) # ‘def’
    >>> re.search(r’abc|def’, ‘abdef’).group(0) # ‘def’
    

    例2:使用括号时,| 只作用到括号内,括号内左边和右边出现任意一个即可。

    >>> re.search(r’ab(c|d)ef’, ‘abcef’).group(0) # ‘abcef’
    >>> re.search(r’ab(c|d)ef’, ‘abdef’).group(0) # ‘abdef’
    

    10. 分组、命名分组、引用分组

    说明:

    1. (…) :括起来的内容作为普通分组,以数字编号(每遇到一个左括号,编号加1);
      说明1:分组做为一个整体,后面可以接数量词,表示这个分组出现多次;
      说明2:分组中可以使用表达式(|),这个“或”仅在该组中有效;
    2. (?P…) :括起来的内容做为命名分组,作用类似于普通分组。
      区别是这个组还被指定了一个额外的名字;
    3. <number> :引用编号为的分组;
    4. (?P=name) :引用名称为的分组;

    例:

    re.match(r’(d)abc1’, ‘9abc9’).group(1) # 返回9,普通分组,匹配成功。
    

    在正则中使用1向前引用,在match对象中使用group(1)访问;

    re.match(r’(?P<idx>d)abc(?P=idx)’, ‘9abc9’).group(‘idx’) # 返回9, 命名分组,成功。
    

    在正则中使用(?P=idx)向前引用,在match对象中使用group(‘idx’)访问;

    re.match(r’(?P<idx>d)abc1’, ‘9abc9’).group(1) # 同上,1和group(1)仍然可以使用。
    
    re.match(r’(?P<idx>d)abc(?P=idx)’, ‘9abc9’).group(2) # IndexError, no such group。
    

    注意:向前引用(?P=idx) 中有括号,但并不占据分组group(2);

    s1 = re.sub(r'come (w+), go 1', 'g<1>', ‘come dog, go dog’) # 返回dog
    

    11. 特殊构造(构造中的括号不作为分组)

    特殊构造 说明
    (?:…) (…)的不分组/不捕获版本,这个地方的左括号不计入编号;
    可以用于把多个字符做为一个整体使用‘|’或使用数量词,同时不影响其它分组的编号。如:
    re.match(r’(?:abc){2}(d)’, ‘abcabc9’).group(1) # 返回9,abc的括号不占用group(1)。
    (?iLmsux) 用在pattern开头,用于指定匹配模式,可以使用iLmsux中的一个或多个;
    如:re.match(r’(?i)(abc)’, ‘AbC’).group(1) # 返回AbC,pattern开头的(?i)表示忽略大小写;更多匹配模式见第9.2节。
    (?#...) #后的内容做为注释被忽略;如:
    re.match(r’abc(?#ignore)(123)’, ‘abc123’).group(1)
    # 返回123,(?#ignore)被忽略;
    x(?=…) x之后必须有…才能匹配成功,但…不消耗字符串内容。如:re.match(r’a(?=d)(w+)’, ‘a1bc’).group(1) #返回1bc,a(?=d)表示a后面要跟数字,但这个数字并没有在这里被匹配,而是被后面的(w+)匹配,并放到了group(1)中。
    x(?!...) x之后必须没有…才能匹配成功,但…不消耗字符串内容。
    (?<=…)x x之前必须有…才能匹配成功,但…不消耗字符串内容。
    (?<!...)x x之前必须没有…才能匹配成功,但…不消耗字符串内容。
    (?(id/name)yes-patt|no-patt) 如果group(id/name)匹配到字符,则需要匹配yes_pattern,否则需要匹配no_pattern,|no_pattern可以省略。

    12. 在正则表达式的patten中使用变量

    >>> import re
    >>> a = ‘1234’
    >>> b = ‘1234567’
    >>> re.match(f’{a}’, b)
    <_sre.SRE_Mathc object; span=(0, 4), match=’1234’>
    
  • 相关阅读:
    PHP温故知新(一)
    DNS 与 CoreDNS
    如何实现服务端Moc
    nginx用logrotate工具对日志进行分割备份
    postman 关联参数值
    python3.7 allure-commandline-2.13.1.zip 下载地址
    jmeter JDBC Request
    JMeterQuestions english
    python 接口自动化 依赖包源 可以选豆瓣源
    python 3 升级pip不成功 解决方法
  • 原文地址:https://www.cnblogs.com/gaiqingfeng/p/13231561.html
Copyright © 2020-2023  润新知