python正则表达式要点概述

       正则表达式在文本字符串处理上功能强大,python的re模块是一个标准模块,其实现了正则表达式的所有功能,而且其匹配引擎是用C语言编写的,所以在性能上也是很高的,本文将对python的正则表达式的较为常用的要点进行一些总结。

目录

一、语法

捕获组(...)

非捕获组(?:..)

反斜杠\

对捕获组的引用\number

贪心算法和非贪心算法

二、matchObject

三、Regular Expression Object

四、re模块常用函数

match(pattern,string,flags=0)

search(pattern,string,flags=0)

findall(pattern,string,flags=0)

fullmatch(pattern,string,flags=0)

split(pattern,string,maxsplit=0,flags=0)

finditer(pattern,string,flags=0)


一、语法

捕获组(...)

       基本的匹配语法本文不再赘述,网上以及官方文档都有详细的说明。本文先对group语法做一下说明。(...)标志表示一个捕获组,括号中的...表示正则表达式,捕获组语法一般和matchObject对象结合使用,使用该对象的group函数,可以指定捕获组返回该组匹配到的括号内的内容;但是对于findall函数来说,直接返回捕获组内匹配到的内容列表,如果有多个捕获组,则返回元组列表。

       如果我们想给一个捕获组命名,可以通过这样的方式:(?P<name>...),其中name表示我们想赋予的名称,...表示正则表达式。

import re

s='ababcdaabc'
l1=re.findall('(ab)c',s)
print(l1)
# ['ab','ab']

l2=re.dindall('((ab)c)',s)
print(l2)
# [('abc','ab'),('abc','ab')]

非捕获组(?:..)

       正则表达式中和括号相关的语法还有其他,比如(?:...)语法,其中...表示正则表达式。该语法是一种非捕获组语法,当我们相对一个正则表达式整体进行操作但又不想把这个整体当作一个捕获组捕获时,可以使用该语法。比如我想匹配axax这种类型的子字符串,那么只需要利用((?:a.){2})这个正则表达式去匹配即可,其中{2}表示对a.这个正则表达式整体重复两次,但是其返回的并不是括号(?:...)中的匹配到的内容。捕获组语法也可以实现对整个正则表达式进行打包操作,但是和非捕获组的区别在于,其是会被捕获返回的。

l3=re.findall('((?:a.){2})',s)
print(l3)
# ['abab']

反斜杠\

       首先,在python本身的字符串语法中,反斜杠\就有转义符的意义,而在正则表达式中,\又具有独特的含义,此外,在正则表达式中,\也有针对正则表达式的转义作用,即如果要在正则表达式中表示原生的\。需要用\\来表示。于是,如果用python字符串来表示正则表达式中的\,需要消除两层转义:python字符串本身的转义,正则表达式的转义。于是,在python的正则表达式中,如果用字符串表示\,需要这样表示:\\\\。因此,为了消除python本身字符串的所有转义,可以用r表示的原生字符串来表示正则表达式,这样就只剩下正则表达式本身的转义了,即如果用原生字符串来表示正则表达式中的\,那么只需要表示为:r'\\'。所以,建议在用正则表达式匹配时,利用原生字符串来写正则表达式,以消除python字符串本身的转义,从而只专注在正则表达式本身。

对捕获组的引用\number

       对于\,需要特别注意的一个语法是:\number,其中number是一个整数,表示对匹配到的group的引用,整数表示group的序号。这里强调是匹配到的group,而不是捕获组中的正则表达式,由于是对匹配到的内容的引用,那么我们后续对这个引用进行操作,就是直接操作匹配到的内容,而不是正则表达式本身,两者的区别可看如下例子。

s='ababcdaaaaabc'
l4=re.findall(r'((\w)\2+)',s)
print(l4)
# [('aaaaa','a')]

l5=re.findall(r'((\w)+)',s)
print(l5)
# [('ababcdaaaaabc','c')]

l6=re.findall(r'((b.)+)',s}
print(l6)
# [('babc','bc'),('bc','bc)]

       可以看到,上面例子中,对捕获组匹配到的内容的引用进行+操作,匹配到的是重复的内容aaaaa,而直接对正则表达式本身进行+操作,比如(\w)+,就当相当于(\w)(\w)...,这样就会匹配到整个字符串。这里还需要注意的是,当对捕获组进行操作的时候,比如+操作,那么最终返回的是最后一个匹配到的捕获组的内容,比如l5返回的第二个捕获组的内容就是c,为最后一个字符,l6返回的第二个捕获组的内容为bc,也是最后一个匹配到的捕获组内容。

贪心算法和非贪心算法

       对于贪心算法和非贪心算法,可点击查看笔者专门写的另一篇文章

二、matchObject

       matchObject是re模块中的匹配对象,search函数和match函数都会返回这个对象。该对象比较常用的函数为group([group1...])和groups(),前者默认返回匹配到的完整的字符串,如果设定了参数指定特定的group,则返回指定的group匹配到的子字符串;后者返回所有的group匹配到的子字符串。如果正则表达式中给捕获组设定了名称(通过(?P<name>...)给捕获组设定名称),还可以用groupdict函数返回字典,不然会返回空字典。此外还有比较常用的span(group)方法,其返回指定group匹配到的子字符串在原字符串中的起始和结束的位置,默认group为0,返回完整的匹配位置,如果没有匹配到,则返回(-1,-1)。

       如果我们想知道这个matchObject是匹配哪个字符串,则可以利用其string属性来获取。

三、Regular Expression Object

       正则表达式对象是由re.compile(regex,flags=0)返回的对象,regex表示正则表达式,flag表示re模块的flags,如果有多个flag,可以用+进行连接。为什么要对正则表达式进行编译?这是因为,正则表达式在匹配时,需要先将正则表达式字符串编译成正则表达式对象,然后再进行匹配,并且这个编译过程是相对消耗时间的,所以如果我们要对一个正则表达式进行对此利用匹配,那么我们就应该先将其编译,然后再用编译后的正则表达式对象进行匹配,而不是每次匹配都要进行编译,从而可以节省编译的时间。

       正则表达式对象拥有所有匹配函数,比如findall,match,search等,只是参数略有不同,不再需要正则表达式字符串。此外,还可以通过对象的pattern属性获取相应的正则表达式字符串。

四、re模块常用函数

match(pattern,string,flags=0)

       从头开始匹配,如果string头部可以匹配上对于的pattern,则返回一个matchObject,不然返回None。故可以通过返回对象的布尔值判断是否匹配上。

search(pattern,string,flags=0)

       不同于match,不再局限于头部匹配,如果头部没有匹配上,会从左到右搜索整个string,直到匹配上pattern为止,匹配上,则说明string中含有符合pattern的子串,返回一个matchObject,不然返回None。

findall(pattern,string,flags=0)

       该函数返回一个非重叠的匹配到的子字符串列表,没有匹配上返回空列表。非重叠的意思是不会对string进行重复匹配,只要匹配过的位置,便不会再进行匹配,看如下示例。返回的结果只有一个'aa'组成的列表,而不是两个'aa',这是因为对于字符串'aaa',最开始的两个'aa'被匹配后,不会再进行匹配,所以最后再剩下一个'a'不会被匹配上,所以只返回一个'aa'。

s='aaa'
l=re.findall('aa',s)
print(l)
# ['aa']

fullmatch(pattern,string,flags=0)

       只有string完整的符合pattern,即整个string全部匹配上,才会返回matchObject,不然返回None。

split(pattern,string,maxsplit=0,flags=0)

       返回一个由pattern匹配上的字符串作为分隔符的子字符串列表,其中maxsplit可以指定最大分隔次数,默认为0表示全部分隔。

finditer(pattern,string,flags=0)

      同findall,但是返回的不再是一个列表,而是一个迭代器,这在string较大时,返回的列表较大时比较有用,可以有效的节省内存占用。

s='ab123cdbf12'
rep=re.sub(r'(b)(\d+)',lambda x:x.group(1)+'<num>',s)
print(rep)
# 'ab<num>cdbf12'

       上例中,我们只想替换s中字符b后面的数字,用<num>替换,那么匹配时的pattern里面必须以b为首,但是又不想把b给替换掉,所以不能直接用字符串<num>,而应该用函数,返回的字符串中应该保留b。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值