我们使用办公软件如Word、Excel等工具的时候,如果我们想搜索某个字符、人名等,就会使用CTRL+F,进行搜索。
在Python中给我们提供的有正则表达式来查找文本:
正则表达式对象:Python中所有的正则表达式的函数都在re模块中。
比如我们使用re模块匹配日期:
>>> import re >>> myexpress=re.compile(r'd{4}-d{1,2}-d{1,2}') >>> myexpress re.compile('\d{4}-\d{1,2}-\d{1,2}') >>> type(myexpress) <class 're.Pattern'> >>> result=myexpress.search('我在1998-7-1日去过北京') >>> result <re.Match object; span=(2, 10), match='1998-7-1'> >>> result.group() '1998-7-1' >>> type(result) <class 're.Match'>
说明:
- 导入re模块
- 使用re.compile()创建一个Regex对象
- 向Regex对象的search()方法传入先查找的字符串,它会返回一个Match对象
- 调用Match对象的group()对象可以得到匹配到的文本
注意:
- compile()里面传递的规则是以r开头的字符串,使用r这样的原始字符串解释为了解决正则表达中出现的反斜杠
- search()就匹配一次
正则表达的分组匹配模式:
一个()是一组,正则表达式中如果出现多个(),那么使用group()方法的时候得向group()中传入整数作为下标。其实我们还可以通过groups()来获取所有分组的匹配数据,那么groups()返回的是一个tuple。
>>> group_express= re.compile(r'(d{4})-(d{1,2})-(d{1,2})') >>> group_express re.compile('(\d{4})-(\d{1,2})-(\d{1,2})') >>> matchs=group_express.search('在1993-12-26号的时候他出生了,那2020-2-22的时候他几岁?') >>> matchs <re.Match object; span=(1, 11), match='1993-12-26'> >>> matchs.group(0) '1993-12-26' >>> matchs.group(1) '1993' >>> matchs.group(2) '12' >>> matchs.group(3) '26' >>> match_tuple=matchs.groups() >>> match_tuple ('1993', '12', '26')
说明:使用几个(),可以将正则表达式进行分组;match对象调用groups()方法得到的是一个元组。
findall()方法:
该方法能够返回一组字符串,包含整个字符串中的所有匹配。findall返回的是个列表。
>>> import re >>> reg=re.compile(r'd{4}-d{1,2}-d{1,2}') >>> mylis=reg.findall('我在1984-7-11日,在波尔多酒庄买到了一瓶1573-12-1日生产的洋河天之蓝') >>> mylis ['1984-7-11', '1573-12-1']
字符分类:字符分类就是为了缩短正则表达式长度而诞生的。
- 数字使用d表示
- 数字、字母、下划线使用w表示
- 空格、制表符、换行符等这样的空白符号(space)使用s表示
>>> mystr=''' ... woshinide xiaoya xiapingguo ... zenme aini 1314 wodou bu xianduo''' >>> mystr ' woshinide xiaoya xiapingguo zenme aini 1314 wodou bu xianduo' >>> space_lis=re.compile(r's+').findall(mystr) >>> space_lis [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '] >>> number_lis=re.compile(r'd+').findall(mystr) >>> number_lis ['1314'] >>> char_lis=re.compile(r'[a-z]+').findall(mystr) >>> char_lis ['woshinide', 'xiaoya', 'xiapingguo', 'zenme', 'aini', 'wodou', 'bu', 'xianduo']
说明:
- [abc]、[a-z]、[0-9]~~~表示的是一个集合,只要某个字符出现在这个集合中就算能够匹配上,如对于[adb]而言,ab10匹配出来的就是ab;
- {n,m}~~~表示限定出现次数,比如d{1,2}表示出现一个或两个数字,如:22、2、02这样都可以匹配上;
- +~~~表示出现一次或多次,如d+而言,10100101103s-121u,就能够匹配出来10100101103和121;
- *~~~表示出现零次或多次,这个范围就比较大了,例如上面的我们把[a-z]+改成[a-z]*结果就大不相同了。
插入字符(^)和美元字符()$:
一个表示匹配开始--比如r'^Hello',表示以Hello开始的字符串能够匹配上;
一个表示匹配结束--比如r'Hello$',表示以Hello结束的字符串能够匹配上。
>>> ex=re.compile(r'^d+$') >>> str1='asdfasdf322qw4123' >>> str2='12123s8dasdf8112' >>> str3='1212312312312312' >>> ex.findall(str1) [] >>> ex.findall(str2) [] >>> ex.findall(str3) ['1212312312312312']
split()方法:
和字符串类型中的split()将字符串按照某个字符分割成列表是一样的,只不过我们这里是按照规则拆分成列表。
>>> sp_str='12-121212*2314sdsfs*asdfask-32fq3' >>> re.split(r'[-*]',sp_str) ['12', '121212', '2314sdsfs', 'asdfask', '32fq3']
字符串不识别连续空格,下面这个例子能看出来正则的split()比str的split()要厉害的地方:
>>> sss.split(' ') ['我', '', '', '爱你', '', '宝宝'] >>> sss='我 爱你 宝宝' >>> sss.split(' ') ['我', '', '', '爱你', '', '宝宝'] >>> re.split(r's+',sss) ['我', '爱你', '宝宝']
说明:字符串不能识别连续空格,所以最后我们使用字符串的分割函数难以达到效果。
sub()方法:
类似字符串类型中的replace()方法,第一个参数是规则,第二个参数是拿来用于替换的,第三个是目标字符串,第四个参数是替换次数。
>>> ss='小了白了兔白了又了白' >>> re.sub(r'了','',ss) '小白兔白又白'