Python 匹配不是特定字符连续延伸的字符串部分

Python 匹配不是特定字符连续延伸的字符串部分,python,regex,regex-negation,Python,Regex,Regex Negation,我有一个简单的函数,它可以从一个字符串中产生至少连续N的所有拉伸: def get_gap_coordinates(sequence, gapSize=25): gapPattern = "N{"+str(gapSize)+",}" p = re.compile(gapPattern) m = p.finditer(sequence) for gap in m: start,stop = gap.span() yield(start

我有一个简单的函数,它可以从一个字符串中产生至少连续N的所有拉伸:

def get_gap_coordinates(sequence, gapSize=25):
    gapPattern = "N{"+str(gapSize)+",}"
    p = re.compile(gapPattern)
    m = p.finditer(sequence)
    for gap in m:
        start,stop = gap.span()
        yield(start,stop)
现在我想要一个函数,它的作用正好相反:匹配所有不是至少gapSize N连续延伸的字符。这些拉伸可能发生在任何给定数字的字符串中的任何位置(开始、中间和结束)

我已经调查了周围的环境并尝试了

(?!N{25,}).*
但这并不能满足我的需要。 非常感谢您的帮助

编辑:
例如:序列nnnnnn actgacgtnnnactgcnnnnnnnnnn与应匹配的ACTGACGTNNNACTGAC用于gapSize=5,ACTGACGT&ACTGAC用于gapSize=3

我想你可以做如下事情:

gapPattern = "(N{"+str(gapSize)+",})"
p = re.compile(gapPattern)
i = 0
for s in re.split(p, sequence):
    if not re.match(p, s):
        yield i
    i += len(s)

这将生成一系列偏移量到子字符串,这些子字符串根据函数不是
gap\u size
“N”
字符。

我曾考虑使用正则表达式直接匹配所需的块,但没想到有什么好处。我认为最好继续寻找间隙,并简单地使用间隙坐标来获得良好的块坐标。我是说,他们基本上是一样的,对吧?间隙停止是块启动,间隙启动是块停止

def get_block_coordinates(sequence, gapSize=25):
    gapPattern = "N{"+str(gapSize)+",}"
    p = re.compile(gapPattern)
    m = p.finditer(sequence)
    prevStop = 0
    for gap in m:
        start,stop = gap.span()
        if start:
            yield(prevStop,start)
        prevStop = stop
    if prevStop < len(sequence):
        yield(prevStop,len(sequence))
def get_block_坐标(顺序,间隙=25):
gapPattern=“N{”+str(gapSize)+”,}”
p=重新编译(gapPattern)
m=p.finditer(序列)
prevStop=0
对于m中的间隙:
开始,停止=间隙。span()
如果启动:
产量(停止、开始)
停止
如果prevStop
所以这里有一个纯正则表达式解决方案,这似乎是您想要的,但我想知道是否有更好的方法来实现这一点。我将在提出备选方案时添加它们。我使用了几个在线正则表达式工具,也在shell中玩了起来

有一个很好的正则表达式和工具的图形来生成答案代码:正则表达式(间距为10)是:

用法


消极的前瞻似乎是可行的。例如,对于间隙尺寸3,regexp应为:

N{3,}?([^N](?:(?!N{3,}?).)*) 
试试看


警告:如果字符串不是以“N”序列开头,则这可能与字符串开头不匹配。但是,您可以始终在字符串的左侧填充间距大小乘以“N”。

您可以发布一个包含您试图匹配的字符的示例短语吗?请不要将问题的标签放在标题中。你有标签区,是的。这不是短语,而是DNA序列。例如:
nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn actgtagtgannnacgtgtgtg
我想匹配
acgtgtgtg
acgtgtgtac
。但是,N可能在任何地方,因此您基本上希望匹配任何没有N的组?@lfk:请将这些示例编辑到问题中。至于解决方案,您可以使用
N{,}
拆分输入。感谢Misandrist,但我只需要匹配部分的坐标,而不是实际拆分序列本身。另外,我很感兴趣的是如何用正则表达式来解决这个问题。如果你用re.split和一个匹配组来拆分它们,你可以通过使用序列拆分返回的长度来跟踪位置。谢谢,类似这样的东西就是我要找的!除了填充之外,你能想出任何处理初始N的方法吗?我认为这一个可以完成任务(例如间隙大小3):
((?:^N{0,2})[^N](?一般情况是:
((?:^N{0,%s})[^N](?在这种情况下,字符串的开头是用第一个非caputring组显式处理的,然后有一个反向查找。
s = 'NAANANNNNNNNNNNBBBBNNNCCNNNNNNNNNNDDDDN'
def foo(s, gapSize = 25):
    '''yields non-gap items (re.match objects) in s or
       if gaps are not present raises StopIteration immediately
    '''
    # beginning of string and followed by a 'gap' OR
    # preceded a 'gap' and followed by a 'gap' OR
    # preceded a 'gap' and followed by end of string
    pattern = r'^.*?(?=N{{{}}})|(?<=N{{{}}})[^N].*?(?=N{{{}}})|(?<=N{{{}}})[^N].*?$'
    pattern = pattern.format(gapSize, gapSize, gapSize, gapSize)
    for match in re.finditer(pattern, s):
        #yield match.span()
        yield match

for match in foo(s, 10):
    print match.span(), match.group()

'''
>>> 
(0, 5) NAANA
(15, 24) BBBBNNNCC
(34, 39) DDDDN
>>>
'''
s = 'NAANANNNNNNNNNNBBBBNNNCCNNNNNNNNNNDDDDN'
def bar(s, n):
    '''Yields the span of non-gap items in s or
       immediately raises StopIteration if gaps are not present.
    '''
    gap = r'N{{{},}}'.format(n)
    # initialize the placeholders
    previous_start = 0
    end = len(s)
    for match in re.finditer(gap, s):
        start, end = match.span()
        if start == 0:
            previous_start = end
            continue
        end = start
        yield previous_start, end
        previous_start = match.end()
    if end != len(s):
        yield previous_start, len(s)
for start, end in bar(s, 4):
    print (start, end), s[start:end]

'''
>>>
(0, 5) NAANA
(15, 24) BBBBNNNCC
(34, 39) DDDDN
>>>
''' 
N{3,}?([^N](?:(?!N{3,}?).)*) 
import re

def get_gap_coordinates(sequence, gapSize=25):
    gapPattern = "N{%s,}?([^N](?:(?!N{%s,}?).)*)" % (gapSize, gapSize)
    p = re.compile(gapPattern)
    m = p.finditer(sequence)
    for gap in m:
        start,stop = gap.start(1), gap.end(1)
        yield(start,stop)


for x in get_gap_coordinates('NNNNNNACTGACGTNNNACTGACNNNNN', 3):
    print x