Regex - сопоставить слова в шаблоне, кроме как в пределах адреса электронной почты

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

Чтобы упростить шаблон "правильных слов" \w+\.\w+ - один или несколько символов, фактический период и другая серия символов.

Предложение, которое вызывает проблему, например, a.a b.b:c.c d.d@e.e.e,

Цель состоит в том, чтобы соответствовать только [a.a, b.b, c.c], С большинством регулярных выражений, которые я строю, e.e также возвращает (потому что я использую какое-то совпадение границ слов).

Например:

>>> re.findall(r"(?:^|\s|\W)(?<!@)(\w+\.\w+)(?!@)\b", "a.a b.b:c.c d.d@e.e.e") ['a.a', 'b.b', 'c.c', 'e.e']

Как найти совпадение только среди слов, которые не содержат "@"?

3 ответа

Я определенно очистил бы это сначала и упростил бы регулярное выражение.

сначала мы имеем

words = re.split(r':|\s', "a.a b.b:c.c d.d@e.e.e")

затем отфильтровать слова, которые имеют @ в них.

words = [re.search(r'^((?!@).)*$', word) for word in words]

Вы можете сопоставить почтовые подстроки с \S+@\S+\.\S+ и сопоставить и захватить ваш шаблон с (\w+\.\w+) во всех других контекстах. использование re.findall только вернуть захваченные значения и отфильтровать пустые элементы (они будут в re.findall результаты, когда есть совпадение по электронной почте):

import re
rx = r"\S+@\S+\.\S+|(\w+\.\w+)"
s = "a.a b.b:c.c d.d@e.e.e"
res = filter(None, re.findall(rx, s))
print(res)
# => ['a.a', 'b.b', 'c.c']

Посмотрите демо Python.

Смотрите демо-версию регулярного выражения.

Правильный анализ адресов электронной почты с помощью регулярных выражений чрезвычайно сложен, но для вашего упрощенного случая, с простым определением слова ~ \w\.\w и электронная почта ~ any sequence that contains @Вы можете найти это регулярное выражение, чтобы сделать то, что вам нужно:

>>> re.findall(r"(?:^|[:\s]+)(\w+\.\w+)(?=[:\s]+|$)", "a.a b.b:c.c d.d@e.e.e")
['a.a', 'b.b', 'c.c']

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

Другой трюк заключается в правильном определении разделителей слов. Перед словом мы допустим несколько пробелов, : и начало строки, потребляя эти символы, но не захватывая их. После слова нам требуется почти то же самое (за исключением конца строки вместо начала), но мы не потребляем эти символы - мы используем предварительное утверждение.

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