在正则表达式中使用组时 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
'''
我希望正则表达式匹配完整的名称,例如 'Mr. Schafer'
使用 finditer():
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']
"()" 部分是捕获指标。
添加“?:”以设置 non-capturing。
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/
左侧有备忘单。
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')]
我更喜欢 finditer
而不是 findall
。 finditer
returns 文本中匹配对象的迭代器,而 findall
returns 文本中匹配模式的列表。对于有效性生成器比列表更好,因为列表所有读取数据到内存而层没有。要从 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)
考虑以下字符串
text2 = '''
Mr. Schafer
Mr Smith
Ms Davis
Mrs. Robinson
Mr. T
'''
我希望正则表达式匹配完整的名称,例如 'Mr. Schafer'
使用 finditer():
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']
"()" 部分是捕获指标。
添加“?:”以设置 non-capturing。
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/ 左侧有备忘单。
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')]
我更喜欢 finditer
而不是 findall
。 finditer
returns 文本中匹配对象的迭代器,而 findall
returns 文本中匹配模式的列表。对于有效性生成器比列表更好,因为列表所有读取数据到内存而层没有。要从 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)