如果你想匹配或者搜索特定的字段的时候,如果你匹配的是相对比较简单的字符串的时候你只需要利用find()
、rfind()
、endswitch()
、startswitch()
等类似的方法即可,示例如下:
>>> info = "My host ip address is 10.0.1.10"
>>> info == 'ip'
False
>>> info.startswith('My')
True
>>> info.endswith('0')
True
>>> info.find('d')
12
对于复杂的匹配我们就要使用正则表了,那既然用到正则的话我们就得利用re
模块的方法了。为了解释正则表达式的基本使用,我们假设要匹配数字格式的字符串比如: 2018-06-27
,示例如下:
>>> date1 = '2018-06-27'
>>> date2 = '2018-06-nock'
>>> import re
>>> # 简单匹配:\d+表示匹配一个或多个数字
>>> print('match yes') if re.match(r'\d+-\d+-\d+', date1) else print('match no')
match yes
>>> print('match yes') if re.match(r'\d+-\d+-\d+', date2) else print('match no')
match no
如果你想使用同一个模式去做多次匹配,那你应该先将模式字符串预先编译为模式对象,然后再去做匹配,示例如下:
>>> import re
>>> matchObject = re.compile(r'\d+/\d+/\d+')
>>> text = '07/08/2018'
>>> print('match yes') if matchObject.match(text) else print('match failed')
match yes
>>> print(matchObject.match(text))
<_sre.SRE_Match object; span=(0, 10), match='07/08/2018'>
>>> text = 'Today is 07/08/2018, PyCon starts 03/13/2013'
>>> print('match yes') if matchObject.match(text) else print('match failed')
match failed
>>> print(matchObject.match(text)) # 默认返回空
None
match()
方法的查找是从头开始去做完全匹配的,如果你想查找到字符串任意位置出现的匹配模式,并且希望得到结果,你可以使用findall()
去替代,示例如下:
>>> import re
>>> text = 'Today is 07/08/2018, PyCon starts 03/13/2013'
>>> matchObject = re.compile(r'\d+/\d+/\d+')
>>> matchObject.findall(text)
['07/08/2018', '03/13/2013']
>>>
如上所示就把字符串中,你要的结果都找到了,并且默认输出是一个列表,如果没有匹配到任何内容,默认返回一个空列表。
在定义正则的时候,通常会利用括号去做捕获分组,比如:
matchObjec = = re.compile(r'(\d+)/(\d+)/(\d+)')
捕获分组之后可以使得后面的处理更加简单,因为可以分别将每个组的内容提取出来,示例如下:
>>> matchObject = re.compile(r'(\d+)/(\d+)/(\d+)')
>>> m = matchObject.match('10/08/2018')
>>> m.group(0)
'10/08/2018'
>>> m.group(1)
'10'
>>> m.group(2)
'08'
>>> m.group(3)
'2018'
>>> m.groups()
('10', '08', '2018')
>>> month, day, year = m.groups()
>>> print(month, day, year)
10 08 2018
>>> # 查找所有匹配项
>>> text = 'Today is 07/08/2018, PyCon starts 03/13/2013'
>>> matchObject = re.compile(r'(\d+)/(\d+)/(\d+)')
>>> matchObject.findall(text)
[('07', '08', '2018'), ('03', '13', '2013')]
>>> for month, day, year in matchObject.findall(text):
... print('{}-{}-{}'.format(year, month, day))
...
...
2018-07-08
2013-03-13
findall()
方法会搜索文本并以列表形式返回所有的匹配。 如果你想以迭代方式返回匹配,可以使用 finditer()
方法来代替,比如:
>>> text = 'Today is 07/08/2018, PyCon starts 03/13/2013'
>>> matchObject = re.compile(r'(\d+)/(\d+)/(\d+)')
>>> for m in matchObject.finditer(text):
... print(m.groups())
...
...
('07', '08', '2018')
('03', '13', '2013')
>>> for m in matchObject.finditer(text):
... print(m.group())
...
...
07/08/2018
03/13/2013
总结
上面主要讲解了一下利用re
模块进行字符串的匹配和搜索的基本用法,核心方法就是先使用re.compile()
编译你想匹配的正则表达式字符串内容,然后再使用match()
,findall()
和finditer()
方法的结合使用。
当你编写正则表达式的时候,低昂对普通的做法是使用原始字符串,比如: r'(\d+)/(\d+)/(\d+)'
。这种字符串将不去解析反斜杠,这在正则表达式中是很有用的。 如果不这样做的话,你必须使用两个反斜杠,类似 '(\\d+)/(\\d+)/(\\d+)'
。
需要注意的是match()
方法仅仅检查字符串的开始部分。它的匹配结果有可能并不是你期望的那样精确,如果你想精确匹配,确保你的正则表达式以$结尾,就像这么这样:
>>> m = matchObject.match('10/08/2018abcd')
>>> m
<_sre.SRE_Match object; span=(0, 10), match='10/08/2018'>
>>> m.group()
'10/08/2018'
>>> matchObject = re.compile(r'(\d+)/(\d+)/(\d+)$')
>>> m = matchObject.match('10/08/2018abcd')
>>> print(type(m))
<class 'NoneType'>
>>> m = matchObject.match('10/08/2018')
>>> print(type(m))
<class '_sre.SRE_Match'>
>>> m.group()
'10/08/2018'
最后,如果你仅仅是做一次简单的文本匹配/搜索操作的话,可以略过编译部分,直接使用 re 模块级别的函数。比如:
>>> text = 'Today is 07/08/2018, PyCon starts 03/13/2013'
>>> re.findall(r'(\d+)/(\d+)/(\d+)', text)
[('07', '08', '2018'), ('03', '13', '2013')]
但是需要注意的是,如果你打算做大量的匹配和搜索操作的话,最好先编译正则表达式,然后再重复使用它。 模块级别的函数会将最近编译过的模式缓存起来,因此并不会消耗太多的性能, 但是如果使用预编译模式的话,你将会减少查找和一些额外的处理损耗。
本文由 空心菜 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Aug 8, 2018 at 11:14 am