使用Python正则表达式在一个模式中剪切

时间:2016-06-20 17:50:26

标签: python regex string split protein-database

目标:我正在尝试在Python RegEx中执行切换,其中拆分并不能完全符合我的要求。我需要在一个模式中剪切,但在角色之间剪切。

我在寻找什么:

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

模式:CDE|FG

字符串:ABCDEFGHIJKLMNOCDEFGZYPE

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

我尝试了什么:

我似乎使用带括号的split是接近的,但它并没有像我需要的那样将搜索模式保持在结果上。

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

给出,

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

当我真正需要时,

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

动机:

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

4 个答案:

答案 0 :(得分:7)

非正则表达方式是replace带有管道值的模式,然后是split

>>> pattern = 'CDE|FG'
>>> s = 'ABCDEFGHIJKLMNOCDEFGZYPE'
>>> s.replace('CDEFG',pattern).split('|')
['ABCDE', 'FGHIJKLMNOCDE', 'FGZYPE']

答案 1 :(得分:5)

您可以使用re.split()和肯定"look arounds"来解决此问题:

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

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

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']

答案 2 :(得分: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) ]

答案 3 :(得分: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