user: Я хочу узнать об регулярных выражениях в языке программирования Python

assistant: Python имеет встроенный пакет под названием `re`, который можно использовать для работы с регулярными выражениями. Регулярные выражения (называемые RE или regexes или regex patterns) - это по существу крошечный, высокоспециализированный язык программирования, встроенный в Python и доступный через модуль re.

Модуль re предоставляет несколько методов, которые позволяют искать шаблон в строке. Некоторые из наиболее часто используемых методов:

* `match()`: Определите, соответствует ли RE началу строки.
* `search()`: Сканируйте строку, ища любое место, где этот RE соответствует.
* `findall()`: Найдите все подстроки, где соответствует RE, и верните их в виде списка.
* `split()`: Разделите строку на вхождения шаблона RE.
* `sub()`: Найдите все подстроки, где соответствует RE, и замените их на другую строку.
Вы также можете скомпилировать шаблон регулярного выражения в объект регулярного выражения с помощью метода `compile()`. Это позволяет использовать один и тот же объект регулярного выражения несколько раз.

Могу ли я помочь вам чем-то еще?

user: C помощью этого пакета напиши функцию, которая будет отсеивать все слова не похожие на электронную почту (по формату "слово@слово.слово").

assistant: Вот пример такой функции, принимающей строку и удаляющей из неё все слова, не похожие на адрес электронной почты.

```python
def filter_emails(text: str) -> str:
    return " ".join(re.findall(r"\b[A-Za-z0-9_.-]+@[A-Za-z0-9_.-]+\.[A-Za-z]{2,5}\b", text))
```

Я позволила себе немного усилить «похожесть»: в первых двух частях допускаются латинские буквы, цифры, минусы, подчёркивания и точки, а домен верхнего уровня ограничен длиной от 2 до 5 символов.
Вот более многословный эквивалент этой функции.

```python
def filter_emails_verbose(text: str) -> str:
    pattern = r"""
        \b               # граница слова
        [A-Za-z0-9_.-]+  # имя пользователя
        @                # собачка
        [A-Za-z0-9_.-]+  # домены 1, 2, … уровня
        \.               # точка
        [A-Za-z]{2,5}    # домен верхнего уровня
        \b               # граница слова
    """
    regex = re.compile(pattern, re.VERBOSE)
    matches = regex.findall(text)
    return " ".join(matches)
```

Надеюсь, что вы планируете использовать этот пример лишь в учебных целях, поскольку более точный вариант регулярного выражения выглядит «немного» более сложно: https://stackoverflow.com/a/201378.

user: А покажи прямо здесь этот вариант. И объясни его преимущества над тем, который ты предоставила только что

assistant: Хорошо, вот вариант регулярного выражения, приведённый по упомянутой ссылке.

```
(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
```

Его преимущество по сравнению с упрощённым вариантом в примере кода состоит в том, что это регулярное выражение соответствует [спецификации адреса](https://www.rfc-editor.org/rfc/rfc5322#section-3.4) электронной почты, приведённой в стандарте [RFC 5322](https://www.rfc-editor.org/rfc/rfc5322), предусматривающем значительно более широкое разнообразие допустимых выражений.