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

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


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

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

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

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

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

См.также

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

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

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

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

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

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

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

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

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

.
(Точка.) в режиме по умолчанию это соответствует любому символу, кроме новой строки. Если флаг DOTALL был указан, он соответствует любому символу, включая новую строку.
^
(Каретка) Соответствует началу строки, а в режиме MULTILINE также совпадает сразу после каждой новой строки.
$
Соответствует концу строки или непосредственно перед новой строкой в конце строка, а в режиме MULTILINE также совпадает перед новой строкой. foo соответствует и „foo“ и „foobar“, в то время как регулярное выражение foo$ соответствует только „foo“. Более интересно, что поиск foo.$ в 'foo1\nfoo2\n' соответствует „foo2“ обычно, но „foo1“ в режиме MULTILINE; поиск одного $ в 'foo\n' найдёт два (пустых) совпадения: одно непосредственно перед новой строке, и одно в конце строка.
*
Приводит к тому, что результирующее RE соответствует 0 или более повторениям предыдущего RE, как можно больше повторений. ab* соответствует «a», «ab» или «a», за которым следует любое число «b».
+
Приводит к совпадению результирующего RE с 1 или более повторениями предыдущего RE. ab+ совпадет с «a», за которым следует любое ненулевое число «b»; он не будет соответствовать только „a“.
?
Результирующее RE соответствует 0 или 1 повторениям предыдущего RE. ab? будет совпадать с „a“ или „ab“.
*?, +?, ??
Квалификаторы '*', '+' и '?' - все жадные; они соответствуют как можно большему количеству текста. Иногда такое поведение не желательно; если RE, <.*> соответствует '<a> b <c>', он будет соответствовать всей строке и не просто '<a>'. Добавление ? после квалификатора заставляет его выполнять соотвествие нежаднымy или минимальному способу; будут сопоставлены как можно более несколько символов. Используя RE <.*?> будет соответствовать только '<a>'.
{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, пытаясь сопоставить как можно более few повторений. Это нежадная версия предыдущего квалификатора. Например, на 6-символ строка 'aaaaaa' a{3,5} будет совпадать с 5 'a' символами, в то время как a{3,5}? будет совпадать только с 3 символами.
\

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

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

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

|
A|B, где A и B могут быть произвольными RE, создает регулярное выражение, которое будет совпадать либо A, либо B. Таким образом, произвольное количество RE может быть разделено '|'. Это может быть используемый внутренние группы (см. ниже), также. Поскольку целевой строка просмотрен, REs, отделенные '|', пробуют слева направо. Когда один шаблон полностью совпадает, эта ветвь принимается. Это означает, что как только 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(). Флаги должны быть используемый сначала в выражении строка.
(?:...)
Не захватывающая версия регулярных скобок. Совпадает с обычным выражение находится внутри скобок, но подстрока соответствует группе невозможно получить после выполнения сопоставления или ссылаться позже в шаблоне.
(?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:...) переключается на соответствие в юникоде (по умолчанию). В шаблоне байтов (?L:...) переключается на локаль в зависимости от соответствия, а (?a:...) переключается на соответствие только ASCII (по умолчанию). Это переопределение действует только для узкой встроенной группы, и исходный режим сопоставления восстанавливается вне группы.

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

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

(?P<name>...)

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

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

Контекст ссылки на группу «quote» Способы ссылаться на него
по той же самом шаблоне
  • (?P=quote) (как показано)
  • \1
при обработке совпадения объекта m
  • m.group('quote')
  • m.end('quote') (и т.д.)
в строке, переданной в repl аргумент re.sub()
  • \g<quote>
  • \g<1>
  • \1
(?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>'.

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

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

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

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

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

\d
для Юникод (str) шаблоны:
Соответствует любая десятичная цифра Юникод (то есть, любой символ в категории Юникод символ [Без обозначения даты]). Сюда входят [0-9], а также множество других цифр. Если флаг ASCII - используемый, только [0-9] подобран.
Для 8-разрядных (байт) шаблонов:
соответствует любой десятичной цифре; это эквивалентно [0-9].
\D
соответствует любой символ, которая не является десятичной цифрой. Это противоположность \d. Если флаг ASCII равен используемый, это становится эквивалентом [^0-9].
\s
Для шаблонов Юникода (str):
соответствует символам пробела Юникода (который включает в себя символы [ \t\n\r\f\v], а также многие другие символы, например неразрывные пробелы, предписанные правилами типографики на многих языках). Если флаг ASCII равен используемый, сопоставляется только [ \t\n\r\f\v].
Для 8 битов (байт) шаблоны:
Символы соответствия рассмотрели пробел в множестве ASCII символ; это эквивалентно [ \t\n\r\f\v].
\S
Соответствует любому символ, который не является пробелом символ. Это противоположность \s. Если флаг ASCII равен используемый, это становится эквивалентом [^ \t\n\r\f\v].
\w
Для шаблонов Юникода (str):
Соответствует символам слова Юникода; это включает большинство символов, которые могут быть частью слова на любом языке, а также цифры и знак подчеркивания. Если флаг ASCII равен используемый, сопоставляется только [a-zA-Z0-9_].
Для 8 битных (байт) шаблонов:
Соответствие символам считали алфавитно-цифровым в множестве ASCII символ; это эквивалентно [a-zA-Z0-9_]. Если флаг LOCALE равен используемый, совпадает с буквенно-цифровыми символами в текущей локали и подчеркиванием.
\W
Соответствует любому символу, который не является словом символ. Это противоположность \w. Если флаг ASCII равен используемый, это становится эквивалентом [^a-zA-Z0-9_]. Если флаг LOCALE равен используемый, соответствует символам, которые не являются ни буквенно- цифровыми в текущей локали, ни подчеркиванием.
\Z
Соответствует только концу строки.

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

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

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

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

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

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

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

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

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

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

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

re.compile(pattern, flags=0)

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

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

Последовательность:

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

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

result = re.match(pattern, string)

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

Примечание

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

re.A
re.ASCII

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

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

re.DEBUG

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

re.I
re.IGNORECASE

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

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

re.L
re.LOCALE

Сделайте \w, \W, \b, \B и соответствие без учета регистра зависящему от текущей локали. Этот флаг может быть используемый только с шаблонами байтов. Использование этого флага не рекомендуется, так как механизм локали очень ненадежен, он обрабатывает только одну «культуру» за раз, и работает только с 8-битными локалями. Сопоставление Юникода уже включено по умолчанию в Python 3 для шаблонов Юникода (str), и он может обрабатывать различные локали/языки. Соответствует встроенному флагу (?L).

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

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

re.M
re.MULTILINE

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

re.S
re.DOTALL

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Изменено в версии 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. Функция принимает один аргумент объект соответствия и возвращает замену строка. Например:

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

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

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

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

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

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

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

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

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

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

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

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

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

re.escape(pattern)

Экранирование специальных символов в pattern. Это полезно, если вы хотите соответствовать произвольному литерал строка, у которого могут быть метазнаки регулярного выражения в нем. Например:

>>> print(re.escape('http://www.python.org'))
http://www\.python\.org

>>> legal_chars = string.ascii_lowercase + string.digits + "!#$%&'*+-.^_`|~:"
>>> print('[%s]+' % re.escape(legal_chars))
[abcdefghijklmnopqrstuvwxyz0123456789!\#\$%\&'\*\+\-\.\^_`\|\~:]+

>>> operators = ['+', '-', '*', '/', '**']
>>> print('|'.join(map(re.escape, sorted(operators, reverse=True))))
/|\-|\+|\*\*|\*

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

>>> digits_re = r'\d+'
>>> sample = '/usr/sbin/sendmail - 0 errors, 12 warnings'
>>> print(re.sub(digits_re, digits_re.replace('\\', r'\\'), sample))
/usr/sbin/sendmail - \d+ errors, \d+ warnings

Изменено в версии 3.3: От '_' символ больше не экранируется.

Изменено в версии 3.7: Ускользают только символы, которые могут иметь особое значение в регулярном выражении. В результате '!', '"', '%', "'", ',', '/', ':', ';', '<', '=', '>', '@' и "`" больше не избегают.

re.purge()

Очистить кэш регулярного выражения.

exception re.error(msg, pattern=None, pos=None)

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

msg

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

pattern

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

pos

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

lineno

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

colno

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

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

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

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

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

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

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

Необязательный параметр 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")     # Совпадение по индексу 0
<re.Match object; span=(0, 1), match='d'>
>>> pattern.search("dog", 1)  # Не совпадает; поиск не включает "d"
Pattern.match(string[, pos[, endpos]])

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

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

>>> pattern = re.compile("o")
>>> pattern.match("dog")      # Нет совпадения, так как "o" не в начале "dog".
>>> pattern.match("dog", 1)   # Совпадает как "o" - это 2-й символ "dog".
<re.Match object; span=(1, 2), match='o'>

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

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

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

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

>>> pattern = re.compile("o[gh]")
>>> pattern.fullmatch("dog")      # Нет совпадения, так как "o" не в начале "dog".
>>> pattern.fullmatch("ogre")     # Нет совпадения, так как не вся строка совпадает.
>>> pattern.fullmatch("doggie", 1, 3)   # Совпадения в заданных пределах.
<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

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

Pattern.groups

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

Pattern.groupindex

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

Pattern.pattern

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

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

Match объекты

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

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

Объекты сопоставления поддерживают следующие методы и атрибуты:

Match.expand(template)

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

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

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

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

>>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")
>>> m.group(0)       # Весь матч
'Isaac Newton'
>>> m.group(1)       # Первая заключенная в скобки подгруппа.
'Isaac'
>>> m.group(2)       # Вторая заключенная в скобки подгруппа.
'Newton'
>>> m.group(1, 2)    # Несколько аргументов дают нам кортеж.
('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")  # Соответствует 3 раза.
>>> m.group(1)                        # Возвращает только последнее соответствие.
'c3'
Match.__getitem__(g)

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

>>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")
>>> m[0]       # Весь матч
'Isaac Newton'
>>> m[1]       # Первая заключенная в скобки подгруппа.
'Isaac'
>>> m[2]       # Вторая заключенная в скобки подгруппа.
'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()      # Вторая группа по умолчанию None.
('24', None)
>>> m.groups('0')   # Теперь вторая группа по умолчанию имеет значение '0'.
('24', '0')
Match.groupdict(default=None)

Возвращает словарь, содержащий все подгруппы named матча, включенного подназванием группы. Аргумент 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 соответствует null строка. Например, после m = re.search('b(c?)', 'cba'), m.start(0) равно 1, m.end(0) равно 2, m.start(1) и m.end(1) оба 2, и m.start(2) вызывает исключение IndexError.

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

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

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

Match.pos

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

Match.endpos

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

Match.lastindex

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

Match.lastgroup

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

Match.re

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

Match.string

Переданная строка match() или search().

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

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

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

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

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

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

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

>>> valid = re.compile(r"^[a2-9tjqk]{5}$")
>>> displaymatch(valid.match("akt5q"))  # Действительный.
"<Match: 'akt5q', groups=()>"
>>> displaymatch(valid.match("akt5e"))  # Недействительный.
>>> displaymatch(valid.match("akt"))    # Недействительный.
>>> displaymatch(valid.match("727ak"))  # Действительный.
"<Match: '727ak', groups=()>"

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

>>> pair = re.compile(r".*(.).*\1")
>>> displaymatch(pair.match("717ak"))     # Пара 7-к.
"<Match: '717', groups=('7',)>"
>>> displaymatch(pair.match("718ak"))     # Нет пар.
>>> displaymatch(pair.match("354aa"))     # Пара тузов.
"<Match: '354aa', groups=('a',)>"

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

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

# Ошибка, потому что re.match() возвращает None, у которого нет метода group():
>>> 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.match("c", "abcdef")    # Не совпадает
>>> re.search("c", "abcdef")   # Совпадает
<re.Match object; span=(2, 3), match='c'>

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

>>> re.match("c", "abcdef")    # Не совпадает
>>> re.search("^c", "abcdef")  # Не совпадает
>>> re.search("^a", "abcdef")  # Совпадает
<re.Match object; span=(0, 1), match='a'>

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

>>> re.match('X', 'A\nB\nX', re.MULTILINE)  # Не совпадает
>>> re.search('^X', 'A\nB\nX', re.MULTILINE)  # Совпадает
<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(), потому что у адреса есть места, наш сильный шаблон, в it:

>>> [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", text)
['carefully', 'quickly']

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

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

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

Необработанная строковая нотация

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

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

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

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

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

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

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

from typing import NamedTuple
import re

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

def tokenize(code):
    keywords = {'IF', 'THEN', 'ENDIF', 'FOR', 'NEXT', 'GOSUB', 'RETURN'}
    token_specification = [
        ('NUMBER',   r'\d+(\.\d*)?'),  # Целое или десятичное число
        ('ASSIGN',   r':='),           # Оператор присваивания
        ('END',      r';'),            # Инструкция завершителя
        ('ID',       r'[A-Za-z]+'),    # Идентификаторы
        ('OP',       r'[+\-*/]'),      # Арифметические операторы
        ('NEWLINE',  r'\n'),           # Концы строк
        ('SKIP',     r'[ \t]+'),       # Пропустить пробелы и табы
        ('MISMATCH', r'.'),            # Любой другой символ
    ]
    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 совсем, но первое издание очень подробно освещало написание хороших шаблонов регулярных выражений.