Я сопоставляю названия фильмов, которые обычно имеют вид
[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 ]
Как я могу это исправить
Если бы у нас были бы те же шаблоны верхнего и нижнего регистра, подобные перечисленным в вопросе, мы бы начали с простого выражения, такого как:
([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]+)
: захватить необязательные буквенно-цифровые символы и пробелыИзвините, я не объяснил полностью, я хочу извлечь заголовок и год в отдельные группы, как в моем регулярном выражении.
Чтобы было ясно, можете ли вы явно добавить примеры входных данных и их ожидаемых результатов?
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 цифрам
match = re.match("\[?.*?\](.*)([0-9]{4})(.*)\[?.*\]?", title)
. Ты был почти там. Теперь первая группа будет соответствовать названию фильма, а вторая - году.