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

时间:2014-04-14 13:59:18

标签: python regex

我正在尝试在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")

2 个答案:

答案 0 :(得分:6)

这是你的正则表达式:

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

Regular expression visualization

Debuggex Demo

您的目标是捕获紧随ABC#后的所有 AAA。正如您在此Debuggex演示中所看到的,所有ABC#确实匹配(它们以黄色突出显示)。但是,因为只有“正在重复的部分”部分

ABC[0-9]\r\n

正在captured(位于括号内)及其quantifier

{1,}

未被捕获,因此导致除最后一个之外的所有匹配被丢弃。要获得它们,您还必须捕获量词:

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

Regular expression visualization

Debuggex Demo

我已将“正在重复的内容”部分(ABC[0-9]\r\n)放入non-capturing group。 (我也停止捕捉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)


请考虑将Stack Overflow Regular Expressions FAQ加入书签以供将来参考。这个答案中的链接来自它。

答案 1 :(得分:0)

您希望以最贪婪的方式在 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]