Вырезать внутри шаблона с использованием регулярного выражения Python

Цель: Я пытаюсь выполнить сокращение в Python RegEx, где split не совсем делает то, что я хочу. Мне нужно вырезать внутри шаблона, но между символами.

То, что я ищу:

Мне нужно распознать шаблон ниже в строке и разбить строку в месте расположения канала. Труба на самом деле не находится в строке, она просто показывает, где я хочу разделить.

Выкройка: CDE|FG

Строка: ABCDEFGHIJKLMNOCDEFGZYPE

Результаты: ['ABCDE', 'FGHIJKLMNOCDE', 'FGZYPE']

Что я пробовал:

Мне кажется, что использование split с круглыми скобками близко, но оно не поддерживает привязку шаблона поиска к результатам, как мне это нужно.

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

дает,

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

Когда мне действительно нужно,

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

Мотивация:

Практикуя с RegEx, и я хотел бы узнать, могу ли я использовать RegEx для создания script, который предсказал бы фрагменты белкового расщепления с использованием конкретных протеаз.

Ответ 1

Не регулярным способом будет replace шаблон с указанным в нем значением, а затем split.

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

Ответ 2

Вы можете решить его с помощью 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']

Ответ 3

Чтобы сохранить шаблон разделения при разделении с помощью 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) ]

Ответ 4

Более безопасное решение без регулярных выражений может быть следующим:

import re

def split(string, pattern):
    """Split the given string in the place indicated by a pipe (|) in the pattern"""
    safe_splitter = "#@#@[email protected]#@#"
    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