簡體   English   中英

Python re.finditer match.groups() 不包含匹配中的所有組

[英]Python re.finditer match.groups() does not contain all groups from match

我正在嘗試在 Python 中使用正則表達式從多行搜索中查找和打印所有匹配的行。 我正在搜索的文本可能具有以下示例結構:

AAA
ABC1
ABC2
ABC3
AAA
ABC1
ABC2
ABC3
ABC4
ABC
AAA
ABC1
AAA

我想從中檢索至少出現一次並以AAA開頭的ABC*

問題是,盡管小組抓住了我想要的東西:

match = <_sre.SRE_Match object; span=(19, 38), match='AAA\nABC2\nABC3\nABC4\n'>

...我只能訪問該組的最后一場比賽:

match groups = ('AAA\n', 'ABC4\n')

下面是我用於此問題的示例代碼。

#! python
import sys
import re
import os

string = "AAA\nABC1\nABC2\nABC3\nAAA\nABC1\nABC2\nABC3\nABC4\nABC\nAAA\nABC1\nAAA\n"
print(string)

p_MATCHES = []
p_MATCHES.append( (re.compile('(AAA\n)(ABC[0-9]\n){1,}')) ) #   
matches = re.finditer(p_MATCHES[0],string)

for match in matches:
    strout = ''
    gr_iter=0
    print("match = "+str(match))
    print("match groups = "+str(match.groups()))
    for group in match.groups():
    gr_iter+=1
    sys.stdout.write("TEST GROUP:"+str(gr_iter)+"\t"+group) # test output
    if group is not None:
        if group != '':
            strout+= '"'+group.replace("\n","",1)+'"'+'\n'
sys.stdout.write("\nCOMPLETE RESULT:\n"+strout+"====\n")

這是您的正則表達式:

(AAA\r\n)(ABC[0-9]\r\n){1,}

正則表達式可視化

Debuggex演示

您的目標是捕獲緊隨AAA 所有 ABC# 如您在此Debuggex演示中所見,所有ABC#確實都已匹配(它們以黃色突出顯示)。 但是,由於只有“正在重復的內容”部分

ABC[0-9]\r\n

捕獲 (在括號內)及其量詞

{1,}

未被捕獲,因此將導致除最后一場比賽之外的所有比賽被丟棄。 要獲取它們,還必須捕獲量詞:

AAA\r\n((?:ABC[0-9]\r\n){1,})

正則表達式可視化

Debuggex演示

我已將“正在重復的內容”部分( ABC[0-9]\\r\\n )放入一個非捕獲組 (由於您似乎不需要AAA ,因此我也已停止捕獲它。)

捕獲的文本可以在換行符上分割,並且將為您提供所有所需的內容。

(請注意, \\n本身在Debuggex中不起作用。它需要\\r\\n 。)


這是一種解決方法。 沒有太多的正則表達式類型可以通過重復捕獲(哪些捕獲?)進行迭代。 一種更普通的方法是遍歷並處理找到的每個匹配項。 這是來自Java的示例:

   import java.util.regex.*;

public class RepeatingCaptureGroupsDemo {
   public static void main(String[] args) {
      String input = "I have a cat, but I like my dog better.";

      Pattern p = Pattern.compile("(mouse|cat|dog|wolf|bear|human)");
      Matcher m = p.matcher(input);

      while (m.find()) {
         System.out.println(m.group());
      }
   }
}

輸出:

cat
dog

(摘自http://ocpsoft.org/opensource/guide-to-regular-expressions-in-java-part-1/ ,大約減少了1/4)


請考慮將“ 堆棧溢出正則表達式” FAQ標記為書簽,以備將來參考。 這個答案中的鏈接來自它。

您希望以最貪婪的方式在AAA\\n之后出現連續ABC\\n的模式。 您還需要連續的ABC\\n組,而不是該組和最近的ABC\\n的元組。 因此,在您的正則表達式中,排除組內的子組。 注意模式,寫出代表整個字符串的模式。

AAA\n(ABC[0-9]\n)+

然后用 () 捕獲您感興趣的那個,同時記住要排除子組

AAA\n((?:ABC[0-9]\n)+)

然后您可以使用 findall() 或 finditer()。 我發現 findIter 更容易,尤其是當您處理多個捕獲時。 查找器:-

import re
matches_iter = re.finditer(r'AAA\n((?:ABC[0-9]\n)+)', string)

[print(i.group(1)) for i in matches_iter]

findall,使用原來的 {1,} 作為其更冗長的 + 形式:-

matches_all = re.findall(r'AAA\n((?:ABC[0-9]\n){1,})', string)

[[print(x) for x in y.split("\n")] for y in matches_all]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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