重叠的正则表达式匹配(Overlapping regex matches)

2019-08-19 08:10发布

我试图创建下面的正则表达式:返回之间的串AUG和( UAGUGAUAA从以下RNA字符串): AGCCAUGUAGCUAACUCAGGUUACAUGGGGAUGACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCCUGAAUGAUCCGAGUAGCAUCUCAG ,让所有的比赛会被发现,包括重叠的。

我试过几个正则表达式,有这样的事情结束了:

matches = re.findall('(?=AUG)(\w+)(?=UAG|UGA|UAA)',"AGCCAUGUAGCUAACUCAGGUUACAUGGGGAUGACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCCUGAAUGAUCCGAGUAGCAUCUCAG")

你能告诉我在我的正则表达式中的错误?

Answer 1:

一个正则表达式这样做实际上是相当困难的,因为大多数用户特别希望重叠的匹配。 你可以,但是,与一些简单的迭代做到这一点:

regex = re.compile('(?=AUG)(\w+)(?=UAG|UGA|UAA)');
RNA = 'AGCCAUGUAGCUAACUCAGGUUACAUGGGGAUGACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCCUGAAUGAUCCGAGUAGCAUCUCAG'
matches = []
tmp = RNA
while (match = regex.search(tmp)):
    matches.append(match)
    tmp = tmp[match.start()-2:]  #Back up two to get the UG portion.  Shouldn't matter, but safer.

for m in matches:
    print m.group(0)

虽然,这存在一些问题。 你会期望回报是在的情况下AUGUAGUGAUAA ? 是否有要返回两个字符串? 或者只是一个? 现在,你的正则表达式甚至没有能够捕获UAG ,因为它继续通过匹配UAGUGA并获得切断UAA 。 为了解决这个问题,那么,你可能希望使用的? 操作让你的运营商懒惰 - 的做法,那么将无法捕获长串。

也许遍历所有字符串两次是答案,但随后如果你的RNA序列包含AUGAUGUAGUGAUAA ? 什么是正确的行为呢?

我可能有利于正则表达式免费的方式,通过遍历字符串及其子:

RNA = 'AGCCAUGUAGCUAACUCAGGUUACAUGGGGAUGACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCCUGAAUGAUCCGAGUAGCAUCUCAG'
candidates = []
start = 0

while (RNA.find('AUG', start) > -1):
    start = RNA.find('AUG', start) #Confound python and its lack of assignment returns
    candidates.append(RNA[start+3:])
    start += 1

matches = []

for candidate in candidates:
    for terminator in ['UAG', 'UGA', 'UAA']:
        end = 1;
        while(candidate.find(terminator, end) > -1):
            end = candidate.find(terminator, end)
            matches.append(candidate[:end])
            end += 1

for match in matches:
    print match

这样一来,你一定会得到所有的比赛,不管是什么。

如果你需要保持每场比赛的位置的轨迹,您可以修改您的考生数据结构使用哪个维持起始位置的元组:

RNA = 'AGCCAUGUAGCUAACUCAGGUUACAUGGGGAUGACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCCUGAAUGAUCCGAGUAGCAUCUCAG'
candidates = []
start = 0

while (RNA.find('AUG', start) > -1):
    start = RNA.find('AUG', start) #Confound python and its lack of assignment returns
    candidates.append((RNA[start+3:], start+3))
    start += 1

matches = []

for candidate in candidates:
    for terminator in ['UAG', 'UGA', 'UAA']:
        end = 1;
        while(candidate[0].find(terminator, end) > -1):
            end = candidate[0].find(terminator, end)
            matches.append((candidate[1], candidate[1] + end, candidate[0][:end]))
            end += 1

for match in matches:
    print "%d - %d: %s" % match

其打印:

7 - 49: UAGCUAACUCAGGUUACAUGGGGAUGACCCCGCGACUUGGAU
7 - 85: UAGCUAACUCAGGUUACAUGGGGAUGACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCCUGAAUGAUCCGAG
7 - 31: UAGCUAACUCAGGUUACAUGGGGA
7 - 72: UAGCUAACUCAGGUUACAUGGGGAUGACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCC
7 - 76: UAGCUAACUCAGGUUACAUGGGGAUGACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCCUGAA
7 - 11: UAGC
7 - 66: UAGCUAACUCAGGUUACAUGGGGAUGACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAA
27 - 49: GGGAUGACCCCGCGACUUGGAU
27 - 85: GGGAUGACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCCUGAAUGAUCCGAG
27 - 31: GGGA
27 - 72: GGGAUGACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCC
27 - 76: GGGAUGACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCCUGAA
27 - 66: GGGAUGACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAA
33 - 49: ACCCCGCGACUUGGAU
33 - 85: ACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCCUGAAUGAUCCGAG
33 - 72: ACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCC
33 - 76: ACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCCUGAA
33 - 66: ACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAA
78 - 85: AUCCGAG

该死的,字面上三行代码,你甚至可以在比赛根据他们的RNA序列排序下降:

from operator import itemgetter
matches.sort(key=itemgetter(1))
matches.sort(key=itemgetter(0)) 

这放在最后打印网在你面前:

007 - 011: UAGC
007 - 031: UAGCUAACUCAGGUUACAUGGGGA
007 - 049: UAGCUAACUCAGGUUACAUGGGGAUGACCCCGCGACUUGGAU
007 - 066: UAGCUAACUCAGGUUACAUGGGGAUGACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAA
007 - 072: UAGCUAACUCAGGUUACAUGGGGAUGACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCC
007 - 076: UAGCUAACUCAGGUUACAUGGGGAUGACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCCUGAA
007 - 085: UAGCUAACUCAGGUUACAUGGGGAUGACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCCUGAAUGAUCCGAG
027 - 031: GGGA
027 - 049: GGGAUGACCCCGCGACUUGGAU
027 - 066: GGGAUGACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAA
027 - 072: GGGAUGACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCC
027 - 076: GGGAUGACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCCUGAA
027 - 085: GGGAUGACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCCUGAAUGAUCCGAG
033 - 049: ACCCCGCGACUUGGAU
033 - 066: ACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAA
033 - 072: ACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCC
033 - 076: ACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCCUGAA
033 - 085: ACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCCUGAAUGAUCCGAG
078 - 085: AUCCGAG


Answer 2:

不幸的是, re模块不提供支持的那一刻重叠的匹配,但你可以轻松突破解下来,像这样:

'AGCCAUGUAGCUAACUCAGGUUACAUGGGGAUGACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCCUGAAUGAUCCGAGUAGCAUCUCAG'
matches = []

for m in re.finditer('AUG', str):
    for n in re.finditer('(UAG)|(UGA)|(UAA)', str[m.start():]):
        matches.append(str[m.start()+3:m.start()+n.end()-3]

print matches


Answer 3:

如果你不认为在“比赛”的方面,而是在“间隔”的方面,我想你会发现它更容易。 这是@约努茨-hulub做。 你可以做一个单一的传球,因为我证明如下,但除非你有足够的RNA字符串你应该使用更简单的finditer()方法(或它们是足够长的时间),你需要避免冗余经过的字符串。

s = 'AGCCAUGUAGCUAACUCAGGUUACAUGGGGAUGACCCCGCGACUUGGAUUAGAGUCUCUUUUGGAAUAAGCCUGAAUGAUCCGAGUAGCAUCUCAG'

def intervals(s):
    state = []
    i = 0
    max = len(s) - 2
    while i < max:
        if s[i] == 'A' and s[i+1] == 'U' and s[i+2] == 'G':
            state.append(i)
        if s[i] == 'U' and (s[i+1] == 'A' and s[i+2] == 'G') or (s[i+1] == 'G' and s[i+2] == 'A') or (s[i+1] == 'A' and s[i+2] == 'A'):
            for b in state:
                yield (b, i)
        i += 1

for interval in intervals(s):
    print interval


文章来源: Overlapping regex matches