Spec-Zone.ru › Python 3.11

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

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

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

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

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

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

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

См. также

Модуль сторонних разработчиков regex, у которого есть API, совместимый с модулем стандартной библиотеки re модуля, но он предлагает дополнительные возможности и более полную поддержку Юникода.

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

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

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

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

Регулярные выражения могут содержать как специальные, так и обычные символы. Большинство обычных символов, такие как '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’.

*?, +?, ??

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

*+, ++, ?+

Как и квантификаторы '*', '+', и '?', те, где '+' добавлено, также соответствуют как можно большему количеству раз. Однако, в отличие от истинных жадных квантификаторов, они не позволяют откат, когда выражение, которое следует за ним, не может быть сопоставлено. Эти квантификаторы известны как поглощающие. Например, 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?) соответственно.

Добавлен в версии 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}).

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

\

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

Если вы не используете строку без начального символа для выражения шаблона, помните, что 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', а [^^] будет соответствовать любому символу, кроме '^'. ^ не имеет особого значения, если это не первый символ в наборе.
  • Чтобы сопоставить буквальный ']' внутри набора, поместите перед ним обратную косую черту или поместите его в начало набора. Например, оба [()[\]{}] и []()[{}] будут соответствовать правой квадратной скобке, а также левой квадратной скобке, фигурным скобкам и круглым скобкам.
  • Поддержка вложенных наборов и операций над наборами, как в Unicode Technical Standard #18, может быть добавлена в будущем. Это изменит синтаксис, поэтому для облегчения этого изменения в неоднозначных случаях будет подниматься FutureWarning. Это включает наборы, начинающиеся с буквального '[' или содержащие буквальные последовательности символов '--', '&&', '~~', и '||'. Чтобы избежать предупреждения, экранируйте их обратной косой чертой.

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

|

A|B, где A и B могут быть произвольными выражениями регулярных выражений, создает регулярное выражение, которое будет соответствовать либо 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 (сопоставление Unicode) и re.X (развернутый), для всего регулярного выражения. (Флаги описаны в Содержимое модуля.) Это полезно, если вы хотите включить флаги в часть регулярного выражения, вместо того, чтобы передавать аргумент флага функции 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 (сопоставление Unicode) и re.X (развернутый), для части выражения. (Флаги описаны в Содержимое модуля.)

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

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

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

(?>...)

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

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

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

Устарело начиная с версии 3.11: Группа name, содержащая символы за пределами ASCII-диапазона (b'\x00'-b'\x7f') в шаблонах bytes.

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

Устарело начиная с версии 3.11: Группа id, содержащая что-либо кроме ASCII-цифр. Группа name, содержащая символы за пределами ASCII-диапазона (b'\x00'-b'\x7f') в строках замены bytes.

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

\number

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

\A

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

\b

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

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

\B

Сопоставляется с пустой строкой, но только когда она не находится в начале или конце слова. Это означает, что r'py\B' соответствует 'python', 'py3', 'py2', но не 'py', 'py.', или 'py!'. \B является просто обратным \b, поэтому символы слов в Unicode-паттернах — это Unicode-алфанумерические символы или подчёркивание, хотя это можно изменить, используя флаг ASCII. Границы слов определяются текущей локалью, если используется флаг LOCALE.

\d
Для Unicode (str) шаблонов:

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

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

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

\D

Сопоставляет любой символ, который не является десятичной цифрой. Это противоположно \d. Если используется флаг ASCII, это становится эквивалентом [^0-9].

\s
Для Unicode (str) шаблонов:

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

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

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

\S

Сопоставляет любой символ, который не является символом пробела. Это противоположно \s. Если используется флаг ASCII, это становится эквивалентом [^ \t\n\r\f\v].

\w
Для Unicode (str) шаблонов:

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

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

Совпадает с символами, которые считаются буквенно-цифровыми в наборе символов 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' последовательности эскейпов распознаются только в Unicode-шаблонах. В шаблонах байтов они являются ошибками. Неизвестные эскейпы ASCII-символов зарезервированы для будущего использования и обрабатываются как ошибки.

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

Изменено в версии 3.3: Последовательности эскейпов '\u' и '\U' были добавлены.

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

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

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

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

Флаги

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

class re.RegexFlag

Класс enum.IntFlag, содержащий опции регулярных выражений, перечисленные ниже.

Новое в версии 3.11: - добавлено в __all__

re.A
re.ASCII

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

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

re.DEBUG

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

re.I
re.IGNORECASE

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

Обратите внимание, что при использовании шаблонов Unicode [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-битными локалями. Соответствие Unicode уже включено по умолчанию в Python 3 для шаблонов Unicode (str), и он может обрабатывать различные локали/языки. Соответствует встроенному флагу (?L).

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

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

re.M
re.MULTILINE

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

re.NOFLAG

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

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

Новое в версии 3.11.

re.S
re.DOTALL

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

re.U
re.UNICODE

В Python 2 этот флаг заставлял специальные последовательности включать символы Unicode в совпадения. С Python 3 символы Unicode соответствуют по умолчанию.

См. A для ограничения соответствия на символы 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).

END_OF_DOCUMENT_MARKER

Функции

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.search(pattern, string, flags=0)

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

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

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

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

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

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

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

New 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.', 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)

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

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

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

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

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

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

Устарело начиная с версии 3.11: Группа id, содержащая что-либо кроме ASCII цифр. Группа name, содержащая символы за пределами ASCII диапазона (b'\x00'-b'\x7f') в строках замены bytes.

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

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

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

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

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.error(msg, pattern=None, pos=None)

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

msg

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

pattern

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

pos

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

lineno

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

colno

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

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

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

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() (см. также search() против match()).

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

Новое в версии 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(). Скомпилированные объекты регулярных выражений считаются атомарными.

Объекты совпадений

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

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

Объект совпадения, возвращаемый при успешных match и search.

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

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

Новое в версии 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 по умолчанию равен нулю (вся сопоставленная подстрока). Возвращает -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» для десятки, а «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() объекта совпадения следующим образом:

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

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

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, 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\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='\\'>

Создание токенизатора

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

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

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

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

© 2001–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.11/library/re.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API