首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在regex中使用组时,re.findall()和re.finditer()之间的区别?

在regex中使用组时,re.findall()和re.finditer()之间的区别?
EN

Stack Overflow用户
提问于 2020-09-25 05:49:36
回答 3查看 1K关注 0票数 1

考虑下面的字符串

代码语言:javascript
复制
text2 = '''
Mr. Schafer
Mr Smith
Ms Davis
Mrs. Robinson
Mr. T
'''

我希望regex与全名相匹配,例如在“Schafer先生”中

使用finditer():

代码语言:javascript
复制
matches = re.finditer(r'(Mr|Ms|Mrs)\.?\s[A-Z]\w*', text2)
for match in matches:
    print(match)

结果:

代码语言:javascript
复制
<_sre.SRE_Match object; span=(1, 12), match='Mr. Schafer'>
<_sre.SRE_Match object; span=(13, 21), match='Mr Smith'>
<_sre.SRE_Match object; span=(22, 30), match='Ms Davis'>
<_sre.SRE_Match object; span=(31, 44), match='Mrs. Robinson'>
<_sre.SRE_Match object; span=(45, 50), match='Mr. T'>

finditer()给出了我想要的结果,但不在列表中。

但是当我使用findall()时:

代码语言:javascript
复制
re.findall(r'(Mr|Ms|Mrs)\.?\s[A-Z]\w*', text2)

结果:

代码语言:javascript
复制
['Mr', 'Mr', 'Ms', 'Mrs', 'Mr']

,这是为什么?如何使用findall()获得我想要的结果

我想要这个结果:

代码语言:javascript
复制
['Mr. Schafer', 'Mr Smith', 'Ms Davis', 'Mrs. Robinson', 'Mr. T']
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-09-25 06:21:07

re.findall返回的列表包含:

  • 每个匹配的文本,如果正则表达式没有捕获
  • ,则每个匹配中的捕获文本,如果正则表达式恰好有一个捕获
  • ,则每个捕获对应的子字符串元组,如果正则表达式有多个捕获。

捕获是被括号包围的正则表达式的一部分,除非使用(?:...);上下文中的?:告诉Python库不要将括号视为定义捕获。(当然,它仍然用于分组。)

因此,最简单的(也可能是最快的)解决方案是确保regex没有捕获,方法是使用(?:...)来包围标题,而不仅仅是(...)

代码语言:javascript
复制
>>> re.findall(r'(?:Mr|Ms|Mrs)\.?\s[A-Z]\w*', text2)
['Mr. Schafer', 'Mr Smith', 'Ms Davis', 'Mrs. Robinson', 'Mr. T']

您还可以显式捕获完整的名称:

代码语言:javascript
复制
>>> re.findall(r'((?:Mr|Ms|Mrs)\.?\s[A-Z]\w*)', text2)
['Mr. Schafer', 'Mr Smith', 'Ms Davis', 'Mrs. Robinson', 'Mr. T']

在这种情况下,这样做没有多大意义,但是如果希望在输出中不显示模式的一部分,那么“一个捕获”表单就会很有用。

最后,您可能希望同时使用元组中的尊称和姓氏:

代码语言:javascript
复制
>>> re.findall(r'(?:(Mr|Ms|Mrs)\.?\s([A-Z]\w*))', text2)
[('Mr', 'Schafer'), ('Mr', 'Smith'), ('Ms', 'Davis'), ('Mrs', 'Robinson'), ('Mr', 'T')]
票数 4
EN

Stack Overflow用户

发布于 2020-09-25 06:16:26

"()“部分是捕获指示器。

添加"?:“设置非捕获。

代码语言:javascript
复制
import re

text2 = '''
        Mr. Schafer
        Mr Smith
        Ms Davis
        Mrs. Robinson
        Mr. T
        '''
print(re.findall(r"(?:Mr|Ms|Mrs)\.?\s[A-Za-z]*w*", text2))
# ['Mr. Schafer', 'Mr Smith', 'Ms Davis', 'Mrs. Robinson', 'Mr. T']

https://regexr.com/的左边有一个便笺表。

票数 1
EN

Stack Overflow用户

发布于 2020-09-25 06:32:58

我更喜欢finditer而不是findallfinditer返回文本中匹配对象的迭代器,而findall返回文本中匹配模式的列表。为了提高效率,生成器比列表更好,因为列表将所有数据读入内存,而层没有。要从iterator获取值,只需使用.group()

代码语言:javascript
复制
import re

text2 = '''
Mr. Schafer
Mr Smith
Ms Davis
Mrs. Robinson
Mr. T
'''


matches = re.finditer(r'(Mr|Ms|Mrs)\.?\s[A-Z]\w*', text2)

match_list = [match.group() for match in matches]
print(match_list)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64058532

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档