функция для работы со всеми частями строки, которые не соответствуют шаблону регулярных выражений - PullRequest
0 голосов
/ 27 февраля 2019

Скажем, у меня есть строка:

"a bb c exclude_start d 3 f g h _ k l . exclude_end n 0 P exclude_start q r exclude_end s"

И, скажем, я бы применил функцию upper, которая будет возвращать:

"A BB C exclude_start d 3 f g h _ k l . exclude_end N 0 P exclude_start q r exclude_end S"

Я бы хотел решение, которое позволитдля n числа исключенных блоков и будет применять функцию upper только к символам за пределами этих блоков.

Было бы хорошо, если бы был способ regex сопоставлять только строки за пределамиexcludes, тогда примените только upper к ним.

1 Ответ

0 голосов
/ 27 февраля 2019

Я не уверен, есть ли способ сделать это с помощью одного регулярного выражения, но вот мой мыслительный процесс для этого.Я полагаю, что мы хотим разделить строку так, чтобы мы могли использовать только те части, которые отсутствуют в блоках исключения.Для этого можно сделать регулярное выражение, соответствующее блоку исключения:

>>> import re
>>> exclude_pattern = re.compile(r'(exclude_start.*?exclude_end)')

Нам нужно включить знак вопроса, чтобы он не совпадал с жадностью.

Поскольку мы хотим сохранить части строки, которые соответствуют нашим exclude_pattern, а не просто выбрасывать их, мы можем использовать re.split:

Если скобки для захватаиспользуется в pattern , тогда текст всех групп в шаблоне также возвращается как часть полученного списка.

, поэтому нам нужны скобки в нашем exclude_pattern.

Далее мы хотим разделить строку, используя этот шаблон:

>>> input_string = "a bb c exclude_start d 3 f g h _ k l . exclude_end n 0 P exclude_start q r exclude_end s"
>>> exclude_pattern.split(input_string)
['a bb c ', 'exclude_start d 3 f g h _ k l . exclude_end', ' n 0 P ', 'exclude_start q r exclude_end', ' s']

Это дает нам необходимое разделение.

Следующее, что мы хотим, это upper только строки, которые не соответствуют нашему шаблону исключения.Для этого я считаю, что мы можем сопоставить лямбду над нашим списком, которая проверяет каждую запись на соответствие нашему шаблону исключения, и только upper s те, которые не совпадают:

>>> list(map(lambda s: s.upper() if not exclude_pattern.match(s) else s, exclude_pattern.split(input_string)))
['A BB C ', 'exclude_start d 3 f g h _ k l . exclude_end', ' N 0 P ', 'exclude_start q r exclude_end', ' S']

list() простотак что мы можем видеть, что находится в результирующем объекте карты.

После этого мы просто объединяем все это вместе:

>>> ''.join(map(lambda s: s.upper() if not exclude_pattern.match(s) else s, exclude_pattern.split(input_string)))
'A BB C exclude_start d 3 f g h _ k l . exclude_end N 0 P exclude_start q r exclude_end S'

Если вы не хотите делать это как однострочник(это немного брутто), мы можем превратить это в функцию:

def excluded_upper(input_string):
    exclude_pattern = re.compile(r'(exclude_start.*?exclude_end)')
    split_string = exclude_pattern.split(input_string)
    output = []
    for s in split_string:
        if exclude_pattern.match(s):
            output.append(s)
        else:
            output.append(s.upper())
    return ''.join(output)
...