<p><strong>tdlr</strong>:由于在同一起始字符串索引中可能存在多个正则表达式匹配项,<code>re.findall</code>或其他正则表达式方法在每个起始索引中只能找到一个匹配项。你必须中断搜索才能找到所有的</p>
<hr/>
<p>问题是正则表达式findall不能从每个索引中找到所有组合;它从每个索引中只找到一个匹配项,通常是最长的匹配项。查找重叠匹配的技术仍然会错过单个字符串索引中可能的多个匹配。你需要修改你的方法</p>
<p>如果您检查您的正则表达式:</p>
<pre><code>([G]{3,6}[ACTG]{1,33}[G]{3,6}[ACTG]{1,33}[G]{3,6}[ACTG]{1,33}[G]{3,6})
</code></pre>
<p>您将注意到,匹配的序列必须以至少3<code>G</code>开始,并以相同的序列结束。<code>GGG[in_between_part]GGG</code>之间的序列短至9个字符,长至84个字符(可能包含相同的<code>'GGG'</code>起始/结束序列)</p>
<p>我们可以使用这些信息来找到所有符合该描述的可能字符串序列。然后我们使用您的正则表达式来过滤确定的序列确实是我们想要的序列</p>
<p>首先找到每个可能的<code>'GGG'</code>的字符串索引,子字符串将从这里开始或结束(根据定义):</p>
<pre><code>s = "GGGGAGAAGGGGGGCCTTCCTGGGTCCCCGAGAGTGCAGACATGCCTGGGTCCACAGCCACGGTTTGGG"
offset=0
indicies=[]
while (s_idx:=s[offset:].find('GGG'))>-1:
indicies.append(s_idx+offset)
offset+=s_idx+1
>>> indicies
[0, 1, 8, 9, 10, 11, 21, 47, 66]
# these are the indicies of 'GGG' that might be that start or end
# of a sub string of interest.
</code></pre>
<p>现在我们有了字符串中每个<code>'GGG'</code>的起始索引。我们现在可以使用正则表达式和对分模块来过滤正则表达式字符串中所有可能的匹配项</p>
<p>我们使用<a href="https://docs.python.org/3/library/bisect.html" rel="nofollow noreferrer">bisect</a>查找候选结束锚的结束位置,该位置与开始锚相同。对分模块允许我们构造一个切片,该切片形成以下子字符串:a)以<code>'GGG'</code>(来自<code>indicies</code>列表)开头,b)以<code>'GGG'</code>结尾,c)在起始和结束锚定之间的长度在9到84个字符之间。然后,我们使用<a href="https://docs.python.org/3/library/re.html#re.fullmatch" rel="nofollow noreferrer">re.fullmatch</a>确保候选子字符串完全匹配您的模式:</p>
<pre><code>import re
import bisect
matches=[]
min_len=3+9
max_len=3+84
pat=re.compile(r'([G]{3,6}[ACTG]{1,33}[G]{3,6}[ACTG]{1,33}[G]{3,6}[ACTG]{1,33}[G]{3,6})')
for x in indicies:
min_offest=bisect.bisect(indicies,x+min_len)
max_offset=bisect.bisect(indicies,x+max_len)
for idx in indicies[min_offest:]+indicies[max_offset:]:
candidate=s[x:idx+3]
if pat.fullmatch(candidate):
matches.append(candidate)
</code></pre>
<p>现在,我们可以打印找到的所有匹配项,其索引为<code>s</code>,长度为:</p>
<pre><code>>>> for ss in matches: print((s.index(ss), len(ss)),ss)
# This is only a primitive shortcut. If you want the actual
# index, save it when 'candidate' matches the regex
</code></pre>
<p>打印所有八个唯一匹配项,包括来自同一起始索引的匹配项:</p>
<pre><code>(0, 50) GGGGAGAAGGGGGGCCTTCCTGGGTCCCCGAGAGTGCAGACATGCCTGGG
(0, 69) GGGGAGAAGGGGGGCCTTCCTGGGTCCCCGAGAGTGCAGACATGCCTGGGTCCACAGCCACGGTTTGGG
(1, 49) GGGAGAAGGGGGGCCTTCCTGGGTCCCCGAGAGTGCAGACATGCCTGGG
(1, 68) GGGAGAAGGGGGGCCTTCCTGGGTCCCCGAGAGTGCAGACATGCCTGGGTCCACAGCCACGGTTTGGG
(8, 61) GGGGGGCCTTCCTGGGTCCCCGAGAGTGCAGACATGCCTGGGTCCACAGCCACGGTTTGGG
(9, 60) GGGGGCCTTCCTGGGTCCCCGAGAGTGCAGACATGCCTGGGTCCACAGCCACGGTTTGGG
(10, 59) GGGGCCTTCCTGGGTCCCCGAGAGTGCAGACATGCCTGGGTCCACAGCCACGGTTTGGG
(11, 58) GGGCCTTCCTGGGTCCCCGAGAGTGCAGACATGCCTGGGTCCACAGCCACGGTTTGGG
</code></pre>
<hr/>
<p>注:</p>
<p>如注释中所述,<a href="https://pypi.org/project/regex/" rel="nofollow noreferrer">regex module</a><strong>确实支持可变宽度的lookbehind</p>
<p>因此,您可能会想:</p>
<pre><code>m1=regex.findall(r'([G]{3,6}[ACTG]{1,33}[G]{3,6}[ACTG]{1,33}[G]{3,6}[ACTG]{1,33}[G]{3,6})', s, overlapped=True)
# produces 6 unique matches
m2=regex.findall(r'(?<=([G]{3,6}[ACTG]{1,33}[G]{3,6}[ACTG]{1,33}[G]{3,6}[ACTG]{1,33}[G]{3,6}))', s, overlapped=True)
# produces 2 matches, but one is a duplicate from m1
</code></pre>
<p>虽然这个组合找到了一个额外的字符串,即您正在寻找的字符串,但它没有找到所有8个唯一的匹配项。缺少索引1处的字符串<code>GGGAGAAGGGGGGCCTTCCTGGGTCCCCGAGAGTGCAGACATGCCTGGG</code></p>