Python中的字符串搜索

Home

Python中的字符串搜索

python_cookbook tricks

Directory

阅读《Python Cookbook》体验到了不一样的Python,坚持一日一读一练。

问题

匹配或搜索特性模式的文本。

解决方案

如果只是想在字符串中查出特定字符,只需要调用字符方法即可:str.startswith() / str.endswith() / str.endswith() 等。

In [1]: text = "yeah, but no, but yeah, but no, but yeah"
# Exact match
In [2]: text == 'yeah'
Out[2]: False

# Match at start or end
In [3]: text.startswith('yeah')
Out[3]: True
In [4]: text.endswith('no')
Out[4]: False

# Search for location of first occurrence
In [5]: text.find('no')
Out[5]: 10

如何希望比之复杂的字符串提取和匹配,最好还是使用re模块:

In [6]: import re

In [7]: text1 = '25/7/2017'

In [8]: text2 = 'Nov 25, 2017'

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

re.match()里的正则表达式\d+代表匹配一个或多个数字。r'\d+/\d+/\d+'代表试图匹配出数字/数字/数字类似于text1这种形式。将该表达式匹配给text2就会返回no:

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

为了匹配一个r'\d+/\d+/\d+'这样的模式,我们写了两次重复代码,其实为了将一个模式运用用多次匹配,应该先将模式字符串预编译为模式对象。

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

In [12]: if datePattern.match(text1):
   ....:     print('yes')
   ....: else:
   ....:     print('no')
   ....:
yes

In [13]: if datePattern.match(text2):
   ....:     print('yes')
   ....: else:
   ....:     print('no')
   ....:
no

match()会从字符串最开始自左向右匹配,发现第一个匹配规则后立即返回,如果想对整个字符串分析取出所有符合规则的字符串,则需要祭出findall():

In [14]: text = '今天是25/7/2017. 明天是26/7/2017.'

In [15]: datePattern.findall(text)
Out[15]: ['25/7/2017', '26/7/2017']

我们的正则已经具备从字符串中提取出日期的模式,如果想从日期中提出月和日呢?需要改写一个datePattern

In [16]: datePattern
Out[16]: re.compile(r'\d+/\d+/\d+')

# 重写`datePattern`为其\d+补上一个括号
In [17]: datePattern = re.compile(r'(\d+)/(\d+)/(\d+)')

# 开始测试
In [18]: pickUp = datePattern.match('25/7/2017')

In [19]: pickUp.group(0)
Out[19]: '25/7/2017'

In [20]: pickUp.group(1)
Out[20]: '25'

In [21]: pickUp.group(2)
Out[21]: '7'

In [22]: pickUp.group(3)
Out[22]: '2017'

In [25]: pickUp.groups()
Out[25]: ('25', '7', '2017')

In [27]: month, day, year = pickUp.groups()

In [29]: print(text)
今天是25/7/2017. 明天是26/7/2017.

In [30]: datePattern.findall(text)
Out[30]: [('25', '7', '2017'), ('26', '7', '2017')]

In [31]: for month,day,year in datePattern.findall(text):
   ....:     print('{}-{}-{}'.format(year, month, day))
   ....:
2017-25-7
2017-26-7

findall()方法会搜索文本并以列表形式返回所有的匹配。如果你想以迭代方式返会所有匹配结果,使用finditer():

In [32]: for m in datePattern.finditer(text):
   ....:     print(m.groups())
   ....:
('25', '7', '2017')
('26', '7', '2017')

到此为止,对于复杂字符串搜索,就是使用正则,一般使用正则的流程就是:re.compile()先编一个正则式,然后match()/findall()...做查找,然后就是groups()提出来