python - 在正则表达式中使用组时 re.findall() 和 re.finditer() 之间的区别?
问题描述
考虑以下字符串
text2 = '''
Mr. Schafer
Mr Smith
Ms Davis
Mrs. Robinson
Mr. T
'''
我希望正则表达式匹配完整的名称,如 'Mr. 以谢弗为例
使用 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']
解决方案
返回的列表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')]
推荐阅读
- activemq - ActiveMQ 配置:BrokerXMLConfig activemq.xml - 未找到相对路径文件
- r - 如何在 igraph 中保留网络的一般形状?
- android - 如何读取所有子节点值并在firebase android中使用它们
- java - Java 中列表 String 和 String[] 列表,或 T 列表和 T[] 列表的通用方法
- php - 在运行时禁用 XDebug
- php - Mongo Db PHP 根据特定字段查找行数
- python - Python if 函数以无效语法回复
- java - 如何反/序列化具有动态类型属性的实例
- java - Thymeleaf 无法在单元测试的临时目录中找到片段
- java - o(1) 或 o(n) 的复杂度是多少?