re — Операции с регулярными выражениями в Python3.7

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

И шаблоны и строки использующиеся как данные для сопоставления или поиска МОГУТ быть как Unicode строками (str), так и 8-битными строками (последовательностями байт bytes). Следует отметить, что Unicode строки и 8-битовые строки не могут использоваться совместно: вы не можете осуществлять сопоставление Unicode шаблона и bytes строки и наоборот. Похожая ситуация и в случае с подстановкой/заменой: заменяемая строка обязана быть того же самого типа, что и шаблон и исходная строка.

Регулярные выражения используют символ обратного слэша ( бэкслэша/обратной косой черты '\') для указания на специальные формы или для предоставления возможности использования специальных символов без обращения к их особому значению. Это противоречит обычному использованию в Python этих же символов в подобном назначении в обычных строковых литералах. К примеру, для сопоставления с строковым значением обратного слэша придётся использовать '\\\\' как строкового шаблона, потому что регулярное выражение должно быть \\ и всякий обратный слэш обязан быть выражен как \\ внутри регулярного строкового литерала в Python.

Решение подобной проблемы в использовании сырых строк для шаблонов регулярных выражений в Python. Обратные слэши не обрабатываются особым образом в строковых литералах, предваряемые символом 'r'. Так, 'r"\n"' двухсимволльная строка содержащая '\' и 'n', в то время, как обычная запись "\n" это односимвольная строка содержащая символ “перевода строки”. Обычно шаблоны выражаются в виде сырых строк в Python.

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

Обратите внимание на модуль regex, который предоставляет API совместимое с re модулем, но предлагает дополнительную функциональность и более ориентирован на поддержку Unicode.

Синтаксис регулярных выражений

Регулярные выражения могут быть сконкатенированы (последовательно объединены) для получения новых регулярных выражений; если %%A%% и %%B%% оба являются регулярными выражениями, то %%AB%% также является регулярным выражением. В общем, если строка %%p%% сопоставляется с %%A%%, а другая строка %%q%% соответствует %%B%%, строка %%pq%% будет соответствовать %%AB%%. Это верно до тех пор, пока %%A%% или %%B%% содержат операции с низким приоритетом; граничные условия между %%А%% и %%В%%; или пронумерованные групповые ссылки. Если это так, то сложные выражения могут быть легко построены из более простых примитивных выражений, подобных описанным здесь. За подробностями теории и реализации регулярных выражений обращайтесь к книге Фридла [Frie09] или почти к любому учебнику об архитектуре построения компилятора.

Регулярные выражения могут содержать как обычные так и специальные символы. Большинство обычных символов, таких как 'A', 'a', '0' и т.д., являются простейшими регулярными выражениями: они соответствуют сами себе. Вы можете сконкатенировать обычные символы. Так, last соответствует строке 'last'. Чтобы устранить путаницу, мы будем записывать регулярные выражения без кавычек, а строки для сопоставления с кавычками, например, 'вот строка для сопоставления'.


.
(Точка.) В режиме по умолчанию это соответствует любому символу, кроме новой строки. Если указан флаг DOTALL, он соответствует любому символу, включая символ новой строки.
^
(каретка.) Соответствует началу строки, а в режиме MULTILINE также соответствует “сразу после каждой новой строки”.
$
Сопоставляется с концом строки или непосредственно перед символом новой строки в конце строки. В режиме MULTILINE также соответствует символу новой строки. foo совпадает как с 'foo', так и с 'foobar', а регулярное выражение foo$ соответствует только 'foo'.
Значительно более интересен вот какой пример: поиск foo.$ в 'foo1\nfoo2\n' будет успешно сопоставлен с 'foo2'. Но в режиме MULTILINE ему также будет сопоставлен и 'foo1'. поиск же $ в 'foo\n' найдет два (пустых) совпадения: одно непосредственно перед новой строкой, а другое - в конце всей строки.
*
Основание для сопоставления с каким угодно количеством предшествующего этому символу регулярного выражения. Например, ab* состоит из конкатенированных a + b*. Поэтому, такому выражению будет соответствовать такие строки: 'a', 'ab', 'abb' и 'abbbb' или другими словами, 'a' с любым количеством следующих за ним 'b'.
+
Основание для сопоставления с ОДНИМ ИЛИ БОЛЕЕ повторений предшествующего регулярного выражения. ab+ будет сопоставляться с любой строкой, состоящей из 'ab' + любое количество символов 'b'. Например, 'ab', 'abbb', 'abbbbbb', 'abbbbbbb' и так далее.
?
Основание для сопоставления с отсутствием или единичным присутствием (0 или 1 раз) предшествующего регулярного выражения. ab? будет соответствовать ТОЛЬКО строкам 'a' или 'ab' и больше никаким.
*?, +?, ??
Выражения '*', '+', '?' квалифицируются как жадные (greedy). Они соответствуют такому количеству текста, которое только возможно. Порой такое поведение нежелательно. Например, выражение <.*> будет применяться относительно '<a> b <c>', то соответствовать оно будет всей строке, а не только '<a>'. Добавление ? меняет поведение, заставляя сопоставляться на “не жадный” или “минимальный” манер. В данном случае, лучше всего проиллюстрировать примером:
>>> import re
>>> p = re.compile('<.*?>')
>>> p.findall('<a> b <c>')
['<a>', '<c>']
>>> p.match('<a> b <c>')
<_sre.SRE_Match object; span=(0, 3), match='<a>'>
{m}, где %%m%% — целое число
Указывает, что в точности %%m%% повторений должно присутствовать в предшествующем регулярном выражении. Меньшее количество не будет сопоставлено. Например, a{3} будет успешно сопоставлено с 'aaa', 'aaaa', 'aaaaaaa', но не будет с 'aa'.
{m,n}, где %%m%% и %%n%% — целые числа
Соответствует такому условию для сопоставления, при котором предыдущее регулярное выражение должно встречаться от %%m%% до %%n%% раз, пытаясь всякий раз сопоставить столько повторений, сколько возможно. К примеру, a{3,5} будет соответствовать любой строке, состоящей от 3 до 5 символов 'a' ('aaa', 'aaaa', 'aaaaa'). Можно избежать указания верхней и нижней границы. Так, отсутствие %%m%% подразумевает 0, а %%n%% — бесконечность как верхнюю границу. Так, например, a{2,}b будет соответствовать 'aab' или 'aaaaaaaaaab', но не будет соответствовать 'ab'. Обратите внимание, что запятая не может быть исключена, потому что произойдёт смешивание с предыдущей описанной выше формой.
{m,n}?, где %%m%% и %%n%% — целые числа
не жадный вариант предыдущего шаблона. Соответствует такому сопоставлению, при котором осуществлятся от %%m%% до %%n%% вхождений регулярного выражения с как можно меньшим вхождением повторений. К примеру, 'aaaaaa', a{3,5} будет соотвествовать 5 символам 'a', в то время как a{3,5}? будет соответствовать лишь трём таким символам.
\
Используется и для экранирования специальных символов (что позволяет включать такие символы как '*' или '?', например) или сигнализирует о специальной последовательности. Эта функциональность будет рассмотрена ниже.
Если используется обычная, а не сырая (raw) строка для выражения шаблона, следует помнить, что Python использует обратный слэш как экранирующий символ в строковых литералах. Если такая экранирующая последовательность не распознаётся парсером Python, то и обратный слэш и следующий за ним символ включаются в полученную строку. На самом деле, если Python следует распознать результирующую последовательность, то бэкслеш должен использоваться дважды. Это сложно и трудно для восприятия. И именно поэтому крайне рекомендуется использование raw строк для всех, за исключением самых тривиальных выражений.
[]

Используется для выражения набора символов. В таком наборе:

  • Символы могут перечисляться индивидуально. Так, [folk] будет соответствовать 'f', 'k', 'l', 'o'.
  • Диапазоны символов могут быть определены разделением двух граничных символов символом '-', например:

    • '[a-z]' — строчные сивмолы английского алфавита по таблице символов ASCII.
    • [0-5][0-9] — будут соответствовать двузначному номеру от 00 до 59,
    • [0-9A-Fa-f] — будет соответствовать символам, использующимся для составления шестнадцатеричного числа

если символ '-' 'экранирован (например, '[a\-v]') ИЛИ используется как первый или последний символ (например, '[b-]', '[-v]'), то он обозначает не диапазон, а отдельный символ '-'

  • Специальные символы утрачивают их особое значение внутри набора данных. К примеру, [(+*)] будут обозначать любой из литералов, обозначающих символы '(', ')', '+', '*',
  • Символьные классы, такие как \w или \S (будет разьяснено ниже) также принимаются внутри наборов, а значение этих классов определяется от режима (ASCII или LOCALE) принудительно,
  • Если требуется осуществить сопоставление, при котором существуют символы, которые НЕ должны находиться в наборе, то используется синтаксис с предшествующим символом '^' (не путать с отдельным использованием этого символа без границ набора []). Так, например, использование [^5] будет соответствать ЛЮБОМУ символу, кроме '5'. А [^^], будет соответствовать любому символу, кроме '^'. ВНИМАНИЕ! ^ не имеет никакого специального значения, если используется НЕ ПЕРВЫМ символом в наборе.
  • Сопоставление со специальным символом ']' внутри набора, предполагает ЛИБО экранирование его обратным слэшем, либо помещением первым символом в набор. Так, оба выражения: [()[]] и []()[] обозначают одно и тоже: использование любых типов скобок,

    Поддержка вложенных наборов и наборов операций как в Unicode Technical Standard #18 может быть добавлена в будущем. Это может существенно изменить синтаксис, поэтому для содействия этим изменениям был добавлен FutureWarning (Исключительная ситуация), которое возбуждается, в ситуациях неоднозначного толкования в ряде случаев. Такие ситуации, это наборы, стартующие с [ или содержащие символьные последовательности '--', '&&', '~~' и '||'. Чтобы избежать это исключение экранируйте их в обратные слэши

|
A|B в которых и A и B могут быть произвольными регулярными выражениями, создаёт такое регулярное выражение, которое будет соответствовать или A или B. Количество произвольных конкатенаций выражений может быть любым, в качестве разделителей всегда используется |. Подобный синтаксис может использоваться и внутри групп. Когда целевая строка сканируется, регулярные выражения, разделённые символом | проверяются на сопоставление слева направо. Когда первый из шаблонов сопоставляется, вся ветка принимается и обработка завершается. Это обозначает, что если A сработал, то B больше не вызывается. Другими словами, | никогда не бывает жадным. Для сопоставления с символом '|' следует его экранировать.
(...), где ... любое регулярное выражение
Сопоставление произвольного регулярного выражения внутри скобок, которые определяют начало и окончание группы. Содержимое группы может быть получено после сопоставления и может быть сопоставлено позже в строке со специальной последовательностью \number, описанной ниже.
(?...)
Это расширение определения (? следующее за (, в противном случае не имеет смысла). Первый символ в '?' определяется значение и дальнейший синтаксис всей конструкции. Такое расширение обычно не создаёт новую группу.
(?P<name>...) — исключение из общего правила. Следующие ниже примеры иллюстрируют возможное использование:
(?aiLmsux)
Используется ОДИН или более символов из набора 'a', 'i', 'L', 'm', 's', 'u', 'x', Группа может быть и пустым множеством. Каждый символ обозначает соответствующий флаг для всего высказывания:
  • re.A — только ASCII сопоставления
  • re.I — игнорировать регистр (заглавные/строчные)
  • re.L — зависящий от локали
  • re.M — многострочный
  • re.S — точка соответствует любому символу
  • re.U — Unicode сопоставления
  • re.X — подброчный/многословный разбор

Включение флагов как часть регулярного выражения вместо передачи их в вызов re.compile() это довольно удобная практика. Заметим, что флаги должны передаваться первыми в строке.

(?:...) Незахватывающая версия регулярного выражения. Сопоставляется с каким угодно регулярным рыражением внутри скобок, однако подстрока, сопоставленная группой НЕ МОЖЕТ быть извлечена и использована для сопоставления позже в шаблоне.
(?aiLmsux-imsx:)
Используется НИ ОДНОГО или более символов из набора 'a', 'i', 'L', 'm', 's', 'u', 'x', опционально следующего за ним символа '-' с последующим ОДНИМ или более символами из набора 'i', 'm', 's', 'x'. Каждый символ УСТАНАВЛИВАЕТ или УДАЛЯЕТ (если следует за '-') соответствующий флаг для всего высказывания:
Символы 'a', 'L' и 'u' являются взаимно исключающими, когда используются как inline флаги, поэтому они не могут сочетаться или следовать за '-'. Напротив, если один из этих символов появляется в inline группе, это переопределяет режим сопоставления во всей включённой группы. В Unicode шаблоны (?a:...) переключается на сопоставление только с ASCII, а (?u:...) переключает режим в Unicode сопоставление (по умолчанию). В байтовых шаблонах (для байтовых строк/последовательностей) (?L%...) переключает для зависящий от текущей локали режим сопоставления, а (a?...) переключает в режим ASCII (по умолчанию).
Подобное переопределение режима имеет эффект только внутри inline группы, а оригинальный режим сопоставления остаётся/восстанавливается снаружи группы.

В Python 3.7

Символы 'a', 'L', 'u' также могут использоваться в группах

(?P<name>...)
Похоже на обычные высказывания в скобках, но подстроки, сопоставленные группой, доступны через символическое имя группы name. Имена групп обязаны быть корректными идентификаторами Python и каждое имя группы обязано быть определено единожды во всём регулярном выражении. Сомволические группы также являются нумерованными группами, как если бы группа не имела имени.
Сослаться на именованную группу можно в трёх разных контекстах. Если шаблон соответствует (?P<quote>['"]).*?(?P=quote) — то есть на основании соответствия строки, заключённой в одинарные или двойные кавычки:
Контект ссылки на группу “quote” Способ сослаться
В том же самом шаблоне (?P=quote) — как в примере
\1
Когда происходит обработка объекта %%m%% m.group('quote')
m.end('quote') (etc.)
В строке, переданной аргументу repl re.sub() \q<quote>
\q<1>
\1
(?P=name)
Обратная ссылка именованной группы. Сопоставляет любой текст, который был сопоставлен ранее группой с именем name.
(?#...)
Комментарий. Весь контент внутри скобок будет проигнорирован.
(?=...)
Сопоставляется в конструкции if ... сопоставить следующее, но не включает само условие в качестве результата сопоставления. Это называется УПРЕЖДАЮЩЕЕ УТВЕРЖДЕНИЕ. К примеру, Isaac (?=Asimov) будет сопоставлен с 'Isaac ' только в том случае, если за ним следует Asimov
(?!...)
Сопоставляется в конструкции if ... NOT следующее. Это негативное упреждающее утверждение. К примеру, Isaac (?!Asimov) будет сопоставлен только с Isaac только если следует НЕ будет Asimov.
(?<=...)
Сопоставляется с текстом, если текущая позтиция в строке предваряется соответствием с ... которое заканчивается на текущей позиции. Это называется позитивным упреждающим утверждением.
(?<=abc)def будет соответствовать abcdef, поскольку конструкция позитивного упреждающего утверждения создаст буфер на 3 символа и проверит, соответствует ли ей содержащийся шаблон. Контейнер подобного типа ОБЯЗАН содержать только строки фиксированной длинны. Это означает, что abcd или a|b разрешены, но конструкции с переменным числом символов — НЕТ (такие, как a* или a{3,4}).
Шаблон, который начинается с позитивного упреждающего утверждения не будет соответствовать поисковой строке целиком (с первого символа утверждения). По сценариям использования, вероятнее всего, вы пожелаете использовать из-за этого search() вместо match():
>>> import re
>>> m = re.search('(?<=abc)def', 'abcdef')
>>> m.group(0)
'def'
(?<!...)
Соопоставление в том случае, если текущая позиция в строке не предваряется совпадением с .... Называется это негативным упреждающим утверждением. Как и в позитивном упреждающем утверждении, содержащийся шаблон может состоять только из строк фиксированной длинны. Шаблоны, которые начинаются с негативного упреждающего утверждения МОГУТ соответствовать началу строки, по которой осуществляется поиск.
(?(id/name)yes-pattern|no-pattern)
Будет пробовать сопоставить с yes-pattern если существует группа с соответствующим id или name и с no-pattern в противном случае. no-pattern опциональный и может не указываться.
К примеру, (<)?(\w+@\w+(?:.\w+)+)(?(1)>|$) паттерн на проверку ошибок в e-mail адресе. Он будет соответстовать <user@host.com> также, как и user@host.com, но не будет работать с user@host.com>.

Таблица спецсимволов

Спецсимволы, содержат '\' и следующий за ним символ из списка, приведённого ниже.

\number
Соответствует контенту группы имещей этот самый номер. Группы нумеруются начиная с 1.
Например, (.+) \1 соответствует 'tu tu' или '5 5', но НЕ СООТВЕТСТВУЕТ'tuktuk' или '66' (обратите внимание на значащий пробел). Эта специальная служебная последовательность, которая позволяет производить сопоставление только с 99 группами.
Если первый символ это число 0 или число имеет длинну 3 октета, то этот номер не будет интерпретироваться как номер группы. В этом случае это будет распознаваться как восьмибитное цифровое значение числа.
Внутри квадратных скобок ('[' и ']') символьного класса, все числовые экранирования распознаются как символы.
\A
Соответствует началу строки
\b
Соответствует пустой строке, но только в начале или окончании слова. Формально, \b определяется как ГРАНИЦЫ СЛОВА (boundary) между \w и \W символом (и так далее) или между \w и началом или окончанием строки. Слово определяется как последовательность печатных символов.
Это обозначает, что r'\bfoo\b' соответствует 'foo', 'foo.', '(foo)', 'bar foo baz', но не соответствует 'foobar' или 'foo3'.
По умолчанию только буквенно-цифровые символы Unicode используются в Unicode шаблонах, но это поведение можно изменить используя ASCII флаг. Границы слов определяются в текущей локали, если флаг LOCALE используется. Внутри символьного диапазона \b представляется как “возврат каретки” (backspace) символ, в целях совместимости со строковыми литералами Python.
\B
Соответствует пустой строке, но только в том случае, если НЕ приходится на начало или окончание слова. Это обозначает, что r'pyth\B' будет соответствовать 'python', 'pyth3', но не будет 'pyth', 'pyth.' или 'pyth!'. '\B' по поведению является противоположностью '\b', поэтому ограничения на Unicode поведение и границы слова в LOCALE аналогичны.
'\d'
для Unicode шаблонов: соответствует десятичному числу (уточняем: любому символу в Unicode символьной категории [Nd]). Этот набор включает [0-9], а также кучу других цифровых символов. Если выставлен ASCII флаг, то используется ТОЛЬКО [0-9].
Для 8-битовых шаблонов: Соответствует любому десятичному числу. Это эквивалент [0-9].
'\D'
Соответствует любому символу, который НЕ является десятичным числом. Это, по сути, противоположность для '\d'. В ASCII это соответствует высказыванию [^0-9].
'\s'
Для строковых шаблонов Unicode: соответствует пробельным символам Unicode (включающим [ \t\n\r\f\v]) и множество других символов. К примеру, неразрывные типографские пробелы, существующие в наборах для различных языков. Для ASCII строк включает только [ \t\n\r\f\v].
Для 8-битных шаблонов: Соответствует ASCII.
'\S'
Соответствует ЛЮБОМУ символу, НЕ ЯВЛЯЮЕЩЕМУСЯ пробельным для строковых шаблонов Unicode: ([^ \t\n\r\f\v]). Для ASCII строк включает только [^ \t\n\r\f\v].
'\w'
Соответствует любому печатаемому символу в шаблонах Unicode. В ASCII соответствует только [a-zA-Z0-9_].
Для 8-ми битных шаблонов: соответствует буквенно-цифровым символам ASCII. Эквивалент [a-zA-Z0-9_]. Если флаг LOCALE установлен, соответствует буквенно-цифровым символам текущей локали + символ подчёркивания.
'\W'
соответствует любому небуквенно-нецифровому символу. Противоположность для '\w'. В ASCII соответствует [^a-zA-Z0-9_]. Соответственно, если используется флаг LOCALE, то используется сопоставление с текущей локалью.
'\Z'
Соответствует концу строки.

Большинство стандартных экранирований поддерживаемым строковыми литералами Python также поддерживаются парсером регулярных выражений:

		\a	\b	\f	\n
		\r	\t	\u	\U
		\v	\x	\

Обратите внимание, что \b используется для представления границ слова, и обозначает “возврат каретки” только внутри символьных классов.

'\u' и '\U' имеют смысл только внутри Unicode шаблона. В байтовых шаблонах это ошибка. Неопределённые экранирования символов в ASCII зарезервированы на будущее и интерпретируются как ошибки.