[英]Why does re.findall() give me different results than re.finditer() in Python?
[英]Different behavior between re.finditer and re.findall
我正在使用以下代碼:
CARRIS_REGEX=r'<th>(\d+)</th><th>([\s\w\.\-]+)</th><th>(\d+:\d+)</th><th>(\d+m)</th>'
pattern = re.compile(CARRIS_REGEX, re.UNICODE)
matches = pattern.finditer(mailbody)
findall = pattern.findall(mailbody)
但是finditer和findall是在找不同的東西。 Findall 確實找到了給定字符串中的所有匹配項。 但是finditer只找到第一個,返回一個只有一個元素的迭代器。
如何使 finditer 和 findall 的行為相同?
謝謝
我在這里無法重現。 在Python 2.7和3.1上都嘗試過。
finditer
和findall
之間的一個區別是,前者返回正則表達式匹配對象,而另一個則返回匹配的捕獲組的元組(如果沒有捕獲組,則返回整個匹配項)。
所以
import re
CARRIS_REGEX=r'<th>(\d+)</th><th>([\s\w\.\-]+)</th><th>(\d+:\d+)</th><th>(\d+m)</th>'
pattern = re.compile(CARRIS_REGEX, re.UNICODE)
mailbody = open("test.txt").read()
for match in pattern.finditer(mailbody):
print(match)
print()
for match in pattern.findall(mailbody):
print(match)
版畫
<_sre.SRE_Match object at 0x00A63758>
<_sre.SRE_Match object at 0x00A63F98>
<_sre.SRE_Match object at 0x00A63758>
<_sre.SRE_Match object at 0x00A63F98>
<_sre.SRE_Match object at 0x00A63758>
<_sre.SRE_Match object at 0x00A63F98>
<_sre.SRE_Match object at 0x00A63758>
<_sre.SRE_Match object at 0x00A63F98>
('790', 'PR. REAL', '21:06', '04m')
('758', 'PORTAS BENFICA', '21:10', '09m')
('790', 'PR. REAL', '21:14', '13m')
('758', 'PORTAS BENFICA', '21:21', '19m')
('790', 'PR. REAL', '21:29', '28m')
('758', 'PORTAS BENFICA', '21:38', '36m')
('758', 'SETE RIOS', '21:49', '47m')
('758', 'SETE RIOS', '22:09', '68m')
如果要從finditer
獲得與從findall
獲得相同的輸出,則需要
for match in pattern.finditer(mailbody):
print(tuple(match.groups()))
re.findall(pattern.string)
findall()返回字符串中所有不重復的模式匹配作為字符串列表。
re.finditer()
finditer()返回可調用對象 。
在這兩個函數中,從左到右掃描字符串,並按找到的順序返回匹配項。
您不能使它們的行為相同,因為它們是不同的。 如果您確實想從finditer
創建結果列表,則可以使用列表finditer
:
>>> [match for match in pattern.finditer(mailbody)]
[...]
通常,使用for
循環訪問re.finditer
返回的匹配re.finditer
:
>>> for match in pattern.finditer(mailbody):
... ...
我從Python 2 **中的 正則表達式操作中獲得了該示例,並且對該示例進行了詳細的修改,並對它進行了詳細描述。 為了說明整個示例,讓我們獲取字符串類型的變量調用,
text = "He was carefully disguised but captured quickly by police."
編譯類型正則表達式模式為
regEX = r"\w+ly"
pattern = re.compile(regEX)
\\w
mean 匹配任何單詞字符(字母數字和下划線) , +
mean 匹配前面的標記中的1個或多個,並且整個含義是選擇任何以 ly
結尾的單詞 。 只有兩個2個單詞(“仔細地”和“迅速地”)滿足上述正則表達式。
在進入re.findall()或re.finditer()之前 ,讓我們看看re.search()在Python 2. * Documentation中的含義。
掃描字符串以查找正則表達式模式產生匹配項的第一個位置,然后返回相應的MatchObject實例。 如果字符串中沒有位置與模式匹配,則返回None;否則返回No。 請注意,這與在字符串中的某個點找到零長度匹配不同。
以下代碼行為您提供了對re.search()的基本了解。
search = pattern.search(text)
print(search)
print(type(search))
#output
<re.Match object; span=(7, 16), match='carefully'>
<class 're.Match'>
根據Python 2. * Documentation ,它將生成類類型對象的re.MatchObject ,它具有13種受支持的方法和屬性。 這個span()方法由text
變量中匹配單詞的起點和終點(在上面的示例中為7和16)組成。 re.search()方法僅考慮第一個匹配項,否則返回None
。
讓我們進入一個問題,在此之前先看看re.finditer()在Python 2. * Documentation中的含義。
返回一個迭代器,該迭代器在字符串的RE模式的所有非重疊匹配上產生MatchObject實例。 從左到右掃描該字符串,並以找到的順序返回匹配項。 空匹配項包含在結果中。
接下來的代碼行使您對re.finditer()有了基本的了解。
finditer = pattern.finditer(text)
print(finditer)
print(type(finditer))
#output
<callable_iterator object at 0x040BB690>
<class 'callable_iterator'>
上面的示例為我們提供了需要循環的迭代器對象 。 這顯然不是我們想要的結果。 讓我們循環finditer
,看看Iterator Objects內部有什么。
for anObject in finditer:
print(anObject)
print(type(anObject))
print()
#output
<re.Match object; span=(7, 16), match='carefully'>
<class 're.Match'>
<re.Match object; span=(40, 47), match='quickly'>
<class 're.Match'>
此結果與我們之前獲得的re.search()結果非常相似。 但是我們可以在上面的輸出<re.Match object; span=(40, 47), match='quickly'>
看到新結果<re.Match object; span=(40, 47), match='quickly'>
<re.Match object; span=(40, 47), match='quickly'>
。 正如我之前在Python 2. * Documentation中提到的那樣, re.search()將掃描字符串以查找正則表達式模式產生匹配的第一個位置,而re.finditer()將掃描字符串以查找所有位置。正則表達式模式產生匹配項,並且比re.findall()方法返回更多詳細信息。
這是re.findall()在Python 2. * Documentation中的含義。
返回字符串中模式的所有非重疊匹配項,作為字符串列表。 從左到右掃描該字符串,並以找到的順序返回匹配項。 如果該模式中存在一個或多個組,則返回一個組列表;否則,返回一個列表。 如果模式包含多個組,則這將是一個元組列表。 空匹配項包含在結果中。
讓我們了解一下re.findall()中發生的情況。
findall = pattern.findall(text)
print(findall)
print(type(findall))
#output
['carefully', 'quickly']
<class 'list'>
此輸出僅為我們提供text
變量中匹配的單詞,否則返回一個空列表 。 輸出中的列表類似於re.MatchObject中的match
屬性。
這是完整的代碼,我在Python 3.7中嘗試過。
import re
text = "He was carefully disguised but captured quickly by police."
regEX = r"\w+ly"
pattern = re.compile(regEX)
search = pattern.search(text)
print(search)
print(type(search))
print()
findall = pattern.findall(text)
print(findall)
print(type(findall))
print()
finditer = pattern.finditer(text)
print(finditer)
print(type(finditer))
print()
for anObject in finditer:
print(anObject)
print(type(anObject))
print()
我來到這里試圖從我的.finditer()
的正則表達式結果中獲取一個字符串
解決方案實際上是我需要創建至少一個組,這樣才能從組 dict 中獲取它
- yield from zip(re.finditer(r"\w+", line) ...
+ yield from zip(re.finditer(r"(\w+)", line) ...
...
- block.(miscellaneous attempts)
+ block.group(1)
從大文件中提取時使用 finditer(),因為它將返回一個迭代器 object,這有助於保存 memory 另一方面 findall() 返回一個列表。 finditer() 的提取方式與 findall() 不同。
例如:
text_to_search = ''' abcdefghijklmnopqurtuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ\s 321-555-4321 1234567890 Ha HaHa MetaCharacters (Need to be escaped): . ^ $ * + ? { } [ ] \ | ( ) khanafsaan11.com 321-555-4321 123.555.1234 123*555*-1234 123.555.1234 800-555-1234 900-555-1234 Mr. Schafer Mr Smith Ms Davis Mrs. Robinson Mr. T Mr_hello ''' pattern=re.compile(r'M(r|rs|s)\.? [A-Z][a-z]*') print(list(pattern.finditer(text_to_search))) #converted to list print(pattern.findall(text_to_search))
Output:
['r', 'r', 's', 'rs', 'r'] [, , , , ]
你可以從 finditer() output 得到像 findall() 這樣的 output 如下
for obj in pattern.finditer(text_to_search): print(obj.group()) #group() is an attribute of re.Match object #ouput Mr. Schafer Mr Smith Ms Davis Mrs. Robinson Mr. T
finditer() 返回迭代器 object,finditer() 有助於提高 memory 基於生成器的效率。
def my_ranger(max_num):
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.