re — Операции с регулярными выражениями
Исходный код: Lib/re.py
Этот модуль предоставляет операции сопоставления с регулярными выражениями, аналогичные операциям в Perl.
И шаблоны, и строки, которые будут проверяться на соответствие, могут быть строками Юникода (str), а также 8-битными строками (bytes). Однако строки Юникода и 8-битные строки не могут смешиваться: то есть вы не можете сопоставить строку Юникода с шаблоном байтов или наоборот; аналогично, при запросе замены строка замены должна быть того же типа, что и шаблон и строка поиска.
В регулярных выражениях символ обратного слэша ('\') используется для обозначения специальных форм или для возможности использования специальных символов без вызова их специального значения. Это конфликтует с использованием Python того же символа для той же цели в строковых литералах; например, чтобы сопоставить буквенный обратный слэш, нужно написать '\\\\' в качестве строки шаблона, потому что регулярное выражение должно быть \\, а каждый обратный слэш должен быть выражен как \\ внутри обычной строки Python.
Решение заключается в использовании синтаксиса необработанных строк Python для шаблонов регулярных выражений; обратные слэши не обрабатываются каким-либо специальным образом в строковом литерале, начинающемся с 'r'. Так r"\n" — это строка из двух символов, содержащая '\' и 'n', а "\n" — это строка из одного символа, содержащая новую строку. Обычно шаблоны выражаются в коде Python с использованием этого синтаксиса необработанных строк.
Важно отметить, что большинство операций с регулярными выражениями доступны в виде функций уровня модуля и методов для скомпилированных регулярных выражений. Функции являются сокращениями, которые не требуют предварительной компиляции объекта regex, но пропущены некоторые параметры тонкой настройки.
См. также
Модуль сторонних разработчиков regex, который имеет API, совместимый со стандартной библиотекой re модуль, но предлагает дополнительные функции и более полную поддержку Юникода.
Синтаксис регулярных выражений
Регулярное выражение (или 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».
-
*?, +?, ?? -
Квалификаторы
'*','+', и'?'являются жадными; они сопоставляют как можно больше текста. Иногда такое поведение нежелательно; если RE<.*>сопоставляется со строкой'<a> b <c>', он будет сопоставляться со всей строкой, а не только со'<a>'. Добавление?после квалификатора заставляет его выполнять сопоставление в нежадном или минимальном режиме; будет сопоставлено как можно меньше символов. Использование RE<.*?>соответствует только'<a>'.
-
{m} -
Указывает, что должно быть сопоставлено ровно m копий предыдущего RE; меньше соответствий приводят к тому, что все RE не соответствуют. Например,
a{6}соответствует ровно шести'a'символам, но не пяти. -
{m,n} -
Заставляет результирующее RE соответствовать от m до n повторений предшествующего RE, пытаясь сопоставить как можно больше повторений. Например,
a{3,5}соответствует от 3 до 5'a'символам. Пропуск m задает нижнюю границу 0, а пропуск n задает бесконечную верхнюю границу. В качестве примера,a{4,}bсоответствует'aaaab'или тысяче'a'символов, за которыми следует'b', но не'aaab'. Запятая не может быть опущена, иначе модификатор был бы спутано с ранее описанной формой. -
{m,n}? -
Заставляет результирующее RE соответствовать от m до n повторений предшествующего RE, пытаясь сопоставить как можно меньше повторений. Это нежадная версия предыдущего квалификатора. Например, в 6-символьной строке
'aaaaaa',a{3,5}соответствует 5'a'символам, в то время какa{3,5}?соответствует только 3 символам.
-
\ -
Либо экранирует специальные символы (позволяя вам сопоставлять символы, такие как
'*','?', и так далее), либо сигнализирует о специальной последовательности; специальные последовательности обсуждаются ниже.Если вы не используете необработанную строку для выражения шаблона, помните, что Python также использует обратный слэш в качестве escape-последовательности в строковых литералах; если escape-последовательность не распознается анализатором Python, обратный слэш и последующий символ включаются в результирующую строку. Однако, если Python распознает получившуюся последовательность, обратный слэш должен быть повторен дважды. Это сложно и трудно понять, поэтому настоятельно рекомендуется использовать необработанные строки для всех выражений, кроме самых простых.
-
[] -
Используется для указания набора символов. В наборе:
- Символы могут быть перечислены по отдельности, например,
[amk]соответствует'a','m', или'k'.
- Диапазоны символов могут быть указаны, задав два символа и разделив их
'-', например,[a-z]соответствует любой строчной букве ASCII,[0-5][0-9]соответствует всем двузначным числам от00до59, и[0-9A-Fa-f]соответствует любой шестнадцатеричной цифре. Если-экранируется (например,[a\-z]) или если оно стоит первым или последним символом (например,[-a]или[a-]), оно соответствует литеральному символу'-'. - Специальные символы теряют своё специальное значение внутри наборов. Например,
[(+*)]соответствует любому из литеральных символов'(','+','*', или')'.
- Классы символов, такие как
\wили\S(определены ниже), также принимаются внутри набора, хотя символы, которым они соответствуют, зависят от того, включен ли режимASCIIилиLOCALE.
- Символам, которые не входят в диапазон, можно соответствовать путём дополнения набора. Если первым символом набора является
'^', будут сопоставляться все символы, которые не входят в набор. Например,[^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(). Флаги должны использоваться первыми в строке выражения.
-
(?:...) -
Незахватывающая версия обычных круглых скобок. Сопоставляет то регулярное выражение, что находится в скобках, но подстрока, сопоставленная с группой, не может быть получена после выполнения сопоставления или не может быть отслежена позже в шаблоне.
-
(?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-буквой, то полученная регулярная запись будет соответствовать второму символу. Например, \$ соответствует символу '$'.
-
\number -
Соответствует содержимому группы с тем же номером. Группы нумеруются, начиная с 1. Например,
(.+) \1соответствует'the the'или'55 55', но не'thethe'(обратите внимание на пробел после группы). Эта специальная последовательность может быть использована только для соответствия одной из первых 99 групп. Если первая цифра числа равна 0 или число имеет длину 3 восьмеричных цифр, то оно не будет интерпретироваться как совпадение группы, а как символ с восьмеричным значением число. Внутри'['и']'класса символов все числовые эскейпы обрабатываются как символы.
-
\A -
Соответствует только в начале строки.
-
\b -
Соответствует пустой строке, но только в начале или конце слова. Слово определяется как последовательность символов слова. Обратите внимание, что формально
\bопределяется как граница между\wи символом\W(или наоборот), или между\wи началом/концом строки. Это означает, чтоr'\bfoo\b'соответствует'foo','foo.','(foo)','bar foo baz', но не'foobar'или'foo3'.По умолчанию в шаблонах Unicode используются Unicode-алфавитно-цифровые символы, но это можно изменить, используя флаг
ASCII. Границы слов определяются текущим языковым стандартом, если используется флагLOCALE. Внутри диапазона символов\bпредставляет символ вставки, для совместимости с строковыми литералами Python.
-
\B -
Совпадает с пустой строкой, но только тогда, когда она не находится в начале или конце слова. Это означает, что
r'py\B'соответствует'python','py3','py2', но не'py','py.'или'py!'.\Bпросто противоположность\b, поэтому символы слов в шаблонах Unicode являются Unicode-алфавитно-цифровыми символами или символом подчёркивания, хотя это можно изменить, используя флагASCII. Границы слов определяются текущим языковым стандартом, если используется флагLOCALE.
-
\d -
- Для шаблонов Unicode (str):
-
Совпадает с любой десятичной цифрой Unicode (то есть любым символом в категории Unicode [Nd]). Это включает
[0-9], а также многие другие цифровые символы. Если используется флагASCII, совпадает только[0-9]. - Для шаблонов 8-битных (bytes):
-
Совпадает с любой десятичной цифрой; это эквивалентно
[0-9].
-
\D -
Соответствует любому символу, который не является десятичной цифрой. Это противоположность
\d. Если используется флагASCII, это становится эквивалентом[^0-9].
-
\s -
- Для шаблонов Unicode (str):
-
Совпадает с символами Unicode-пробела (включая
[ \t\n\r\f\v], и также многие другие символы, например, неразрывные пробелы, предписанные правилами типографики во многих языках). Если используется флагASCII, совпадает только[ \t\n\r\f\v]. - Для шаблонов 8-битных (bytes):
-
Совпадает с символами, считающимися пробелами в ASCII-наборе символов; это эквивалентно
[ \t\n\r\f\v].
-
\S -
Соответствует любому символу, который не является символом пробела. Это противоположность
\s. Если используется флагASCII, это становится эквивалентом[^ \t\n\r\f\v].
-
\w -
- Для шаблонов Unicode (str):
-
Совпадает с Unicode-символами слова; это включает большинство символов, которые могут быть частью слова на любом языке, а также цифры и знак подчёркивания. Если используется флаг
ASCII, совпадает только[a-zA-Z0-9_]. - Для шаблонов 8-битных (bytes):
-
Совпадает с символами, считающимися алфавитно-цифровыми в наборе символов ASCII; это эквивалентно
[a-zA-Z0-9_]. Если используется флагLOCALE, совпадает с символами, считающимися алфавитно-цифровыми в текущем языковом стандарте, и знаком подчёркивания.
-
\W -
Соответствует любому символу, который не является символом слова. Это противоположность
\w. Если используется флагASCII, это становится эквивалентом[^a-zA-Z0-9_]. Если используется флагLOCALE, совпадает с символами, которые не являются алфавитно-цифровыми в текущем языковом стандарте, или знаком подчёркивания.
-
\Z -
Совпадает только в конце строки.
Большинство стандартных эскейпов, поддерживаемых строковыми литералами Python, также принимаются анализатором регулярных выражений:
\a \b \f \n \r \t \u \U \v \x \\
(Обратите внимание, что \b используется для представления границ слов и означает «вставка» только внутри классов символов.)
'\u' и '\U' эскейпы распознаются только в шаблонах Unicode. В шаблонах bytes они являются ошибками. Неизвестные эскейпы ASCII-букв зарезервированы для будущего использования и обрабатываются как ошибки.
Восьмеричные эскейпы включены в ограниченной форме. Если первая цифра 0, или если есть три восьмеричных цифры, то это считается восьмеричным эскейпом. В противном случае это ссылка на группу. Как и в строковых литералах, восьмеричные эскейпы всегда имеют длину не более трёх цифр.
Изменено в версии 3.3: Добавлены эскейпы '\u' и '\U'.
Изменено в версии 3.6: Неизвестные эскейпы, состоящие из '\' и ASCII-буквы, теперь являются ошибками.
Содержание модуля
Модуль определяет несколько функций, констант и исключение. Некоторые из функций являются упрощёнными версиями полнофункциональных методов для скомпилированных регулярных выражений. Большинство нетривиальных приложений всегда используют скомпилированную форму.
Изменено в версии 3.6: Константы флагов теперь являются экземплярами RegexFlag, который является подклассом enum.IntFlag.
-
re.compile(pattern, flags=0) -
Компилирует шаблон регулярного выражения в объект регулярного выражения, который можно использовать для сопоставления с помощью его методов объекта регулярного выражения
match(),search()и других, описанных ниже.Поведение выражения можно изменить, указав значение флаги. Значения могут быть любыми из следующих переменных, объединённых с помощью побитового ИЛИ (оператора
|).Последовательность
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, а не с полным Unicode. Это имеет смысл только для шаблонов Unicode и игнорируется для шаблонов байтов. Соответствует встроенному флагу(?a).Обратите внимание, что для обратной совместимости флаг
re.Uвсё ещё существует (а также его синонимre.UNICODEи его встроенный аналог(?u)), но они избыточны в Python 3, так как для строк сопоставления по умолчанию являются Unicode (а Unicode-сопоставление не разрешено для байтов).
-
re.DEBUG -
Отобразить отладочную информацию о скомпилированном выражении. Нет соответствующего встроенного флага.
-
re.I -
re.IGNORECASE -
Выполнять сопоставление без учёта регистра; выражения, такие как
[A-Z]будут также соответствовать строчным буквам. Полное сопоставление Unicode (например,Üсовпадает сü) также работает, если не используется флагre.ASCIIдля отключения сопоставлений, не относящихся к ASCII. Текущий локали не влияет на действие этого флага, если также не используется флагre.LOCALE. Соответствует встроенному флагу(?i).Обратите внимание, что при использовании Unicode-шаблонов
[a-z]или[A-Z]в сочетании с флагомIGNORECASEони будут сопоставляться с 52 ASCII буквами и 4 дополнительными не-ASCII буквами: ‘İ’ (U+0130, заглавная латинская буква I с точкой сверху), ‘ı’ (U+0131, строчная латинская буква без точки i), ‘ſ’ (U+017F, строчная латинская буква длинная s) и ‘K’ (U+212A, знак Кельвина). Если используется флагASCII, сопоставляются только буквы от ‘a’ до ‘z’ и от ‘A’ до ‘Z’.
-
re.L -
re.LOCALE -
Заставить
\w,\W,\b,\Bи сопоставление без учёта регистра зависеть от текущей локали. Этот флаг может быть использован только с шаблонами байтов. Использование этого флага не рекомендуется, так как механизм локали очень ненадежен, он обрабатывает только одну «культуру» за раз, и он работает только с 8-битными локалями. Сопоставление Unicode по умолчанию включено в Python 3 для Unicode (str) шаблонов, и он может обрабатывать разные локали/языки. Соответствует встроенному флагу(?L).Изменено в версии 3.6:
re.LOCALEможет быть использован только с шаблонами байтов и несовместим сre.ASCII.Изменено в версии 3.7: Объекты скомпилированных регулярных выражений с флагом
re.LOCALEбольше не зависят от локали во время компиляции. Только локаль во время сопоставления влияет на результат сопоставления.
-
re.M -
re.MULTILINE -
При указании символ шаблона
'^'соответствует началу строки и началу каждой строки (непосредственно после каждой новой строки); и символ шаблона'$'соответствует концу строки и концу каждой строки (непосредственно перед каждой новой строкой). По умолчанию'^'соответствует только началу строки, а'$'только концу строки и непосредственно перед новой строкой (если таковая есть) в конце строки. Соответствует встроенному флагу(?m).
-
re.S -
re.DOTALL -
Заставляет специальный символ
'.'соответствовать любому символу, включая новую строку; без этого флага'.'будет соответствовать любому символу *кроме* новой строки. Соответствует встроенному флагу(?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) -
Просматривает строку, ища первое местоположение, где регулярное выражение шаблон даёт совпадение, и возвращает соответствующий объект совпадения. Возвращает
Noneесли ни одна позиция в строке не соответствует шаблону; обратите внимание, что это отличается от нахождения совпадения нулевой длины в какой-то точке строки.
-
re.match(pattern, string, flags=0) -
Если ноль или более символов в начале строки соответствуют регулярному выражению шаблон, возвращает соответствующий объект совпадения. Возвращает
Noneесли строка не соответствует шаблону; обратите внимание, что это отличается от совпадения нулевой длины.Обратите внимание, что даже в режиме
MULTILINE,re.match()будет соответствовать только началу строки, а не началу каждой строки.Если вы хотите найти совпадение где-либо в строке, используйте
search()вместо этого (см. также search() против match()).
-
re.fullmatch(pattern, string, flags=0) -
Если вся строка соответствует регулярному выражению шаблон, возвращает соответствующий объект совпадения. Возвращает
Noneесли строка не соответствует шаблону; обратите внимание, что это отличается от совпадения нулевой длины.Добавлено в версии 3.4.
-
re.split(pattern, string, maxsplit=0, flags=0) -
Разделяет строку по вхождениям шаблона. Если в шаблоне используются группирующие скобки, то текст всех групп в шаблоне также возвращается как часть результирующего списка. Если maxsplit не равно нулю, выполняется не более maxsplit разделений, и остальная часть строки возвращается как последний элемент списка.
>>> re.split(r'\W+', 'Words, words, words.') ['Words', 'words', 'words', ''] >>> re.split(r'(\W+)', 'Words, words, words.') ['Words', ', ', 'words', ', ', 'words', '.', ''] >>> re.split(r'\W+', 'Words, words, words.', 1) ['Words', 'words, words.'] >>> re.split('[a-f]+', '0a3B9', flags=re.IGNORECASE) ['0', '3', '9']Если в разделителе есть группирующие скобки, и он соответствует началу строки, результат начнётся с пустой строки. То же самое верно и для конца строки:
>>> re.split(r'(\W+)', '...words, words...') ['', '...', 'words', ', ', 'words', '...', '']
Таким образом, компоненты разделителя всегда находятся в тех же относительных индексах в результирующем списке.
Пустые совпадения для шаблона разделяют строку только тогда, когда они не примыкают к предыдущему пустому совпадению.
>>> re.split(r'\b', 'Words, words, words.') ['', 'Words', ', ', 'words', ', ', 'words', '.'] >>> re.split(r'\W*', '...words...') ['', '', 'w', 'o', 'r', 'd', 's', '', ''] >>> re.split(r'(\W*)', '...words...') ['', '...', '', '', 'w', '', 'o', '', 'r', '', 'd', '', 's', '...', '', '', '']
Изменено в версии 3.1: Добавлен необязательный аргумент флаги.
Изменено в версии 3.7: Добавлена поддержка разделения по шаблону, который может соответствовать пустой строке.
-
re.findall(pattern, string, flags=0) -
Возвращает все неперекрывающиеся совпадения шаблона в строке, как список строк. Строка сканируется слева направо, и совпадения возвращаются в порядке обнаружения. Если в шаблоне присутствует одна или несколько групп, возвращается список групп; это будет список кортежей, если шаблон содержит более одной группы. Пустые совпадения включаются в результат.
Изменено в версии 3.7: Непустые совпадения теперь могут начинаться сразу после предыдущего пустого совпадения.
-
re.finditer(pattern, string, flags=0) -
Возвращает итератор, который выдает объекты совпадения для всех неперекрывающихся совпадений регулярного выражения pattern в 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-'.В аргументах repl типа строка, помимо описанных выше управляющих последовательностей и обратных ссылок,
\g<name>будет использовать подстроку, соответствующую группе с именемname, как определено в синтаксисе(?P<name>...).\g<number>использует соответствующий номер группы;\g<2>поэтому эквивалентен\2, но не является неоднозначным в замене, такой как\g<2>0.\20будет интерпретироваться как ссылка на группу 20, а не на группу 2, за которой следует буква'0'. Обратная ссылка\g<0>заменяет всю подстроку, соответствующую регулярному выражению.Изменено в версии 3.1: Добавлен необязательный аргумент flags.
Изменено в версии 3.5: Несоответствующие группы заменяются пустой строкой.
Изменено в версии 3.6: Неизвестные управляющие последовательности в 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: Добавлен необязательный аргумент flags.
Изменено в версии 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. Это не полностью эквивалентно срезу строки; символ'^'соответствует фактическому началу строки и позициям сразу после новой строки, но не обязательно индексу, с которого начинается поиск.Необязательный параметр endpos ограничивает область поиска в строке; это как если бы строка имела длину endpos символов, поэтому будут проверяться только символы от pos до
endpos - 1на предмет совпадения. Если endpos меньше pos, совпадение не будет найдено; в противном случае, если rx — объект скомпилированного регулярного выражения,rx.search(string, 0, 50)эквивалентноrx.search(string[:50], 0).>>> pattern = re.compile("d") >>> pattern.search("dog") # Match at index 0 <re.Match object; span=(0, 1), match='d'> >>> pattern.search("dog", 1) # No match; search doesn't include the "d"
-
Pattern.match(string[, pos[, endpos]]) -
Если ноль или более символов в начале string соответствуют этому регулярному выражению, возвращает соответствующий объект совпадения. Возвращает
Noneесли строка не соответствует шаблону; обратите внимание, что это отличается от совпадения нулевой длины.Необязательные параметры pos и endpos имеют то же значение, что и для метода
search().>>> pattern = re.compile("o") >>> pattern.match("dog") # No match as "o" is not at the start of "dog". >>> pattern.match("dog", 1) # Match as "o" is the 2nd character of "dog". <re.Match object; span=(1, 2), match='o'>Если вы хотите найти совпадение где-либо в string, используйте
search()(см. также search() vs. match()).
-
Pattern.fullmatch(string[, pos[, endpos]]) -
Если вся string соответствует этому регулярному выражению, возвращает соответствующий объект совпадения. Возвращает
Noneесли строка не соответствует шаблону; обратите внимание, что это отличается от совпадения нулевой длины.Необязательные параметры pos и endpos имеют то же значение, что и для метода
search().>>> pattern = re.compile("o[gh]") >>> pattern.fullmatch("dog") # No match as "o" is not at the start of "dog". >>> pattern.fullmatch("ogre") # No match as not the full string matches. >>> pattern.fullmatch("doggie", 1, 3) # Matches within given limits. <re.Match object; span=(1, 3), match='og'>Введено в версии 3.4.
-
Pattern.split(string, maxsplit=0) -
Идентично функции
split(), использующей скомпилированный шаблон.
-
Pattern.findall(string[, pos[, endpos]]) -
Аналогично функции
findall(), использующей скомпилированный шаблон, но также принимает необязательные параметры pos и endpos, которые ограничивают область поиска, как и в случае сsearch().
-
Pattern.finditer(string[, pos[, endpos]]) -
Аналогично функции
finditer(), использующей скомпилированный шаблон, но также принимает необязательные параметры pos и endpos, которые ограничивают область поиска, как и дляsearch().
-
Pattern.sub(repl, string, count=0) -
Идентично функции
sub(), использующей скомпилированный шаблон.
-
Pattern.subn(repl, string, count=0) -
Идентично функции
subn(), использующей скомпилированный шаблон.
-
Pattern.flags -
Флаги сопоставления регулярных выражений. Это комбинация флагов, заданных для
compile(), любых флагов в шаблоне(?...), и неявных флагов, таких какUNICODE, если шаблон является строкой Unicode.
-
Pattern.groups -
Количество захватывающих групп в шаблоне.
-
Pattern.groupindex -
Словарь, сопоставляющий имена символьных групп, определённых в
(?P<id>), с номерами групп. Словарь пуст, если в шаблоне не использовались символьные группы.
-
Pattern.pattern -
Строка шаблона, из которой был скомпилирован объект шаблона.
Изменено в версии 3.7: Добавлена поддержка copy.copy() и copy.deepcopy(). Объекты скомпилированных регулярных выражений считаются атомарными.
Объекты совпадений
Объекты совпадений всегда имеют булево значение True. Так как match() и search() возвращают None при отсутствии совпадения, можно проверить наличие совпадения с помощью простого оператора if.
match = re.search(pattern, string)
if match:
process(match)
Объекты совпадений поддерживают следующие методы и атрибуты:
-
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) # 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'
Введено в версии 3.6.
-
Match.groups(default=None) -
Возвращает кортеж, содержащий все подгруппы совпадения, от 1 до количества групп в шаблоне. Аргумент default используется для групп, которые не участвовали в совпадении; по умолчанию он равен
None.Например:
>>> m = re.match(r"(\d+)\.(\d+)", "24.1632") >>> m.groups() ('24', '1632')Если десятичная точка и всё после неё являются необязательными, не все группы могут участвовать в совпадении. Эти группы будут иметь значение по умолчанию
None, если аргумент default не указан:>>> m = re.match(r"(\d+)\.?(\d+)?", "24") >>> m.groups() # Second group defaults to None. ('24', None) >>> m.groups('0') # Now, the second group defaults to '0'. ('24', '0')
-
Match.groupdict(default=None) -
Возвращает словарь, содержащий все именованные подгруппы совпадения, с ключами — именами подгрупп. Аргумент default используется для групп, которые не участвовали в совпадении; по умолчанию он равен
None. Например:>>> m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds") >>> m.groupdict() {'first_name': 'Malcolm', 'last_name': 'Reynolds'}
-
Match.start([group]) -
Match.end([group]) -
Возвращает индексы начала и конца подстроки, соответствующей group; group по умолчанию равен нулю (вся подстрока совпадения). Возвращает
-1если group существует, но не участвует в совпадении. Для объекта совпадения m и группы g, которая участвовала в совпадении, подстрока, соответствующая группе g (эквивалентнаm.group(g)) равнаm.string[m.start(g):m.end(g)]
Обратите внимание, что
m.start(group)будет равноm.end(group)если group совпала с пустой строкой. Например, послеm = re.search('b(c?)', 'cba'),m.start(0)равно 1,m.end(0)равно 2,m.start(1)иm.end(1)оба равны 2, аm.start(2)вызывает исключениеIndexError.Пример удаления remove_this из адресов электронной почты:
>>> email = "tony@tiremove_thisger.net" >>> m = re.search("remove_this", email) >>> email[:m.start()] + email[m.end():] 'tony@tiger.net'
-
Match.span([group]) -
Для совпадения m возвращает кортеж
(m.start(group), m.end(group)). Обратите внимание, что если group не участвовала в совпадении, это(-1, -1). group по умолчанию равна нулю, всему совпадению.
-
Match.pos -
Значение pos, переданное методу
search()илиmatch()объекта объекта регулярного выражения. Это индекс в строке, с которого движок 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()которого создал этот экземпляр совпадения.
Изменено в версии 3.7: Добавлена поддержка copy.copy() и copy.deepcopy(). Объекты совпадения считаются атомарными.
Примеры регулярных выражений
Проверка на пару
В этом примере мы используем следующую вспомогательную функцию, чтобы отобразить объекты совпадения немного нагляднее:
def displaymatch(match):
if match is None:
return None
return '<Match: %r, groups=%r>' % (match.group(), match.groups())
END_OF_DOCUMENT_MARKER Предположим, вы пишете программу для покера, где рука игрока представлена строкой из 5 символов, каждый из которых представляет карту: «a» для туза, «k» для короля, «q» для дамы, «j» для валета, «t» для 10, а «2» по «9» представляют карту с соответствующим значением.
Чтобы проверить, является ли заданная строка действительной рукой, можно сделать следующее:
>>> valid = re.compile(r"^[a2-9tjqk]{5}$")
>>> displaymatch(valid.match("akt5q")) # Valid.
"<Match: 'akt5q', groups=()>"
>>> displaymatch(valid.match("akt5e")) # Invalid.
>>> displaymatch(valid.match("akt")) # Invalid.
>>> displaymatch(valid.match("727ak")) # Valid.
"<Match: '727ak', groups=()>"
Последняя рука, "727ak", содержала пару, или две карты с одинаковым значением. Для сопоставления с этим регулярным выражением можно использовать обратные ссылки следующим образом:
>>> pair = re.compile(r".*(.).*\1")
>>> displaymatch(pair.match("717ak")) # Pair of 7s.
"<Match: '717', groups=('7',)>"
>>> displaymatch(pair.match("718ak")) # No pairs.
>>> displaymatch(pair.match("354aa")) # Pair of aces.
"<Match: '354aa', groups=('a',)>"
Чтобы узнать, какая карта составляет пару, можно использовать метод group() объекта совпадения следующим образом:
>>> pair.match("717ak").group(1)
'7'
# Error because re.match() returns None, which doesn't have a group() method:
>>> pair.match("718ak").group(1)
Traceback (most recent call last):
File "<pyshell#23>", line 1, in <module>
re.match(r".*(.).*\1", "718ak").group(1)
AttributeError: 'NoneType' object has no attribute 'group'
>>> pair.match("354aa").group(1)
'a'
Моделирование scanf()
В Python в настоящее время нет эквивалента scanf(). Регулярные выражения, как правило, более мощные, хотя и более громоздкие, чем scanf() форматы строк. В таблице ниже приведены более или менее эквивалентные сопоставления между scanf() форматами токенов и регулярными выражениями.
| Регулярное выражение |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Для извлечения имени файла и чисел из строки, такой как
/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") # No match
>>> re.search("c", "abcdef") # Match
<re.Match object; span=(2, 3), match='c'>
Регулярные выражения, начинающиеся с '^', могут использоваться с search() для ограничения совпадения началом строки:
>>> re.match("c", "abcdef") # No match
>>> re.search("^c", "abcdef") # No match
>>> re.search("^a", "abcdef") # Match
<re.Match object; span=(0, 1), match='a'>
Однако обратите внимание, что в режиме MULTILINE match() соответствует только началу строки, в то время как использование search() с регулярным выражением, начинающимся с '^', будет соответствовать началу каждой строки.
>>> re.match('X', 'A\nB\nX', re.MULTILINE) # No match
>>> re.search('^X', 'A\nB\nX', re.MULTILINE) # Match
<re.Match object; span=(4, 5), match='X'>
Создание телефонной книги
split() разбивает строку на список, ограниченный переданным шаблоном. Этот метод незаменим для преобразования текстовых данных в структуры данных, которые легко читаются и изменяются в Python, как показано в следующем примере, создающем телефонную книгу.
Сначала вот входные данные. Обычно они могут поступать из файла, здесь мы используем синтаксис строк с тройными кавычками:
>>> text = """Ross McFluff: 834.345.1254 155 Elm Street ... ... Ronald Heathmore: 892.345.3428 436 Finley Avenue ... Frank Burger: 925.541.7625 662 South Dogwood Way ... ... ... Heather Albrecht: 548.326.4584 919 Park Place"""
Записи разделены одной или несколькими строками новой строки. Теперь мы преобразуем строку в список, где каждая непустая строка имеет свою запись:
>>> entries = re.split("\n+", text)
>>> entries
['Ross McFluff: 834.345.1254 155 Elm Street',
'Ronald Heathmore: 892.345.3428 436 Finley Avenue',
'Frank Burger: 925.541.7625 662 South Dogwood Way',
'Heather Albrecht: 548.326.4584 919 Park Place']
Наконец, разделим каждую запись на список с именем, фамилией, номером телефона и адресом. Мы используем параметр maxsplit split(), потому что в адресе есть пробелы, наш разделительный шаблон:
>>> [re.split(":? ", entry, 3) for entry in entries]
[['Ross', 'McFluff', '834.345.1254', '155 Elm Street'],
['Ronald', 'Heathmore', '892.345.3428', '436 Finley Avenue'],
['Frank', 'Burger', '925.541.7625', '662 South Dogwood Way'],
['Heather', 'Albrecht', '548.326.4584', '919 Park Place']]
Шаблон :? соответствует двоеточию после фамилии, чтобы он не появлялся в результирующем списке. С maxsplit 4, мы могли бы разделить номер дома и название улицы:
>>> [re.split(":? ", entry, 4) for entry in entries]
[['Ross', 'McFluff', '834.345.1254', '155', 'Elm Street'],
['Ronald', 'Heathmore', '892.345.3428', '436', 'Finley Avenue'],
['Frank', 'Burger', '925.541.7625', '662', 'South Dogwood Way'],
['Heather', 'Albrecht', '548.326.4584', '919', 'Park Place']]
Обработка текста
sub() заменяет каждое вхождение шаблона строкой или результатом функции. Этот пример демонстрирует использование sub() с функцией для «обработки» текста или случайной перестановки порядка всех символов в каждом слове предложения, за исключением первого и последнего символов:
>>> def repl(m): ... inner_word = list(m.group(2)) ... random.shuffle(inner_word) ... return m.group(1) + "".join(inner_word) + m.group(3) >>> text = "Professor Abdolmalek, please report your absences promptly." >>> re.sub(r"(\w)(\w+)(\w)", repl, text) 'Poefsrosr Aealmlobdk, pslaee reorpt your abnseces plmrptoy.' >>> re.sub(r"(\w)(\w+)(\w)", repl, text) 'Pofsroser Aodlambelk, plasee reoprt yuor asnebces potlmrpy.'
Поиск всех наречий
findall() находит все вхождения шаблона, а не только первое, как search(). Например, если автор хотел найти все наречия в каком-то тексте, он мог бы использовать findall() следующим образом:
>>> text = "He was carefully disguised but captured quickly by police." >>> re.findall(r"\w+ly", 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='\\'>
Написание токенизатора
Токенизатор или сканер анализирует строку для категоризации групп символов. Это полезный первый шаг при написании компилятора или интерпретатора.
Категории текста задаются с помощью регулярных выражений. Прием заключается в объединении их в одно общее регулярное выражение и в цикле по последовательным совпадениям:
import collections
import re
Token = collections.namedtuple('Token', ['type', 'value', 'line', 'column'])
def tokenize(code):
keywords = {'IF', 'THEN', 'ENDIF', 'FOR', 'NEXT', 'GOSUB', 'RETURN'}
token_specification = [
('NUMBER', r'\d+(\.\d*)?'), # Integer or decimal number
('ASSIGN', r':='), # Assignment operator
('END', r';'), # Statement terminator
('ID', r'[A-Za-z]+'), # Identifiers
('OP', r'[+\-*/]'), # Arithmetic operators
('NEWLINE', r'\n'), # Line endings
('SKIP', r'[ \t]+'), # Skip over spaces and tabs
('MISMATCH', r'.'), # Any other character
]
tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification)
line_num = 1
line_start = 0
for mo in re.finditer(tok_regex, code):
kind = mo.lastgroup
value = mo.group()
column = mo.start() - line_start
if kind == 'NUMBER':
value = float(value) if '.' in value else int(value)
elif kind == 'ID' and value in keywords:
kind = value
elif kind == 'NEWLINE':
line_start = mo.end()
line_num += 1
continue
elif kind == 'SKIP':
continue
elif kind == 'MISMATCH':
raise RuntimeError(f'{value!r} unexpected on line {line_num}')
yield Token(kind, value, line_num, column)
statements = '''
IF quantity THEN
total := total + price * quantity;
tax := price * 0.05;
ENDIF;
'''
for token in tokenize(statements):
print(token)
Токенизатор выводит следующий результат:
Token(type='IF', value='IF', line=2, column=4) Token(type='ID', value='quantity', line=2, column=7) Token(type='THEN', value='THEN', line=2, column=16) Token(type='ID', value='total', line=3, column=8) Token(type='ASSIGN', value=':=', line=3, column=14) Token(type='ID', value='total', line=3, column=17) Token(type='OP', value='+', line=3, column=23) Token(type='ID', value='price', line=3, column=25) Token(type='OP', value='*', line=3, column=31) Token(type='ID', value='quantity', line=3, column=33) Token(type='END', value=';', line=3, column=41) Token(type='ID', value='tax', line=4, column=8) Token(type='ASSIGN', value=':=', line=4, column=12) Token(type='ID', value='price', line=4, column=15) Token(type='OP', value='*', line=4, column=21) Token(type='NUMBER', value=0.05, line=4, column=23) Token(type='END', value=';', line=4, column=27) Token(type='ENDIF', value='ENDIF', line=5, column=4) Token(type='END', value=';', line=5, column=9)
-
Frie09 -
Фридль, Джеффри. Освоение регулярных выражений. 3-е изд., O’Reilly Media, 2009. Третье издание книги больше не охватывает Python, но первое издание подробно рассказывало о написании хороших шаблонов регулярных выражений.
© 2001–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.7/library/re.html