Spec-Zone.ru › Python 3.14

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

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

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

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

В регулярных выражениях символ обратной косой черты ('\') используется для обозначения специальных конструкций или для возможности использовать специальные символы, не вызывая их специального значения. Это конфликтует с использованием Python того же символа для той же цели в строковых литералах; например, чтобы сопоставить буквальную обратную косую черту, строку шаблона, возможно, придётся записать как '\\\\', поскольку регулярное выражение должно быть \\, а каждая обратная косая черта внутри обычного строкового литерала Python должна быть представлена как \\. Кроме того, обратите внимание, что любые недопустимые escape-последовательности при использовании обратной косой черты в строковых литералах Python теперь вызывают SyntaxWarning, а в будущем будут вызывать 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, соответствует любому символу, включая символ новой строки. (?s:.) соответствует любому символу независимо от флагов.

^

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

$

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

*

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

+

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

?

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

*?, +?, ??

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

*+, ++, ?+

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

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

{m}

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

{m,n}

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

{m,n}?

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

{m,n}+

Заставляет полученное RE соответствовать от m до n повторений предшествующего RE, пытаясь сопоставить максимально возможное количество повторений, не создавая точек возврата. Это вариант приведённого выше квантификатора со свойством обладания. Например, в строке '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.

\

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

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

[]

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

  • Символы можно перечислять по отдельности; например, [amk] соответствует 'a', 'm' или 'k'.
  • Диапазоны символов можно задавать, указывая два символа через '-'. Например, [a-z] соответствует любой строчной латинской букве ASCII, [0-5][0-9] — любому двузначному числу от 00 до 59, а [0-9A-Fa-f] — любой шестнадцатеричной цифре. Если - экранирован (например, [a\-z]) или стоит первым либо последним символом (например, [-a] или [a-]), он соответствует буквальному символу '-'.
  • Специальные символы, кроме обратной косой черты, теряют своё специальное значение внутри наборов. Например, [(+*)] соответствует любому из буквальных символов '(', '+', '*' или ')'.
  • Обратная косая черта либо экранирует символы, имеющие специальное значение в наборе, например '-', ']', '^' и саму '\\', либо обозначает специальную последовательность, представляющую один символ, например \xa0 или \n, либо класс символов, например \w или \S (определённые ниже). Обратите внимание: \b обозначает один символ «возврата на шаг назад», а не границу слова, как за пределами набора; числовые escape-последовательности, такие как \1, всегда являются восьмеричными escape-последовательностями, а не ссылками на группы. Специальные последовательности, не соответствующие одному символу, например \A и \z, недопустимы.
  • Символы, не входящие в диапазон, можно сопоставить, выполнив дополнение набора. Если первым символом набора является '^', будут сопоставлены все символы, не входящие в набор. Например, [^5] соответствует любому символу, кроме '5', а [^^] соответствует любому символу, кроме '^'. Символ ^ не имеет специального значения, если он не является первым символом набора.
  • Чтобы сопоставить буквальный символ ']' внутри набора, поставьте перед ним обратную косую черту или поместите его в начало набора. Например, и [()[\]{}], и []()[{}] соответствуют закрывающей квадратной скобке, а также открывающей квадратной скобке, фигурным и круглым скобкам.
  • В будущем может быть добавлена поддержка вложенных наборов и операций над наборами, как в Техническом стандарте Unicode № 18. Это изменит синтаксис, поэтому для упрощения такого перехода в неоднозначных случаях пока будет выдаваться FutureWarning. К таким случаям относятся наборы, начинающиеся с буквального символа '[' или содержащие буквальные последовательности символов '--', '&&', '~~' и '||'. Чтобы избежать предупреждения, экранируйте их обратной косой чертой.

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

|

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

(...)

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

(?...)

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

(?aiLmsux)

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

  • re.A (сопоставление только ASCII)
  • re.I (без учёта регистра)
  • re.L (зависит от локали)
  • re.M (многострочный режим)
  • re.S (точка соответствует любому символу)
  • re.U (сопоставление 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 (по умолчанию). В байтовых шаблонах (?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>' (в первом случае re.search() находит только 'user@host.com').

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

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

\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 обозначает символ возврата на шаг назад для совместимости со строковыми литералами Python.

\B

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

Изменено в версии 3.14: \B теперь соответствует пустой входной строке.

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

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

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

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

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

\D

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

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

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

Соответствует пробельным символам Unicode (как определено в str.isspace()). Сюда входят [ \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

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

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

\Z

То же, что и \z. Для совместимости со старыми версиями Python.

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

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

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

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

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

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

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

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

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

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

Флаги

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

class re.RegexFlag

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

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

re.A
re.ASCII

Заставляет \w, \W, \b, \B, \d, \D, \s и \S выполнять поиск только по ASCII, а не по всему набору символов Unicode. Это имеет смысл только для шаблонов Unicode (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 (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, если в строке нет позиции, соответствующей шаблону; обратите внимание, что это не то же самое, что найти в строке совпадение нулевой длины.

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

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

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

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

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

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

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

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

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

Добавлено в версии 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.', maxsplit=1)
['Words', 'words, words.']
>>> re.split('[a-f]+', '0a3B9', flags=re.IGNORECASE)
['0', '3', '9']

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Поведение выражения можно изменить, указав значение 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-' вместо '-a-b-d-'.

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

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

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

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

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

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

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

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

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

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

Поведение выражения можно изменить, указав значение 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.PatternError(msg, pattern=None, pos=None)

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

msg

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

pattern

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

pos

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

lineno

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

colno

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

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

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

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

class re.Pattern

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

Шаблоны являются обобщёнными относительно типа обрабатываемой строки (str или bytes).

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

Совпадения являются обобщёнными относительно типа сопоставленной строки (str или bytes).

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

Возвращает кортеж, содержащий все подгруппы совпадения — от первой до последней группы в шаблоне. Аргумент 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, maxsplit=3) for entry in entries]
[['Ross', 'McFluff', '834.345.1254', '155 Elm Street'],
['Ronald', 'Heathmore', '892.345.3428', '436 Finley Avenue'],
['Frank', 'Burger', '925.541.7625', '662 South Dogwood Way'],
['Heather', 'Albrecht', '548.326.4584', '919 Park Place']]

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

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

Преобразование текста

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

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

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

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

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

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

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

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

Запись необработанных строк

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

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

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

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

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

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

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

from typing import NamedTuple
import re

class Token(NamedTuple):
    type: str
    value: int | float | 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]

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

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

Spec-Zone.ru

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