Spec-Zone.ru › Python 3.12

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

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

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

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

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

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

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

См. также

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

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

Регулярное выражение (или 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, соответствует любому символу, включая новую строку. (?s:.) соответствует любому символу независимо от флагов.

^

(Знак вставки.) Соответствует началу строки, а в режиме 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 задаёт нижнюю границу 0, а пропуск 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's, потребует больше символов, чем доступно, и, следовательно, потерпит неудачу, в то время как a{3,5}aa будет соответствовать a{3,5} захватив 5, затем 4 'a's с помощью обратного отслеживания, а затем 2 последних 'a's будут соответствовать последнему aa в шаблоне. x{m,n}+ эквивалентно (?>x{m,n}).

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

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

|

A|B, где A и B могут быть произвольными выражениями регулярного выражения, создаёт регулярное выражение, которое будет соответствовать либо A, либо B. В таком виде можно разделять произвольное количество выражений регулярного выражения. Это может быть использовано и внутри групп (см. ниже). При сканировании целевой строки выражения регулярного выражения, разделённые '|', пытаются сопоставится слева направо. Когда один шаблон полностью совпадает, этот вариант принимается. Это означает, что как только A совпадет, B больше не будет проверяться, даже если он даст более длинное соответствие в целом. Другими словами, оператор '|' никогда не является жадным. Чтобы сопоставить буквальный '|', используйте \|, или заключите его в набор символов, как в [|].

(...)

Сопоставляет то регулярное выражение, которое находится внутри скобок, и указывает начало и конец группы; содержимое группы может быть получено после выполнения сопоставления и может быть сопоставлено позже в строке с использованием \number специальной последовательности, описанной ниже. Чтобы сопоставить буквальные '(' или ')', используйте \( или \), или заключите их в набор символов: [(], [)].

(?...)

Это обозначение расширения ('?' после '(' в противном случае не имеет смысла). Первый символ после '?' определяет смысл и дальнейший синтаксис конструкции. Расширения обычно не создают новых групп; (?P<name>...) является единственным исключением из этого правила. Ниже приведены поддерживаемые расширения.

(?aiLmsux)

(Одна или несколько букв из набора 'a', 'i', 'L', 'm', 's', 'u', 'x'.) Группа соответствует пустой строке; буквы устанавливают соответствующие флаги для всего регулярного выражения:

  • re.A (только ASCII-сопоставление)
  • re.I (не учитывать регистр)
  • re.L (зависит от локали)
  • re.M (многострочный)
  • re.S (точка соответствует всем)
  • re.U (Unicode-сопоставление)
  • re.X (развёрнутый)

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

Изменено в версии 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, а в шаблонах bytes они могут содержать только байты в ASCII-диапазоне. Каждое имя группы должно быть определено только один раз в регулярном выражении. Символическая группа также является пронумерованной группой, как если бы группа не имела имени.

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

Контекст ссылки на группу «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.

(?#...)

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

(?=...)

Соответствует, если ... соответствует следующему, но не потребляет никакой части строки. Это называется утверждением оглядки вперёд. Например, 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.12: Идентификатор группы id может содержать только ASCII-цифры. В шаблонах bytes имя группы name может содержать только байты в ASCII-диапазоне (b'\x00'-b'\x7f').

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

\number

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

\A

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

\b

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

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

Примечание

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

\B

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

\d
Для шаблонов Unicode (строки):

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

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

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

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

\D

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

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

\s
Для шаблонов Unicode (строки):

Соответствует символам 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-битных (bytes):

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

\W

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

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

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

\Z

Соответствует только концу строки.

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

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

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

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

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

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

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

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

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

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

Флаги

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

class re.RegexFlag

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

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

re.A
re.ASCII

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

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

Примечание

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

re.DEBUG

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

Нет соответствующего встроенного флага.

re.I
re.IGNORECASE

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

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

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

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

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

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

re.M
re.MULTILINE

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

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

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 3 Unicode-символы соответствуют по умолчанию для шаблонов 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)

Компилирует шаблон регулярного выражения в объект регулярного выражения объект регулярного выражения, который может использоваться для сопоставления с помощью его методов 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 , если ни одна позиция в строке не соответствует шаблону; обратите внимание, что это отличается от поиска соответствия нулевой длины в какой-либо точке строки.

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

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

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

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

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

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

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

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

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

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

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

Изменено в версии 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')]

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

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

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

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

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

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

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

Возвращает строку, полученную путём замены всех неперекрывающихся вхождения шаблона pattern в строке string заменой repl. Если шаблон не найден, возвращается исходная строка string без изменений. 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 является функцией, она вызывается для каждого неперекрывающегося вхождения pattern. Функция принимает один аргумент 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> заменяется на всю подстроку, соответствующую регулярному выражению.

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

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

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

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

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

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

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

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

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

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

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

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

re.escape(pattern)

Экранирует специальные символы в 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

Индекс в pattern, где произошла ошибка компиляции (может быть 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]])

Ищет в строке string первое вхождение регулярного выражения и возвращает соответствующий объект 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]])

Если нуль или более символов в начале строки string соответствуют этому регулярному выражению, возвращает соответствующий объект 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'>

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

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

Если вся строка string соответствует этому регулярному выражению, возвращает соответствующий объект 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, если шаблон является строкой 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>) заменяются содержимым соответствующей группы. Обратная ссылка \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'

Добавлена в версии 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. Это индекс в строке, с которого движок RE начал поиск совпадения.

Match.endpos

Значение endpos, которое было передано методу search() или match() объекта объекта regex. Это индекс в строке, дальше которого движок 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(). Объекты совпадения считаются атомарными.

END_OF_DOCUMENT_MARKER

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

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

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

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

>>> 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–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.12/library/re.html

Spec-Zone.ru

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