python正则表达式对搜索字符串的每个索引进行多次匹配
我正在寻找一种方法,使pythonre模块或更新的regex模块的finditer函数能够匹配特定模式的所有可能变化,不管是重叠的还是其他的。我知道在不使用搜索字符串的情况下使用lookaheads来获取匹配项,但我仍然只在每个索引中获取一个正则表达式,在这里我可以获取多个正则表达式 我使用的正则表达式如下所示:python正则表达式对搜索字符串的每个索引进行多次匹配,python,regex,regex-lookarounds,regex-greedy,Python,Regex,Regex Lookarounds,Regex Greedy,我正在寻找一种方法,使pythonre模块或更新的regex模块的finditer函数能够匹配特定模式的所有可能变化,不管是重叠的还是其他的。我知道在不使用搜索字符串的情况下使用lookaheads来获取匹配项,但我仍然只在每个索引中获取一个正则表达式,在这里我可以获取多个正则表达式 我使用的正则表达式如下所示: (?=A{2}[BA]{1,6}A{2}) 因此,在字符串中: aabaabaa 它应该能够匹配: AABAA aabaabaa AABBAA 但目前它将只匹配最后两个。我意识到这与[
(?=A{2}[BA]{1,6}A{2})
因此,在字符串中:
aabaabaa
它应该能够匹配:
AABAA
aabaabaa
AABBAA
但目前它将只匹配最后两个。我意识到这与
[BA]{1,6}
的贪婪有关。有没有办法让正则表达式匹配从最懒到最贪婪的所有模式?此正则表达式正确匹配3个字符串:
AABAA AABAABBAA AABBAA
((^(AA){1}(BAA)$){1})|(((AA){1}(BB){1}(AA){1}$){1})
如果要用python搜索字符串“aabaabaa”中的这些子字符串,可以使用方法“search”:
您将无法为此使用
finditer()
,也无法使用任何常规的匹配导航方法。我管理它的唯一方法(在Java中,而不是Python中)是手动迭代源字符串的每个唯一子字符串(由起始位置和长度决定),以正常方式(不是使用lookarounds)将正则表达式应用于每个子字符串,并在两端锚定
Java的Matcher类通过其region()
方法提供了一种方便的方法。它允许您假装源的任何子字符串都是真正的全部,而不必生成大量新的字符串对象。而matches()
方法会自动将匹配锚定在两端,因此您根本不必修改正则表达式
我很确定Python的re
模块不支持这样的功能,但是在另一个模块中可能有一些东西可以用来达到类似的效果(我对Python不太精通,所以这只是乐观)。我甚至不太熟悉regex
模块,但它似乎支持所有其他风格的最甜美的功能,因此值得一看
如果您感兴趣,下面是我的Java解决方案:
public static void printAllMatches(String text, String regex)
{
System.out.printf("%s results:%n", text);
Matcher m = Pattern.compile(regex).matcher(text);
int end = text.length();
for (int i = 0; i < end; ++i)
{
for (int j = i + 1; j <= end; ++j)
{
m.region(i, j);
if (m.matches())
{
for (int k = 0; k < i; k++)
{
System.out.print(" ");
}
System.out.println(m.group());
}
}
}
}
我意识到这和[BA]{1,6}的贪婪有关。有没有办法让正则表达式匹配从最懒惰到最贪婪的所有模式?
这个问题有两个方面
1. Regex engines will only match once at a character position.
2. There is not a regex construct of between lazy and greedy
it's either one or the other.
跳过问题1。目前
问题2:可能存在一种情况,即存在
{1,6}
1,2,3,4,5或6个匹配项指在给定位置上的结构(字符) 要解决这个问题,必须指定独立的{1}、{2}、{3}、{4}、{5}、{6}
作为该位置的可选替代品。
显然,范围
{1,6}
不起作用
就范围而言,可以指定它来查找通过添加惰性修饰符(如
{1,6}?
但这只能找到它能找到的最小数量,不能多,也不能少 最后, 问题1:
当正则表达式引擎匹配时,它总是向前推进当前位置
等于最后一场比赛长度的数量。
对于匹配的零长度断言,它会人为地增加
该位置向前移动一个字符
因此,考虑到这两个问题,我们可以利用这些优势/劣势来解决
需要一个解决方法,并且必须承受一些副作用 变通办法:
将所有可能的备选方案放在一个位置,作为要分析的断言。 一个位置的每个匹配项都将包含一个包含变体的组列表。
因此,如果您在6个可能的变体组中匹配了3个变体,则具有值的组将是变体 如果所有组都没有值,则在该位置未发现变体。
由于所有断言都是可选的,因此不会发生任何变体。
为了避免在这些特定位置进行不必要的匹配,最终的
条件可用于不报告这些。(即,
(?(1)|(?(2)|(?!))
等)
让我们以您的范围示例为例。
我们将在结尾使用条件验证匹配的组,
但是没有它也可以做到。
_请注意,使用此范围示例会导致与相同的重叠
最后一场比赛中的值。这不会确保在
位置(下面的示例显示了如何避免此情况) 输出:
** Grp 1 - ( pos 0 , len 5 )
AABAA
** Grp 2 - ( pos 0 , len 9 )
AABAABBAA
-------------
** Grp 1 - ( pos 3 , len 6 )
AABBAA
** Grp 2 - ( pos 3 , len 6 )
AABBAA
** Grp 1 - ( pos 0 , len 5 )
AABAA
** Grp 2 - NULL
** Grp 3 - NULL
** Grp 4 - NULL
** Grp 5 - ( pos 0 , len 9 )
AABAABBAA
** Grp 6 - NULL
------------------
** Grp 1 - NULL
** Grp 2 - ( pos 3 , len 6 )
AABBAA
** Grp 3 - NULL
** Grp 4 - NULL
** Grp 5 - NULL
** Grp 6 - NULL
相同,但没有范围问题。
在这里,我们明确定义了独特的结构。
注意每个位置的唯一值 输出:
** Grp 1 - ( pos 0 , len 5 )
AABAA
** Grp 2 - ( pos 0 , len 9 )
AABAABBAA
-------------
** Grp 1 - ( pos 3 , len 6 )
AABBAA
** Grp 2 - ( pos 3 , len 6 )
AABBAA
** Grp 1 - ( pos 0 , len 5 )
AABAA
** Grp 2 - NULL
** Grp 3 - NULL
** Grp 4 - NULL
** Grp 5 - ( pos 0 , len 9 )
AABAABBAA
** Grp 6 - NULL
------------------
** Grp 1 - NULL
** Grp 2 - ( pos 3 , len 6 )
AABBAA
** Grp 3 - NULL
** Grp 4 - NULL
** Grp 5 - NULL
** Grp 6 - NULL
最后,您只需在每场比赛中抓取捕获组并将它们放入数组中 我不确定正则表达式是否适合这项工作,或者至少它本身不是。您可以使用两个函数,一个用于将字符串拆分为所有可能的子字符串,另一个用于检查每个子字符串是否与模式匹配。这适用于我给出的特定示例,但看起来并不能真正回答我关于同时匹配贪婪和懒惰的更一般的问题。这是一个非常聪明的解决方案!非常感谢,一旦我赢得足够的声誉来奖励它,你将获得+1!不幸的是,这似乎是使用单个正则表达式的唯一方法,然而,因为我正在处理的实际情况有三个长度范围1-7,所以我可能需要编写一个包含7^3个不同选项的正则表达式,或者一些荒谬的事情@马修帕克-如果你需要的话,我给了你一些机会。作为一名工程师,在这种情况下,我经常想到熵(或跨城交通)。宇宙的δS总是>或=为零。一个范围可以量化一组结构(即(?:X | YR | M.P | T(?=u))
{1}
)。那么你只需要7个。(1-7). 在r
# (?=(A{2}[BA]{1}A{2}))?(?=(A{2}[BA]{2}A{2}))?(?=(A{2}[BA]{3}A{2}))?(?=(A{2}[BA]{4}A{2}))?(?=(A{2}[BA]{5}A{2}))?(?=(A{2}[BA]{6}A{2}))?(?(1)|(?(2)|(?(3)|(?(4)|(?(5)|(?(6)|(?!)))))))
(?=
( # (1 start)
A{2}
[BA]{1}
A{2}
) # (1 end)
)?
(?=
( # (2 start)
A{2}
[BA]{2}
A{2}
) # (2 end)
)?
(?=
( # (3 start)
A{2}
[BA]{3}
A{2}
) # (3 end)
)?
(?=
( # (4 start)
A{2}
[BA]{4}
A{2}
) # (4 end)
)?
(?=
( # (5 start)
A{2}
[BA]{5}
A{2}
) # (5 end)
)?
(?=
( # (6 start)
A{2}
[BA]{6}
A{2}
) # (6 end)
)?
(?(1)|(?(2)|(?(3)|(?(4)|(?(5)|(?(6)|(?!)))))))
** Grp 1 - ( pos 0 , len 5 )
AABAA
** Grp 2 - NULL
** Grp 3 - NULL
** Grp 4 - NULL
** Grp 5 - ( pos 0 , len 9 )
AABAABBAA
** Grp 6 - NULL
------------------
** Grp 1 - NULL
** Grp 2 - ( pos 3 , len 6 )
AABBAA
** Grp 3 - NULL
** Grp 4 - NULL
** Grp 5 - NULL
** Grp 6 - NULL