Как сопоставить названия работ / файлов с дополнительными элементами, используя Python 3 Regex - PullRequest
0 голосов
/ 17 апреля 2020

У меня есть средний уровень навыков в regex - я использовал его годами на нескольких разных языках - но у меня возникают проблемы с более сложными выражениями в Python 3.6+, где могут отсутствовать несколько частей запроса. Различные части моего регулярного выражения играют в перетягивание каната друг с другом, но после ночного чтения, SO и работы я все еще не смог сопоставить все мои тестовые примеры, которые являются основными c файлами или рабочими названиями. Вот диаграмма того, что мне нужно сопоставить:

"" "

Title[ *semantic* version][ | Container/Collection (after *literal* vertical bar/pipe)]

" ""

Вот мой код, разложенный на основы, regex и некоторые тестовые случаи:

"" "

import re

titles = (
    'Title Of Program 1.2.3 | Project Name',
    'Title Of Program 1 | Project Name',
    'Title Of Program | Project Name',
    'Title Of Program 1.2.3',
    'Title Of Program',
    '2 Hard Bonus',
)

regex = re.compile(r'(^.+?)(?: ?)((?:\d+(?:\.)*)+)(?: \| )*(.*)', re.M | re.S)

for title in titles:
    try:
        match = regex.search(title)
        print('(1)', match.group(1), '(2)', match.group(2), '(3)', match.group(3))
    except AttributeError:
        print('Failed match!')

" ""

Вторая группа захвата, кажется, дает большинство проблем, так как нужно сделать небольшие изменения он необязательный (например, для тестовых случаев 3, 5 и 6) делает его * слишком * необязательным и, кажется, его никогда не заберут. Тем не менее, все группы, кажется, сильно пострадали от изменений в другой, что сводит меня к пределу моего опыта. У меня есть тривиальное решение для этого с использованием "" "split()" "и" "" strip() "" ", но мне нужно решить его с помощью одного регулярного выражения, так как шаблон регулярного выражения является частью гораздо большего словаря шаблонов, что одиночная функция перебирает Спасибо.

1 Ответ

1 голос
/ 17 апреля 2020

Это регулярное выражение должно давать вам нужные результаты:

^(.+?) ?((?:\d+\.)*\d)?(?= \||$)(?: \| )?(.+)?$

Он ищет некоторое минимальное количество символов (захвачено в группе 1), за которым следует дополнительный пробел и последовательность цифр и точек, начинающихся с и заканчивается ди git например 1.2.3, но не 1.2. (захвачено в группе 2). В этой точке используется прямой прогноз, чтобы соответствовать либо |, либо концу строки; это заставляет предыдущую часть регулярного выражения в максимально возможной степени совпадать с разделителем, если он существует (в противном случае (.+) может захватывать все, кроме первого символа в строке). После этого мы фиксируем любые символы после | до конца строки в группе 3.

Демонстрация по regex101

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...