繁体   English   中英

在正则表达式中使用组时 re.findall() 和 re.finditer() 之间的区别?

[英]Difference between re.findall() and re.finditer() when using groups in regex?

考虑以下字符串

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

我希望正则表达式匹配完整的名称,如“先生”。 Schafer'例如

使用查找器():

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

结果:

<_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() 时:

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

结果:

['Mr', 'Mr', 'Ms', 'Mrs', 'Mr']

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

['Mr. Schafer', 'Mr Smith', 'Ms Davis', 'Mrs. Robinson', 'Mr. T']

re.findall返回的列表包含:

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

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

所以最简单(也可能是最快)的解决方案是确保正则表达式没有捕获,通过使用(?:...)来包围标题,而不仅仅是(...)

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

您还可以明确捕获完整名称:

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

在这种情况下这样做没有多大意义,但是如果您希望模式的一部分不显示在输出中,则“一次捕获”形式可能很有用。

最后,您可能需要元组中的敬语和姓氏:

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

“()”部分是捕获指示符。

添加“?:”以设置非捕获。

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/左侧有一个备忘单。

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

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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM