基于《PythonCookbook》的学习(4)—— 文本模式的匹配和查找

1、如果只是匹配简单字符串

In [2]: text = 'yeah, but no, but yeah, but no, but yeah'

In [3]: text
Out[3]: 'yeah, but no, but yeah, but no, but yeah'

In [4]: text == 'yeah'
Out[4]: False

In [5]: text.startswith('yeah')
Out[5]: True

In [6]: text.endswith('yeah')
Out[6]: True

In [7]: text.endswith('no')
Out[7]: False

In [8]: text.find('no')
Out[8]: 10

2、对于复杂的匹配需要使用正则表达式和re 模块

In [10]: text1 = '11/27/2022'

In [11]: text2 = 'Nov 27, 2022'

In [12]: import re

In [17]: if re.match(r'\d+/\d+/\d+',text1):
    ...:     print('yes')
    ...: else:
    ...:     print('no')
    ...:
yes

In [18]: if re.match(r'\d+/\d+/\d+',text2):
    ...:     print('yes')
    ...: else:
    ...:     print('no')
    ...:
no

想使用同一个模式去做多次匹配,你应该先将模式字符串预编译为模式对象。比如:

In [19]: pattern = re.compile(r'\d+/\d+/\d+')

In [20]: if pattern.match(text1):
    ...:     print('yes')
    ...:
yes

match()总是从字符串开始去匹配,如果你想查找字符串任意部分的模式出现位置,使用findall()方法去代替:

In [23]: text = 'Today is 11/27/2012. PyCon starts 3/13/2013.'

In [24]: text
Out[24]: 'Today is 11/27/2012. PyCon starts 3/13/2013.'

In [25]: pattern.findall(text)
Out[25]: ['11/27/2012', '3/13/2013']

当定义正则表达式的时候,我们经常讲部分模式用 “()”包起来的方式引入捕获组。因为捕获组通常能简化后续对匹配文本的处理,因为每个组的内容都可以单独提取出来

In [26]: pattern = re.compile(r'(\d+)/(\d+)/(\d+)')

In [27]: pattern
Out[27]: re.compile(r'(\d+)/(\d+)/(\d+)', re.UNICODE)

In [28]: type(pattern)
Out[28]: _sre.SRE_Pattern

In [29]: m = pattern.match('11/27/1100')

In [30]: m
Out[30]: <_sre.SRE_Match object; span=(0, 10), match='11/27/1100'>

In [31]: type(m)
Out[31]: _sre.SRE_Match

In [32]: m.group(0)
Out[32]: '11/27/1100'

In [33]: m.group(1)
Out[33]: '11'

In [34]: m.group(2)
Out[34]: '27'

In [35]: m.group(3)
Out[35]: '1100'

In [36]: m.groups()
Out[36]: ('11', '27', '1100')

In [37]: month,day,year = m.groups()

In [38]: text
Out[38]: 'Today is 11/27/2012. PyCon starts 3/13/2013.'

In [39]: pattern.findall(text)
Out[39]: [('11', '27', '2012'), ('3', '13', '2013')]

In [40]: for month,day,year in pattern.findall(text):
    ...:     print('{}-{}-{}'.format(year,month,day))
    ...:
2012-11-27
2013-3-13

findall() 方法会搜索文本并以列表形式返回所有的匹配

如果想以迭代方式找出匹配项,可以使用 finditer() 方法

In [41]: for m in pattern.finditer(text):
    ...:     print(m.groups())
    ...:
('11', '27', '2012')
('3', '13', '2013')

讨论

使用re模块进行匹配和搜索文本的最基本方法。核心步骤就是先使用re.compile()编译正则表达式字符串,然后使用match(), findall()或者finditer() 等方法做匹配或搜索

当写正则式字符串的时候,相对普遍的做法是使用原始字符串比如r'(nd+)/(nd+)/(nd+)'。这种字符串将不去解析反斜杠,这在正则表达式中是很有用的。

如果你打算做大量的匹配和搜索操作的话,最好先编译正则表达式,然后再重复使用它。模块级别的函数会将最近编译过的模式缓存起来,因此并不会消耗太多的性能,但是如果使用预编译模式的话,你将会减少查找和一些额外的处理损耗。

你可能感兴趣的:(PythonCookbook)