Spec-Zone.ru › Python 3.11

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

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

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

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

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

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

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

См. также

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

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

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

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

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

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

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

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

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

.

(Точка.) В режиме по умолчанию соответствует любому символу, кроме перевода строки. Если указан флаг DOTALL, соответствует любому символу, включая перевод строки.

^

(Карет.) Соответствует началу строки, а в режиме MULTILINE также соответствует позиции сразу после каждого перевода строки.

$

Соответствует концу строки или позиции непосредственно перед переводом строки в конце строки, а в режиме MULTILINE также соответствует позиции перед переводом строки. foo соответствует и ‘foo’, и ‘foobar’, тогда как регулярное выражение foo$ соответствует только ‘foo’. Более интересный пример: поиск foo.$ в 'foo1\nfoo2\n' обычно находит ‘foo2’, но в режиме MULTILINE находит ‘foo1’; поиск одного $ в 'foo\n' обнаружит два (пустых) совпадения: одно непосредственно перед переводом строки, а другое в конце строки.

*

Заставляет результирующее регулярное выражение соответствовать 0 или более повторениям предшествующего регулярного выражения — максимально возможному их количеству. ab* будет соответствовать ‘a’, ‘ab’ или ‘a’, за которым следует любое количество символов ‘b’.

+

Заставляет результирующее регулярное выражение соответствовать 1 или более повторениям предшествующего регулярного выражения. ab+ будет соответствовать ‘a’, за которым следует ненулевое количество символов ‘b’; одной букве ‘a’ оно не соответствует.

?

Заставляет результирующее регулярное выражение соответствовать 0 или 1 повторению предшествующего регулярного выражения. ab? будет соответствовать либо ‘a’, либо ‘ab’.

*?, +?, ??

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

*+, ++, ?+

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

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

{m}

Указывает, что должно быть сопоставлено ровно m копий предыдущего регулярного выражения; если совпадений меньше, всё регулярное выражение не будет соответствовать строке. Например, a{6} соответствует ровно шести символам 'a', но не пяти.

{m,n}

Заставляет результирующее регулярное выражение соответствовать от m до n повторений предшествующего регулярного выражения, пытаясь сопоставить как можно больше повторений. Например, a{3,5} соответствует от 3 до 5 символам 'a'. Если m не указано, нижняя граница равна нулю; если n не указано, верхняя граница бесконечна. Например, a{4,}b соответствует 'aaaab' или тысяче символов 'a', за которыми следует 'b', но не 'aaab'. Запятую нельзя опускать, иначе модификатор можно будет спутать с описанной выше формой.

{m,n}?

Заставляет результирующее регулярное выражение соответствовать от m до n повторений предшествующего регулярного выражения, пытаясь сопоставить как можно меньше повторений. Это нежадная версия предыдущего квантификатора. Например, для строки 'aaaaaa' длиной 6 символов a{3,5} соответствует 5 символам 'a', тогда как a{3,5}? соответствует только 3 символам.

{m,n}+

Заставляет результирующее регулярное выражение соответствовать от m до n повторений предшествующего регулярного выражения, пытаясь сопоставить как можно больше повторений, не устанавливая точек возврата. Это версия приведённого выше квантификатора, обладающая жадностью без возврата. Например, для строки 'aaaaaa' длиной 6 символов 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 (определённые ниже), хотя соответствующие им символы зависят от используемых флагов.
  • Символы, не входящие в диапазон, можно сопоставить, если инвертировать набор. Если первый символ набора — '^', будут сопоставляться все символы, которые не входят в набор. Например, [^5] соответствует любому символу, кроме '5', а [^^] соответствует любому символу, кроме '^'. ^ не имеет особого значения, если находится не в начале набора.
  • Чтобы сопоставить буквальный ']' внутри набора, поставьте перед ним обратную косую черту или поместите его в начало набора. Например, и [()[\]{}], и []()[{}] соответствуют закрывающей квадратной скобке, а также открывающей квадратной скобке, фигурным и круглым скобкам.
  • В будущем может быть добавлена поддержка вложенных наборов и операций над наборами, как в Техническом стандарте Unicode № 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 (подробный режим)

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

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

(?:...)

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

(?aiLmsux-imsx:...)

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

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

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

Буквы 'a', 'L' и 'u' взаимоисключающие, если используются как встроенные флаги, поэтому их нельзя объединять или ставить после '-'. Вместо этого, если одна из них появляется во встроенной группе, она переопределяет режим сопоставления во внешней группе. В шаблонах Unicode (?a:...) переключает сопоставление в режим только ASCII, а (?u:...) — в режим Unicode (по умолчанию). В шаблонах bytes (?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, результирующее регулярное выражение будет соответствовать этому второму символу. Например, \$ соответствует символу '$'.

\number

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

\A

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

\b

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

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

Примечание

Внутри диапазона символов \b обозначает символ возврата на одну позицию (backspace) для совместимости со строковыми литералами Python.

\B

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

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

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

При использовании флага ASCII соответствует [0-9].

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

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

\D

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

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

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

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

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

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

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

\S

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

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

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

Соответствует символам слова Unicode; сюда входят все буквенно-цифровые символы Unicode (как определено в 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

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

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

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

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

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

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

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

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

Изменено в версии 3.8: Добавлена escape-последовательность '\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 (str) и игнорируется для шаблонов bytes.

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

Примечание

Флаг U по-прежнему существует для обратной совместимости, но в Python 3 он избыточен: соответствия для шаблонов str по умолчанию выполняются с учётом Unicode, а для шаблонов bytes поиск с учётом Unicode не допускается. Флаг 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 (str) поиск с учётом Unicode включён по умолчанию и позволяет работать с разными локалями и языками.

Изменено в версии 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 для шаблонов str по умолчанию выполняется поиск с учётом символов Unicode. Поэтому этот флаг избыточен и не оказывает никакого эффекта; он сохранён только для обратной совместимости.

См. 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)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Если repl — функция, она вызывается для каждого неперекрывающегося вхождения pattern. Функция принимает единственный аргумент 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, помимо описанных выше символьных escape-последовательностей и обратных ссылок, \g<name> использует подстроку, соответствующую группе с именем name, заданным с помощью синтаксиса (?P<name>...). \g<number> использует соответствующий номер группы; поэтому \g<2> эквивалентно \2, но не создаёт неоднозначности при замене, например, \g<2>0. \20 будет интерпретировано как ссылка на группу 20, а не как ссылка на группу 2, за которой следует буквальный символ '0'. Обратная ссылка \g<0> подставляет всю подстроку, соответствующую регулярному выражению.

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

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

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

Изменено в версии 3.7: Неизвестные escape-последовательности в 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)

Экранирует специальные символы в 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) или bytes. См. Тип универсального псевдонима.

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) или bytes. См. Тип универсального псевдонима.

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 возвращает кортеж из двух элементов (m.start(group), m.end(group)). Обратите внимание, что если group не участвовала в совпадении, возвращается (-1, -1). По умолчанию group равен нулю — всему совпадению.

Match.pos

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

Match.endpos

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

Match.lastindex

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

Match.lastgroup

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

Match.re

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

Match.string

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

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

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

Поиск пары

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

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

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

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

>>> valid = re.compile(r"^[a2-9tjqk]{5}$")
>>> displaymatch(valid.match("akt5q"))  # 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.11/library/re.html

Spec-Zone.ru

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