我试图捕获n个连续的大写单词。我目前的代码是
n=5
a='This is a Five Gram With Five Caps and it also contains a Two Gram'
re.findall(' ([A-Z]+[a-z|A-Z]* ){n}',a)
返回以下内容:
['Caps ']
它识别出第五个连续的大写单词,但我希望它返回整个大写单词串。换一种说法:
[' Five Gram With Five Caps ']
请注意,|
不会在角色类中充当OR
。它会与字面上的|
相匹配。另一个问题是findall
的行为是返回比赛,除非存在一个组(尽管python's documentation并没有真正明确这一点):
从左到右扫描字符串,并按找到的顺序返回匹配项。如果模式中存在一个或多个组,则返回组列表
所以这就是为什么你得到第一个捕获组的结果,这是Caps
的最后一个大写字母。
简单的解决方案是将捕获组更改为非捕获组。我也在开始时将空间更改为\b
,以便不匹配额外的空格(我认为你打算计划修剪)。
import re
r = re.compile(r"\b(?:[A-Z][a-zA-Z]* ){5}")
s = "This is a Five Gram With Five Caps and it also contains a Two Gram"
print(r.findall(s))
\b(?:[A-Z][a-zA-Z]* ){5}
\b
将位置断言为单词边界(?:[A-Z][a-zA-Z]* ?){5}
完全匹配以下5次
[A-Z]
匹配一个大写的ASCII字母一次
[a-zA-Z]*
任意次数匹配任何ASCII字母
匹配一个空间结果:['Five Gram With Five Caps ']
此外,您可以使用正则表达式\b\[A-Z\]\[a-zA-Z\]*(?: \[A-Z\]\[a-zA-Z\]*){4}\b
。这将允许匹配字符串的开头/结尾以及中间的任何位置,而不会占用额外的空格。另一种选择可能包括(?:^|(?<= ))\[A-Z\]\[a-zA-Z\]*(?: \[A-Z\]\[a-zA-Z\]*){4}(?= |$)