簡體   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