Regex, чтобы гарантировать, что групповое совпадение не заканчивается конкретным символом - PullRequest
1 голос
/ 19 мая 2010

У меня проблемы с созданием регулярного выражения, соответствующего конкретному случаю. У меня есть список ТВ-шоу в 4 форматах:

  • Name.Of.Show.S01E01
  • Name.Of.Show.0101
  • Name.Of.Show.01x01
  • Name.Of.Show.101

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

"^([0-9a-zA-Z\.]+)(S[0-9]{2}E[0-9]{2}|[0-9]{4}|[0-9]{2}x[0-9]{2}|[0-9]{3})"

Некоторые примеры:

>>> import re

>>> SHOW_INFO = re.compile("^([0-9a-zA-Z\.]+)(S[0-9]{2}E[0-9]{2}|[0-9]{4}|[0-9]{2}x[0-9]{2}|[0-9]{3})")
>>> match = SHOW_INFO.match("Name.Of.Show.S01E01")
>>> match.groups()
('Name.Of.Show.', 'S01E01')
>>> match = SHOW_INFO.match("Name.Of.Show.0101")
>>> match.groups()
('Name.Of.Show.0', '101')
>>> match = SHOW_INFO.match("Name.Of.Show.01x01")
>>> match.groups()
('Name.Of.Show.', '01x01')
>>> match = SHOW_INFO.match("Name.Of.Show.101")
>>> match.groups()
('Name.Of.Show.', '101')

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

var.strip(".")

Однако это не относится к случаю "Name.Of.Show.0101". Есть ли способ, которым я мог бы улучшить регулярное выражение, чтобы лучше справиться с этим делом?

Заранее спасибо.

Ответы [ 5 ]

2 голосов
/ 19 мая 2010

Я думаю, что это будет делать:

>>> regex = re.compile(r'^([0-9a-z.]+)\.(S[0-9]{2}E[0-9]{2}|[0-9]{3,4}|[0-9]{2}x[0-9]{2})$', re.I)
>>> regex.match('Name.Of.Show.01x01').groups()
('Name.Of.Show', '01x01')
>>> regex.match('Name.Of.Show.101').groups()
('Name.Of.Show', '101')

ETA : Конечно, если вы просто пытаетесь извлечь разные биты из доверенных строк, вы можете использовать строковые методы:

>>> 'Name.Of.Show.101'.rpartition('.')
('Name.Of.Show', '.', '101')
2 голосов
/ 19 мая 2010

То есть единственное реальное ограничение для последней группы - это то, что она не содержит точку? Легко:

^(.*?)(\.[^.]+)$

Это соответствует чему угодно, без жадности. Важной частью является вторая группа, которая начинается с точки, а затем соответствует любому не точечному символу до конца строки.

Это работает со всеми вашими тестами.

1 голос
/ 19 мая 2010

Похоже, проблема в том, что вы не указали период до последней группы, поэтому что-то вроде ^ ([0-9a-zA-Z \.] +) \. (S [0- 9] {2} Е [0-9] {2} | [0-9] {4} | [0-9] {2} х [0-9] {2} | [0-9] {3} ) может сработать.

1 голос
/ 19 мая 2010

Я верю, что это будет делать то, что вы хотите:

^([0-9a-z\.]+)\.(?:S[0-9]{2}E[0-9]{2}|[0-9]{3,4}|[0-9]{2}(?:x[0-9]+)?)$

Я проверил это по следующему списку шоу:

  • 30.Rock.S01E01
  • The.Office.0101
  • Lost.01x01
  • How.I.Met.Your.Mother.101

Если эти 4 случая представляют типы файлов, которые у вас есть, то это регулярное выражение должно поместить заголовок шоу в свою собственную группу захвата и отбросить остальные. Этот фильтр, возможно, немного более ограничен, чем некоторые другие, но я большой поклонник сопоставления именно того, что вам нужно.

0 голосов
/ 19 мая 2010

Если последняя часть никогда не содержит точку: ^(.*)\.([^\.]+)$

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