第二十一天python3 python的正则表达式re模块学习
python的正则表达式
python使用re模块提供了正则表达式处理的能力;
模式修正符
也叫正则修饰符,模式修正符就是给正则模式增强或增加功能的。
修正符 | re模块提供的变量 | 描述 |
i | re.I | 使模式对大小写不敏感,不区分大小写。 |
x | re.X | 忽略表达式中的空白字符。 |
m | re.M | 使模式在多行文本中可以多个行头和行尾,影响^和$。 |
s | re.S | 让通配符“.”可以代替任意原子,包括换行符\n在内。 |
import re text = """ <12 > <x yz> <!@#$%> <1a!# e2> <> """ ret1 = re.findall("<.*?>", text, re.S) print(ret1) """ 执行结果: ['<12\n>', '<x\n yz>', '<!@#$%>', '<1a!#\n e2>', '<>']
默认“.”是不会匹配换行符的,当添加上re.S之后,“.”就拥有了匹配任意字符的能力,包括换行符。 """
re.M re.MULTILINE 多行模式 re.S re.DOTALL 单行模式 re.I re.IGNORECASE 忽略大小写 re.X re.VERBOSE 忽略表达式中的空白字符 使用|位或运算开启多种选项
#示例:n = re.match('b',s,re.M)
编译
re.compile(pattern,flags=0) 设定flags,编译模式,返回正则表达式对象regex; pattern就是正则表达式字符串,flags就是选项。正则表达式需要被编译,为了提高效率,这些编译后的结果被保存,下次使用同样的pattern的时候,就不需熬再次编译;
单次匹配
re.match(pattern,string,flags=0) regex.match(string[,pos[,endpos]]) match匹配从字符串的开头匹配,只匹配一次,返回match对象; re.search(pattern,string,flag=0) regex.search(string[,pos[,endpos]]) 从头搜索直到第一个匹配,regex对象search方法可以重新设定开始位置和结束位置,返回match对象; re.fullmatch(pattern,string,flags=0) regex.fullmatch(string[,pos[,endpos]]) 整个字符串和正则表达式匹配;
示例:
import re s = """bootle\nbag\nbig\napple""" for i,c in enumerate(s,1): print((i-1,c),end='\n' if i%8 == 0 else ' ') #执行结果: (0, 'b') (1, 'o') (2, 'o') (3, 't') (4, 'l') (5, 'e') (6, '\n') (7, 'b') (8, 'a') (9, 'g') (10, '\n') (11, 'b') (12, 'i') (13, 'g') (14, '\n') (15, 'a') (16, 'p') (17, 'p') (18, 'l') (19, 'e') #之所以这样做是为了更好的理解match的边界问题;
n = re.match('b',s,re.M) m = re.match('boot',s) l = re.match('t',s) print(n) print(m) print(l) 执行结果: <_sre.SRE_Match object; span=(0, 1), match='b'> <_sre.SRE_Match object; span=(0, 4), match='boot'> None #n和m都返回了一个match对象,并且给出了边界范围,是前包后不包;并且只匹配一次; #l返回的结果是None,是因为match的特性就是从字符串的开头开始匹配;相当于^\w;
"(0, 'b') (1, 'o') (2, 'o') (3, 't') (4, 'l') (5, 'e') (6, '\n') (7, 'b') (8, 'a') (9, 'g') (10, '\n') (11, 'b') (12, 'i') (13, 'g') (14, '\n') (15, 'a') (16, 'p') (17, 'p') (18, 'l') (19, 'e')" #将需要匹配的字母"b"格式化 regex = re.compile('b') #调用格式化后的match方法,并打印结果 print(regex.match(s)) print(regex.match(s,7)) print(regex.match(s,7,10)) print(regex.match(s,8)) #执行结果 #没有指定边界,默认从头开始找,默认匹配了第一个b; <_sre.SRE_Match object; span=(0, 1), match='b'> #指定了边界,把索引7作为开始,匹配到了第七个b; <_sre.SRE_Match object; span=(7, 8), match='b'> #指定了边界范围,指定7到10的索引范围,匹配到了7-10范围内的第一个b; <_sre.SRE_Match object; span=(7, 8), match='b'> #在指定的边界内,没有b字母,返回None; None #总结:对需要匹配的字符串进行编译(compile);相当于生成了关于match的一个编译对象;再去调用这个对象的match方法,就可以定义范围了;
"(0, 'b') (1, 'o') (2, 'o') (3, 't') (4, 'l') (5, 'e') (6, '\n') (7, 'b') (8, 'a') (9, 'g') (10, '\n') (11, 'b') (12, 'i') (13, 'g') (14, '\n') (15, 'a') (16, 'p') (17, 'p') (18, 'l') (19, 'e')" #对需要匹配的big进行格式化 regex = re.compile('big') #调用格式化的fullmatch方法 print(regex.fullmatch(s,11)) print(regex.fullmatch(s,11,14)) print(regex.fullmatch(s,11,15)) #执行结果 None <_sre.SRE_Match object; span=(11, 14), match='big'> None #从上面的执行结果可以看出fullmatch必须要给定明确的需要匹配字符串的边界范围,才有返回值;
全文搜索
re.findall(pattern,string,flags=0) regex.findall(string[,pos[,endpos]]) 对整个字符串,从左至右匹配,返回所有匹配项的列表; re.finditer(pattern,string,flags=0) regex.finditer(string[,pos[,endpos]]) 对真个字符串,从左至右匹配,返回所有匹配项,返回迭代器; 注意每次迭代返回的是match对象;
示例:
import re s = """bootle\nbag\nbig\napple""" for i,c in enumerate(s,1): print((i-1,c),end='\n' if i%8 == 0 else ' ') #执行结果 #(0, 'b') (1, 'o') (2, 'o') (3, 't') (4, 'l') (5, 'e') (6, '\n') (7, 'b') (8, 'a') (9, 'g') (10, '\n') (11, 'b') (12, 'i') (13, 'g') (14, '\n') (15, 'a') (16, 'p') (17, 'p') (18, 'l') (19, 'e')
n = re.findall('b',s) m = re.findall('b\w',s) print(n) print(m)
# 执行结果
['b', 'b', 'b']
['bo', 'ba', 'bi']
#锚定 regex = re.compile('^b\w',re.M) regex1 = re.compile('^b\w',re.S) print(regex.findall(s),"多行模式") print(regex1.findall(s),"单行模式") #执行结果 ['bo', 'ba', 'bi'] 多行模式 ['bo'] 单行模式 #不锚定 regex = re.compile('b\w',re.M) regex1 = re.compile('b\w',re.S) print(regex.findall(s),"多行模式") print(regex1.findall(s),"单行模式") #执行结果 ['bo', 'ba', 'bi'] 多行模式 ['bo', 'ba', 'bi'] 单行模式
#这地方要注意,当在finditer中用\b时,要加上r,防止\b被转译,如果不加r,则在finditer中\b表示的是ascii码中的含义,所以会有匹配不到的问题; m = re.finditer(r'\bb',s) print(m,type(m)) for r in m: print(r) 执行结果: #finditer返回了一个可迭代对象; <callable_iterator object at 0x0000022FE0280BA8> <class 'callable_iterator'> #用for循环迭代这个可迭代对象,finditer不但可以匹配到字符串,而且何以打印出字符的边界; <_sre.SRE_Match object; span=(0, 1), match='b'> <_sre.SRE_Match object; span=(7, 8), match='b'> <_sre.SRE_Match object; span=(11, 12), match='b'>
匹配替换
re.sub(pattern,replacement,string,count=0,flags=0) regex.sub(replacement,string,count=0) 使用pattern对字符串string进行匹配,对匹配项使用repl替换。replacement可以是string、bytes、function; re.subn(pattern,replacement,string,count=0,flags=0) regex.subn(replacement,string,count=0) 同sub返回一个元组(new_string、number_of_subs_made),并且告诉总共匹配了几次;
示例:
import re s = """bootle\nbag\nbig\napple""" m = re.sub('b\w','AAA',s) print(m) 执行结果: AAAotle\nAAAg\nAAAg\napple
import re s = """bootle\nbag\nbig\napple""" n = re.sub('b\w',"AAA",s,count=1) print(n) #执行结果 AAAotle\nbag\nbig\napple
import re s = """bootle\nbag\nbig\napple""" regex = re.compile('b\w') print(regex.sub('RRR',s,count=2)) 执行结果: RRRotle\nRRRg\nbig\napple
import re s = """bootle\nbag\nbig\napple""" m = re.subn('b\w','AAA',s) print(m) regex = re.compile('b\w') print(regex.subn('RRR',s,count=2)) print(regex.subn('RRR',s,count=10)) #执行结果 ('AAAotle\nAAAg\nAAAg\napple', 3) ('RRRotle\nRRRg\nbig\napple', 2) ('RRRotle\nRRRg\nRRRg\napple', 3)
分割字符串
re.split(pattern,string,maxsplit=0,flags=0) re.split分割字符串
import re s = """01 bottle 02 bag 03 big1 100 able""" result1 = re.split('[\s\d]+',s) print(1,result1) regex2 = re.compile('^[\s\d]+') result2 = regex2.split(s) print(2,result2) regex3 = re.compile('^[\s\d]+',re.M) result3 = regex3.split(s) print(3,result3) regex4 = re.compile('\s+\d+\s+') result4 = regex4.split(s) print(4,result4)
#执行结果: 1 ['', 'bottle', 'bag', 'big', 'able'] 2 ['', 'bottle\n02 bag\n03 big1\n100 able'] 3 ['', 'bottle\n', 'bag\n', 'big1\n', 'able'] 4 ['01 bottle', 'bag', 'big1', 'able']
分组
使用小括号的pattern捕获的数据被放到了组group中; match、search函数可以返回match对象;findall返回字符串列表;finditer返回一个个match对象; 如果pattern中使用了分组,如果有匹配的结果,会在match对象中: 1、使用group(N)方式返回对应分组;1-N是对应的分组,0返回整个匹配的字符串; 2、如果使用了命名分组,可以使用group(‘name’)的方式取分组; 3、也可以使用groups()返回所有分组; 4、使用groupdict()返回所有命名的分组;
示例:
import re s = """bootle\nbag\nbig\napple""" print("分组") regex = re.compile('(b\w+)') result = regex.match(s) print(type(result)) print(1,'match',result.groups()) result1 = regex.search(s,1) print(2,'search',result1.groups()) print('命名分组') regex2 = re.compile('(b\w+)\n(?P<name2>b\w+)\n(?P<name3>b\w+)') result2 = regex2.match(s) print(3,'match',result2) print(4,result2.group(3),result2.group(2),result2.group(1)) print(5,result2.group(0).encode()) print(6,result2.group('name2'),result2.group('name3')) print(7,result2.groups()) print(8,result2.groupdict()) print('#####') result3 = regex.findall(s) for x in result3: print(type(x),x) regex3 = re.compile('(?P<head>b\w+)') result3 = regex3.finditer(s) for r in result3: print(type(r),r,r.group(),r.group('head'))
#执行结果 分组 <class '_sre.SRE_Match'> 1 match ('bootle',) 2 search ('bag',) 命名分组 3 match <_sre.SRE_Match object; span=(0, 14), match='bootle\nbag\nbig'> 4 big bag bootle 5 b'bootle\nbag\nbig' 6 bag big 7 ('bootle', 'bag', 'big') 8 {'name3': 'big', 'name2': 'bag'} ##### <class 'str'> bootle <class 'str'> bag <class 'str'> big <class '_sre.SRE_Match'> <_sre.SRE_Match object; span=(0, 6), match='bootle'> bootle bootle <class '_sre.SRE_Match'> <_sre.SRE_Match object; span=(7, 10), match='bag'> bag bag <class '_sre.SRE_Match'> <_sre.SRE_Match object; span=(11, 14), match='big'> big big