[英]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,}
您的目標是捕獲緊隨AAA
所有 ABC#
。 如您在此Debuggex演示中所見,所有ABC#
確實都已匹配(它們以黃色突出顯示)。 但是,由於只有“正在重復的內容”部分
ABC[0-9]\r\n
{1,}
未被捕獲,因此將導致除最后一場比賽之外的所有比賽都被丟棄。 要獲取它們,還必須捕獲量詞:
AAA\r\n((?:ABC[0-9]\r\n){1,})
我已將“正在重復的內容”部分( 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.