当前位置: 首页 > 科技观察

Python正则表达式re模块简明笔记

时间:2023-03-20 01:33:11 科技观察

简介正则表达式(regularexpressions)是可以匹配文本片段的模式。最简单的正则表达式是一个匹配自身的普通字符串。例如,正则表达式“hello”匹配字符串“hello”。需要注意的是,正则表达式不是程序,而是一种处理字符串的模式。如果要用它来处理字符串,就必须使用支持正则表达式的工具,比如Linux中的awk、sed、grep,或者编程语言Perl、Python、Java等,正则表达式有很多种不同风格.下表列出了一些针对Python或Perl等编程语言的元字符和说明:re模块在Python中,我们可以通过内置的re模块来使用正则表达式。需要注意的一件事是正则表达式使用\来转义特殊字符。例如,为了匹配字符串'python.org',我们需要使用正则表达式'python\.org',而Python字符串本身也是用\转义的,所以上面的正则表达式应该写成'python\\.org'在Python中,很容易陷入\的麻烦,所以我们推荐使用Python的rawstring,只需要加一个r前缀,上面的正则表达式可以写成:r'python\.org'的re模块提供了很多有用的函数来匹配字符串,例如:compile函数match函数search函数findall函数finditer函数split函数sub函数subn函数re模块的一般使用步骤如下:使用compile函数编译字符串形式将正则表达式转化为一个Pattern对象使用Pattern对象提供的一系列方法对文本进行匹配搜索得到匹配结果(一个Match对象)***使用Match对象提供的属性和方法获取信息,并执行根据需要进行操作。compile函数compile函数用于编译一个正则表达式并生成一个Pattern对象。它的一般用法如下:re.compile(pattern[,flag])其中,pattern是一个字符串形式的正则表达式,flag是一个可选参数,表示匹配方式,比如忽略大小写,multi-行模式等。下面我们来看一个例子。importre#将一个正则表达式编译成一个Pattern对象pattern=re.compile(r'\d+')上面我们已经将一个正则表达式编译成一个Pattern对象,接下来我们就可以使用pattern的一系列方法了正文是搜索匹配项。Pattern对象的一些常用方法有:match方法search方法findall方法finditer方法split方法sub方法subn方法match方法match方法用于查找字符串的头部(也可以指定起始位置),它是一个匹配,只要找到就只返回一个匹配项,而不是查找所有匹配项。它的一般使用形式如下:match(string[,pos[,endpos]])其中string为要匹配的字符串,pos和endpos为可选参数,指定字符串的开始和结束位置,默认值分别是0和len(字符串长度)。因此,当不指定pos和endpos时,match方法默认匹配字符串的头部。匹配时返回Match对象,如果不匹配则返回None。看看例子。>>>importre>>>pattern=re.compile(r'\d+')#用于匹配至少一个数字>>>m=pattern.match('one12twothree34four')#寻找头部,没有匹配>>>printmNone>>>m=pattern.match('one12twothree34four',2,10)#从'e'的位置开始匹配,不匹配>>>printmNone>>>m=pattern.match('one12twothree34four',3,10)#从位置'1'开始匹配,只匹配>>>printm#返回一个Match对象<_sre.SRE_Matchobjectat0x10a42aac0>>>>m.group(0)#0'12'>可以省略>>m.start(0)#03可以省略>>>m.end(0)#05可以省略>>>m.span(0)#0(3,5)可以省略上面省略,当匹配成功时返回一个Match对象,其中:group([group1,…])方法用于获取一个或多个组匹配字符串,当想获取整个匹配子串时,可以直接使用group()或组(0);start([group])方法用于获取group匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为0;end([group])方法用于获取group匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引+1),参数默认值为0;span([group])方法返回(start(group),end(group))。再看一个例子:>>>importre>>>pattern=re.compile(r'([a-z]+)([a-z]+)',re.I)#re.I表示忽略大小写>>>m=pattern.match('HelloWorldWideWeb')>>>printm#如果匹配成功,返回一个Match对象<_sre.SRE_Matchobjectat0x10bea83e8>>>m.group(0)#返回整个匹配成功的组Substring'HelloWorld'>>>m.span(0)#返回匹配成功的整个子串的索引(0,11)>>>m.group(1)#返回第一个匹配成功的组匹配子串String'Hello'>>>m.span(1)#返回匹配第一组成功的子串的索引(0,5)>>>m.group(2)#返回匹配成功的子串第二组Substring'World'>>>m.span(2)#返回匹配第二组(6,11)的子串>>>m.groups()#等价于(m.group(1),m.group(2),...)('Hello','World')>>>m.group(3)#没有第三组Traceback(mostrecentcalllast):File"",line1、在IndexError:nosuchgroupsearchmethodsearch方法用于查找字符串的任意位置,也是匹配,只要找到匹配的结果就会返回,而不是查找所有匹配的结果,它的一般使用形式如下:search(string[,pos[,endpos]])其中string为要匹配的字符串,pos和endpos为可选参数,指定字符串的开始和结束位置,默认值是0和len(字符串长度)。匹配时返回Match对象,如果不匹配则返回None。看个例子:>>>importre>>>pattern=re.compile('\d+')>>>m=pattern.search('one12twothree34four')#这里如果使用match方法,会匹配不上>>>m<_sre.SRE_Matchobjectat0x10cc03ac0>>>>m.group()'12'>>>m=pattern.search('one12twothree34four',10,30)#指定字符串区间>>>m<_sre.SRE_Matchobjectat0x10cc03b28>>>>m.group()'34'>>>m.span()(13,15)再看一个例子:#-*-coding:utf-8-*-importre#将正则表达式编译成一个Pattern对象pattern=re.compile(r'\d+')#使用search()寻找匹配的子串,如果没有匹配的子串则返回None#这里match()不能匹配成功m=pattern.search('hello123456789')ifm:#使用Match获取组信息print'matchingstring:',m.group()print'position:',m.span()执行结果:matchingstring:123456position:(6,12)findall方法上面的match和search方法都是匹配,只要找到匹配结果,它会回来的。然而,大多数时候,我们需要搜索整个字符串以获得所有匹配结果。findall方法的使用形式如下:findall(string[,pos[,endpos]])其中,string为要匹配的字符串,pos和endpos为可选参数,指定字符串的起止位置,默认值分别是0和len(字符串长度)。findall将所有匹配的子字符串作为列表返回,如果没有匹配则返回空列表。看例子:importrepattern=re.compile(r'\d+')#Findnumbersresult1=pattern.findall('hello123456789')result2=pattern.findall('one1two2three3four4',0,10)printresult1printresult2executeResult:['123456','789']['1','2']finditer方法finditer方法的行为类似于findall。它还搜索整个字符串并获得所有匹配结果。但它返回一个迭代器,该迭代器按顺序访问每个匹配结果(Match对象)。看例子:#-*-coding:utf-8-*-importrepattern=re.compile(r'\d+')result_iter1=pattern.finditer('hello123456789')result_iter2=pattern.finditer('one1two2three3four4',0,10)printtype(result_iter1)printtype(result_iter2)print'result1...'form1inresult_iter1:#m1是一个Match对象print'matchingstring:{},position:{}'.format(m1.group(),m1.span())print'result2...'form2inresult_iter2:print'matchingstring:{},position:{}'.format(m2.group(),m2.span())执行结果:result1...匹配字符串:123456,位置:(6,12)匹配字符串:789,位置:(13,16)result2...matchingstring:1,position:(3,4)matchingstring:2,position:(7,8)split方法split方法根据可以匹配的子串对字符串进行拆分,返回一个列表。其用法如下:split(string[,maxsplit])其中,maxsplit用于指定最大拆分次数,不指定则全部拆分。看例子:importrep=re.compile(r'[\s\,\;]+')printp.split('a,b;;cd')执行结果:['a','b','c','d']sub方法sub方法用于替换。它的使用形式如下:sub(repl,string[,count])其中repl可以是一个字符串或者一个函数:如果repl是一个字符串,repl将被用来替换字符串的每一个匹配的子串,并返回被替换的细绳。另外,repl也可以用\id的形式来引用组,但是不能用数字0;如果repl是一个函数,这个方法应该只接受一个参数(Match对象)并返回一个字符串用于替换(返回的字符串中不能再引用组)。count用于指定最大替换次数,不指定则全部替换。看例子:importrep=re.compile(r'(\w+)(\w+)')s='hello123,hello456'deffunc(m):return'hi'+''+m.group(2)printp.sub(r'helloworld',s)#将'hello123'和'hello456'替换为'helloworld'printp.sub(r'\2\1',s)#referencegroupprintp.sub(func,s)printp.sub(func,s,1)#最多替换一个执行结果:helloworld,helloworld123hello,456hellohi123,hi456hi123,hello456subnmethodsubnmethod和sub方法的行为类似,也用于替换。它以下面的形式使用:subn(repl,string[,count])返回一个元组:(sub(repl,string[,count]),替换次数)该元组有两个元素,第一个元素是Usingsub方法的结果,第二个元素返回原始字符串被替换的次数。看例子:importrep=re.compile(r'(\w+)(\w+)')s='hello123,hello456'deffunc(m):return'hi'+''+m.group(2)printp.subn(r'helloworld',s)printp.subn(r'\2\1',s)printp.subn(func,s)printp.subn(func,s,1)执行结果:('helloworld,helloworld',2)('123hello,456hello',2)('hi123,hi456',2)('hi123,hello456',1)otherfunctionfacts以上,compile函数生成的Pattern对象的一系列方法对应re模块的大部分函数,??只是在用法上有细微差别。match函数match函数的使用形式如下:re.match(pattern,string[,flags]):其中,pattern为正则表达式的字符串形式,如\d+,[a-z]+。而Pattern对象的match方法的使用形式为:match(string[,pos[,endpos]])可以看到,match函数不能指定字符串的区间,只能搜索头部,见示例:importrem1=re.match(r'\d+','One12twothree34four')ifm1:print'matchingstring:',m1.group()else:print'm1is:',m1m2=re.match(r'\d+','12twothree34four')ifm2:print'matchingstring:',m2.group()else:print'm2is:',m2执行结果:m1is:Nonematchingstring:12search函数的用法搜索函数如下:re.search(pattern,string[,flags])搜索函数不能指定字符串的搜索范围,其用法类似于Pattern对象的搜索方法。findall函数findall函数的使用形式如下:re.findall(pattern,string[,flags])findall函数不能指定字符串的搜索范围,其用法类似于Pattern对象的findall方法.看例子:importreprintre.findall(r'\d+','hello12345789')#output['12345','789']finditer函数finditer函数的使用类似于Pattern的finditer方法,形式如下:re.finditer(pattern,string[,flags])splitfunctionsplit函数的使用形式如下:re.split(pattern,string[,maxsplit])subfunctionsubfunction的使用形式如下:re.sub(pattern,repl,string[,count])subn函数subn函数的使用形式如下:re.subn(pattern,repl,string[,count])使用哪种方式?从上面可以看出,re模块的使用有两种方式:使用re.compile函数生成一个Pattern对象,然后使用Pattern对象的一系列方法进行文本匹配和查找;直接使用re.match、re.search、re.findall等函数直接匹配搜索文本;下面,我们用一个例子来展示这两种方法。先看第一个用法:importre#将正则表达式编译成Pattern对象pattern=re.compile(r'\d+')printpattern.match('123,123')printpattern.search('234,234')printpattern.findall('345,345')看第二种用法:importreprintre.match(r'\d+','123,123')printre.search(r'\d+','234,234')printre.findall(r'\d+','345,345')如果一个正则表达式需要多次使用(比如上面的\d+),往往会在很多场合使用,对于为了效率,我们应该预先编译正则表达式生成一个Pattern对象,然后使用该对象的一系列方法来匹配要匹配的文件;如果我们直接使用re.match、re.search等函数,每传入一个正则表达式,都会编译一次,效率会大大降低。因此,我们推荐用法1.匹配中文在某些情况下,我们希望匹配文本中的汉字。需要注意的一点是中文的unicode编码范围主要在[\u4e00-\u9fa5]。这主要是因为这个范围不完整,比如不包括全角(中文)标点符号,但在大多数情况下应该足够了。假设现在你想从字符串中提取中文title=u'Hello,hello,world',你可以这样做:#-*-coding:utf-8-*-importretitle=u'Hello,hello,world'pattern=re.compile(ur'[\u4e00-\u9fa5]+')result=pattern.findall(title)printresult注意我们在正则表达式前面加了两个前缀ur,其中r表示使用原字符串,u表示它是一个unicode字符串。执行结果:[u'\u4f60\u597d',u'\u4e16\u754c']贪心匹配在Python中,正则匹配默认为贪心匹配(少数语言可能是非贪心的),即匹配尽可能多的字符可能的。例如,我们要查找字符串中所有的div块:importrecontent='aa

test1
bb
test2
cc'pattern=re.compile(r'
.*
')result=pattern.findall(content)printresult执行结果:['
test1
bb
test2
']因为正则匹配是贪心匹配,即尽可能多的匹配,所以当它成功匹配到第一个
时,它也会尝试向右匹配,看看是否有更长的子串可以匹配成功。如果我们要非贪婪匹配,可以加一个?,如下:importrecontent='aa
test1
bb
test2
cc'pattern=re.compile(r'
.*?
')#添加?result=pattern.findall(content)打印结果Result:['
test1
','
test2
']Summaryre模块的一般使用步骤如下:使用compile函数将正则表达式的字符串形式编译成Pattern对象;使用Pattern对象提供的一系列方法对文本进行匹配查找,得到匹配结果(一个Match对象);***使用Match对象提供的属性和方法可以获取信息,可以根据需要进行其他操作;Python的正则匹配默认是贪心匹配。