Python正则表达式re模块
re模块(* * * * *)
就其本质而言,正则表达式(或 RE)是一种小型的、高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。
正则 就是对字符串进行模糊匹配
字符匹配(普通字符,元字符):
1、普通字符:大多数字符和字母都会和自身匹配
>>> re.findall('alvin','yuanaleSxalexwupeiqi')
['alvin']
2、元字符: . ^ $ * + ? { } [ ] | ( ) \的详细解释:
^
匹配行首,以 xxx为开头
$
匹配行尾,以xxx结尾。
\
转义字符,如果要匹配\本身,需要使用再次转义:\\。
一些特殊字符:
\d:匹配:[0-9]
\D:匹配:[^0-9]
\s:匹配:任何空白符,即:[\t\n\r\f\v]
\S:匹配:任何非空白符,即:[^\t\n\r\f\v]
\w:匹配:[a-zA-Z0-9_ ]
\W:匹配:[^a-zA-Z0-9_ ]
*
匹配前一个字符或子表达式出现 0次或多次。
+
匹配前一个字符或子表达式出现 1次或多次。
?
(1) 匹配前一个字符或子表达式出现 0次或1次。
(2) 跟在 * 或 + 后面表示非贪婪匹配:
*? 匹配0个
+? 匹配1个
importre#贪婪模式,会尽量多地去匹配
r1 = re.compile(r'ab+')
s1= 'abbb'
print(re.findall(r1,s1)) #['abbb']
#非贪婪模式,会尽量少地去匹配
r2 = re.compile(r'ab+?')
s2= 'abbb'
print(re.findall(r2,s2)) #['ab']
{}
匹配前一个字符或子表达式出现指定次数:
{0,}:0次或多次,相当于 *
{1,}:1次或多次,相当于 +
{0,1}:0次或1次,相当于 ?
{m,n}:m次到n次(m <= n)
importre
ret=re.findall('a..in','helloalvin')print(ret)#['alvin']
ret=re.findall('^a...n','alvinhelloawwwn')print(ret)#['alvin']
ret=re.findall('a...n$','alvinhelloawwwn')print(ret)#['awwwn']
ret=re.findall('a...n$','alvinhelloawwwn')print(ret)#['awwwn']
ret=re.findall('abc*','abcccc')#贪婪匹配[0,+oo]
print(ret)#['abcccc']
ret=re.findall('abc+','abccc')#[1,+oo]
print(ret)#['abccc']
ret=re.findall('abc?','abccc')#[0,1]
print(ret)#['abc']
ret=re.findall('abc{1,4}','abccc')print(ret)#['abccc'] 贪婪匹配
注意:前面的 *,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配(非贪婪匹配)
ret=re.findall('abc*?','abcccccc')print(ret)#['ab']
跟着教程敲代码练习:
"""第一类元字符 . ^ $ * + ? {}"""
importre""". 匹配除了 \n 之外的任意字符,一个 . 只能匹配一个字符"""re.findall("alex","djkalfjioealexieou") ##['alex']
re.findall("a..x",'jowutojoauixuoero') #['auix']
re.findall("a...x",'jowutojoauixuoero') #[]
"""^ 开头匹配"""re.findall("^a...x",'jowutojoauixuoero') #[]
re.findall("^j..u",'jowutojowuixuoero') #['jowu']
re.findall("j..u",'jowutojowuixuoero') #['jowu', 'jowu']
"""$ 结尾匹配"""re.findall("j..u$",'jowutojowuixuoejrou') #['jrou']
re.findall("j..u$",'jowutojowuixuoejrou$') #[]
"""* 紧挨着的字符 匹配0~无穷次"""
"""+ 紧挨着的字符 匹配1~无穷次"""re.findall("alex*","uoghkalexxx") #['alexxx']
re.findall("alex+","uoghkalexxx") #['alexxx']
re.findall("alex*","uoghkale") #['ale']
re.findall("alex+","uoghkale") #[]
"""? 紧挨着的字符 匹配0~1"""re.findall("alex?","uoghkale") #['ale']
re.findall("alex?","uoghkalex") #['alex']
re.findall("alex?","uoghkalexxxx") #['alex']
"""{} 是上面 * + ? 的集合,并且可自定义
{0,} <===> *
{1,} <===> +
{0,1} <===> ?
{1,6} 1 2 3 4 5 6 都可以"""re.findall("alex{6}","uoghkalexxxxxx") #['alexxxxxx']
re.findall("alex{0,6}","uoghkalexxx") #['alexxx']
re.findall("alex{0,6}","uoghkale") #['ale']
re.findall("alex{0,1}","uoghkale") #['ale']
re.findall("alex{0,1}","uoghkalex") #['alex']
#惰性匹配 在元字符后面加上 ?
re.findall("alex*?","uoghkalexxxx") #['ale']
re.findall("alex+?","uoghkalexxxx") #['alex']
re.findall("alex+","uoghkalexxxx") #['alexxxx']
我的理解
元字符之字符集[]:
(1) 常用来指定一个字符集,如[abc]匹配:a或b或c
(2) 元字符. * ? + ^ $ 在[]中不起所用,比如:[a+]匹配:a或+
但注意:在方括号中:要匹配转义符“\”本身,要用:\\;要匹配方括号开头的^符本身,要用:\^;要匹配-字符,需要用:\-
(3) 补集匹配:[^a],匹配非a的一个字符,^在[ ]中表示取非
(4) 匹配连续字符:[a-zA-Z0-9],匹配大小写英文字母和数字
#--------------------------------------------字符集[]
ret=re.findall('a[bc]d','acd')print(ret)#['acd']
ret=re.findall('[a-z]','acd')print(ret)#['a', 'c', 'd']
ret=re.findall('[.*+]','a.cd+')print(ret)#['.', '+']
#在字符集里有功能的符号: - ^ \
ret=re.findall('[1-9]','45dha3')print(ret)#['4', '5', '3']
ret=re.findall('[^ab]','45bdha3')print(ret)#['4', '5', 'd', 'h', '3']
ret=re.findall('[\d]','45bdha3')print(ret)#['4', '5', '3']
跟着教程敲代码练习:
"""[] 中:^ 非 ,- 表示从。。到。。 a-z 所有小写字母,\ 转义 \( 就表示左括号。
其他的元字符失去意义,如 * 不表示(0-无穷),()就只是表示括号"""ret= re.findall('a[bc]d', 'acd') #匹配 abd 或 acd
print(ret) #['acd']
ret= re.findall('[a-z]', 'acd') #一个字符 从a到z
print(ret) #['a', 'c', 'd']
ret= re.findall('[.*+]', 'a.cd+') #* 失去特殊意义 就表示一个 *
print(ret) #['.', '+']
#在字符集里有功能的符号: - ^ \
ret= re.findall('[1-9]', '45dha3')print(ret) #['4', '5', '3']
ret= re.findall('[^ab]', '45bdha3')print(ret) #['4', '5', 'd', 'h', '3']
ret= re.findall('[\d]', '45bdha3')print(ret) #['4', '5', '3']
我的理解
#一个特殊案例:匹配表达式里面 最内层括号(13-6)
re.findall("\([^()]*\)","12+(34*6+2-5*(13-6))") #['(13-6)']
元字符之转义符 \
反斜杠后边跟元字符去除特殊功能,比如 \.
反斜杠后边跟普通字符实现特殊功能,比如 \d
\d 匹配任何十进制数;它相当于类 [0-9]。
\D 匹配任何非数字字符;它相当于类 [^0-9]。
\s 匹配任何空白字符;它相当于类 [ \t\n\r\f\v]。
\S 匹配任何非空白字符;它相当于类 [^ \t\n\r\f\v]。
\w 匹配任何字母数字字符;它相当于类 [a-zA-Z0-9_]。
\W 匹配任何非字母数字字符;它相当于类 [^a-zA-Z0-9_]
\b 匹配一个特殊字符边界,比如空格 ,&,#等
ret=re.findall('I\b','I am LIST')print(ret)#[]
ret=re.findall(r'I\b','I am LIST')print(ret)#['I']
r'I\b' 其中 r=raw 表示原始的 未经处理的
re.findall(r'I\b','I am LIST') #r'I\b' 要先经过Python解释器编译 然后传递给re模块,re模块处理 \b 匹配到 空格
现在我们聊一聊 \ ,先看下面两个匹配:
#-----------------------------eg1:
importre
ret=re.findall('c\l','abc\le')print(ret)#[]
ret=re.findall('c\\l','abc\le')print(ret)#[]
ret=re.findall('c\\\\l','abc\le')print(ret)#['c\\l']
ret=re.findall(r'c\\l','abc\le')print(ret)#['c\\l']
#-----------------------------eg2:#之所以选择\b是因为\b在ASCII表中是有意义的
m = re.findall('\bblow', 'blow')print(m)
m= re.findall(r'\bblow', 'blow')print(m)
由于Python的字符串本身也用 \转义,所以要特别注意:
s = 'ABC\\-001' #Python的字符串#对应的正则表达式字符串变成:#'ABC\-001'
因此我们强烈建议使用Python的 r前缀,就不用考虑转义的问题了:
s = r'ABC\-001' #Python的字符串#对应的正则表达式字符串不变:#'ABC\-001'
元字符之分组 ()
(?P\d+) 有名分组 可以通过ret.group('分组名') 取得匹配结果
m = re.findall(r'(ad)+', 'add')print(m) #ad
ret=re.search('(?P\d{2})/(?P\w{3})','23/com')print(ret.group()) #23/com
print(ret.group('id')) #23
##'(?P\d{2})/(?P\w{3})' ?P 分组 组名为ip, \d{2} 匹配后面两位整数#(?P\w{3}) ?P 分组 组名为name,\w{3} 匹配3位 大小写字母 数字 下划线
>>> re.search(r'(.*).*
(.*)
',s).group(1)'更多'>>> re.search(r'(.*).*
(.*)
',s).group(2)'dfsl'>>> ss = re.search(r'(?P.*).*
(?P.*)
',s)>>> ss.group('txt')'更多'>>> ss.group('txt2')
练习:
>>> re.findall(r'(abc)+','adklnvkaj45d6kasdfeabcwoibcfabcabcabcdf')
['abc', 'abc']>>> re.findall(r'abc+','adklnvkaj45d6kasdfeabcwoibcfabcabcabcdf')
['abc', 'abc', 'abc', 'abc']>>> re.findall(r'(abc)+','abcabcabcabc')
['abc']>>> re.findall(r'(abc)*','abcabcabcabc')
['abc', '']>>> re.findall(r'(ab)+','abcabcabcabc')
['ab', 'ab', 'ab', 'ab']>>> re.findall(r'(abc)+','abcabcabcabc')
['abc']>>> re.findall(r'(abc)+','abcccccc')
['abc']>>> re.findall(r'(?P[a-z]+)\d+','xiong26wang33zhang23sun56')
['xiong', 'wang', 'zhang', 'sun']>>> re.search(r'(?P[a-z]+)\d+','xiong26wang33zhang23sun56')<_sre.sre_match object span="(0," match="xiong26">
>>> re.search(r'(?P[a-z]+)\d+','xiong26wang33zhang23sun56').group()'xiong26'
>>> re.search(r'(?P[a-z]+)\d+','xiong26wang33zhang23sun56').group("name")'xiong'
>>> re.search(r'(?P[a-z]+)(?P\d+)','xiong26wang33zhang23sun56').group("name")'xiong'
>>> re.search(r'(?P[a-z]+)(?P\d+)','xiong26wang33zhang23sun56').group("age")'26'
cmd执行
元字符之|
ret=re.search('(ab)|\d','rabhdg8sd')print(ret.group())#ab
re模块下的常用方法
#1
re.findall('a', 'alvin yuan') #返回所有满足匹配条件的结果,放在列表里#2
re.search('a', 'alvin yuan').group() #函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以#通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。
#3
re.match('a', 'abc').group() #同search,不过要在字符串开始处进行匹配,相当于re.search('^','')
#4
ret = re.split('[ab]', 'abcd') #先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割
print(ret) #['', '', 'cd']
#5
ret = re.sub('\d', 'A', 'alvin5yuan6', 1) ## 替换 数字 替换为 A , 只替换第一个
print(ret) #alvinAyuan6
ret = re.subn('\d', 'A', 'alvin5yuan6') #将替换结果 和 替换个数 返回为一个元组
print(ret) #('alvinAyuanA', 2)
#6
obj = re.compile('\d{3}') ## 编译,如果使用多次匹配规则 效率就体现出来了
ret = obj.search('abc123eeee')print(ret.group()) #123
处理大量数据,匹配结果返回一个迭代器
importre
ret=re.finditer('\d','ds3sy4784a')print(ret) #
print(next(ret).group())print(next(ret).group())
注意:
ret = re.findall('www.(baidu|oldboy).com', 'www.oldboy.com')print(ret) #['oldboy'] 这是因为findall会优先把匹配结果分组里内容返回,如果想要匹配结果,取消权限即可
ret= re.findall('www.(?:baidu|oldboy).com', 'www.oldboy.com')print(ret) #['www.oldboy.com']
补充练习题:
>>> importre>>> re.findall('\d+','nka15640-8dasgwe-96dagv-6')
['15640', '8', '96', '6']>>> re.findall('^\d+','nka15640-8dasgwe-96dagv-6')
[]>>> re.findall('[^-]\d+','nka15640-8dasgwe-96dagv-6')
['a15640', '96']>>> re.findall('\d{3}\s+\d{3,8}','sdfag123 7845agewgv')
['123 7845']>>> re.findall('\d+@$','1351655382@qq.com')
[]>>> re.findall('\d+','1351655382@qq.com')
['1351655382']>>> re.findall(r'ka|b','adklnvkj45d6kaewoib')
['ka', 'b']>>> re.findall(r'ka|b','adklnvkj45d6ksdfewoibfadf')
['b']>>> re.findall(r'ka|bc','adklnvkaj45d6kasdfewoibcfadf')
['ka', 'ka', 'bc']>>> re.findall(r'(abc)+','adklnvkaj45d6kasdfeabcwoibcfabcabcabcdf')
['abc', 'abc']>>> re.findall(r'abc+','adklnvkaj45d6kasdfeabcwoibcfabcabcabcdf')
['abc', 'abc', 'abc', 'abc']>>> re.findall(r'(abc)+','abcabcabcabc')
['abc']>>> re.findall(r'(abc)*','abcabcabcabc')
['abc', '']>>> re.findall(r'(ab)+','abcabcabcabc')
['ab', 'ab', 'ab', 'ab']>>> re.findall(r'(abc)+','abcabcabcabc')
['abc']>>> re.findall(r'(abc)+','abcccccc')
['abc']>>> re.findall(r'(?P[a-z]+)\d+','xiong26wang33zhang23sun56')
['xiong', 'wang', 'zhang', 'sun']>>> re.search(r'(?P[a-z]+)\d+','xiong26wang33zhang23sun56')<_sre.sre_match object span="(0," match="xiong26">
>>> re.search(r'(?P[a-z]+)\d+','xiong26wang33zhang23sun56').group()'xiong26'
>>> re.search(r'(?P[a-z]+)\d+','xiong26wang33zhang23sun56').group("name")'xiong'
>>> re.search(r'(?P[a-z]+)(?P\d+)','xiong26wang33zhang23sun56').group("name")'xiong'
>>> re.search(r'(?P[a-z]+)(?P\d+)','xiong26wang33zhang23sun56').group("age")'26'
>>> re.findall('(ab)|\d','rabhdg8sd')
['ab', '']>>> re.findall('(ab)|\d+','rabhdg8sd')
['ab', '']>>> re.findall('(ab)|\d+','rab632hdg8sd')
['ab', '', '']>>> re.findall('(ab)|\d','rab632hdg8sd')
['ab', '', '', '', '']>>> re.findall('(ab)|\d+','rab632hdg8sd')
['ab', '', '']>>> re.findall('(ab).*\d+','rab632hdg8sd')
['ab']>>> re.match('a', 'abc').group()'a'
>>> re.match('a', 'abcadfa').group()'a'
>>>
####################split分割
>>> re.split(' ','hello world xiong')
['hello', 'world', 'xiong']>>> re.split('[ |]','hello world|xiong')
['hello', 'world', 'xiong']>>> re.split('[ab]','vnklaouojbouhg')
['vnkl', 'ouoj', 'ouhg']>>> re.split('[ab]','auouabuobuo')
['', 'uou', '', 'uo', 'uo']>>> re.split('[ab]','asdabcd')
['', 'sd', '', 'cd']>>> re.split('[ab]','abc')
['', '', 'c']>>>
>>>############# '替换'
>>> re.sub('\d+','A','as451da23bc23d5dae')'asAdaAbcAdAdae'
>>> re.sub('\d','A','as451da23bc23d5dae')'asAAAdaAAbcAAdAdae'
>>> re.sub('\d','A','as451da23bc23d5dae',3)'asAAAda23bc23d5dae'
>>> re.sub('\d','A','as451da23bc23d5dae',2)'asAA1da23bc23d5dae'
>>> re.subn('\d','A','as451da23bc23d5dae')
('asAAAdaAAbcAAdAdae', 8)>>>
###########compile编译
>>> com = re.compile("\d+")>>> com.findall("uoihja37jdaogj230ldaoje")
['37', '230']>>>
>>> re.findall("\d","af7nka89wejojk03oajag")
['7', '8', '9', '0', '3']>>> re.finditer("\d","af7nka89wejojk03oajag")
>>> ret = re.finditer("\d","af7nka89wejojk03oajag")>>> ret.__next__()<_sre.sre_match object span="(2," match="7">
>>> ret.__next__().group()'8'
>>>#############结果返回为一个迭代器
>>> ret = re.finditer("www\.(baidu|163)\.com","af7nkawww.baidu.com89wejojk03oajag")>>> re.finditer("www\.(baidu|163)\.com","af7nkawww.baidu.com89wejojk03oajag")
###################匹配结果优先返回为匹配到的分组内容
>>> re.findall("www\.(baidu|163)\.com","af7nkawww.baidu.com89wejojk03oajag")
['baidu']>>> re.findall("www\.(?:baidu|163)\.com","af7nkawww.baidu.com89wejojk03oajag")
['www.baidu.com']
练习
补充1:
importreprint(re.findall("\w+)>\w+(?P=tag_name)>","
hello
"))print(re.search("\w+)>\w+(?P=tag_name)>","hello
"))print(re.search(r"\w+\1>","hello
"))View Code
补充2:
#匹配出所有的整数
importre#ret=re.findall(r"\d+{0}]","1-2*(60+(-40.35/5)-(-4*3))")
ret=re.findall(r"-?\d+\.\d*|(-?\d+)","1-2*(60+(-40.35/5)-(-4*3))")
ret.remove("")print(ret)
View Code