Регулярное выражение Python, соответствующее цифрам после текста

Я сопоставляю названия фильмов, которые обычно имеют вид

[BLA VLA] The Matrix 1999 bla bla [bla bla]

Мое регулярное выражение

match = re.match("\[?.*?\](.*?)([0-9]{4})(.*)\[?.*\]?", title)

Это работает нормально в большинстве случаев, но не работает для таких фильмов, как

[bla bla] 1990 The Bronx Warriors 1982
[ bl bla] 2012 2009 [ bla bla ]

Как я могу это исправить

match = re.match("\[?.*?\](.*)([0-9]{4})(.*)\[?.*\]?", title) . Ты был почти там. Теперь первая группа будет соответствовать названию фильма, а вторая - году.
igrinis 11.06.2019 06:56
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
1
66
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Если бы у нас были бы те же шаблоны верхнего и нижнего регистра, подобные перечисленным в вопросе, мы бы начали с простого выражения, такого как:

([A-Z][a-z]+\s)+

Демо

Тестовое задание

# coding=utf8
# the above tag defines encoding for this document and is for Python 2.x compatibility

import re

regex = r"([A-Z][a-z]+\s)+"

test_str = ("[bla bla] 1990 The Bronx Warriors 1982\n"
    "[ bl bla] 2012 2009 [ bla bla ]\n"
    "[BLA VLA] The Matrix 1999 bla bla [bla bla]\n")

matches = re.finditer(regex, test_str, re.MULTILINE)

for matchNum, match in enumerate(matches, start=1):

    print ("Match {matchNum} was found at {start}-{end}: {match}".format(matchNum = matchNum, start = match.start(), end = match.end(), match = match.group()))

    for groupNum in range(0, len(match.groups())):
        groupNum = groupNum + 1

        print ("Group {groupNum} found at {start}-{end}: {group}".format(groupNum = groupNum, start = match.start(groupNum), end = match.end(groupNum), group = match.group(groupNum)))

# Note: for Python 2.7 compatibility, use ur"" to prefix the regex and u"" to prefix the test string and substitution.

регулярное выражение

Если это выражение вам не нужно или вы хотите изменить его, посетите regex101.com.

Цепь регулярных выражений

jex.im визуализирует регулярные выражения:

Попробуй это

re.match( r"\[.*?\]\s([\w\s]+)", title).groups()[0].strip()

Код

Идя дальше, рассмотрите возможность повторного использования вашего кода в функции. Вот эквивалентный код:

import re


def get_title(s):
    """Return the title from a string."""
    pattern = r"\[.*?\]\s([\w\s]+)"
    p = re.compile(pattern)
    m = p.match(s)
    g = m.groups()
    return g[0].strip()

Демо

get_title("[BLA VLA] The Matrix 1999 bla bla [bla bla]")
# 'The Matrix 1999 bla bla'

get_title("[bla bla] 1990 The Bronx Warriors 1982")
# '1990 The Bronx Warriors 1982'

get_title("[ bl bla] 2012 2009 [ bla bla ]")
# '2012 2009'

Подробности

См. шаблон здесь:

  • \[.*?\]\s: за ведущими скобками и пробелами
  • ([\w\s]+): захватить необязательные буквенно-цифровые символы и пробелы

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

rgd 11.06.2019 07:39

Чтобы было ясно, можете ли вы явно добавить примеры входных данных и их ожидаемых результатов?

pylang 11.06.2019 08:07
movies = '''[bla bla] 1990 The Bronx Warriors 1982
[ bl bla] 2012 2009 [ bla bla ]
[ bl bla] Normal movie title 2009 [ bla bla ]'''

import re

for movie, year in re.findall(r']\s+(.*)\s+(\d{4}).*?$', movies, flags=re.MULTILINE):
    print('Movie title: [{}] Movie year: [{}]'.format(movie, year))

Отпечатки:

Movie title: [1990 The Bronx Warriors] Movie year: [1982]
Movie title: [2012] Movie year: [2009]
Movie title: [Normal movie title] Movie year: [2009]
Ответ принят как подходящий

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

\[[^\]]+\] (.+?) (\d{4})

Объяснение

  • \[[^\]]+\] Сопоставьте часть с квадратными скобками
  • (.+?) Захват в группе 1 соответствует пробелу, 1+ раз любой символ не жадный и пробел
  • (\d{4}) Захват в группе 2 соответствует 4 цифрам

Демонстрация регулярных выражений

Другие вопросы по теме