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

Исходный код: Lib/re.py


Модуль предоставляет операции сопоставления регулярных выражений, аналогичные тем, что есть в Perl.

И шаблоны, и строки для поиска могут быть строками Юникод (str), а также 8-битными строками (bytes). Однако строки Юникод и 8-битные строки нельзя смешивать: то есть вы не можете сопоставить строку Юникод с байтовым шаблоном или наоборот; аналогично, при запросе замены, строка замены должна быть того же типа, что и шаблон, и строка поиска.

В регулярных выражениях используется обратная косая черта ('\') для обозначения специальных форм или для разрешения использования специальных символов без указания их особого значения. Это противоречит тому, что Python использует тот же символ для той же цели в строковых литералах; например, чтобы сопоставить буквальную обратную косую черту, можно было бы написать '\\\\' в качестве строки шаблона, потому что регулярное выражение должно быть \\, а каждая обратная косая черта должна быть выражена как \\ внутри обычного строкового литерала Python. Также обратите внимание, что любые недопустимые escape-последовательности при использовании Python обратной косой черты в строковых литералах теперь генерируют DeprecationWarning, а в будущем он станет SyntaxError. Такое поведение произойдет, даже если это допустимая escape-последовательность для регулярного выражения.

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

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

См.также

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

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

Регулярное выражение (или RE) определяет набор строк, которые ему соответствуют; функции в этом модуле позволяют проверить, соответствует ли конкретная строка заданному регулярному выражению (или соответствует ли данное регулярное выражение определенной строке, что сводится к тому же самому).

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

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

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

Некоторые символы, например '|' или '(', являются специальными. Специальные символы обозначают классы обычных символов или влияют на интерпретацию окружающих их регулярных выражений.

Квалификаторы повторения (*, +, ?, {m,n} и т. д.) не могут быть вложены напрямую. Это позволяет избежать двусмысленности с суффиксом не жадного модификатора ? и другими модификаторами в других реализациях. Чтобы применить второе повторение к внутреннему повторению, можно использовать круглые скобки. Например, выражение (?:a{6})* соответствует любому кратному шести символу 'a'.

Специальные символы:

.
(Точка). В режиме по умолчанию это соответствует любому символу, кроме новой строки. Если указан флаг DOTALL, он соответствует любому символу включая новую строку.
^
(Каретка.) Соответствует началу строки, а также в режиме MULTILINE соответствует сразу после каждой новой строки.
$
Соответствует концу строки или непосредственно перед новой строкой в конце строки, а в режиме MULTILINE также соответствует перед новой строкой. foo соответствует как «foo», так и «foobar», а регулярное выражение foo$ соответствует только «foo». Что ещё интереснее, поиск foo.$ в 'foo1\nfoo2\n' обычно соответствует «foo2», но и «foo1» в режиме MULTILINE; поиск одного $ в 'foo\n' найдёт два (пустых) совпадения: одно непосредственно перед переводом строки и одно в конце строки.
*
Заставляет результирующий RE соответствовать 0 или более повторениям предыдущего RE, как можно больше повторений. ab* будет соответствовать следующим буквам «a», «ab» или «a» любому количеству букв «b».
+
Заставляет результирующий RE соответствовать 1 или более повторениям предыдущего RE. ab+ будет соответствовать «a», за которым следует любое ненулевое количество «b»; оно не будет просто совпадать с «а».
?
Заставляет результирующий RE соответствовать 0 или 1 повторению предыдущего RE. ab? будет соответствовать либо «a», либо «ab».
*?, +?, ??
Все квалификаторы '*', '+' и '?'жадные; они захватывают как можно больше текста. Иногда такое поведение нежелательно; если RE <.*> совпадает с '<a> b <c>', оно будет соответствовать всей строке, а не только '<a>'. Добавление ? после квалификатора переключает это сопоставление в режим не жадный или минимальный; по возможности будет сопоставлено минимальное кол-во символов. Использование RE <.*?> будет соответствовать только '<a>'.
{m}
Указывает, что должно быть сопоставлено ровно m копий предыдущего RE; меньше совпадения приводят к несоответствию всего RE. Например, a{6} будет соответствовать ровно шести символам 'a', но не пять.
{m,n}
Заставляет результирующее RE соответствовать от m до n повторений предыдущего RE, пытаясь сопоставить как можно больше повторений. Например, a{3,5} соответствует от 3 до 5 символов 'a'. Отсутствие m указывает на нижнюю границу равную нулю, а отсутствие n указывает на бесконечную верхнюю границу. Например, a{4,}b будет соответствовать 'aaaab' или тысяче символов 'a' за которым следует 'b', но не 'aaab'. Запятая не может быть пропущен или модификатор можно спутать с ранее описанной формой.
{m,n}?
Заставляет результирующее RE соответствовать от m до n повторений предыдущего RE, пытаясь сопоставить как можно меньше повторений. Это не жадная версия предыдущего квалификатора. Например, на строке из 6 символов 'aaaaaa', a{3,5} будет соответствовать 5 символам 'a' , в то время как a{3,5}? будет соответствовать только 3 символам.
\

Либо экранирует специальные символы (позволяя вам сопоставлять такие символы, как '*', '?' и т. д.) или сигнализирует особую последовательность; специальные последовательности обсуждаются ниже.

Если вы не используете необработанную строку для выражения шаблона, помните, что Python также использует обратную косую черту как escape- последовательность в строковых литералах; если escape-последовательность не распознаётся парсером Python, обратная косая черта и последующий символ включаются в результирующую строку. Однако, если Python распознает полученную последовательность, обратную косую черту следует повторить дважды. Это сложно и трудно понять, поэтому настоятельно рекомендуется использовать необработанные строки для всех, кроме простейших выражений.

[]

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

  • Символы могут быть перечислены индивидуально, например [amk] будет соответствовать 'a', 'm' или 'k'.

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

  • Специальные символы теряют свое особое значение внутри наборов. Например, [(+*)] будет соответствовать любому из литеральных символов '(', '+', '*' или ')'.

  • Классы символов, такие как \w или \S (определенные ниже), также принимаются внутри набора, хотя соответствующие им символы зависят от того, активен ли режим ASCII или LOCALE.
  • Символы, которые не входят в диапазон, могут быть сопоставлены дополняя набор. Если первый символ набора — '^', все символы, которых нет в множестве, будут сопоставлены. Например, [^5] будет соответствовать любому символу, кроме '5', а [^^] будет соответствовать любому символу, кроме '^'. ^ не имеет особого значения, если это не первый символ в множестве.
  • Чтобы соответствовать литералу ']' внутри набора, поставьте перед ним обратную косую черту или поместите его в начало набора. Например, и [()[\]{}], и []()[{}] будут соответствовать круглой скобке.
  • Поддержка вложенных наборов и операций над наборами, как в Техническом стандарте Юникода № 18, может быть добавлен в будущем. Это изменит синтаксис, поэтому, чтобы облегчить это изменение, в неоднозначных случаях в настоящее время будет вызываться FutureWarning. Сюда входят наборы, начинающиеся с литерального символа '[' или содержащие литеральные последовательности символов '--', '&&', '~~' и '||'. Чтобы избежать предупреждения, используйте обратную косую черту.

Изменено в версии 3.7: Появляется FutureWarning, если набор символов содержит конструкции, которые будут семантически изменяться в будущем.

|
A|B, где A и B могут быть произвольными RE; создаёт регулярное выражение, которое будет соответствовать либо A, либо B. Таким образом произвольное количество RE может быть разделено символом '|'. Это также можно использовать внутри групп (см. ниже). Целевая строка сканируется, а RE, разделенные '|', пробуются слева направо. Когда один шаблон полностью совпадает, эта ветвь принимается. Это означает что как только 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 (Юникод соответствие) и re.X (подробнее), для всего регулярного выражения. (Флаги описаны в Содержание модуля.) Это полезно, если вы хотите включить флаги как часть регулярное выражение вместо того, чтобы передавать аргумент flag в функцию re.compile(). Флаги следует использовать первыми в строке выражения.
(?:...)
Не захватывающая версия обычных скобок. Соответствует любому регулярному выражению, заключенному в круглые скобки, но соответствующая группе подстрока, не может быть получена после выполнения сопоставления или получения ссылки на неё позже в шаблоне.
(?aiLmsux-imsx:...)

(Ноль или более букв из набора 'a', 'i', 'L', 'm' , 's', 'u', 'x', за которым необязательно следует '-', за которым следует одна или несколько букв из 'i', 'm', 's', 'x'.) Буквы устанавливают или снимают соответствующие флажки: re.A (соответствие только ASCII), re.I (без учёта регистра) , re.L (зависеть от локали), re.M (многострочный) , re.S (точка соответствует всему), re.U (Юникод соответствие) и re.X (подробный) для части выражения. (Флаги описаны в Содержание модуля.)

Буквы 'a', 'L' и 'u' являются взаимоисключающими при использовании в качестве встроенных флагов, поэтому их нельзя объединены или следовать за '-'. Вместо этого, когда один из них появляется во встроенной группе, он отменяет режим сопоставления во включающей группе. В Юникод шаблонах (?a:...) переключается на сопоставление только ASCII, а (?u:...) переключается на Юникод сопоставление (по умолчанию). В байтовом шаблоне (?L:...) переключается на соответствие в зависимости от локали, а (?a:...) переключается на соответствие только ASCII (по умолчанию). Это переопределение действует только для узкой встроенной группы, и исходный режим сопоставления восстанавливается за пределами группы.

Добавлено в версии 3.6.

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

(?P<name>...)

Подобно обычным круглым скобкам, но соответствует подстроке группы доступный через символическое имя группы name. Имена групп должны быть действительными Python идентификаторами, и каждое имя группы должно быть определено только один раз в регулярном выражении. Символическая группа также является пронумерованной группой, как если бы группа не была названа.

На именованные группы можно ссылаться в трёх контекстах. Если шаблон — (?P<quote>['"]).*?(?P=quote) (т. е. соответствует строке, заключенной в одинарные или двойные кавычки):

Контекст ссылки на группу «quote» Способы ссылаться на него
в том же самом шаблоне
  • (?P=quote) (как показано)
  • \1
при обработке совпадения объекта m
  • m.group('quote')
  • m.end('quote') (и т. д.)
в строке, переданной в repl аргумента re.sub()
  • \g<quote>
  • \g<1>
  • \1
(?P=name)
Обратная ссылка на именованную группу; она соответствует любому тексту, которому соответствует ранее именуемая группа name.
(?#...)
Комментарий; содержимое круглых скобок просто игнорируется.
(?=...)
Соответствует, если ... соответствует следующему, но не использует никакую строку. Это называется прогнозируемым утверждением. Например, Isaac (?=Asimov) будет соответствовать 'Isaac ', только если за ним следует 'Asimov'.
(?!...)
Соответствует, если ... не соответствует следующему. Это негативное прогнозируемое утверждение. Например, Isaac (?!Asimov) будет соответствовать 'Isaac ', только если за ним не будет следовать 'Asimov'.
(?<=...)

Соответствует, если текущей позиции в строке предшествует совпадение для ..., которое заканчивается в текущей позиции. Это называется положительное прогнозируемое утверждение. (?<=abc)def найдёт совпадение в 'abcdef', поскольку при просмотре назад будет выполнено резервное копирование 3 символов и проверяется, совпадает ли содержащийся шаблон. Содержащийся шаблон должен соответствовать только строкам некоторой фиксированной длины, что означает, что abc или a|b разрешены, а a* и a{3,4} — нет. Обратите внимание, что шаблоны, которые начинаются с положительного прогнозируемого утверждения, не будут совпадать в начале поисковой строки; вы, скорее всего, захотите использовать функцию search(), а не функцию match():

>>> import re
>>> m = re.search('(?<=abc)def', 'abcdef')
>>> m.group(0)
'def'

В этом примере выполняется поиск слова после дефиса:

>>> m = re.search(r'(?<=-)\w+', 'spam-egg')
>>> m.group(0)
'egg'

Изменено в версии 3.5: Добавлена поддержка групповых ссылок фиксированной длины.

(?<!...)
Соответствует, если текущей позиции в строке не предшествует совпадение для .... Это называется отрицательное прогнозируемое утверждение. Походит на положительное прогнозируемое утверждение, содержащийся в нём шаблон должен соответствовать только строкам некоторой фиксированной длинны. Шаблоны, которые начинаются с отрицательного прогнозируемого утверждения, могут совпадать в начале искомой строки.
(?(id/name)yes-pattern|no-pattern)
Будет пытаться сопоставить с yes-pattern, если группа с данным id или name существует, и с no-pattern, если нет. no-pattern — необязательный и может быть пропущен. Например, (<)?(\w+@\w+(?:\.\w+)+)(?(1)>|$) — плохой шаблон сопоставления электронной почты, который будет соответствовать '<user@host.com>', а также 'user@host.com', но не с '<user@host.com' или 'user@host.com>'.

Специальные последовательности состоят из '\' и символа из списка ниже. Если обычный символ не является цифрой ASCII или буквой ASCII, то результирующий RE будет соответствовать второму символу. Например, \$ соответствует символу '$'.

\number
Соответствует содержимому группы с таким же номером. Группы пронумерованы начиная с 1. Например, (.+) \1 соответствует 'the the' или '55 55' , но не 'thethe' (обратите внимание на пробел после группы). Это особая последовательность может использоваться только для соответствия одной из первых 99 групп. Если первая цифра number равна 0 или number состоит из трех восьмеричных цифр, оно не будет интерпретировано как групповое совпадение, но как символ с восьмеричным number. Внутри '[' и ']' символьного класса, все числовые escape-символы обрабатываются как символы.
\A
Соответствует только началу строки.
\b

Соответствует пустой строке, но только в начале или в конце слова. Слово определяется как последовательность символов слова. Отметим, что формально \b определяется как граница между символом \w и \W (или наоборот), или между \w и началом/концом строки. Это означает, что r'\bfoo\b' соответствует 'foo', 'foo.', '(foo)' , 'bar foo baz', но не 'foobar' или 'foo3'.

По умолчанию в Юникод шаблонах используются буквенно-цифровые Юникод символы, но это можно изменить с помощью флага ASCII. Границы слов определяются текущей локалью, если используется флаг LOCALE. Внутри диапазона символов \b представляет backspace символ для совместимости со строковыми литералами Python.

\B
Соответствует пустой строке, но только если она не находится в начале или конце слова. Это означает, что r'py\B' соответствует 'python', 'py3' , 'py2', но не 'py', 'py.' или 'py!'. \B — полная противоположность \b, поэтому символы слова в Юникод шаблонах представляют собой буквенно-цифровые символы Юникода или знак подчеркивания, хотя это возможно можно изменить с помощью флага ASCII. Границы слов определяются текущей локалью, если используется флаг LOCALE.
\d
Для Юникод (str) шаблонов:
Соответствует любой десятичной цифре Юникода (то есть любому символу в категории символов Юникода [Nd]). Сюда входят [0-9] и также многие другие цифровые символы. Если установлен флаг ASCII будут поризводиться только [0-9] совпадения.
Для 8-разрядных (байтовых) шаблонов:
Соответствует любой десятичной цифре; эквивалентно [0-9].
\D
Соответствует любому символу, кроме десятичной цифры. Это противоположность \d. Если используется флаг ASCII, то становится эквивалентом [^0-9].
\s
Для Юникод (str) шаблонов:
Соответствует пробельным символам Юникода (включая [ \t\n\r\f\v], а также многие другие символы, например неразрывные пробелы, предусмотренные правилами типографики во многих языках). Если используется флаг ASCII будет совпадение для [ \t\n\r\f\v].
Для 8-разрядных (байтовых) шаблонов:
Соответствует символам, считающихся пробельными в множестве символов ASCII; это эквивалентно [ \t\n\r\f\v].
\S
Соответствует любому символу, кроме символа пробела. Это противоположность \s. Если используется флаг ASCII, то это становится эквивалентом [^ \t\n\r\f\v].
\w
Для Юникод (str) шаблонов:
Соответствует символам Юникод слова; включает в себя большинство символов которые могут быть частью слова на любом языке, а также числа и подчеркивание. Если используется флаг 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
\N      \r      \t      \u
\U      \v      \x      \\

(Обратите внимание, что \b используется для представления границ слова и означает «возврат» только внутри классов символов.)

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

Восьмеричные escape-последовательности включены в ограниченной форме. Если первая цифра — 0, или если есть три восьмеричных цифры, это считается восьмеричным escape-символом. В противном случае это групповая ссылка. Что касается строковых литералов, восьмеричные escape-последовательности всегда имеют длину не более трёх цифр.

Изменено в версии 3.3: Добавлены escape-последовательности '\u' и '\U'.

Изменено в версии 3.6: Неизвестные escape-последовательности, состоящие из '\' и буквы ASCII, теперь являются ошибками.

Изменено в версии 3.8: Добавлена escape-последовательность '\N{name}'. Как и в строковых литералах, он расширяется до именованного символа Юникода (например, '\N{EM DASH}').

Содержание модуля

Модуль определяет несколько функций, констант и исключение. Некоторые функции являются упрощенными версиями полнофункциональных методов для скомпилированных регулярных выражений. Большинство нетривиальных приложений всегда используют скомпилированную форму.

Изменено в версии 3.6: Константы флагов теперь являются экземплярами RegexFlag, который является подклассом enum.IntFlag.

re.compile(pattern, flags=0)

Скомпилировать шаблон регулярного выражения в объект регулярного выражения, который можно использовать для сопоставления с помощью match(), search() и других методов, описанных ниже.

Поведение выражения можно изменить, указав значение flags. Значения могут быть любыми из следующих переменных, объединенных с помощью побитового ИЛИ (оператор |).

Последовательность

prog = re.compile(pattern)
result = prog.match(string)

эквивалентно

result = re.match(pattern, string)

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

Примечание

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

re.A
re.ASCII

Сделать так, чтобы \w, \W, \b, \B, \d, \D, \s и \S выполняли сопоставление только ASCII вместо полного Юникод сопоставления. Имеет значение только для Юникод шаблонов и игнорируется для байтовых шаблонов. Соответствует встроенному флагу (?a).

Обратите внимание, что для обратной совместимости флаг re.U всё ещё существует (а также его синоним re.UNICODE и его встроенный аналог (?u)), но они избыточны в Python 3, поскольку совпадения по умолчанию для Юникод строк (а Юникод сопоставление не разрешено для байтов). ).

re.DEBUG

Показать отладочную информацию о скомпилированном выражении. Нет соответствующего встроенного флага.

re.I
re.IGNORECASE

Выполнять сопоставление без учёта регистра; такие выражения, как [A-Z], также будут соответствовать строчным буквам. Полное соответствие Юникоду (например, Ü, соответствующее ü) также работает, если только флаг re.ASCII не используется для отключения совпадений, отличных от ASCII. Текущая локаль не изменяет действие этого флага, если также не используется флаг re.LOCALE. Соответствует встроенному флагу (?i).

Обратите внимание, что когда Юникод шаблоны [a-z] или [A-Z] используются в сочетании с флагом IGNORECASE, они будут соответствовать 52 буквам ASCII и 4 дополнительным буквам, отличным от ASCII: „İ“ (U+0130, заглавная латинская буква I с точкой выше), „ı“ (U+0131, латинская строчная буква без точки i), „ſ“ (U+017F, латинская строчная буква длинная s) и „K“ (U+212A, знак кельвина). Если используется флаг ASCII, сопоставляются только буквы от «a» до «z» и от «A» до «Z».

re.L
re.LOCALE

Сделать \w, \W, \b, \B и сопоставлять без учёта регистра в зависимости от текущей локали. Флаг можно использовать только с байтовыми шаблонами. Использование этого флага не рекомендуется, поскольку механизм локали очень ненадёжен, он обрабатывает только одну «культуру» за раз и работает только с 8-битными языковыми стандартами. Соответствие Юникоду уже включено по умолчанию в Python 3 для Юникод (str) шаблонов, и оно может обрабатывать различные локали/языки. Соответствует встроенному флагу (?L).

Изменено в версии 3.6: re.LOCALE может использоваться только с байтовыми шаблонами и несовместим с re.ASCII.

Изменено в версии 3.7: Скомпилированные объекты регулярных выражений с флагом re.LOCALE больше не зависят от локали во время компиляции. Только локаль во время сопоставления влияет на результат сопоставления.

re.M
re.MULTILINE

Если указано, шаблонный символ '^' соответствует началу строки и началу каждой строки (сразу после каждой новой строки); шаблонный символ '$' соответствует концу строки и в конце каждой строки (непосредственно перед каждой новой строкой). По умолчанию '^' соответствует только в начале строки, а '$' только в конце строки и непосредственно перед новой строкой (если есть) в конце строки. Соответствует встроенному флагу (?m).

re.S
re.DOTALL

Сделать так, чтобы специальный символ '.' соответствовал любому символу, включая перевод строки; без этого флага '.' будет соответствовать чему угодно, кроме новой строки. Соответствует встроенному флагу (?s).

re.X
re.VERBOSE

Этот флаг позволяет вам писать регулярные выражения, которые выглядят лучше и удобнее для чтения, позволяя визуально разделять логические части шаблона и добавлять комментарии. Пробелы в шаблоне игнорируются, кроме тех случаев, когда они находятся в классе символов, или когда им предшествует неэкранированная обратная косая черта, или внутри токенов, таких как *?, (?: или (?P<...>. Когда строка содержит #, который не принадлежит к классу символов и которому не предшествует неэкранированная обратная косая черта, все символы от самого левого такого # до конца строки игнорируются.

Это означает, что два следующих объекта регулярного выражения, которые соответствуют десятичному числу, функционально равны:

a = re.compile(r"""\d +  # целая часть
                   \.    # десятичная точка
                   \d *  # некоторые дробные цифры """, re.X)
b = re.compile(r"\d+\.\d*")

Соответствует встроенному флагу (?x).

re.search(pattern, string, flags=0)

Просканировать string в поисках первого места, где pattern регулярного выражения даёт совпадение, и возвращает соответствующий объект соответствия. Возвращает None, если ни одна позиция в строке не соответствует шаблону; обратите внимание, что эта функция отличается от поиска совпадения нулевой длины в некоторой точке строки.

re.match(pattern, string, flags=0)

Если ноль или более символов в начале string соответствуют pattern регулярного выражения; возвращает соответствующий объект сопоставления. Возвращает None, если строка не соответствует шаблону; обратите внимание, что это отличается от совпадения нулевой длины.

Обратите внимание, что даже в режиме MULTILINE re.match() будет соответствовать только началу строки, а не в начале каждой строки.

Если вы хотите найти совпадение в любом месте string, используйте вместо неё search() (см. также search() против match()).

re.fullmatch(pattern, string, flags=0)

Если вся string соответствует pattern регулярного выражения, возвращает соответствующий объект сопоставления. Возвращает None, если строка не соответствует шаблону; обратите внимание, что это отличается от совпадения нулевой длины.

Добавлено в версии 3.4.

re.split(pattern, string, maxsplit=0, flags=0)

Разделить string по экземплярам pattern. Если в шаблоне используются захватывающие круглые скобки, то текст всех групп в pattern также возвращается как часть результирующего списка. Если maxsplit отличен от нуля, происходит не более maxsplit разбиений, а остаток строки возвращается как последний элемент списка.

>>> re.split(r'\W+', 'Words, words, words.')
['Words', 'words', 'words', '']
>>> re.split(r'(\W+)', 'Words, words, words.')
['Words', ', ', 'words', ', ', 'words', '.', '']
>>> re.split(r'\W+', 'Words, words, words.', 1)
['Words', 'words, words.']
>>> re.split('[a-f]+', '0a3B9', flags=re.IGNORECASE)
['0', '3', '9']

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

>>> re.split(r'(\W+)', '...words, words...')
['', '...', 'words', ', ', 'words', '...', '']

Таким образом, компоненты-разделители всегда находятся по одним и тем же относительным индексам в списке результатов.

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

>>> re.split(r'\b', 'Words, words, words.')
['', 'Words', ', ', 'words', ', ', 'words', '.']
>>> re.split(r'\W*', '...words...')
['', '', 'w', 'o', 'r', 'd', 's', '', '']
>>> re.split(r'(\W*)', '...words...')
['', '...', '', '', 'w', '', 'o', '', 'r', '', 'd', '', 's', '...', '', '', '']

Изменено в версии 3.1: Добавлен необязательный аргумент flags.

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

re.findall(pattern, string, flags=0)

Возвращает все неперекрывающиеся совпадения pattern в string в виде списка строк. string просматривается слева направо, и совпадения возвращаются в найденном порядке. Если в шаблоне присутствует одна или несколько групп, возвращает список групп; это будет список кортежей, если в шаблоне больше одной группы. В результат включаются пустые совпадения.

Изменено в версии 3.7: Непустые совпадения теперь могут начинаться сразу после предыдущего пустого совпадения.

re.finditer(pattern, string, flags=0)

Возвращает итератор, отдающий объекты сопоставления по всем неперекрывающимся совпадениям для pattern RE в string. string просматривается слева направо, и совпадения возвращаются в найденном порядке. В результат включаются пустые совпадения.

Изменено в версии 3.7: Непустые совпадения теперь могут начинаться сразу после предыдущего пустого совпадения.

re.sub(pattern, repl, string, count=0, flags=0)

Возвращает строку, полученную заменой крайних левых неперекрывающихся вхождений pattern в string с заменой repl. Если шаблон не найден, string возвращается без изменений. repl может быть строкой или функцией; если это строка, то в ней обрабатываются любые escape-символы. Т. е. \n преобразуется в одиночный символ новой строки, \r преобразуется в возврат каретки и т. д. Неизвестные escape-последовательности букв ASCII зарезервированы для использования в будущем и рассматриваются как ошибки. Другие неизвестные escape-символы, такие как \&, остаются в покое. Обратные ссылки, такие как \6, заменяются подстрокой, соответствующей группе 6 в шаблоне. Например:

>>> re.sub(r'def\s+([a-zA-Z_][a-zA-Z_0-9]*)\s*\(\s*\):',
...        r'static PyObject*\npy_\1(void)\n{',
...        'def myfunc():')
'static PyObject*\npy_myfunc(void)\n{'

Если repl — функция, она вызывается для каждого неперекрывающегося вхождения pattern. Функция принимает единственный аргумент объект сопоставления и возвращает заменяющую строку. Например:

>>> def dashrepl(matchobj):
...     if matchobj.group(0) == '-': return ' '
...     else: return '-'
>>> re.sub('-{1,2}', dashrepl, 'pro----gram-files')
'pro--gram files'
>>> re.sub(r'\sAND\s', ' & ', 'Baked Beans And Spam', flags=re.IGNORECASE)
'Baked Beans & Spam'

Шаблон может быть строкой или объектом шаблона.

Необязательный аргумент count — это максимальное количество замен шаблона; count должно быть неотрицательным целым числом. Если пропущено или равно нулю, все вхождения будут заменены. Пустые совпадения для шаблона заменяются только тогда, когда они не находятся рядом с предыдущим пустым совпадением, поэтому sub('x*', '-', 'abxd') возвращает '-a-b-- d-'.

В аргументах repl строкового типа, помимо экранирования символов и обратных ссылок, описанных выше, \g<name> будет использовать подстроку, соответствующую группе с именем name, как определено синтаксисом (?P<name>...). \g<number> использует соответствующий номер группы; следовательно, \g<2> эквивалентен \2, но не является двусмысленным в замене, такой как \g<2>0. \20 будет интерпретироваться как ссылка на группу 20, а не как ссылку на группу 2, за которой следует буквальный символ '0'. Обратная ссылка \g<0> заменяет всю подстроку, совпадающую с RE.

Изменено в версии 3.1: Добавлен необязательный аргумент flags.

Изменено в версии 3.5: Несовпадающие группы заменяются пустой строкой.

Изменено в версии 3.6: Неизвестные escape-последовательности в pattern, состоящем из '\' и буквы ASCII, теперь являются ошибками.

Изменено в версии 3.7: Неизвестные escape-последовательности в repl, состоящем из '\' и буквы ASCII, теперь являются ошибками.

Изменено в версии 3.7: Пустые совпадения для шаблона заменяются рядом с предыдущим непустым совпадением.

re.subn(pattern, repl, string, count=0, flags=0)

Выполнет ту же операцию, что и sub(), но возвращает кортеж (new_string, number_of_subs_made).

Изменено в версии 3.1: Добавлен необязательный аргумент flags.

Изменено в версии 3.5: Несовпадающие группы заменяются пустой строкой.

re.escape(pattern)

Экранирование (Escape) специальных символов в pattern. Это полезно, если вы хотите сопоставить произвольную литеральную строку, которая может содержать метасимволы регулярного выражения. Например:

>>> print(re.escape('http://www.python.org'))
http://www\.python\.org

>>> legal_chars = string.ascii_lowercase + string.digits + "!#$%&'*+-.^_`|~:"
>>> print('[%s]+' % re.escape(legal_chars))
[abcdefghijklmnopqrstuvwxyz0123456789!\#\$%\&'\*\+\-\.\^_`\|\~:]+

>>> operators = ['+', '-', '*', '/', '**']
>>> print('|'.join(map(re.escape, sorted(operators, reverse=True))))
/|\-|\+|\*\*|\*

Эту функцию нельзя использовать для заменяющей строки в sub() и subn(), следует экранировать только обратную косую черту. Например:

>>> digits_re = r'\d+'
>>> sample = '/usr/sbin/sendmail - 0 errors, 12 warnings'
>>> print(re.sub(digits_re, digits_re.replace('\\', r'\\'), sample))
/usr/sbin/sendmail - \d+ errors, \d+ warnings

Изменено в версии 3.3: Символ '_' больше не экранируется.

Изменено в версии 3.7: Экранируются только символы, которые могут иметь особое значение в регулярном выражении. В результате '!', '"', '%', "'", ',', '/', ':', ';', '<', '=', '>', '@' и "`" больше не экранируются.

re.purge()

Очистить кеш регулярных выражений.

exception re.error(msg, pattern=None, pos=None)

Возникает исключение, если переданная строка одной из функций указанных здесь, не является допустимым регулярным выражением (например, она может содержать несовпадающие круглые скобки) или когда во время компиляции или сопоставления возникает другая ошибка. Если строка не содержит совпадения с шаблоном, это никогда не будет ошибкой. Экземпляр ошибки содержит следующие дополнительные атрибуты:

msg

Неформатированное сообщение об ошибке.

pattern

Шаблон регулярного выражения.

pos

Индекс в pattern, в котором произошла ошибка компиляции (может быть None).

lineno

Строка, соответствующая pos (может быть None).

colno

Столбец, соответствующий pos (может быть None).

Изменено в версии 3.5: Добавлены дополнительные атрибуты.

Объекты регулярных выражений

Скомпилированные объекты регулярного выражения поддерживают следующие методы и атрибуты:

Pattern.search(string[, pos[, endpos]])

Просканировать string в поисках первого места, где регулярное выражение даёт совпадение, и возвращает соответствующий объект сопоставления. Возвращает None, если ни одна позиция в строке не соответствует шаблону; обратите внимание, что это отличается от поиска совпадения нулевой длины в некоторой точке строки.

Необязательный второй параметр pos задает индекс в строке, с которой должен начинаться поиск; по умолчанию это 0. Это не полностью эквивалентно нарезке строки; символ шаблона '^' соответствует реальному началу строки и позициям сразу после новой строки, но не обязательно по индексу, с которого должен начинаться поиск.

Необязательный параметр endpos ограничивает глубину поиска в строке; это будет выглядеть так, как если бы строка состояла из символов endpos, поэтому поиск совпадения будет выполняться только для символов от pos до endpos - 1. Если endpos меньше pos, совпадение не будет найдено; в противном случае, если rx является скомпилированным объектом регулярного выражения, rx.search(string, 0, 50) эквивалентен rx.search(string[:50], 0).

>>> pattern = re.compile("d")
>>> pattern.search("dog")     # Совпадение с индексом 0
<re.Match object; span=(0, 1), match='d'>
>>> pattern.search("dog", 1)  # Не совпадает; поиск не включает "d"
Pattern.match(string[, pos[, endpos]])

Если этому регулярному выражению соответствует ноль или более символов в начале string, возвращает соответствующий объект сопоставления. Возвращает None, если строка не соответствует шаблону; обратите внимание, что это отличается от совпадения нулевой длины.

Необязательные параметры pos и endpos имеют то же значение, что и для метода search().

>>> pattern = re.compile("o")
>>> pattern.match("dog")      # Никакого совпадения, так как "o" нет в начале "dog".
>>> pattern.match("dog", 1)   # Совпадение, т. к. как "o" - это 2-й символ "dog".
<re.Match object; span=(1, 2), match='o'>

Если вы хотите найти совпадение в любом месте string, используйте вместо него search() (см. также search() против match()).

Pattern.fullmatch(string[, pos[, endpos]])

Если вся string соответствует этому регулярному выражению, возвращает соответствующий объект сопоставления. Возвращает None, если строка не соответствует шаблону; обратите внимание, что это отличается от совпадения нулевой длины.

Необязательные параметры pos и endpos имеют то же значение, что и для метода search().

>>> pattern = re.compile("o[gh]")
>>> pattern.fullmatch("dog")      # Никакого совпадения, так как "o" нет в начале "dog".
>>> pattern.fullmatch("ogre")     # Нет совпадений, как совпадений не всей строки.
>>> pattern.fullmatch("doggie", 1, 3)   # Совпадения в заданных пределах.
<re.Match object; span=(1, 3), match='og'>

Добавлено в версии 3.4.

Pattern.split(string, maxsplit=0)

Идентичен функции split() с использованием скомпилированного шаблона.

Pattern.findall(string[, pos[, endpos]])

Подобно функции findall(), использующей скомпилированный шаблон, но также принимает дополнительные параметры pos и endpos, которые ограничивают область поиска, как для search().

Pattern.finditer(string[, pos[, endpos]])

Аналогично функции finditer(), использующей скомпилированный шаблон, но также принимает дополнительные параметры pos и endpos, которые ограничивают область поиска, как для search().

Pattern.sub(repl, string, count=0)

Идентичен функции sub(), с использованием скомпилированного шаблона.

Pattern.subn(repl, string, count=0)

Идентично функции subn() с использованием скомпилированного шаблона.

Pattern.flags

Флаги соответствия регулярному выражению. Это комбинация флагов, присвоенных compile(), любых встроенных флагов (?...) в шаблоне и неявных флагов, таких как UNICODE, если шаблон является Юникод строкой.

Pattern.groups

Количество групп захвата в шаблоне.

Pattern.groupindex

Словарь, отображающий любые символьные имена групп, определенные (?P<id>), на номера групп. Словарь пуст, если в шаблоне не использовались символические группы.

Pattern.pattern

Строка шаблона, из которой был скомпилирован объект шаблона.

Изменено в версии 3.7: Добавлена поддержка copy.copy() и copy.deepcopy(). Скомпилированные объекты регулярных выражений считаются атомарными.

Match объекты

Match объекты всегда рассматриваются в логическом контексте как True. Поскольку match() и search() возвращают None при отсутствии совпадения, вы можете проверить, было ли совпадение, с помощью простого оператора if:

match = re.search(pattern, string)
if match:
    process(match)

Объекты Match поддерживают следующие методы и атрибуты:

Match.expand(template)

Вернуть строку, полученную путём подстановки обратной косой черты в шаблоне строки template, также как это сделано методом sub(). Экранированные, такие как \n, преобразуются в соответствующие символы, а числовые обратные ссылки (\1, \2) и именованные обратные ссылки (\g<1>, \g<name>) заменяются содержимым соответствующей группы.

Изменено в версии 3.5: Несовпадающие группы заменяются пустой строкой.

Match.group([group1, ...])

Возвращает одну или несколько подгрупп совпадения. Если есть один аргумент, результатом будет одна строка; если есть несколько аргументов, результатом будет кортеж с одним элементом на аргумент. Без аргументов группа group1 по умолчанию равна нулю (возвращается все совпадение). Если аргумент groupN равен нулю, соответствующее возвращаемое значение является всей совпадающей строкой; если он находится в включающем диапазоне [1..99], это строка, соответствующая соответствующей группе в скобках. Если номер группы отрицательный или превышает количество групп, определенных в шаблоне, возникает исключение IndexError. Если группа содержится в части шаблона, который не соответствует, соответствующий результат будет None. Если группа содержится в части шаблона, совпадающей несколько раз, возвращается последнее совпадение.

>>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")
>>> m.group(0)       # Всё совпадение
'Isaac Newton'
>>> m.group(1)       # Первая подгруппа в скобках.
'Isaac'
>>> m.group(2)       # Вторая подгруппа в скобках.
'Newton'
>>> m.group(1, 2)    # Несколько аргументов возвращает нам кортеж.
('Isaac', 'Newton')

Если в регулярном выражении используется синтаксис (?P<name>...), аргументы groupN также могут быть строками, идентифицирующими группы по их имени. Если строковый аргумент не используется в качестве имени группы в шаблоне, возникает исключение IndexError.

В меру сложный пример:

>>> m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds")
>>> m.group('first_name')
'Malcolm'
>>> m.group('last_name')
'Reynolds'

Именованные группы также могут упоминаться по их индексу:

>>> m.group(1)
'Malcolm'
>>> m.group(2)
'Reynolds'

Если группа соответствует несколько раз, доступно только последнее совпадение:

>>> m = re.match(r"(..)+", "a1b2c3")  # 3 кратное соответствие.
>>> m.group(1)                        # Возвращает только последнее соответствие.
'c3'
Match.__getitem__(g)

Это идентично m.group(g). Это упрощает доступ к отдельной группе из совпадения:

>>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")
>>> m[0]       # Всё совпадение
'Isaac Newton'
>>> m[1]       # Первая подгруппа в скобках.
'Isaac'
>>> m[2]       # Вторая подгруппа в скобках.
'Newton'

Добавлено в версии 3.6.

Match.groups(default=None)

Возвращает кортеж, содержащий все подгруппы совпадения, от 1 до количества групп в шаблоне. Аргумент default используется для групп, которые не участвовали в совпадении; по умолчанию это None.

Например:

>>> m = re.match(r"(\d+)\.(\d+)", "24.1632")
>>> m.groups()
('24', '1632')

Если мы сделаем десятичный знак и все после него необязательными, не все группы смогут участвовать в совпадении. Группы по умолчанию будут None, если не указан аргумент default:

>>> m = re.match(r"(\d+)\.?(\d+)?", "24")
>>> m.groups()      # Вторая группа по умолчанию - None.
('24', None)
>>> m.groups('0')   # Теперь вторая группа по умолчанию '0'.
('24', '0')
Match.groupdict(default=None)

Возвращает словарь, содержащий все именуемые подгруппы совпадения, с ключом по имени подгруппы. Аргумент default используется для групп, которые не участвовали в совпадении; по умолчанию это None. Например:

>>> m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds")
>>> m.groupdict()
{'first_name': 'Malcolm', 'last_name': 'Reynolds'}
Match.start([group])
Match.end([group])

Возвращает индексы начала и конца подстроки, соответствующей group; group по умолчанию равна нулю (то есть вся совпадающая подстрока). Возвращает -1, если group существует, но не участвовала в совпадении. Для объекта сопоставления m и группы g, которая внесла вклад в сопоставление, подстрока, сопоставленная группой g (эквивалент m.group(g)), равна:

m.string[m.start(g):m.end(g)]

Обратите внимание, что m.start(group) будет равно m.end(group), если group соответствует пустой строке. Например, после m = re.search('b(c?)', 'cba') m.start(0) равен 1, m.end(0) равен 2, m.start(1) и m.end(1) равны 2, а m.start(2) вызывает исключение IndexError.

Пример, который удалит remove_this из адресов электронной почты:

>>> email = "tony@tiremove_thisger.net"
>>> m = re.search("remove_this", email)
>>> email[:m.start()] + email[m.end():]
'tony@tiger.net'
Match.span([group])

Для соответствия m возвращает 2-кортеж (m.start(group), m.end(group)). Обратите внимание: если group не участвовала в совпадении, это (-1, -1). group по умолчанию равна нулю, полное совпадение.

Match.pos

Значение pos, переданное методу search() или match() из объекта регулярного выражения. Это индекс в строке, с которой механизм RE начал поиск совпадения.

Match.endpos

Значение endpos, переданное методу search() или match() из объекта регулярного выражения. Это индекс в строке, за который движок RE не пойдет.

Match.lastindex

Целочисленный индекс последней совпавшей группы захвата или None, если ни одна группа не была сопоставлена вообще. Например, выражения (a)b, ((a)(b)) и ((ab)) будут иметь lastindex == 1, если их применить к строке 'ab', а выражение (a)(b) будет иметь lastindex == 2, если применить к той же строке.

Match.lastgroup

Имя последней совпавшей группы захвата или None, если у группы не было имени или если группа вообще не была сопоставлена.

Match.re

Объект регулярного выражения, чей метод match() или search() создал этот экземпляр соответствия.

Match.string

Строка передается в match() или search().

Изменено в версии 3.7: Добавлена поддержка copy.copy() и copy.deepcopy(). Объекты соответствия считаются атомарными.

Примеры регулярных выражений

Проверка на пару

В этом примере мы будем использовать следующую вспомогательную функцию для более изящного отображения совпадающих объектов:

def displaymatch(match):
    if match is None:
        return None
    return '<Match: %r, groups=%r>' % (match.group(), match.groups())

Предположим, вы пишете покерную программу, в которой рука игрока представлена в виде строки из 5 символов, где каждый символ представляет карту: «a» — туз, «k» — король, «q» — дама, «j» — валет, «t» означает 10, а от «2» до «9» — карту с этим значением.

Чтобы узнать, является ли данная строка допустимой рукой, можно сделать следующее:

>>> valid = re.compile(r"^[a2-9tjqk]{5}$")
>>> displaymatch(valid.match("akt5q"))  # Действительный.
"<Match: 'akt5q', groups=()>"
>>> displaymatch(valid.match("akt5e"))  # Недействительный.
>>> displaymatch(valid.match("akt"))    # Недействительный.
>>> displaymatch(valid.match("727ak"))  # Действительный.
"<Match: '727ak', groups=()>"

Последняя рука, "727ak", содержала пару или две карты одного достоинства. Чтобы сопоставить это с регулярным выражением, можно использовать обратные ссылки как таковые:

>>> pair = re.compile(r".*(.).*\1")
>>> displaymatch(pair.match("717ak"))     # Пара 7-к.
"<Match: '717', groups=('7',)>"
>>> displaymatch(pair.match("718ak"))     # Нет пар.
>>> displaymatch(pair.match("354aa"))     # Пара тузов.
"<Match: '354aa', groups=('a',)>"

Чтобы узнать, из какой карты состоит пара, можно использовать метод group() объекта match следующим образом:

>>> pair = re.compile(r".*(.).*\1")
>>> pair.match("717ak").group(1)
'7'

# Ошибка, потому что re.match() возвращает None, у которого нет метода group():
>>> pair.match("718ak").group(1)
Traceback (most recent call last):
  File "<pyshell#23>", line 1, in <module>
    re.match(r".*(.).*\1", "718ak").group(1)
AttributeError: 'NoneType' object has no attribute 'group'

>>> pair.match("354aa").group(1)
'a'

Имитация scanf()

У Python в настоящее время нет эквивалента scanf(). Регулярные выражения обычно более эффективны, хотя и более подробны, чем форматные строки scanf(). В таблице ниже представлены некоторые более или менее эквивалентные сопоставления между токенами формата scanf() и регулярными выражениями.

scanf() токен Регулярное выражение
%c .
%5c .{5}
%d [-+]?\d+
%e, %E, %f, %g [-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?
%i [-+]?(0[xX][\dA-Fa-f]+|0[0-7]*|\d+)
%o [-+]?[0-7]+
%s \S+
%u \d+
%x, %X [-+]?(0[xX])?[\dA-Fa-f]+

Чтобы извлечь имя файла и числа из строки вроде:

/usr/sbin/sendmail - 0 errors, 4 warnings

вы должны использовать формат scanf(), например:

%s - %d errors, %d warnings

Эквивалентное регулярное выражение было бы:

(\S+) - (\d+) errors, (\d+) warnings

search() против match()

Python предлагает две разные примитивные операции, основанные на регулярных выражениях: re.match() проверяет совпадение только в начале строки, а re.search() проверяет совпадение в любом месте строки (это то, что Perl делает по умолчанию).

Например:

>>> re.match("c", "abcdef")    # Не совпадает
>>> re.search("c", "abcdef")   # Совпадает
<re.Match object; span=(2, 3), match='c'>

Регулярные выражения, начинающиеся с '^', можно использовать с search(), чтобы ограничить совпадение в начале строки:

>>> re.match("c", "abcdef")    # Не совпадает
>>> re.search("^c", "abcdef")  # Не совпадает
>>> re.search("^a", "abcdef")  # Совпадает
<re.Match object; span=(0, 1), match='a'>

Однако обратите внимание, что в режиме MULTILINE match() соответствует только началу строки, тогда как использование search() с регулярным выражением, начинающимся с '^', будет соответствовать началу каждой строки.

>>> re.match('X', 'A\nB\nX', re.MULTILINE)  # Не совпадает
>>> re.search('^X', 'A\nB\nX', re.MULTILINE)  # Совпадает
<re.Match object; span=(4, 5), match='X'>

Создание телефонной книги

split() разбивает строку на список, ограниченный переданным шаблоном. Этот метод неоценим для преобразования текстовых данных в структуры данных, которые могут быть легко прочитаны и изменены Python, как показано в следующем примере создания телефонной книги.

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

>>> text = """Ross McFluff: 834.345.1254 155 Elm Street
...
... Ronald Heathmore: 892.345.3428 436 Finley Avenue
... Frank Burger: 925.541.7625 662 South Dogwood Way
...
...
... Heather Albrecht: 548.326.4584 919 Park Place"""

Записи разделяются одной или несколькими символами новой строки. Теперь преобразуем строку в список, в котором каждая непустая строка содержит свою запись:

>>> entries = re.split("\n+", text)
>>> entries
['Ross McFluff: 834.345.1254 155 Elm Street',
'Ronald Heathmore: 892.345.3428 436 Finley Avenue',
'Frank Burger: 925.541.7625 662 South Dogwood Way',
'Heather Albrecht: 548.326.4584 919 Park Place']

Наконец, разделим каждую запись на список с именем, фамилией, номером телефона и адресом. Мы используем параметр maxsplit в split(), потому что в адресе есть пробелы. Наш шаблон разделения:

>>> [re.split(":? ", entry, 3) for entry in entries]
[['Ross', 'McFluff', '834.345.1254', '155 Elm Street'],
['Ronald', 'Heathmore', '892.345.3428', '436 Finley Avenue'],
['Frank', 'Burger', '925.541.7625', '662 South Dogwood Way'],
['Heather', 'Albrecht', '548.326.4584', '919 Park Place']]

Шаблон :? соответствует двоеточию после фамилии, поэтому он не встречается в списке результатов. С maxsplit или 4 мы могли отделить номер дома от названия улицы:

>>> [re.split(":? ", entry, 4) for entry in entries]
[['Ross', 'McFluff', '834.345.1254', '155', 'Elm Street'],
['Ronald', 'Heathmore', '892.345.3428', '436', 'Finley Avenue'],
['Frank', 'Burger', '925.541.7625', '662', 'South Dogwood Way'],
['Heather', 'Albrecht', '548.326.4584', '919', 'Park Place']]

Выравнивание текста

sub() заменяет каждое вхождение шаблона строкой или результатом функции. В этом примере демонстрируется использование sub() с функцией изменения текста или рандомизации всех символов в каждом слове предложения, кроме первого и последнего символов:

>>> def repl(m):
...     inner_word = list(m.group(2))
...     random.shuffle(inner_word)
...     return m.group(1) + "".join(inner_word) + m.group(3)
>>> text = "Professor Abdolmalek, please report your absences promptly."
>>> re.sub(r"(\w)(\w+)(\w)", repl, text)
'Poefsrosr Aealmlobdk, pslaee reorpt your abnseces plmrptoy.'
>>> re.sub(r"(\w)(\w+)(\w)", repl, text)
'Pofsroser Aodlambelk, plasee reoprt yuor asnebces potlmrpy.'

Поиск всех наречий

findall() соответствует всем вхождениям шаблона, а не только первому, как search(). Например, если писатель хотел найти все наречия в каком-то тексте, он мог бы использовать findall() следующим образом:

>>> text = "He was carefully disguised but captured quickly by police."
>>> re.findall(r"\w+ly", text)
['carefully', 'quickly']

Поиск всех наречий и их положений

Если кто-то хочет получить больше информации обо всех совпадениях шаблона, чем соответствующий текст, полезен finditer(), поскольку он предоставляет объекты сопоставления вместо строк. Продолжая предыдущий пример, если писатель хотел найти все наречия и их позиции в каком-либо тексте, он использовал бы finditer() следующим образом:

>>> text = "He was carefully disguised but captured quickly by police."
>>> for m in re.finditer(r"\w+ly", text):
...     print('%02d-%02d: %s' % (m.start(), m.end(), m.group(0)))
07-16: carefully
40-47: quickly

Обозначение необработанных строк

Нотация необработанных строк (r"text") сохраняет читаемость регулярного выражения. Без неё каждая обратная косая черта ('\') в регулярном выражении должна быть снабжена экранирующим префиксом. Например, две следующие строки кода функционально идентичны:

>>> re.match(r"\W(.)\1\W", " ff ")
<re.Match object; span=(0, 4), match=' ff '>
>>> re.match("\\W(.)\\1\\W", " ff ")
<re.Match object; span=(0, 4), match=' ff '>

Если кто-то хочет сопоставить буквальную обратную косую черту, её нужно экранировать в регулярном выражении. В случае необработанной строковой записи это означает r"\\". Без нотации необработанных строк необходимо использовать "\\\\", что делает следующие строки кода функционально идентичными:

>>> re.match(r"\\", r"\\")
<re.Match object; span=(0, 1), match='\\'>
>>> re.match("\\\\", r"\\")
<re.Match object; span=(0, 1), match='\\'>

Написание токенизатора

Токенизатор или сканер анализирует строку для классификации групп символов. Это ценный первый шаг при написании компилятора или интерпретатора.

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

from typing import NamedTuple
import re

class Token(NamedTuple):
    type: str
    value: str
    line: int
    column: int

def tokenize(code):
    keywords = {'IF', 'THEN', 'ENDIF', 'FOR', 'NEXT', 'GOSUB', 'RETURN'}
    token_specification = [
        ('NUMBER',   r'\d+(\.\d*)?'),  # Целое или десятичное число
        ('ASSIGN',   r':='),           # Оператор присваивания
        ('END',      r';'),            # Инструкция завершителя
        ('ID',       r'[A-Za-z]+'),    # Идентификаторы
        ('OP',       r'[+\-*/]'),      # Арифметические операторы
        ('NEWLINE',  r'\n'),           # Концы строк
        ('SKIP',     r'[ \t]+'),       # Пропустить пробелы и табы
        ('MISMATCH', r'.'),            # Любой другой символ
    ]
    tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification)
    line_num = 1
    line_start = 0
    for mo in re.finditer(tok_regex, code):
        kind = mo.lastgroup
        value = mo.group()
        column = mo.start() - line_start
        if kind == 'NUMBER':
            value = float(value) if '.' in value else int(value)
        elif kind == 'ID' and value in keywords:
            kind = value
        elif kind == 'NEWLINE':
            line_start = mo.end()
            line_num += 1
            continue
        elif kind == 'SKIP':
            continue
        elif kind == 'MISMATCH':
            raise RuntimeError(f'{value!r} unexpected on line {line_num}')
        yield Token(kind, value, line_num, column)

statements = '''
    IF quantity THEN
        total := total + price * quantity;
        tax := price * 0.05;
    ENDIF;
'''

for token in tokenize(statements):
    print(token)

Токенизатор верёт следующий результат:

Token(type='IF', value='IF', line=2, column=4)
Token(type='ID', value='quantity', line=2, column=7)
Token(type='THEN', value='THEN', line=2, column=16)
Token(type='ID', value='total', line=3, column=8)
Token(type='ASSIGN', value=':=', line=3, column=14)
Token(type='ID', value='total', line=3, column=17)
Token(type='OP', value='+', line=3, column=23)
Token(type='ID', value='price', line=3, column=25)
Token(type='OP', value='*', line=3, column=31)
Token(type='ID', value='quantity', line=3, column=33)
Token(type='END', value=';', line=3, column=41)
Token(type='ID', value='tax', line=4, column=8)
Token(type='ASSIGN', value=':=', line=4, column=12)
Token(type='ID', value='price', line=4, column=15)
Token(type='OP', value='*', line=4, column=21)
Token(type='NUMBER', value=0.05, line=4, column=23)
Token(type='END', value=';', line=4, column=27)
Token(type='ENDIF', value='ENDIF', line=5, column=4)
Token(type='END', value=';', line=5, column=9)
[Frie09]Джеффри Фридл. Регулярные выражения. 3е издание, O’Reilly Media, 2009. Третье издание книги больше не касается Python, но первое издание подробно описывало написание хороших шаблонов регулярных выражений.