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']
Хитрость здесь не в том, чтобы сосредоточиться на том, что входит в следующее или предыдущее слово, а на том, как должно выглядеть захваченное в данный момент слово.
Другой трюк заключается в правильном определении разделителей слов. Перед словом мы допустим несколько пробелов, :
и начало строки, потребляя эти символы, но не захватывая их. После слова нам требуется почти то же самое (за исключением конца строки вместо начала), но мы не потребляем эти символы - мы используем предварительное утверждение.