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

Источник: Lib/re/


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

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

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

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

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

См.также

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

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

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

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

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

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

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

Операторы повторения или квантификаторы (*, +, ?, {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“; не будет соответствовать только „a“.

?

Приводит к тому, что результирующий RE будет соответствовать 0 или 1 повторению предыдущего RE. ab? будет соответствовать либо „a“, либо „ab“.

*?, +?, ??

Квантификаторы '*', '+' и '?' - это все greedy; они сопоставляют как можно больше текста. Иногда такое поведение нежелательно; если RE <.*> сопоставляется с '<a> b <c>', то будет сопоставлена вся строка, а не только '<a>'. Добавление ? после квантификатора заставляет его выполнять сопоставление в стиле non-greedy или minimal; при этом будет сопоставлено как можно меньше символов. Использование RE <.*?> приведет к совпадению только с '<a>'.

*+, ++, ?+

Как и квантификаторы '*', '+' и '?', квантификаторы, к которым добавляется '+', также совпадают столько раз, сколько возможно. Однако, в отличие от настоящих жадных квантификаторов, они не позволяют вернуться назад, если выражение, следующее за ними, не совпало. Такие квантификаторы называются possessive. Например, a*a будет соответствовать 'aaaa', потому что a* будет соответствовать всем 4 'a's, но, когда встречается заключительный 'a', выражение возвращается назад, так что в итоге a* будет соответствовать 3 'a's, а четвертый 'a' будет соответствовать заключительному 'a'. Однако если a*+a используется для соответствия 'aaaa', то a*+ будет соответствовать всем 4 'a', но когда конечный 'a' не найдет больше символов для соответствия, выражение нельзя будет отменить, и оно не будет соответствовать. x*+, x++ и x?+ эквивалентны (?>x*), (?>x+) и (?>x?) соответственно.

Added in version 3.11.

{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 символам.

{m,n}+

Приводит к тому, что результирующий RE будет соответствовать от m до n повторений предыдущего RE, пытаясь соответствовать как можно большему количеству повторений без установления каких-либо точек отката. Это притяжательная версия квантификатора выше. Например, для 6-символьной строки 'aaaaaa', a{3,5}+aa попытается сопоставить 5 символов 'a', затем, требуя еще 2 'a'символов, потребует больше символов, чем доступно, и, таким образом, потерпит неудачу, в то время как a{3,5}aa будет сопоставлен с a{3,5}, захватывая 5, затем 4 'a'символов путем отката, и затем последние 2 'a'символов будут сопоставлены с последним aa в шаблоне. x{m,n}+ эквивалентен (?>x{m,n}).

Added in version 3.11.

\

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

Если вы не используете необработанную строку для выражения шаблона, помните, что Python также использует обратный слеш в качестве управляющей последовательности в строковых литералах; если управляющая последовательность не распознается синтаксическим анализатором 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 (определены ниже), также принимаются внутри набора, хотя символы, которым они соответствуют, зависят от используемых флагов.

  • Символы, не входящие в диапазон, могут быть сопоставлены с помощью complementing набора. Если первым символом набора является '^', то будут сопоставлены все символы, которые не входят в набор. Например, [^5] будет соответствовать любому символу, кроме '5', а [^^] будет соответствовать любому символу, кроме '^'. ^ не имеет специального значения, если это не первый символ в наборе.

  • Чтобы сопоставить литерал ']' внутри набора, поставьте перед ним обратную косую черту или поместите его в начало набора. Например, и [()[\]{}], и []()[{}] будут соответствовать правой скобке, а также левой скобке, скобкам и круглым скобкам.

  • В будущем может быть добавлена поддержка вложенных множеств и операций над множествами, как в Unicode Technical Standard #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 (verbose)

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

Изменено в версии 3.11: Эта конструкция может использоваться только в начале выражения.

(?:...)

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

(?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 (verbose)

(Флаги описаны в разделе Содержание модуля).

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

Added in version 3.6.

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

(?>...)

Пытается сопоставить ..., как если бы это было отдельное регулярное выражение, и в случае успеха продолжает сопоставлять остальную часть следующего за ним шаблона. Если последующий шаблон не совпадает, стек можно развернуть только до точки перед (?>...), потому что после выхода из него выражение, известное как atomic group, отбросило все точки стека внутри себя. Таким образом, (?>.*). никогда ничему не будет соответствовать, потому что сначала .* будет соответствовать всем возможным символам, а затем, когда уже нечего будет соответствовать, конечный . не будет соответствовать. Поскольку в атомарной группе не сохранилось ни одной точки стека, а перед ней нет ни одной точки стека, все выражение, таким образом, не совпадет.

Added in version 3.11.

(?P<name>...)

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

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

Контекст ссылки на группу «цитата»

Способы ссылки

по той же схеме

  • (?P=quote) (как показано на рисунке)

  • \1

при обработке объекта совпадения m

  • m.group('quote')

  • m.end('quote') (и т.д.)

в строке, переданной в аргумент repl из re.sub().

  • \g<quote>

  • \g<1>

  • \1

Изменено в версии 3.12: В шаблонах bytes группа name может содержать только байты в диапазоне ASCII (b'\x00'-b'\x7f').

(?P=name)

Обратная ссылка на именованную группу; она соответствует тексту, который был найден предыдущей группой с именем name.

(?#...)

Комментарий; содержимое круглых скобок просто игнорируется.

(?=...)

Совпадает, если ... совпадает со следующей, но не поглощает ни одной строки. Это называется lookahead assertion. Например, Isaac (?=Asimov) будет соответствовать 'Isaac ', только если за ним следует 'Asimov'.

(?!...)

Совпадает, если ... не совпадает со следующим. Это negative lookahead assertion. Например, Isaac (?!Asimov) будет соответствовать 'Isaac ' только в том случае, если за ним не следует 'Asimov'.

(?<=...)

Устанавливает соответствие, если текущей позиции в строке предшествует совпадение с ..., которое заканчивается на текущей позиции. Это называется positive lookbehind assertion. (?<=abc)def найдет совпадение в 'abcdef', поскольку lookbehind вернется на 3 символа назад и проверит, совпадает ли содержащийся шаблон. Содержащийся шаблон должен соответствовать только строкам определенной длины, то есть abc или a|b допустимы, а a* и a{3,4} - нет. Обратите внимание, что шаблоны, начинающиеся с положительных утверждений lookbehind, не будут совпадать с началом искомой строки; скорее всего, вы захотите использовать функцию 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: Добавлена поддержка групповых ссылок фиксированной длины.

(?<!...)

Устанавливает совпадение, если текущей позиции в строке не предшествует совпадение с .... Это называется negative lookbehind assertion. Как и в случае с положительными утверждениями lookbehind, содержащийся шаблон должен соответствовать только строкам некоторой фиксированной длины. Шаблоны, начинающиеся с отрицательных утверждений lookbehind, могут совпадать с началом искомой строки.

(?(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>'.

Изменено в версии 3.12: Группа id может содержать только ASCII-цифры. В шаблонах bytes группа name может содержать только байты в диапазоне ASCII (b'\x00'-b'\x7f').

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

\number

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

\A

Сопоставляет только начало строки.

\b

Сопоставляет пустую строку, но только в начале или в конце слова. Слово определяется как последовательность символов слова. Обратите внимание, что формально \b определяется как граница между символами \w и \W (или наоборот), или между \w и началом или концом строки. Это означает, что r'\bat\b' совпадает с 'at', 'at.', '(at)' и 'as at ay', но не с 'attempt' или 'atlas'.

По умолчанию символами слов в шаблонах Unicode (str) являются алфавитно-цифровые символы Unicode и символ подчеркивания, но это можно изменить с помощью флага ASCII. Границы слов определяются текущей локалью, если используется флаг LOCALE.

Примечание

Внутри диапазона символов \b представляет символ обратного пробела для совместимости со строковыми литералами Python.

\B

Совпадает с пустой строкой, но только если она не находится в начале или конце слова. Это означает, что r'at\B' соответствует 'athens', 'atom', 'attorney', но не 'at', 'at.' или 'at!'. \B противоположен \b, поэтому символы слов в шаблонах Unicode (str) - это алфавитно-цифровые символы Unicode или символ подчеркивания, хотя это можно изменить с помощью флага ASCII. Границы слов определяются текущей локалью, если используется флаг LOCALE.

\d
Для шаблонов Юникода (str):

Сопоставляет любую десятичную цифру Юникода (то есть любой символ в категории символов Юникода [Nd]). Сюда входит [0-9], а также многие другие символы цифр.

Совпадает с [0-9], если используется флаг ASCII.

Для 8-битных (байтовых) шаблонов:

Совпадает с любой десятичной цифрой в наборе символов ASCII; это эквивалентно [0-9].

\D

Сопоставляет любой символ, не являющийся десятичной цифрой. Это противоположность \d.

Совпадает с [^0-9], если используется флаг ASCII.

\s
Для шаблонов Юникода (str):

Сопоставляет символы пробельных символов Unicode (к ним относится [ \t\n\r\f\v], а также многие другие символы, например, неразрывные пробелы, предусмотренные правилами типографики во многих языках).

Совпадает с [ \t\n\r\f\v], если используется флаг ASCII.

Для 8-битных (байтовых) шаблонов:

Сопоставляет символы, считающиеся пробелами в наборе символов ASCII; это эквивалентно [ \t\n\r\f\v].

\S

Сопоставляет любой символ, не являющийся символом пробела. Это противоположность \s.

Совпадает с [^ \t\n\r\f\v], если используется флаг ASCII.

\w
Для шаблонов Юникода (str):

Сопоставляет символы слов Юникода; сюда входят все алфавитно-цифровые символы Юникода (как определено в str.isalnum()), а также символ подчеркивания (_).

Совпадает с [a-zA-Z0-9_], если используется флаг ASCII.

Для 8-битных (байтовых) шаблонов:

Сопоставляет символы, считающиеся алфавитно-цифровыми в наборе символов ASCII; это эквивалентно [a-zA-Z0-9_]. Если используется флаг LOCALE, совпадают символы, считающиеся алфавитно-цифровыми в текущей локали, и символ подчеркивания.

\W

Сопоставляет любой символ, не являющийся символом слова. Это противоположность \w. По умолчанию совпадает с символами без андерскорда (_), для которых str.isalnum() возвращает False.

Совпадает с [^a-zA-Z0-9_], если используется флаг ASCII.

Если используется флаг LOCALE, то совпадают символы, которые не являются ни алфавитно-цифровыми в текущей локали, ни символами подчеркивания.

\Z

Сопоставляет только с концом строки.

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

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

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

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

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

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

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

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

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

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

Флаги

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

class re.RegexFlag

Класс enum.IntFlag, содержащий перечисленные ниже параметры regex.

Added in version 3.11: - added to __all__

re.A
re.ASCII

Заставьте \w, \W, \b, \B, \d, \D, \s и \S выполнять только ASCII-сопоставление вместо полного сопоставления с Unicode. Это имеет смысл только для шаблонов Юникода (str) и игнорируется для шаблонов байтов.

Соответствует флагу вставки (?a).

Примечание

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

re.DEBUG

Отображение отладочной информации о скомпилированном выражении.

Соответствующий флаг в строке отсутствует.

re.I
re.IGNORECASE

Выполняйте сопоставление без учета регистра; выражения типа [A-Z] также будут соответствовать строчным буквам. Полное соответствие Юникоду (например, Ü соответствует ü) также работает, если только не используется флаг ASCII, отключающий совпадения, не относящиеся к ASCII. Текущая локаль не изменяет действие этого флага, если только не используется также флаг 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 и нечувствительное к регистру сопоставление зависимыми от текущей локали. Этот флаг можно использовать только с байтовыми шаблонами.

Соответствует флагу вставки (?L).

Предупреждение

Этот флаг не рекомендуется использовать; вместо него используйте сопоставление с Юникодом. Механизм локалей очень ненадежен, так как он обрабатывает только одну «культуру» за раз и работает только с 8-битными локалями. По умолчанию для шаблонов Юникода (str) включено сопоставление с Юникодом, и оно способно работать с различными локалями и языками.

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

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

re.M
re.MULTILINE

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

Соответствует флагу вставки (?m).

re.NOFLAG

Указывает, что флаг не применяется, значение 0. Этот флаг может использоваться в качестве значения по умолчанию для аргумента ключевого слова функции или в качестве базового значения, которое будет условно объединено в ИЛИ с другими флагами. Пример использования в качестве значения по умолчанию:

def myfunc(text, flag=re.NOFLAG):
    return re.match(text, flag)

Added in version 3.11.

re.S
re.DOTALL

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

Соответствует флагу вставки (?s).

re.U
re.UNICODE

В Python 3 символы Юникода по умолчанию сопоставляются с шаблонами str. Поэтому этот флаг является избыточным и не имеет эффекта и сохраняется только для обратной совместимости.

Чтобы ограничить поиск символами ASCII, смотрите ASCII.

re.X
re.VERBOSE

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

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

a = re.compile(r"""\d +  # the integral part
                   \.    # the decimal point
                   \d *  # some fractional digits""", re.X)
b = re.compile(r"\d+\.\d*")

Соответствует флагу вставки (?x).

Функции

re.compile(pattern, flags=0)

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

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

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

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

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

result = re.match(pattern, string)

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

Примечание

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

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

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

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

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

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

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

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

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

Added in version 3.4.

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

Разделить строку по вхождениям шаблона. Если в шаблоне используются круглые скобки, то текст всех групп в шаблоне также возвращается как часть результирующего списка. Если 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.', maxsplit=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: Добавлена поддержка разбиения на шаблоны, которые могут соответствовать пустой строке.

Не рекомендуется, начиная с версии 3.13: Передача maxsplit и flags в качестве позиционных аргументов устарела. В будущих версиях Python они будут иметь значение keyword-only parameters.

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

Возвращает все непересекающиеся совпадения шаблона в строке в виде списка строк или кортежей. Строка * сканируется слева направо, и совпадения возвращаются в порядке их нахождения. Пустые совпадения включаются в результат.

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

>>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest')
['foot', 'fell', 'fastest']
>>> re.findall(r'(\w+)=(\d+)', 'set width=20 and height=10')
[('width', '20'), ('height', '10')]

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

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

Возвращает iterator, дающий Match объектов по всем непересекающимся совпадениям для RE шаблона в строке. Строка* просматривается слева направо, и совпадения возвращаются в порядке их нахождения. Пустые совпадения включаются в результат.

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

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

Возвращает строку, полученную путем замены крайних левых непересекающихся вхождений шаблона в строке на замену repl. Если шаблон не найден, строка возвращается без изменений. repl может быть строкой или функцией; если это строка, то все обратные косые черты в ней обрабатываются. То есть \n преобразуется в один символ новой строки, \r - в возврат каретки и так далее. Неизвестные эскейпы букв ASCII резервируются для будущего использования и рассматриваются как ошибки. Другие неизвестные эскейпы, такие как \&, оставляются в покое. Обратные ссылки, такие как \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 - это функция, то она вызывается для каждого непересекающегося вхождения шаблона. Функция принимает единственный аргумент Match и возвращает заменяющую строку. Например:

>>> 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'

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

Необязательный аргумент 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: Неизвестные эскейпы в шаблоне, состоящем из '\' и буквы ASCII, теперь являются ошибками.

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

Изменено в версии 3.12: Группа id может содержать только ASCII-цифры. В строках замены bytes группа name может содержать только байты в диапазоне ASCII (b'\x00'-b'\x7f').

Не рекомендуется, начиная с версии 3.13: Передача count и flags в качестве позиционных аргументов устарела. В будущих версиях Python они будут иметь значение keyword-only parameters.

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

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

re.escape(pattern)

Исключить специальные символы в шаблоне. Это полезно, если вы хотите сопоставить произвольную буквенную строку, в которой могут присутствовать метасимволы регулярного выражения. Например:

>>> print(re.escape('https://www.python.org'))
https://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.PatternError(msg, pattern=None, pos=None)

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

msg

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

pattern

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

pos

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

lineno

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

colno

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

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

Изменено в версии 3.13: Изначально PatternError назывался error; для обратной совместимости он оставлен в качестве псевдонима.

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

class re.Pattern

Скомпилированный объект регулярного выражения, возвращаемый re.compile().

Изменено в версии 3.9: re.Pattern поддерживает [] для указания шаблона Unicode (str) или байта. См. Общий тип псевдонима.

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

Просмотрите строку в поисках первого места, где это регулярное выражение дает совпадение, и верните соответствующее значение Match. Верните 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")     # Match at index 0
<re.Match object; span=(0, 1), match='d'>
>>> pattern.search("dog", 1)  # No match; search doesn't include the "d"
Pattern.match(string[, pos[, endpos]])

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

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

>>> pattern = re.compile("o")
>>> pattern.match("dog")      # No match as "o" is not at the start of "dog".
>>> pattern.match("dog", 1)   # Match as "o" is the 2nd character of "dog".
<re.Match object; span=(1, 2), match='o'>

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

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

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

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

>>> pattern = re.compile("o[gh]")
>>> pattern.fullmatch("dog")      # No match as "o" is not at the start of "dog".
>>> pattern.fullmatch("ogre")     # No match as not the full string matches.
>>> pattern.fullmatch("doggie", 1, 3)   # Matches within given limits.
<re.Match object; span=(1, 3), match='og'>

Added in version 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, если шаблон представляет собой строку Unicode.

Pattern.groups

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

Pattern.groupindex

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

Pattern.pattern

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

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

Совпадение объектов

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

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

Соответствует объекту, возвращенному успешными matches и searches.

Изменено в версии 3.9: re.Match поддерживает [] для указания соответствия Unicode (str) или байтам. См. Общий тип псевдонима.

Match.expand(template)

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

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

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

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

>>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")
>>> m.group(0)       # The entire match
'Isaac Newton'
>>> m.group(1)       # The first parenthesized subgroup.
'Isaac'
>>> m.group(2)       # The second parenthesized subgroup.
'Newton'
>>> m.group(1, 2)    # Multiple arguments give us a tuple.
('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")  # Matches 3 times.
>>> m.group(1)                        # Returns only the last match.
'c3'
Match.__getitem__(g)

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

>>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")
>>> m[0]       # The entire match
'Isaac Newton'
>>> m[1]       # The first parenthesized subgroup.
'Isaac'
>>> m[2]       # The second parenthesized subgroup.
'Newton'

Поддерживаются также именованные группы:

>>> m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Isaac Newton")
>>> m['first_name']
'Isaac'
>>> m['last_name']
'Newton'

Added in version 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()      # Second group defaults to None.
('24', None)
>>> m.groups('0')   # Now, the second group defaults to '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() в regex object. Это индекс строки, по которому механизм RE начал искать совпадение.

Match.endpos

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

Match.lastindex

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

Match.lastgroup

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

Match.re

Метод regular expression object, чей 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"))  # Valid.
"<Match: 'akt5q', groups=()>"
>>> displaymatch(valid.match("akt5e"))  # Invalid.
>>> displaymatch(valid.match("akt"))    # Invalid.
>>> displaymatch(valid.match("727ak"))  # Valid.
"<Match: '727ak', groups=()>"

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

>>> pair = re.compile(r".*(.).*\1")
>>> displaymatch(pair.match("717ak"))     # Pair of 7s.
"<Match: '717', groups=('7',)>"
>>> displaymatch(pair.match("718ak"))     # No pairs.
>>> displaymatch(pair.match("354aa"))     # Pair of aces.
"<Match: '354aa', groups=('a',)>"

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

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

# Error because re.match() returns None, which doesn't have a group() method:
>>> 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

поиск() против совпадения()

Python предлагает различные примитивные операции, основанные на регулярных выражениях:

  • re.match() проверяет совпадение только в начале строки

  • re.search() проверяет совпадение в любом месте строки (так Perl делает по умолчанию)

  • re.fullmatch() проверяет совпадение всей строки

Например:

>>> re.match("c", "abcdef")    # No match
>>> re.search("c", "abcdef")   # Match
<re.Match object; span=(2, 3), match='c'>
>>> re.fullmatch("p.*n", "python") # Match
<re.Match object; span=(0, 6), match='python'>
>>> re.fullmatch("r.*n", "python") # No match

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

>>> re.match("c", "abcdef")    # No match
>>> re.search("^c", "abcdef")  # No match
>>> re.search("^a", "abcdef")  # Match
<re.Match object; span=(0, 1), match='a'>

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

>>> re.match("X", "A\nB\nX", re.MULTILINE)  # No match
>>> re.search("^X", "A\nB\nX", re.MULTILINE)  # Match
<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, maxsplit=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, maxsplit=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\b", text)
['carefully', 'quickly']

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

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

>>> text = "He was carefully disguised but captured quickly by police."
>>> for m in re.finditer(r"\w+ly\b", 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='\\'>

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

tokenizer or scanner анализирует строку, чтобы распределить группы символов по категориям. Это полезный первый шаг при написании компилятора или интерпретатора.

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

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*)?'),  # Integer or decimal number
        ('ASSIGN',   r':='),           # Assignment operator
        ('END',      r';'),            # Statement terminator
        ('ID',       r'[A-Za-z]+'),    # Identifiers
        ('OP',       r'[+\-*/]'),      # Arithmetic operators
        ('NEWLINE',  r'\n'),           # Line endings
        ('SKIP',     r'[ \t]+'),       # Skip over spaces and tabs
        ('MISMATCH', r'.'),            # Any other character
    ]
    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]

Фридл, Джеффри. Mastering Regular Expressions. 3-е издание, O’Reilly Media, 2009. В третьем издании книги больше не рассматривается Python, но первое издание очень подробно рассказывало о написании хороших шаблонов регулярных выражений.