python常用模块之re模块(正则)
python种的re模块常用的5种方法,分别是re.match re.search re.findall re.split re.sub。
在介绍五种方法之前,需要介绍一下正则的基础。
. 表示任意字符,除\n以为 \ 转义字符 [...] 字符集,表示取其中任意一个字符。比如[abc]d 可以匹配到ad bd cd。 \d 表示数字,等同于[0-9] \D 表示非数字 [^\d] \s 表示空格 \S 表示非空格 \w 表示单词字符 [a-zA-z_0-9] \W 表示非单词字符 [^\w] * 匹配前面0个或多个字符 + 匹配前面1个或多个字符 ? 匹配前面0个或1个字符 {m} 匹配前面m个字符 {m,n} 匹配前1个字符m至n次 ^ 匹配以什么开头 $ 匹配以什么结尾 \A 匹配以什么开头 \Z 匹配以什么结尾 | 或 左右表达式取一个 ABC|def (..) 表示一个整体,(abc){2} 匹配abc2次 (?P<name>)分组命名 比如(?P<name>tom) \(number) 引用编号为number的分组 比如:(\d)abc\1 1abc1
上述介绍了正则的一些基本语法。下面介绍的是re模块的常用方法。
一,re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。
re模块可以直接使用对应的方法,比如
import re
res = re.match('\d+','123abc123')
if res:
print(res.group())
这样就可以匹配到就是123,所以输出的则是123.
但是一般使用re模块的步骤通常是 将正则表达式的字符串编译为pattern实例,然后使用pattern实例处理文本并获得匹配结果,最后使用对应方法处理。通俗的就是要使用正则,先创建正则规则,然后编译成对象。最种使用正则的对应方法处理即可。
这样的好处就是速度更快。
所以上述代码更新为:
import re pattern = re.compile('\d+') res = re.match(pattr, '123abc123') if res: print(res.group())
为了更直观的显示时间的区别,附上时间差的对比:
import time import re def timeer(fun): def wrapper(): start_time = time.time() fun() stop_time = time.time() print('{0}函数执行时间为{1}'.format(fun.__name__,stop_time-start_time)) return wrapper @timeer def re_compile(): pattern = re.compile('\d+') res = re.match(pattern, '123abc123') if res: print(res.group()) @timeer def re_nocompile(): res = re.match('\d+', '123abc123') if res: print(res.group()) re_compile() re_nocompile()
上面的re.group()这里其实是可以填写对应的数值的。默认就是0,代表输出匹配到所有字符。
import re
pattern = re.compile('(\d+)([a-z]+)(\d+)')
res = re.match(pattern,'123abc123')
if res:
print(res.group(0))
print(res.group(1))
print(res.group(2))
print(res.group(3))
print(res.groups())
0 表示输出匹配到的所有,即默认所以输出的结果为123abc123
1 表示输出第一个括号匹配到的内容,即123
2表示输出第二个括号匹配到的内容,即abc
3表示输出第三个括号匹配到的内容,即123
groups() 返回所有小组匹配到的内容,以元祖的形式输出。即(123,abc,123)
切记:match是从第一字符开始匹配,如果匹配不到,直接返回None.
二,re.search
re.search 扫描整个字符串并返回第一个成功的匹配
import re
pattern = re.compile('[a-z]+(\d+)(\w+)')
res = re.search(pattern,'123abc123_')
if res:
print(res.group())
print(res.group(1))
print(res.group(2))
输出结果:
abc123_
123
_
可以发现,即使search没有匹配到123,但是它还是会往后匹配,而不是直接返回none。再看如下代码:
import re pattern = re.compile('[a-z]+') res = re.search(pattern,'123abc123abd') if res: print(res.group())
输出结果:abc
可见,search匹配整个字符串,找到第一个就会输出。后面的则不匹配。
简单小结:
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。
三,re.findall 在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。findall是没有group方法的。
import re pattern = re.compile('[a-z]+') res = re.findall(pattern,'123abc123abd') print(res) 输出结果:['abc', 'abd']
可见该正则会将匹配到内容按列表的形式输出,它不仅仅是匹配一次,这个是它和search的区别
四, re.split 匹配分割字符串
import re pattern = re.compile('[a-z]+') res = re.split(pattern,'123abc123abd') print(res) 输出结果:['123', '123', '']
五, re.sub 匹配替换
import re pattern = re.compile('[a-z]+') res = re.sub(pattern,'000','123abc123') print(res) 输出结果:123000123
line = '手机号:15200000000,生日:0802' reg_str1 = '.*:' reg_str2 = '.*?:' match_obj1 = re.match(reg_str1,line) match_obj2 = re.match(reg_str2,line) if match_obj1: print(match_obj1.group()) if match_obj2: print(match_obj2.group()) 输出结果: 手机号:15200000000,生日: 手机号: 可见,?是可以限制住*的贪婪匹配的!!!
import re re = re.search('(?P<id>[0-9]+)(?P<name>[a-zA-Z]+)','abcd1233bob@34') if re: print(re.group()) print(re.groupdict()) 输出结果: 1233bob {'id': '1233', 'name': 'bob'}
#比如匹配身份证, import re id = '360201199011113721' res = re.search('(?P<Province_code>[0-9]{2})(?P<City_code>[0-9]{2})(?P<County_code>[0-9]{2})(?P<birthday>[0-9]{8})(?P<policestation_id>[0-9]{2})(?P<sexid>[0-9]{1})(?P<checkid>[0-9]{1})',id) if res: print(res.group()) print(res.groupdict()) 输出结果: 360201199011113721 {'Province_code': '36', 'City_code': '02', 'County_code': '01', 'birthday': '19901111', 'policestation_id': '37', 'sexid': '2', 'checkid': '1'}