Python 如何在正则表达式中使用布尔或
我想使用正则表达式来查找一个子字符串,后跟可变数量的字符,后跟几个子字符串中的任意一个 芬德尔先生Python 如何在正则表达式中使用布尔或,python,regex,parsing,boolean-logic,Python,Regex,Parsing,Boolean Logic,我想使用正则表达式来查找一个子字符串,后跟可变数量的字符,后跟几个子字符串中的任意一个 芬德尔先生 "ATGTCAGGTAAGCTTAGGGCTTTAGGATT" 你应该给我: ['ATGTCAGGTAA', 'ATGTCAGGTAAGCTTAG', 'ATGTCAGGTAAGCTTAGGGCTTTAG'] 我尝试了以下所有方法,但均未成功: import re string2 = "ATGTCAGGTAAGCTTAGGGCTTTAGGATT" re.findall('(ATG.*TAA)|
"ATGTCAGGTAAGCTTAGGGCTTTAGGATT"
你应该给我:
['ATGTCAGGTAA', 'ATGTCAGGTAAGCTTAG', 'ATGTCAGGTAAGCTTAGGGCTTTAG']
我尝试了以下所有方法,但均未成功:
import re
string2 = "ATGTCAGGTAAGCTTAGGGCTTTAGGATT"
re.findall('(ATG.*TAA)|(ATG.*TAG)', string2)
re.findall('ATG.*(TAA|TAG)', string2)
re.findall('ATG.*((TAA)|(TAG))', string2)
re.findall('ATG.*(TAA)|(TAG)', string2)
re.findall('ATG.*(TAA)|ATG.*(TAG)', string2)
re.findall('(ATG.*)(TAA)|(ATG.*)(TAG)', string2)
re.findall('(ATG.*)TAA|(ATG.*)TAG', string2)
我在这里遗漏了什么?这不是很容易,因为a)你想要重叠匹配,b)你想要贪婪和非贪婪,以及两者之间的一切 只要字符串相当短,就可以检查每个子字符串:
import re
s = "ATGTCAGGTAAGCTTAGGGCTTTAGGATT"
p = re.compile(r'ATG.*TA[GA]$')
for start in range(len(s)-6): # string is at least 6 letters long
for end in range(start+6, len(s)):
if p.match(s, pos=start, endpos=end):
print(s[start:end])
这张照片是:
ATGTCAGGTAA
ATGTCAGGTAAGCTTAG
ATGTCAGGTAAGCTTAGGGCTTTAG
因为你似乎在处理DNA序列或类似的东西,所以也一定要检查一下。我喜欢公认的答案很好:-)也就是说,我添加这个是为了获取信息,而不是寻找分数 如果您对此有很大的需求,那么尝试在
O(N^2)
索引对上进行匹配可能很快就会变得极其缓慢。一个改进是使用.search()
方法直接“跳跃”到可能有回报的唯一起始索引。下面就是这样
它还使用.fullmatch()
方法,这样您就不必人为地更改“自然”regexp(例如,在您的示例中,不需要向regexp添加尾随的$
——事实上,在下面的代码中,这样做将不再像预期的那样工作)。请注意,.fullmatch()
是在Python3.4中添加的,因此此代码也需要Python3
最后,本文旨在概括re
模块的finditer()
函数/方法。虽然您不需要匹配对象(您只需要字符串),但它们更普遍适用,而且返回生成器通常比返回列表更友好
因此,不,这并不能完全满足您的需求,但在Python 3中,它可以更快地满足您的需求:
def finditer_overlap(regexp, string):
start = 0
n = len(string)
while start <= n:
# don't know whether regexp will find shortest or
# longest match, but _will_ find leftmost match
m = regexp.search(string, start)
if m is None:
return
start = m.start()
for finish in range(start, n+1):
m = regexp.fullmatch(string, start, finish)
if m is not None:
yield m
start += 1
打印示例中所需的内容。您尝试编写regexp的其他方法也应该有效。在本例中,速度更快,因为外循环的第二次
start
为1,并且regexp.search(string,1)
无法找到另一个匹配项,因此生成器立即退出(因此跳过检查O(N^2)
其他索引对)。findall:返回字符串中所有非重叠匹配项的列表。作为旁注,ATG.*(TAA | TAG)
将只匹配最长的字符串。这是因为*
操作符是贪婪的。有趣的方法。时间复杂度是O(N^3)对吗?它应该是O(N^2),除非我遗漏了什么。提取所有子字符串是O(N^3)独立的(O(N^2)个子字符串,每个子字符串中复制O(N)个字符)。如果有人真的需要使用它,最好重新调用它:编译regexp,并使用它的.match()
方法。它接受pos
和endpos
切片索引,这样就不必创建任何子字符串对象(当然,编译regexp的费用只需支付一次)。@TimPeters我想我在哪里读到过编译regex没有多大帮助,因为解释器通常都在编译它?但我相信你的话。我根据您的建议修改了答案。CPython维护了最近使用的regexp字符串到其编译的regexp对象的缓存映射,但这不是真正的点-真正的点是re.match()
不接受切片索引,只有regexp\u object.match()
接受切片索引。使用切片索引完全避免了创建O(N^2)子字符串对象的开销。
import re
string2 = "ATGTCAGGTAAGCTTAGGGCTTTAGGATT"
pat = re.compile("ATG.*(TAA|TAG)")
for match in finditer_overlap(pat, string2):
print(match.group())