簡體   English   中英

re.finditer 和 re.findall 之間的不同行為

[英]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上都嘗試過。

finditerfindall之間的一個區別是,前者返回正則表達式匹配對象,而另一個則返回匹配的捕獲組的元組(如果沒有捕獲組,則返回整個匹配項)。

所以

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM