匹配字符串中不是特定字符的连续片段的部分
Match parts of string that are not consecutive stretches of certain character
我有一个简单的函数,它从一个字符串中生成至少有 gapSize 个连续 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,}).*
但这不能满足我的需要。
非常感谢任何帮助!
编辑:
例如:一个序列 NNNNNNACTGACGTNNNACTGACNNNNNN 应该匹配 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)
根据 re.split
函数,这将为不是 gap_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))
所以这是一个 pure 正则表达式解决方案,它似乎是你想要的,但我想知道是否真的有更好的方法来做到这一点。当我想到它们时,我会添加替代方案。我使用了几个在线正则表达式工具并在 shell.
中玩了玩
One of the tools 有一个很好的正则表达式图形和生成 SO 答案的工具 代码:正则表达式(间隙为 10)是:
^.*?(?=N{10})|(?<=N{10})[^N].*?(?=N{10})|(?<=N{10})[^N].*?$
用法:
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
>>>
'''
因此,如果您仔细考虑一下,您会发现 gap 的开始是 non-gap 的结束,并且反之亦然。因此,使用一个简单的正则表达式:迭代间隙,向循环添加逻辑以跟踪 非间隙 跨度和 yield
跨度。 (我的占位符变量名可能会得到改进)
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
>>>
'''
否定前瞻似乎工作正常。例如。对于间隙大小 3,正则表达式为:
N{3,}?([^N](?:(?!N{3,}?).)*)
试试看 here.
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
警告:如果字符串不是以 'N' 序列开头,则这可能无法很好地匹配字符串的开头。但是你总是可以从左边用间隙大小倍数 'N' 填充字符串。
我有一个简单的函数,它从一个字符串中生成至少有 gapSize 个连续 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,}).*
但这不能满足我的需要。 非常感谢任何帮助!
编辑: 例如:一个序列 NNNNNNACTGACGTNNNACTGACNNNNNN 应该匹配 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)
根据 re.split
函数,这将为不是 gap_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))
所以这是一个 pure 正则表达式解决方案,它似乎是你想要的,但我想知道是否真的有更好的方法来做到这一点。当我想到它们时,我会添加替代方案。我使用了几个在线正则表达式工具并在 shell.
中玩了玩One of the tools 有一个很好的正则表达式图形和生成 SO 答案的工具 代码:正则表达式(间隙为 10)是:
^.*?(?=N{10})|(?<=N{10})[^N].*?(?=N{10})|(?<=N{10})[^N].*?$
用法:
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
>>>
'''
因此,如果您仔细考虑一下,您会发现 gap 的开始是 non-gap 的结束,并且反之亦然。因此,使用一个简单的正则表达式:迭代间隙,向循环添加逻辑以跟踪 非间隙 跨度和 yield
跨度。 (我的占位符变量名可能会得到改进)
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
>>>
'''
否定前瞻似乎工作正常。例如。对于间隙大小 3,正则表达式为:
N{3,}?([^N](?:(?!N{3,}?).)*)
试试看 here.
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
警告:如果字符串不是以 'N' 序列开头,则这可能无法很好地匹配字符串的开头。但是你总是可以从左边用间隙大小倍数 'N' 填充字符串。