12

目标:我正在尝试在 Python RegEx 中执行剪切,其中 split 并不能完全满足我的要求。我需要在一个模式内剪切,但在字符之间剪切。

我在找什么:

我需要在字符串中识别下面的模式,并在管道的位置拆分字符串。管道实际上不在字符串中,它只是显示我想要拆分的位置。

图案:CDE|FG

细绳:ABCDEFGHIJKLMNOCDEFGZYPE

结果:['ABCDE', 'FGHIJKLMNOCDE', 'FGZYPE']

我试过的:

我似乎使用带括号的拆分很接近,但它不会像我需要的那样将搜索模式附加到结果中。

re.split('CDE()FG', 'ABCDEFGHIJKLMNOCDEFGZYPE')

给,

['AB', 'HIJKLMNO', 'ZYPE']

当我真正需要的时候,

['ABCDE', 'FGHIJKLMNOCDE', 'FGZYPE']

动机:

使用 RegEx 进行练习,并想看看我是否可以使用 RegEx 制作一个脚本,该脚本可以预测使用特定蛋白酶消化蛋白质的片段。

4

4 回答 4

8

一种非正则表达式的方法是用管道值替换模式,然后拆分

>>> pattern = 'CDE|FG'
>>> s = 'ABCDEFGHIJKLMNOCDEFGZYPE'
>>> s.replace('CDEFG',pattern).split('|')
['ABCDE', 'FGHIJKLMNOCDE', 'FGZYPE']
于 2016-06-20T18:04:32.287 回答
5

您可以通过re.split()积极的“环顾四周”来解决它:

>>> re.split(r"(?<=CDE)(\w+)(?=FG)", s)
['ABCDE', 'FGHIJKLMNOCDE', 'FGZYPE']

请注意,如果剪切序列之一是空字符串,您将在结果列表中得到一个空字符串。您可以“手动”处理该示例(我承认,它不是那么漂亮):

import re

s = "ABCDEFGHIJKLMNOCDEFGZYPE"

cut_sequences = [
    ["CDE", "FG"],
    ["FGHI", ""],
    ["", "FGHI"]
]

for left, right in cut_sequences:
    items = re.split(r"(?<={left})(\w+)(?={right})".format(left=left, right=right), s)

    if not left:
        items = items[1:]

    if not right:
        items = items[:-1]

    print(items)

印刷:

['ABCDE', 'FGHIJKLMNOCDE', 'FGZYPE']
['ABCDEFGHI', 'JKLMNOCDEFGZYPE']
['ABCDE', 'FGHIJKLMNOCDEFGZYPE']
于 2016-06-20T17:55:21.907 回答
2

re.split要在使用或部分拆分时保留拆分模式,请将它们括在括号中。

>>> data
'ABCDEFGHIJKLMNOCDEFGZYPE'
>>> pieces = re.split(r"(CDE)(FG)", data)
>>> pieces
['AB', 'CDE', 'FG', 'HIJKLMNO', 'CDE', 'FG', 'ZYPE']

很容易。所有的部分都在那里,但正如你所看到的,它们已经分开了。所以我们需要重新组装它们。这是更棘手的部分。仔细看,你会发现你需要加入前两部分,最后两部分,其余的三元组。我通过填充列表来简化代码,但如果性能有问题,您可以使用原始列表(以及一些额外的代码)来完成。

>>> pieces = [""] + pieces
>>> [ "".join(pieces[i:i+3]) for i in range(0,len(pieces), 3) ]
['ABCDE', 'FGHIJKLMNOCDE', 'FGZYPE']

re.split()保证每个捕获(带括号的)组的一块,加上中间的一块。对于需要自己分组的更复杂的正则表达式,使用非捕获组来保持返回数据的格式相同。(否则您需要调整重新组装步骤。)

PS。我也喜欢 Bhargav Rao 在字符串中插入分隔符的建议。如果性能不是问题,我想这是一个品味问题。

编辑:这是一种(不太透明)的方法,无需在列表中添加空字符串:

pieces = re.split(r"(CDE)(FG)", data)
result = [ "".join(pieces[max(i-3,0):i]) for i in range(2,len(pieces)+2, 3) ]
于 2016-06-21T10:59:57.190 回答
1

一个更安全的非正则表达式解决方案可能是这样的:

import re

def split(string, pattern):
    """Split the given string in the place indicated by a pipe (|) in the pattern"""
    safe_splitter = "#@#@SPLIT_HERE@#@#"
    safe_pattern = pattern.replace("|", safe_splitter)
    string = string.replace(pattern.replace("|", ""), safe_pattern)
    return string.split(safe_splitter)

s = "ABCDEFGHIJKLMNOCDEFGZYPE"
print(split(s, "CDE|FG"))
print(split(s, "|FG"))
print(split(s, "FGH|"))

https://repl.it/C448

于 2016-06-21T10:59:39.820 回答