正则表达式(regular expression),简称为regex,是文本描述的方法。它预定义一个模式,用来表示文本中的特定字符组合,比如\d 表示一个0-9之间的数字;\w表示字母、数字或下划线;\s表示空格、制表符或换行符。利用正则表达式可以定义任何复杂的字符组合,实现文本的精准快速匹配,代码量大幅度减少(少了很多逻辑运算)。
上面介绍了正则表达式是什么东东,下面我们看一下如何利用正则表达式来匹配文本吧!
1.模式匹配流程
(1)导入正则表达式模块,python中所有的正则表达式函数都在re模块中。
import re
(2)创建正则表达式对象pattern
例如,创建一个pattern对象来匹配某种模式的电话号码(028-11111)
phoneRegex = re.compile('\d\d\d-\d\d\d\d\d')
re.compile(‘str_pattern’,flag)函数传入两个参数,str_pattern是字符串形式的正则表达式,flags可选,表示匹配模式如re.I表示忽略大小写。执行结果返回一个pattern对象
(3)匹配pattern对象
pattern对象可以调用match(),search(),findall()方法,当调用前两个方法时,返回一个Match对象,调用findall()方法会返回一个列表,包含了匹配的所有字符串
match=phoneRegex.search('我的电话号码是028-12345,028-23456')
result=match.group()
(4)获取匹配的字符串
当pattern对象调用search()时,仅匹配查找到的第一个匹配,返回一个match对象, match对象里存储‘028-12345’,而028-23456被忽略。要想从match对象里获取匹配的字符串,需要用到match对象中的方法group()
当pattern对象调用findall()时,查到所有的匹配,并返回一个字符串列表
result = phoneRegex.findall('我的电话号码是028-12345,028-23456')
返回['028-12345', '028-23456']
这里需要注意的一点是:findall()返回的是字符串列表,而search()方法返回的是一个match对象,要想得到匹配的字符串还需要调用group()方法。
2.正则表达式的分组
前面我们使用到了group()函数,那么为什么这个函数要命名为group呢?哪里分组了呢?我们不妨看看下面一个例子:
要匹配的电话号码模式为 XXX-XXXXX,其前3位代表了市的编码,我现在想通过模式匹配得到这个市的编码,那应该怎么做呢?这就要用到正则表达式里的分组。
简单来说,分组是对匹配的模式的又一次处理,它用括号()将匹配的模式分为多个组,每个组中存储着相应的信息。
我们对前面的例子进行升级:
phoneRegex = re.compile(r'(\d\d\d)-(\d\d\d\d\d)')
match=phoneRegex.search('我的电话号码是028-12345,028-23456')
result=match.group(0) =====> 输出为‘028-12345’
result=match.group(1) =====> 输出为‘028’
result=match.group(2) =====> 输出为‘12345’
result=match.groups() =====> 输出为元组(‘028’,‘12345’)
除了group()函数之外,match对象还提供了start(),end(),span()函数,目的是获取匹配的字符串分组在整个字符串中的起始结 束索引位置,以上述为例:
match.start(0) ======> 7 # 028-12345中 0在整个字符串中的索引
match.end(0) ======>16 # 028-12345中 5在整个字符串中的索引+1
match.span(0) ======>(7,16)
match.start(1) ======> 7 # 028-12345中 第一个分组(028)中0在整个字符串中的索引
match.end(1) ======> 10 # 028-12345中 第一个分组(028)中8在整个字符串中的索引
如果使用findall()
phoneRegex = re.compile(r'(\d\d\d)-(\d\d\d\d\d)')
phoenRegex.findall('我的电话号码是028-12345,028-23456') ======>输出为列表 [('028', '12345'), ('028', '23456')]