Разница в поведении регулярных выражений между Perl и Python? - PullRequest
3 голосов
/ 16 апреля 2009

У меня есть пара адресов электронной почты, 'support@company.com' и '1234567@tickets.company.com'.

В Perl я могу взять строку To: необработанного электронного письма и найти любой из вышеперечисленных адресов с помощью

/\w+@(tickets\.)?company\.com/i

В python я просто написал приведенное выше регулярное выражение как '\w+@(tickets\.)?company\.com', ожидая того же результата. Однако support@company.com вообще не найден, а findall на втором возвращает список, содержащий только 'tickets.'. Ясно, что '(tickets\.)?' является проблемной областью, но в чем именно заключается разница в правилах регулярных выражений между Perl и Python, которые мне не хватает?

Ответы [ 4 ]

7 голосов
/ 16 апреля 2009

Документация для re.findall:

findall(pattern, string, flags=0)
    Return a list of all non-overlapping matches in the string.

    If one or more groups are present in the pattern, return a
    list of groups; this will be a list of tuples if the pattern
    has more than one group.

    Empty matches are included in the result.

Поскольку (tickets\.) является группой, findall возвращает ее вместо всего совпадения. Если вы хотите получить полное совпадение, создайте группу вокруг всего шаблона и / или используйте несгруппированные совпадения, т.е.

r'(\w+@(tickets\.)?company\.com)'
r'\w+@(?:tickets\.)?company\.com'

Обратите внимание, что вам нужно будет выбрать первый элемент каждого кортежа, возвращаемого findall в первом случае.

4 голосов
/ 16 апреля 2009

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

'(\w+@(?:tickets\.)?company\.com)'
2 голосов
/ 16 апреля 2009

У меня выпадают две проблемы:

  1. Вам нужно использовать необработанную строку, чтобы избежать экранирования "\"
  2. Вам нужно сбежать "."

Так попробуйте:

r'\w+@(tickets\.)?company\.com'

EDIT

Пример вывода:

>>> import re
>>> exp = re.compile(r'\w+@(tickets\.)?company\.com')
>>> bool(exp.match("s@company.com"))
True
>>> bool(exp.match("1234567@tickets.company.com"))
True
1 голос
/ 16 апреля 2009

Нет разницы в регулярных выражениях, но есть разница в том, что вы ищете. Ваше регулярное выражение захватывает только "tickets.", если оно существует в обоих регулярных выражениях. Вы, вероятно, хотите что-то вроде этого

#!/usr/bin/python

import re

regex = re.compile("(\w+@(?:tickets\.)?company\.com)");

a = [
    "foo@company.com", 
    "foo@tickets.company.com", 
    "foo@ticketsacompany.com",
    "foo@compant.org"
];

for string in a:
    print regex.findall(string)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...