正则表达式(regular)知识(整理)
正则(regular),要使用正则表达式需要导入Python中的re(regular正则的缩写)模块。正则表达式是对字符串的处理,我们知道,字符串中有时候包含很多我们想要提取的信息,掌握这些处理字符串的方法,能够方便很多我们的操作。
正则表达式(regular),处理字符串的方法。
正则是一种常用的方法,因为python中文件处理很常见,文件里面包含的是字符串,要想处理字符串,那么就需要用到正则表达式。因而要掌握好正则表达式。下面下来看看正则表达式中包含的方法:
(1)match(pattern,string,flags=0)
defmatch(pattern,string,flags=0): """Trytoapplythepatternatthestartofthestring,returning amatchobject,orNoneifnomatchwasfound.""" return_compile(pattern,flags).match(string)
从上面注释:Trytoapplythepatternatthestartofthestring,returningamatchobject,orNoneifnomatchwasfound.从字符串的开头开始查找,返回一个matchobject对象,如果没有找到,返回一个None。
重点:(1)从开头开始查找;(2)如果查找不到返回None。
下面来看看几个实例:
importre string="abcdef" m=re.match("abc",string)(1)匹配"abc",并查看返回的结果是什么 print(m) print(m.group()) n=re.match("abcf",string) print(n)(2)字符串不在列表中查找的情况 l=re.match("bcd",string)(3)字符串在列表中间查找情况 print(l)
运行结果如下:
<_sre.SRE_Matchobject;span=(0,3),match='abc'>(1)abc(2)None(3) None(4)
从上面输出结果(1)可以看出,使用match()匹配,返回的是一个matchobject对象,要想转换为看得到的情况,要使用group()进行转换(2)处所示;如果匹配的正则表达式不在字符串中,则返回None(3);match(pattern,string,flag)是从字符串开始的地方匹配的,并且只能从字符串的开始处进行匹配(4)所示。
(2)fullmatch(pattern,string,flags=0)
deffullmatch(pattern,string,flags=0): """Trytoapplythepatterntoallofthestring,returning amatchobject,orNoneifnomatchwasfound.""" return_compile(pattern,flags).fullmatch(string)
从上面注释:Trytoapplythepatterntoallofthestring,returningamatchobject,orNoneifnomatchwasfound...
(3)search(pattern,string,flags)
defsearch(pattern,string,flags=0): """Scanthroughstringlookingforamatchtothepattern,returning amatchobject,orNoneifnomatchwasfound.""" return_compile(pattern,flags).search(string) search(pattern,string,flags)的注释是Scanthroghstringlookingforamatchtothepattern,returningamatchobject,orNoneifnomatchwasfound.在字符串任意一个位置查找正则表达式,如果找到了则返回matchobject对象,如果查找不到则返回None。
重点:(1)从字符串中间任意一个位置查找,不像match()是从开头开始查找;(2)如果查找不到则返回None;
importre string="ddafsadadfadfafdafdadfasfdafafda" m=re.search("a",string)(1)从中间开始匹配 print(m) print(m.group()) n=re.search("N",string)(2)匹配不到的情况 print(n)
运行结果如下:
<_sre.SRE_Matchobject;span=(2,3),match='a'>(1)a(2)None(3)
从上面结果(1)可以看出,search(pattern,string,flag=0)可以从中间任意一个位置匹配,扩大了使用范围,不像match()只能从开头匹配,并且匹配到了返回的也是一个match_object对象;(2)要想展示一个match_object对象,那么需要使用group()方法;(3)如果查找不到,则返回一个None。
(4)sub(pattern,repl,string,count=0,flags=0)
defsub(pattern,repl,string,count=0,flags=0): """Returnthestringobtainedbyreplacingtheleftmost non-overlappingoccurrencesofthepatterninstringbythe replacementrepl.replcanbeeitherastringoracallable; ifastring,backslashescapesinitareprocessed.Ifitis acallable,it'spassedthematchobjectandmustreturn areplacementstringtobeused.""" return_compile(pattern,flags).sub(repl,string,count) sub(pattern,repl,string,count=0,flags=0)查找替换,就是先查找pattern是否在字符串string中;repl是要把pattern匹配的对象,就要把正则表达式找到的字符替换为什么;count可以指定匹配个数,匹配多少个。示例如下: importre string="ddafsadadfadfafdafdadfasfdafafda" m=re.sub("a","A",string)#不指定替换个数(1) print(m) n=re.sub("a","A",string,2)#指定替换个数(2) print(n) l=re.sub("F","B",string)#匹配不到的情况(3) print(l)
运行结果如下:
ddAfsAdAdfAdfAfdAfdAdfAsfdAfAfdA --(1)
ddAfsAdadfadfafdafdadfasfdafafda --(2)
ddafsadadfadfafdafdadfasfdafafda --(3)
上面代码(1)是没有指定匹配的个数,那么默认是把所有的都匹配了;(2)处指定了匹配的个数,那么只匹配指定个数的;(3)处要匹配的正则pattern不在字符串中,则返回原来的字符串。
重点:(1)可以指定匹配个数,不指定匹配所有;(2)如果匹配不到会返回原来的字符串;
(5)subn(pattern,repl,string,count=0,flags=0)
defsubn(pattern,repl,string,count=0,flags=0): """Returna2-tuplecontaining(new_string,number). new_stringisthestringobtainedbyreplacingtheleftmost non-overlappingoccurrencesofthepatterninthesource stringbythereplacementrepl.numberisthenumberof substitutionsthatweremade.replcanbeeitherastringora callable;ifastring,backslashescapesinitareprocessed. Ifitisacallable,it'spassedthematchobjectandmust returnareplacementstringtobeused.""" return_compile(pattern,flags).subn(repl,string,count)
上面注释Returna2-tuplecontaining(new_string,number):返回一个元组,用于存放正则匹配之后的新的字符串和匹配的个数(new_string,number)。
importre string="ddafsadadfadfafdafdadfasfdafafda" m=re.subn("a","A",string)#全部替换的情况(1) print(m) n=re.subn("a","A",string,3)#替换部分(2) print(n) l=re.subn("F","A",string)#指定替换的字符串不存在(3) print(l)
运行结果如下:
('ddAfsAdAdfAdfAfdAfdAdfAsfdAfAfdA',11) (1)
('ddAfsAdAdfadfafdafdadfasfdafafda',3) (2)
('ddafsadadfadfafdafdadfasfdafafda',0) (3)
从上面代码输出的结果可以看出,sub()和subn(pattern,repl,string,count=0,flags=0)可以看出,两者匹配的效果是一样的,只是返回的结果不同而已,sub()返回的还是一个字符串,而subn()返回的是一个元组,用于存放正则之后新的字符串,和替换的个数。
(6)split(pattern,string,maxsplit=0,flags=0)
defsplit(pattern,string,maxsplit=0,flags=0): """Splitthesourcestringbytheoccurrencesofthepattern, returningalistcontainingtheresultingsubstrings.If capturingparenthesesareusedinpattern,thenthetextofall groupsinthepatternarealsoreturnedaspartoftheresulting list.Ifmaxsplitisnonzero,atmostmaxsplitsplitsoccur, andtheremainderofthestringisreturnedasthefinalelement ofthelist.""" return_compile(pattern,flags).split(string,maxsplit) split(pattern,string,maxsplit=0,flags=0)是字符串的分割,按照某个正则要求pattern分割字符串,返回一个列表returningalistcontainingtheresultingsubstrings.就是按照某种方式分割字符串,并把字符串放在一个列表中。实例如下: importre string="ddafsadadfadfafdafdadfasfdafafda" m=re.split("a",string)#分割字符串(1) print(m) n=re.split("a",string,3)#指定分割次数 print(n) l=re.split("F",string)#分割字符串不存在列表中 print(l)
运行结果如下:
['dd','fs','d','df','df','fd','fd','df','sfd','f','fd',''](1) ['dd','fs','d','dfadfafdafdadfasfdafafda'](2) ['ddafsadadfadfafdafdadfasfdafafda'](3)
从(1)处可以看出,如果字符串开头或者结尾包括要分割的字符串,后面元素会是一个"";(2)处我们可以指定要分割的次数;(3)处如果要分割的字符串不存在列表中,则把原字符串放在列表中。
(7)findall(pattern,string,flags=)
deffindall(pattern,string,flags=0): """Returnalistofallnon-overlappingmatchesinthestring. Ifoneormorecapturinggroupsarepresentinthepattern,return alistofgroups;thiswillbealistoftuplesifthepattern hasmorethanonegroup. Emptymatchesareincludedintheresult.""" return_compile(pattern,flags).findall(string) findall(pattern,string,flags=)是返回一个列表,包含所有匹配的元素。存放在一个列表中。示例如下: importre string="dd12a32d46465fad1648fa1564fda127fd11ad30fa02sfd58afafda" m=re.findall("[a-z]",string)#匹配字母,匹配所有的字母,返回一个列表(1) print(m) n=re.findall("[0-9]",string)#匹配所有的数字,返回一个列表(2) print(n) l=re.findall("[ABC]",string)#匹配不到的情况(3) print(l)
运行结果如下:
['d','d','a','d','f','a','d','f','a','f','d','a','f','d','a','d','f','a','s','f','d','a','f','a','f','d','a'](1) ['1','2','3','2','4','6','4','6','5','1','6','4','8','1','5','6','4','1','2','7','1','1','3','0','0','2','5','8'](2) [](3)
上面代码运行结果(1)处匹配了所有的字符串,单个匹配;(2)处匹配了字符串中的数字,返回到一个列表中;(3)处匹配不存在的情况,返回一个空列表。
重点:(1)匹配不到的时候返回一个空的列表;(2)如果没有指定匹配次数,则只单个匹配。
(8)finditer(pattern,string,flags=0)
deffinditer(pattern,string,flags=0): """Returnaniteratoroverallnon-overlappingmatchesinthe string.Foreachmatch,theiteratorreturnsamatchobject. Emptymatchesareincludedintheresult.""" return_compile(pattern,flags).finditer(string) finditer(pattern,string)查找模式,Returnaniteratoroverallnon-overlappingmatchesinthestring.Foreachmatch,theiteratoramatchobject.
代码如下:
importre string="dd12a32d46465fad1648fa1564fda127fd11ad30fa02sfd58afafda" m=re.finditer("[a-z]",string) print(m) n=re.finditer("AB",string) print(n)
运行结果如下:
(1) (2)
从上面运行结果可以看出,finditer(pattern,string,flags=0)返回的是一个iterator对象。
(9)compile(pattern,flags=0)
defcompile(pattern,flags=0): "Compilearegularexpressionpattern,returningapatternobject." return_compile(pattern,flags)
(10)pruge()
defpurge(): "Cleartheregularexpressioncaches" _cache.clear() _cache_repl.clear()
(11)template(pattern,flags=0)
deftemplate(pattern,flags=0): "Compileatemplatepattern,returningapatternobject" return_compile(pattern,flags|T)
正则表达式:
语法:
importre string="dd12a32d46465fad1648fa1564fda127fd11ad30fa02sfd58afafda" p=re.compile("[a-z]+")#先使用compile(pattern)进行编译 m=p.match(string)#然后进行匹配 print(m.group())
上面的第2和第3行也可以合并成一行来写:
m=p.match("^[0-9]",'14534Abc')
效果是一样的,区别在于,第一种方式是提前对要匹配的格式进行了编译(对匹配公式进行解析),这样再去匹配的时候就不用在编译匹配的格式,第2种简写是每次匹配的时候都要进行一次匹配公式的编译,所以,如果你需要从一个5w行的文件中匹配出所有以数字开头的行,建议先把正则公式进行编译再匹配,这样速度会快点。
匹配的格式:
(1)^ 匹配字符串的开头
importre string="dd12a32d41648f27fd11a0sfdda" #^匹配字符串的开头,现在我们使用search()来匹配以数字开始的 m=re.search("^[0-9]",string)#匹配字符串开头以数字开始(1) print(m) n=re.search("^[a-z]+",string)#匹配字符串开头以字母开始,如果是从开头匹配,就与search()没有太多的区别了(2) print(n.group())
运行结果如下:
None
dd
在上面(1)处我们使用^从字符串开头开始匹配,匹配开始是否是数字,由于字符串前面是字母,不是数字,所以匹配失败,返回None;(2)处我们以字母开始匹配,由于开头是字母,匹配正确,返回正确的结果;这样看,其实^类似于match()从开头开始匹配。
(2)$ 匹配字符串的末尾
importre string="15111252598" #^匹配字符串的开头,现在我们使用search()来匹配以数字开始的 m=re.match("^[0-9]{11}$",string) print(m.group())
运行结果如下:
15111252598
re.match("^[0-9]{11}$",string)含义是匹配以数字开头,长度为11,结尾为数字的格式;
(3)点(·) 匹配任意字符,除了换行符。当re.DoTALL标记被指定时,则可以匹配包括换行符的任意字符
importre string="1511\n1252598" #点(·)是匹配除了换行符以外所有的字符 m=re.match(".",string)#点(·)是匹配任意字符,没有指定个数就匹配单个(1) print(m.group()) n=re.match(".+",string)#.+是匹配多个任意字符,除了换行符(2) print(n.group())
运行结果如下:
1
1511
从上面代码运行结果可以看出,(1)处点(·)是匹配任意字符;(2)处我们匹配任意多个字符,但是由于字符串中间包含了空格,结果就只匹配了字符串中换行符前面的内容,后面的内容没有匹配。
重点:(1)点(·)匹配除了换行符之外任意字符;(2).+可以匹配多个任意除了换行符的字符。
(4)[...] 如[abc]匹配"a","b"或"c"
[object]匹配括号中的包含的字符。[A-Za-z0-9]表示匹配A-Z或a-z或0-9。
importre string="1511\n125dadfadf2598" #[]匹配包含括号中的字符 m=re.findall("[5fd]",string)#匹配字符串中的5,f,d print(m)
运行结果如下:
['5','5','d','d','f','d','f','5']
上面代码,我们是要匹配字符串中的5,f,d并返回一个列表。
(5)[^...] [^abc]匹配除了abc之外的任意字符
importre string="1511\n125dadfadf2598" #[^]匹配包含括号中的字符 m=re.findall("[^5fd]",string)#匹配字符串除5,f,d之外的字符 print(m)
运行如下:
['1','1','1','\n','1','2','a','a','2','9','8']
上面代码,我们匹配除了5,f,d之外的字符,[^]是匹配非中括号内字符之外的字符。
(6)* 匹配0个或多个的表达式
importre string="1511\n125dadfadf2598" #*是匹配0个或多个的表达式 m=re.findall("\d*",string)#匹配0个或多个数字 print(m)
运行结果如下:
['1511','','125','','','','','','','','2598','']
从上面运行结果可以看出(*)是匹配0个或多个字符的表达式,我们匹配的是0个或多个数字,可以看出,如果匹配不到返回的是空,并且最后位置哪里返回的是一个空("")。
(7)+ 匹配1个或多个的表达式
importre string="1511\n125dadfadf2598" #(+)是匹配1个或多个的表达式 m=re.findall("\d+",string)#匹配1个或多个数字 print(m)
运行如下:
['1511','125','2598']
加(+)是匹配1个或多个表达式,上面\d+是匹配1个或多个数字表达式,至少匹配一个数字。
(8)? 匹配0个或1个的表达式,非贪婪方式
importre string="1511\n125dadfadf2598" #(?)是匹配0个或1个的表达式 m=re.findall("\d?",string)#匹配0个或1个的表达式 print(m)
运行结果如下:
['1','5','1','1','','1','2','5','','','','','','','','2','5','9','8','']
上面问号(?)是匹配0个或1个表达式,上面是匹配0个或1个的表达式,如果匹配不到则返回空("")
(9){n} 匹配n次,定义一个字符串匹配的次数
(10){n,m} 匹配n到m次表达式
(11)\w 匹配字母数字
\w是匹配字符串中的字母和数字,代码如下:
importre string="1511\n125dadfadf2598" #(?)是匹配0个或1个的表达式 m=re.findall("\w",string)#匹配0个或1个的表达式 print(m)
运行如下:
['1','5','1','1','1','2','5','d','a','d','f','a','d','f','2','5','9','8']
从上面代码可以看出,\w是用来匹配字符串中的字母数字的。我们使用正则匹配字母和数字。
(12)\W \W大写的W是用来匹配非字母和数字的,与小写w正好相反
实例如下:
importre string="1511\n125dadfadf2598" #\W用来匹配字符串中的非字母和数字 m=re.findall("\W",string)#\W用来匹配字符串中的非字母和数字 print(m)
运行如下:
['\n']
上面代码中,\W是用来匹配非字母和数字的,结果把换行符匹配出来了。
(13)\s 匹配任意空白字符,等价于[\n\t\f]
实例如下:
importre string="1511\n125d\ta\rdf\fadf2598" #\s是用来匹配字符串中的任意空白字符,等价于[\n\t\r\f] m=re.findall("\s",string)#\s用来匹配字符串中任意空白字符 print(m)
运行如下:
['\n','\t','\r','\x0c']
从上面代码运行结果可以看出:\s是用来匹配任意空的字符,我们把空的字符匹配出来了
(14)\S 匹配任意非空字符
实例如下:
importre string="1511\n125d\ta\rdf\fadf2598" #\S是用来匹配任意非空字符 m=re.findall("\S",string)#\S用来匹配日任意非空字符 print(m)
运行如下:
['1','5','1','1','1','2','5','d','a','d','f','a','d','f','2','5','9','8']
从上面代码可以看出,\S是用来匹配任意非空字符,结果中,我们匹配了任意非空的字符。
(15)\d 匹配任意数字,等价于[0-9]
(16)\D 匹配任意非数字
总结:findall(),split()生成的都是列表,一个是以某个为分隔符,一个是以查找中所有的值。正好相反。