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

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


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

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

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

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

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

См.также

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

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

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

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

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

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

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

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

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

.

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

^

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

$

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

*

Приводит к тому, что результирующий RE соответствует 0 или более повторениям предыдущего RE, столько повторений, сколько возможно. ab* будет соответствовать буквам «a», «ab» или «a», за которыми следует любое количество букв «b».

+

Приводит к тому, что результирующий RE соответствует 1 или более повторениям предыдущего RE. ab+ будет соответствовать «a», за которым следует любое ненулевое число «b»; оно не будет соответствовать только «a».

?

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

*?, +?, ??

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

*+, ++, ?+

Как и кванторы '*', '+', и '?', те, к которым добавляется '+', также совпадают как можно больше раз. Однако, в отличие от истинно жадных кванторов, они не позволяют выполнить обратный поиск, если следующее за ними выражение не соответствует. Они известны как possessive кванторы. Например, a*a будет соответствовать 'aaaa', потому что a* будет соответствовать всем 4 'a's, но когда встречается последний '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, пытаясь сопоставить как можно меньшее количество повторений. Это не жадная версия предыдущего квантификатора. Например, в 6-символьной строке 'aaaaaa', a{3,5} будет соответствовать 5 'a' символам, в то время как a{3,5}? будет соответствовать только 3 символам.

{m,n}+

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

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

\

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

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

[]

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

  • Символы могут быть указаны отдельно, например, [amk] будет соответствовать 'a', 'm', или 'k'.

  • Диапазоны символов можно указать, введя два символа и разделив их символом '-', например, [a-z] будет соответствовать любой строчному алфавиту ASCII, [0-5][0-9] будет соответствовать всем двузначным числам из 00 к 59, а [0-9A-Fa-f] будет соответствовать любой шестнадцатеричной цифре. Если - экранирован (например, [a\-z]) или если он помещен в качестве первого или последнего символа (например, [-a] или [a-]), он будет соответствовать литералу '-'.

  • Специальные символы теряют свое особое значение внутри наборов. Например, [(+*)] будет соответствовать любому из буквенных символов '(', '+', '*', или ')'.

  • Классы символов, такие как \w или \S (определение приведено ниже), также принимаются внутри набора, хотя символы, которым они соответствуют, зависят от используемых флагов.

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

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

  • В будущем может быть добавлена поддержка вложенных наборов и операций с заданиями, как в Unicode Technical Standard #18. Это изменит синтаксис, поэтому для облегчения этого изменения в неоднозначных случаях на данный момент будет использоваться FutureWarning. Это включает в себя наборы, начинающиеся с литерала '[' или содержащие литеральные последовательности символов '--', '&&', '~~', и '||'. Чтобы избежать появления предупреждения, закройте их обратной косой чертой.

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

|

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

(...)

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

(?...)

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

(?aiLmsux)

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

  • re.A (соответствие только ASCII)

  • re.I (регистр игнорируется)

  • re.L (зависит от языкового стандарта)

  • re.M (многострочный)

  • re.S (точка совпадает со всеми)

  • re.U (соответствие Юникоду)

  • 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 (соответствие Юникоду)

  • re.X (подробный)

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

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

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

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

(?>...)

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

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

(?P<name>...)

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

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

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

Способы ссылки на него

в том же самом шаблоне

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

  • \1

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

  • m.group('quote')

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

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

  • \g<quote>

  • \g<1>

  • \1

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

(?P=name)

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

(?#...)

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

(?=...)

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

(?!...)

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

(?<=...)

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

>>> import re
>>> m = re.search('(?<=abc)def', 'abcdef')
>>> m.group(0)
'def'

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

>>> m = re.search(r'(?<=-)\w+', 'spam-egg')
>>> m.group(0)
'egg'

Изменено в версии 3.5: Добавлена поддержка групповых ссылок фиксированной длины.

(?<!...)

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

(?(id/name)yes-pattern|no-pattern)

Будет предпринята попытка сопоставления с yes-pattern, если группа с заданным идентификатором или именем существует, и с no-pattern, если ее нет. no-pattern является необязательным и может быть опущен. Например, (<)?(\w+@\w+(?:\.\w+)+)(?(1)>|$) - это плохой шаблон для сопоставления электронной почты, который будет совпадать с '<user@host.com>', а также с 'user@host.com', но не с '<user@host.com' и не с 'user@host.com>'.

Не рекомендуется, начиная с версии 3.11: Идентификатор группы*, содержащий все, что угодно, кроме цифр ASCII. Название группы*, содержащее символы, не входящие в диапазон ASCII (b'\x00'-b'\x7f') в заменяющих строках bytes.

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

\number

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

\A

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

\b

Совпадает с пустой строкой, но только в начале или конце слова. Слово определяется как последовательность символов word. Обратите внимание, что формально \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, поэтому символы word в шаблонах Unicode (str) являются буквенно-цифровыми символами Unicode или символом подчеркивания, хотя это можно изменить, используя флаг ASCII. Границы слов определяются текущим языковым стандартом, если используется флаг LOCALE.

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

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

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

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

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

\D

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

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

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

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

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

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

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

\S

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

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

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

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

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

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

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

\W

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

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

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

\Z

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

Большинство стандартных экранирующих функций, поддерживаемых строковыми литералами 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}'. Как и в строковых литералах, она расширяется до именованного символа Юникода (например, '\N{EM DASH}').

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

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

Флаги

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

class re.RegexFlag

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

Добавлено в версии 3.11: - added to __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 и встроенный флаг (?u) также являются избыточными.

re.DEBUG

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

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

re.I
re.IGNORECASE

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

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

Обратите внимание, что когда шаблоны Юникода [a-z] или [A-Z] используются в сочетании с флагом IGNORECASE, они будут соответствовать 52 буквам ASCII и 4 дополнительным буквам, отличным от ASCII: „I“ (U+0130, латиница заглавная буква I с точкой над ней), «и» (U+0131, латинская строчная буква i без точки), «ſ» (U+017F, латинская строчная буква s) и «К» (U+212A, знак Кельвина). Если используется флаг ASCII, совпадают только буквы от «a» до «z» и от «A» до «Z».

re.L
re.LOCALE

Установите соответствие \w, \W, \b, \B и без учета регистра в зависимости от текущего языкового стандарта. Этот флаг можно использовать только с шаблонами байтов.

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

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

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

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

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

re.M
re.MULTILINE

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

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

re.NOFLAG

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

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

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

re.S
re.DOTALL

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

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

re.U
re.UNICODE

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

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

re.X
re.VERBOSE

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

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

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

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

Функции

re.compile(pattern, flags=0)

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

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

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

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

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

result = re.match(pattern, string)

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

Примечание

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Если repl - это функция, то она вызывается при каждом непересекающемся появлении pattern. Функция принимает единственный аргумент Match и возвращает строку замены. Например:

>>> def dashrepl(matchobj):
...     if matchobj.group(0) == '-': return ' '
...     else: return '-'
>>> re.sub('-{1,2}', dashrepl, 'pro----gram-files')
'pro--gram files'
>>> re.sub(r'\sAND\s', ' & ', 'Baked Beans And Spam', flags=re.IGNORECASE)
'Baked Beans & Spam'

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

Необязательный аргумент count - это максимальное количество вхождений шаблона, которое необходимо заменить; count должно быть неотрицательным целым числом. Если оно опущено или равно нулю, все вхождения будут заменены. Пустые совпадения для шаблона заменяются только в том случае, если они не совпадают с предыдущим пустым совпадением, поэтому sub('x*', '-', 'abxd') возвращает '-a-b--d-'.

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

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

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

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

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

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

Не рекомендуется, начиная с версии 3.11: Идентификатор группы*, содержащий все, что угодно, кроме цифр ASCII. Название группы*, содержащее символы, не входящие в диапазон 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)

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

msg

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

pattern

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

pos

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

lineno

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

colno

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

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

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

class re.Pattern

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

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

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

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

Необязательный второй параметр pos задает индекс в строке, с которой должен начинаться поиск; по умолчанию он равен 0. Это не совсем эквивалентно разделению строки на части; символ шаблона '^' совпадает в реальном начале строки и в позициях сразу после новой строки, но не обязательно в индексе, с которого должен начинаться поиск.

Необязательный параметр endpos ограничивает диапазон поиска строки; это будет выглядеть так, как если бы строка была длиной в endpos символов, поэтому поиск совпадения будет производиться только по символам от pos до endpos - 1. Если значение endpos меньше значения pos, совпадение найдено не будет; в противном случае, если rx является скомпилированным объектом регулярного выражения, rx.search(string, 0, 50) эквивалентно rx.search(string[:50], 0).

>>> pattern = re.compile("d")
>>> pattern.search("dog")     # Match at index 0
<re.Match object; span=(0, 1), match='d'>
>>> pattern.search("dog", 1)  # No match; search doesn't include the "d"
Pattern.match(string[, pos[, endpos]])

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

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

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

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

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

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

Pattern.split(string, maxsplit=0)

Идентична функции split(), использующей скомпилированный шаблон.

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

Аналогично функции findall(), использующей скомпилированный шаблон, но также принимающей необязательные параметры pos и endpos, которые ограничивают область поиска, как для search().

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

Аналогично функции finditer(), использующей скомпилированный шаблон, но также принимающей необязательные параметры pos и endpos, которые ограничивают область поиска, как для search().

Pattern.sub(repl, string, count=0)

Идентична функции sub(), использующей скомпилированный шаблон.

Pattern.subn(repl, string, count=0)

Идентична функции subn(), использующей скомпилированный шаблон.

Pattern.flags

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

Pattern.groups

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

Pattern.groupindex

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

Pattern.pattern

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

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

Сопоставлять объекты

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

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

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

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

Match.expand(template)

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

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

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

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

>>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")
>>> m.group(0)       # The entire match
'Isaac Newton'
>>> m.group(1)       # The first parenthesized subgroup.
'Isaac'
>>> m.group(2)       # The second parenthesized subgroup.
'Newton'
>>> m.group(1, 2)    # Multiple arguments give us a tuple.
('Isaac', 'Newton')

Если в регулярном выражении используется синтаксис (?P<name>...), аргументами groupN также могут быть строки, идентифицирующие группы по их названию. Если строковый аргумент не используется в шаблоне в качестве имени группы, возникает исключение IndexError.

Умеренно сложный пример:

>>> m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds")
>>> m.group('first_name')
'Malcolm'
>>> m.group('last_name')
'Reynolds'

На именованные группы также можно ссылаться по их индексу:

>>> m.group(1)
'Malcolm'
>>> m.group(2)
'Reynolds'

Если группа совпадает несколько раз, доступно только последнее совпадение:

>>> m = re.match(r"(..)+", "a1b2c3")  # Matches 3 times.
>>> m.group(1)                        # Returns only the last match.
'c3'
Match.__getitem__(g)

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

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

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

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

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

Match.groups(default=None)

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

Например:

>>> m = re.match(r"(\d+)\.(\d+)", "24.1632")
>>> m.groups()
('24', '1632')

Если мы сделаем десятичный знак и все, что после него, необязательными, не все группы смогут участвовать в сопоставлении. По умолчанию для этих групп будет установлено значение None, если не указан аргумент default:

>>> m = re.match(r"(\d+)\.?(\d+)?", "24")
>>> m.groups()      # Second group defaults to None.
('24', None)
>>> m.groups('0')   # Now, the second group defaults to '0'.
('24', '0')
Match.groupdict(default=None)

Возвращает словарь, содержащий все именованные подгруппы в соответствии с именем подгруппы. Аргумент default используется для групп, которые не участвовали в сопоставлении; по умолчанию он равен None. Например:

>>> m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds")
>>> m.groupdict()
{'first_name': 'Malcolm', 'last_name': 'Reynolds'}
Match.start([group])
Match.end([group])

Возвращает индексы начала и конца подстроки, совпадающей с group; значение group по умолчанию равно нулю (что означает всю совпадающую подстроку). Возвращает -1, если group существует, но не участвовала в совпадении. Для совпадающего объекта m и группы g, которые внесли свой вклад в совпадение, подстрока, соответствующая группе g (эквивалентная m.group(g)), равна

m.string[m.start(g):m.end(g)]

Обратите внимание, что m.start(group) будет равно m.end(group), если group соответствует пустой строке. Например, после того, как m = re.search('b(c?)', 'cba'), m.start(0) равно 1, m.end(0) равно 2, m.start(1) и m.end(1) равны 2, а m.start(2) вызывает исключение IndexError.

Пример, который удалит remove_this с адресов электронной почты:

>>> email = "tony@tiremove_thisger.net"
>>> m = re.search("remove_this", email)
>>> email[:m.start()] + email[m.end():]
'tony@tiger.net'
Match.span([group])

Для совпадения m верните кортеж из 2 элементов (m.start(group), m.end(group)). Обратите внимание, что если group не участвовала в совпадении, то это (-1, -1). Значение group по умолчанию равно нулю, то есть соответствует всему совпадению.

Match.pos

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

Match.endpos

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

Match.lastindex

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

Match.lastgroup

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

Match.re

regular expression object, чей метод match() или search() создал этот соответствующий экземпляр.

Match.string

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

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

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

Проверка наличия пары

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

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

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

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

>>> valid = re.compile(r"^[a2-9tjqk]{5}$")
>>> displaymatch(valid.match("akt5q"))  # Valid.
"<Match: 'akt5q', groups=()>"
>>> displaymatch(valid.match("akt5e"))  # Invalid.
>>> displaymatch(valid.match("akt"))    # Invalid.
>>> displaymatch(valid.match("727ak"))  # Valid.
"<Match: '727ak', groups=()>"

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

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

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

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

# Error because re.match() returns None, which doesn't have a group() method:
>>> pair.match("718ak").group(1)
Traceback (most recent call last):
  File "<pyshell#23>", line 1, in <module>
    re.match(r".*(.).*\1", "718ak").group(1)
AttributeError: 'NoneType' object has no attribute 'group'

>>> pair.match("354aa").group(1)
'a'

Имитация scanf()

В настоящее время в Python нет эквивалента scanf(). Регулярные выражения, как правило, более мощные, хотя и более подробные, чем строки формата scanf(). В таблице ниже приведены некоторые более или менее эквивалентные сопоставления между токенами формата c:func:!scanf и регулярными выражениями.

:токен c:func:!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

вы бы использовали формат a scanf(), например

%s - %d errors, %d warnings

Эквивалентным регулярным выражением было бы следующее

(\S+) - (\d+) errors, (\d+) warnings

поиск() и сопоставление()

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

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

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

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

Например:

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

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

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

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

>>> re.match("X", "A\nB\nX", re.MULTILINE)  # No match
>>> re.search("^X", "A\nB\nX", re.MULTILINE)  # Match
<re.Match object; span=(4, 5), match='X'>

Создание телефонной книги

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

Во-первых, вот входные данные. Обычно они могут быть получены из файла, здесь мы используем синтаксис строки в тройных кавычках

>>> text = """Ross McFluff: 834.345.1254 155 Elm Street
...
... Ronald Heathmore: 892.345.3428 436 Finley Avenue
... Frank Burger: 925.541.7625 662 South Dogwood Way
...
...
... Heather Albrecht: 548.326.4584 919 Park Place"""

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

>>> entries = re.split("\n+", text)
>>> entries
['Ross McFluff: 834.345.1254 155 Elm Street',
'Ronald Heathmore: 892.345.3428 436 Finley Avenue',
'Frank Burger: 925.541.7625 662 South Dogwood Way',
'Heather Albrecht: 548.326.4584 919 Park Place']

Наконец, разделите каждую запись на список с именем, фамилией, номером телефона и адресом. Мы используем параметр maxsplit из split(), потому что в адресе есть пробелы, что соответствует нашему шаблону разделения:

>>> [re.split(":? ", entry, 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() с функцией «munge» текста или рандомизации порядка расположения всех символов в каждом слове предложения, за исключением первого и последнего символов:

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

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

A tokenizer or scanner анализирует строку для классификации групп символов. Это полезный первый шаг при написании компилятора или интерпретатора.

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

from typing import NamedTuple
import re

class Token(NamedTuple):
    type: str
    value: str
    line: int
    column: int

def tokenize(code):
    keywords = {'IF', 'THEN', 'ENDIF', 'FOR', 'NEXT', 'GOSUB', 'RETURN'}
    token_specification = [
        ('NUMBER',   r'\d+(\.\d*)?'),  # Integer or decimal number
        ('ASSIGN',   r':='),           # Assignment operator
        ('END',      r';'),            # Statement terminator
        ('ID',       r'[A-Za-z]+'),    # Identifiers
        ('OP',       r'[+\-*/]'),      # Arithmetic operators
        ('NEWLINE',  r'\n'),           # Line endings
        ('SKIP',     r'[ \t]+'),       # Skip over spaces and tabs
        ('MISMATCH', r'.'),            # Any other character
    ]
    tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification)
    line_num = 1
    line_start = 0
    for mo in re.finditer(tok_regex, code):
        kind = mo.lastgroup
        value = mo.group()
        column = mo.start() - line_start
        if kind == 'NUMBER':
            value = float(value) if '.' in value else int(value)
        elif kind == 'ID' and value in keywords:
            kind = value
        elif kind == 'NEWLINE':
            line_start = mo.end()
            line_num += 1
            continue
        elif kind == 'SKIP':
            continue
        elif kind == 'MISMATCH':
            raise RuntimeError(f'{value!r} unexpected on line {line_num}')
        yield Token(kind, value, line_num, column)

statements = '''
    IF quantity THEN
        total := total + price * quantity;
        tax := price * 0.05;
    ENDIF;
'''

for token in tokenize(statements):
    print(token)

Токенизатор выдает следующий результат:

Token(type='IF', value='IF', line=2, column=4)
Token(type='ID', value='quantity', line=2, column=7)
Token(type='THEN', value='THEN', line=2, column=16)
Token(type='ID', value='total', line=3, column=8)
Token(type='ASSIGN', value=':=', line=3, column=14)
Token(type='ID', value='total', line=3, column=17)
Token(type='OP', value='+', line=3, column=23)
Token(type='ID', value='price', line=3, column=25)
Token(type='OP', value='*', line=3, column=31)
Token(type='ID', value='quantity', line=3, column=33)
Token(type='END', value=';', line=3, column=41)
Token(type='ID', value='tax', line=4, column=8)
Token(type='ASSIGN', value=':=', line=4, column=12)
Token(type='ID', value='price', line=4, column=15)
Token(type='OP', value='*', line=4, column=21)
Token(type='NUMBER', value=0.05, line=4, column=23)
Token(type='END', value=';', line=4, column=27)
Token(type='ENDIF', value='ENDIF', line=5, column=4)
Token(type='END', value=';', line=5, column=9)
[Frie09]

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

Вернуться на верх