str re --两种文本模式的匹配查找方式
2018-09-30 本文已影响49人
cook__
1、如果只是简单匹配文字,通常只需要用基本的字符串方法就可以了,比如str.find()、str.endswith()、str.startswith()等
text = 'yeah, but no, but yeah, but no, but yeah'
text.startswith('yeah')
Out[4]: True
text.endswith('yeah')
Out[5]: True
text.find('no')
Out[6]: 10
2、对于更为复杂的匹配则需要使用正则表达式及re模块
使用示例:匹配以数字形式构成的日期:如:30/09/2018
text = '30/09/2018'
re.match(r'\d+/\d+/\d+', text)
Out[8]: <_sre.SRE_Match object; span=(0, 10), match='30/09/2018'>
如果针对同一模式做多次匹配,通常会先将正则表达式模式预编译成一个模式对象
datepat = re.compile(r'\d+/\d+/\d+')
datepat.match(text)
Out[10]: <_sre.SRE_Match object; span=(0, 10), match='30/09/2018'>
match()方法总是尝试在字符串的开头找到匹配项,如果想针对整个文本搜索出所有的匹配项,就应该使用findall()方法
text = 'Today is 30/09/2018. PyCon starts 3/13/2013.'
datepat.findall(text) # 返回一个列表
Out[12]: ['30/09/2018', '3/13/2013']
使用捕获组,它能够简化后续对匹配文本的处理,因为每个组的内容都可以单独提取出来
datepat = re.compile(r'(\d+)/(\d+)/(\d+)') # 使用捕获组
m = datepat.match('30/09/2018')
m
Out[17]: <_sre.SRE_Match object; span=(0, 10), match='30/09/2018'>
m.group(0)
Out[18]: '30/09/2018'
m.group(1)
Out[19]: '30'
m.group(2)
Out[20]: '09'
m.group(3)
Out[21]: '2018'
m.groups()
Out[22]: ('30', '09', '2018')
datepat.findall(text)
Out[23]: [('30', '09', '2018'), ('3', '13', '2013')]
for month, day, year in datepat.findall(text):
print('{}-{}-{}'.format(year, month, day))
2018-30-09
2013-3-13
findall()方法搜索整个文本找出所有的匹配然后放入一个列表中。如果想以迭代的方式找出匹配项,可以使用finditer()方法
m = datepat.finditer(text) # 返回一个迭代器对象
m
Out[26]: <callable_iterator at 0x10d83dd68>
for iter in m:
print(iter.groups())
('30', '09', '2018')
('3', '13', '2013')
使用正则表达式总结:
1、首先用re.compile()对模式进行编译,然后使用像match()、findall()、finditer()这样的方法做匹配和搜索;
2、如果只是想执行简单的文本匹配和搜索操作,通常可以省略编译步骤,直接使用re模块的函数即可;
3、性能比较:直接使用re模块的函数,会对最近编译过得=的模式做缓存处理,因此不会有很大的差异;但是使用编译过得模式会省下一些查找步骤和额外的处理;
4、当指定模式时我们通常会使用原始字符串,比如r'(\d+)/(\d+)/(\d+)'
;
5、如果想精确匹配,请确保在模式中包含一个结束标记($),例:
r('(\d+)/(\d+)/(\d+)$')