问题:按照特定的文本模式进行匹配或查找
解决方法:
1、简单的文字匹配,只需使用str.find()、str.startswith()、str.endswith()或类似的函数即可;
2、复杂的匹配,需要使用正则表达式以及re模块
>>> import re>>> text1='11/23/2016'>>> text2='Nov 23,2016'>>> if re.match(r'\d+/\d+/\d+',text1): print('yes')else: print('no') yes>>> if re.match(r'\d+/\d+/\d+',text2): print('yes')else: print('no') no>>>
若针对同一模式做多次匹配,那么通常会先将正则表达式模式预编译成一个模式对象:
>>> text='today is 11/23/2016. Pycon starts 3/12/2013'>>> datepat.findall(text) #如果要找到整个文本中所有匹配项应该使用findall(),match()总是尝试在字符串的开头找到匹配项['11/23/2016', '3/12/2013']>>> datepat.match(text)>>> print(datepat.match(text))None>>>
findall()方法搜索整个文本并找出所有的匹配项然后将他们以列表的形式返回。若想以迭代的方式找出匹配项,可以使用finditer()方法。
当使用正则表达式时,通常会将部门模式用括号包起来的方式引入“捕获组”,它能简化后续对匹配文本的处理,因为每个组的内容都可以单独提取出来:
>>> datepat=re.compile(r'(\d+)/(\d+)/(\d+)') #引入“捕获组”>>> m=datepat.match('11/23/2016')>>> m<_sre.SRE_Match object; span=(0, 10), match='11/23/2016'>>>> m.group(0)'11/23/2016'>>> m.group(1) #组内元素单独提取出来'11'>>> m.group(2)'23'>>> m.group(3)'2016'>>> m.group()'11/23/2016'>>> m.groups()('11', '23', '2016')>>> month,day,year=m.groups()>>> month'11'>>> day'23'>>> year'2016'>>> text'today is 11/23/2016. Pycon starts 3/12/2013'>>> datepat.findall(text)[('11', '23', '2016'), ('3', '12', '2013')]>>> for month,day,year in datepat.findall(text): print('{}-{}-{}'.format(year,month,day)) 2016-11-232013-3-12>>>
>>> for m in datepat.finditer(text):#使用迭代方式查找匹配项 print( m.groups()) ('11', '23', '2016')('3', '12', '2013')>>>
总之,若打算执行很多匹配或查找操作的话,首先用re.compile()对模式进行预编译,然后使用像match()、findall()、finditer()这样的方法做匹配和搜索。
补充:
注意match()只会检查字符串的开头,想要精确匹配的话,在模式中包含一个结束标记($)即可:
>>> datepatre.compile('(\\d+)/(\\d+)/(\\d+)')>>> m=datepat.match('abc11/23/2016defjh')>>> print(m)None>>> datepat=re.compile(r'(\d+)/(\d+)/(\d+)$')>>> datepat.match('11/23/2016defjh')>>> datepat.match('11/23/2016')<_sre.SRE_Match object; span=(0, 10), match='11/23/2016'>>>>
若只是简单的执行文本匹配和搜索操作,通常可以省略预编译步骤:
>>> text'today is 11/23/2016. Pycon starts 3/12/2013'>>> re.findall(r'(\d+)/(\d+)/(\d+)',text)[('11', '23', '2016'), ('3', '12', '2013')]>>>