re — Операции с регулярными выражениями
Исходный код: Lib/re.py
Этот модуль предоставляет операции сопоставления регулярных выражений, аналогичные тем, которые есть в Perl.
И шаблоны, и строки, которые будут проверяться, могут быть строками Unicode (str) а также строками 8-битовыми (bytes). Однако, строки Unicode и строки 8-битовые не могут смешиваться: то есть вы не можете сопоставить строку Unicode с байтовым шаблоном или наоборот; аналогично, при запросе подстановки строка замены должна быть того же типа, что шаблон и строка поиска.
Регулярные выражения используют обратную косую черту ('\') для указания специальных форм или для разрешения использования специальных символов без вызова их специального значения. Это конфликтует с использованием Python того же символа для той же цели в строковых литералах; например, чтобы сопоставить литеранльную обратную косую черту, необходимо написать '\\\\' в качестве строки шаблона, потому что регулярное выражение должно быть \\, а каждая обратная косая черта должна быть выражена как \\ внутри обычной строки Python.
Решение состоит в использовании синтаксиса сырых строк Python для шаблонов регулярных выражений; обратные косые черты не обрабатываются каким-либо специальным образом в строковом литерале, который начинается с 'r'. Таким образом, r"\n" — это строка из двух символов, содержащая '\' и 'n', в то время как "\n" — это строка из одного символа, содержащая символ новой строки. Обычно шаблоны выражаются в коде Python с использованием этого синтаксиса сырых строк.
Важно отметить, что большинство операций с регулярными выражениями доступны как функции и методы на уровне модуля для скомпилированных регулярных выражений. Функции являются сокращениями, которые не требуют предварительной компиляции объекта regex, но пропускают некоторые параметры тонкой настройки.
См. также
Модуль сторонних разработчиков regex, у которого есть API, совместимый с модулем стандартной библиотеки re, но предлагает дополнительные функции и более полную поддержку Unicode.
6.2.1. Синтаксис регулярных выражений
Регулярное выражение (или 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', а[^^]соответствует любому символу, кроме'^'.^не имеет специального значения, если это не первый символ в наборе. - Чтобы соответствовать точному значению
']'внутри набора, предшествуйте ему обратной косой чертой или поместите его в начало набора. Например, оба[()[\]{}]и[]()[{}]соответствуют скобке.
- Символы могут быть перечислены индивидуально, например
-
| -
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(подробный), для всего регулярного выражения. (Флаги описаны в Содержимое модуля.) Это полезно, если вы хотите включить флаги в состав регулярного выражения вместо передачи аргумента флаг функцииre.compile(). Флаги должны использоваться первыми в строке выражения.
-
(?:...) -
Незахватывающая версия обычных скобок. Соответствует любому регулярному выражению, находящемуся в скобках, но подстрока, соответствующая группе, не может быть извлечена после выполнения соответствия или указана позже в шаблоне.
-
(?imsx-imsx:...) -
(Ноль или более букв из набора
'i','m','s','x', необязательно после'-'и одной или несколькими буквами из того же набора.) Буквы устанавливают или снимают соответствующие флаги:re.I(без учета регистра),re.M(многострочный),re.S(точка соответствует всем) иre.X(подробный), для части выражения. (Флаги описаны в Содержимое модуля.)Добавлено в версии 3.6.
-
(?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', так как lookbehind вернется на 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 -
Совпадает с пустой строкой, но только тогда, когда она не находится в начале или конце слова. Это означает, что
r'py\B'соответствует'python','py3','py2', но не'py','py.'или'py!'.\B— просто противоположность\b, поэтому символы слов в шаблонах Юникод — это символы алфавитно-цифровых Юникод или символ подчеркивания, хотя это можно изменить, используя флагASCII. Границы слов определяются текущим языковым стандартом, если используется флагLOCALE.
-
\d -
- Для шаблонов Юникод (str):
-
Соответствует любой десятичной цифре Юникод (то есть любому символу в категории символов Unicode [Nd]). Это включает
[0-9], а также многие другие символы цифр. Если используется флагASCII, то совпадает только[0-9](но флаг влияет на весь регулярное выражение, поэтому в таких случаях использование явного[0-9]может быть предпочтительнее). - Для 8-битных шаблонов (bytes):
-
Соответствует любой десятичной цифре; это эквивалентно
[0-9].
-
\D -
Соответствует любому символу, который не является десятичной цифрой. Это противоположно
\d. Если используется флагASCII, это становится эквивалентом[^0-9](но флаг влияет на все регулярное выражение, поэтому в таких случаях использование явного[^0-9]может быть предпочтительнее).
-
\s -
- Для шаблонов Юникод (str):
-
Соответствует символам пробелов Юникод (что включает
[ \t\n\r\f\v], а также многие другие символы, например, неразрывные пробелы, предписанные правилами типографики во многих языках). Если используется флагASCII, совпадает только[ \t\n\r\f\v](но флаг влияет на все регулярное выражение, поэтому в таких случаях использование явного[ \t\n\r\f\v]может быть предпочтительнее). - Для 8-битных шаблонов (bytes):
-
Соответствует символам, которые считаются пробелами в ASCII-наборе символов; это эквивалентно
[ \t\n\r\f\v].
-
\S -
Соответствует любому символу, который не является символом пробела. Это противоположно
\s. Если используется флагASCII, это становится эквивалентом[^ \t\n\r\f\v](но флаг влияет на все регулярное выражение, поэтому в таких случаях использование явного[^ \t\n\r\f\v]может быть предпочтительнее).
-
\w -
- Для шаблонов Юникод (str):
-
Соответствует символам слов Юникод; это включает большинство символов, которые могут быть частью слова на любом языке, а также цифры и символ подчеркивания. Если используется флаг
ASCII, совпадает только[a-zA-Z0-9_](но флаг влияет на все регулярное выражение, поэтому в таких случаях использование явного[a-zA-Z0-9_]может быть предпочтительнее). - Для 8-битных шаблонов (bytes):
-
Соответствует символам, которые считаются алфавитно-цифровыми в ASCII-наборе символов; это эквивалентно
[a-zA-Z0-9_]. Если используется флагLOCALE, соответствует символам, считающимся алфавитно-цифровыми в текущем языковом стандарте, и символу подчеркивания.
-
\W -
Соответствует любому символу, который не является символом слова. Это противоположно
\w. Если используется флагASCII, это становится эквивалентом[^a-zA-Z0-9_](но флаг влияет на все регулярное выражение, поэтому в таких случаях использование явного[^a-zA-Z0-9_]может быть предпочтительнее). Если используется флагLOCALE, соответствуют символам, считающимся алфавитно-цифровыми в текущем языковом стандарте, и символу подчеркивания.
-
\Z -
Совпадает только в конце строки.
Большинство стандартных экранирований, поддерживаемых строковыми литералами Python, также принимаются анализатором регулярных выражений:
\a \b \f \n \r \t \u \U \v \x \\
(Обратите внимание, что \b используется для представления границ слов и означает «обратное удаление» только внутри классов символов.)
'\u' и '\U' последовательности экранирования распознаются только в шаблонах Юникод. В шаблонах байтов они являются ошибками.
Восьмеричные экранирования включены в ограниченной форме. Если первая цифра — 0, или если есть три восьмеричных цифры, это считается восьмеричным экранированием. В противном случае это ссылка на группу. Как и в строковых литералах, восьмеричные экранирования всегда имеют длину не более трех цифр.
Изменено в версии 3.3: Добавлены последовательности экранирования '\u' и '\U'.
Изменено в версии 3.6: Неизвестные экранирования, состоящие из '\' и ASCII-буквы, теперь являются ошибками.
6.2.2. Содержание модуля
Модуль определяет несколько функций, констант и исключение. Некоторые функции — это упрощенные версии полных методов для скомпилированных регулярных выражений. Большинство нетривиальных приложений всегда используют скомпилированную форму.
Изменено в версии 3.6: Константы флагов теперь являются экземплярами RegexFlag, который является подклассом enum.IntFlag.
-
re.compile(pattern, flags=0) -
Компилирует шаблон регулярного выражения в объект регулярного выражения, который можно использовать для сопоставления с помощью его методов объекта регулярного выражения,
match(),search()и других методов, описанных ниже.Поведение выражения можно изменить, указав значение flags. Значения могут быть любыми из следующих переменных, объединённых с помощью побитового ИЛИ (оператора
|).Последовательность
prog = re.compile(pattern) result = prog.match(string)
эквивалентна
result = re.match(pattern, string)
но использование
re.compile()и сохранение полученного объекта регулярного выражения для повторного использования более эффективно, когда выражение будет использоваться несколько раз в одной программе.Примечание
Компилированные версии последних шаблонов, переданных в
re.compile()и функции сопоставления на уровне модуля, кэшируются, поэтому программы, использующие только несколько регулярных выражений за раз, не должны беспокоиться о компиляции регулярных выражений.
-
re.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» (но флаг влияет на всё регулярное выражение, поэтому в таких случаях использование явного(?-i:[a-zA-Z])может быть лучшим вариантом).
-
re.L -
re.LOCALE -
Сделать
\w,\W,\b,\Bи сопоставление без учёта регистра зависящими от текущей локали. Этот флаг может использоваться только с шаблонами байтов. Использование этого флага не рекомендуется, так как механизм локали очень ненадежный, он обрабатывает только одну «культуру» за раз и работает только с 8-битными локалями. Сопоставление Unicode уже включено по умолчанию в Python 3 для шаблонов Unicode (str), и он может обрабатывать различные локали/языки. Соответствует встроенному флагу(?L).
-
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', '...', '']
Таким образом, компоненты разделителя всегда находятся на тех же относительных индексах в результирующем списке.
Примечание
split()в настоящее время не разделяет строку по пустым совпадениям шаблона. Например:>>> re.split('x*', 'axbc') ['a', 'bc']Несмотря на то, что
'x*'также соответствует 0 'x' перед 'a', между 'b' и 'c' и после 'c', в настоящее время эти совпадения игнорируются. Правильное поведение (т. е. разделение по пустым совпадениям и возврат['', 'a', 'b', 'c', '']) будет реализовано в будущих версиях Python, но поскольку это изменение несовместимо с предыдущими версиями, в настоящее время будет генерироватьсяFutureWarning.Шаблоны, которые могут соответствовать только пустым строкам, в настоящее время никогда не разделяют строку. Поскольку это не соответствует ожидаемому поведению, начиная с Python 3.5, будет генерироваться
ValueError:>>> re.split("^$", "foo\n\nbar\n", flags=re.M) Traceback (most recent call last): File "<stdin>", line 1, in <module> ... ValueError: split() requires a non-empty pattern match.Изменено в версии 3.1: Добавлен необязательный аргумент flags.
Изменено в версии 3.5: Разделение по шаблону, который может соответствовать пустой строке, теперь вызывает предупреждение. Шаблоны, которые могут соответствовать только пустым строкам, теперь отклоняются.
-
re.findall(pattern, string, flags=0) -
Возвращает все неперекрывающиеся совпадения pattern в string в виде списка строк. string сканируется слева направо, а совпадения возвращаются в порядке их нахождения. Если в шаблоне присутствует одна или несколько групп, возвращается список групп; это будет список кортежей, если шаблон имеет более одной группы. Пустые совпадения включаются в результат.
Примечание
Из-за ограничений текущей реализации символ, следующий за пустым совпадением, не включается в следующее совпадение, поэтому
findall(r'^|\w+', 'two words')возвращает['', 'wo', 'words'](замечено пропущенное «t»). Это изменено в Python 3.7.
-
re.finditer(pattern, string, flags=0) -
Возвращает итератор, возвращающий объекты совпадения для всех неперекрывающихся совпадений шаблона pattern в string. string сканируется слева направо, а совпадения возвращаются в порядке их нахождения. Пустые совпадения включаются в результат. См. также примечание о
findall().
-
re.sub(pattern, repl, string, count=0, flags=0) -
Возвращает строку, полученную путем замены левого неперекрывающегося вхождения pattern в string заменой repl. Если шаблон не найден, возвращается string без изменений. repl может быть строкой или функцией; если это строка, все обратные слэши в ней обрабатываются. То есть,
\nпреобразуется в один символ новой строки,\rпреобразуется в символ возврата каретки и так далее. Неизвестные экранирования, такие как\&оставляются без изменений. Ссылки на обратные выражения, такие как\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*', '-', 'abc')возвращает'-a-b-c-'.В аргументах 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.5, будет удалено в версии 3.7: Неизвестные экранирования в repl, состоящие из
'\'и ASCII-буквы, теперь вызывают предупреждение об устаревании и будут запрещены в Python 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, кроме ASCII-букв, цифр и
'_'. Это полезно, если вам нужно сопоставить произвольную строку, которая может содержать метасимволы регулярных выражений. Например:>>> print(re.escape('python.exe')) python\.exe >>> 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: Символ
'_'больше не экранируется.
-
re.purge() -
Очищает кэш регулярных выражений.
-
exception re.error(msg, pattern=None, pos=None) -
Исключение, которое возникает, когда строка, переданная одной из функций, не является допустимым регулярным выражением (например, может содержать несовпадающие скобки) или когда возникает другая ошибка во время компиляции или сопоставления. Ошибка никогда не возникает, если строка не содержит совпадений с шаблоном. Объект ошибки имеет следующие дополнительные атрибуты:
-
msg -
Неформализованное сообщение об ошибке.
-
pattern -
Шаблон регулярного выражения.
-
pos -
Индекс в pattern, где произошла ошибка компиляции (может быть
None).
-
lineno -
Строка, соответствующая pos (может быть
None).
-
colno -
Столбец, соответствующий pos (может быть
None).
Изменено в версии 3.5: Добавлены дополнительные атрибуты.
-
6.2.3. Объекты регулярных выражений
Компилированные объекты регулярных выражений поддерживают следующие методы и атрибуты:
-
regex.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 <_sre.SRE_Match object; span=(0, 1), match='d'> >>> pattern.search("dog", 1) # No match; search doesn't include the "d"
-
regex.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". <_sre.SRE_Match object; span=(1, 2), match='o'>Если вам нужно найти совпадение в любой части string, используйте
search()(см. также search() vs. match()).
-
regex.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. <_sre.SRE_Match object; span=(1, 3), match='og'>Новое в версии 3.4.
-
regex.split(string, maxsplit=0) -
Идентично функции
split(), использующей скомпилированный шаблон.
-
regex.findall(string[, pos[, endpos]]) -
Аналогично функции
findall(), использующей скомпилированный шаблон, но также принимает необязательные параметры pos и endpos, которые ограничивают область поиска, как и дляsearch().
-
regex.finditer(string[, pos[, endpos]]) -
Аналогично функции
finditer(), использующей скомпилированный шаблон, но также принимает необязательные параметры pos и endpos, которые ограничивают область поиска, как и дляsearch().
-
regex.sub(repl, string, count=0) -
Точно такая же, как функция
sub(), использующая скомпилированный шаблон.
-
regex.subn(repl, string, count=0) -
Точно такая же, как функция
subn(), использующая скомпилированный шаблон.
-
regex.flags -
Флаги соответствия регулярных выражений. Это комбинация флагов, заданных для
compile(), любых(?...)встроенных флагов в шаблоне и неявных флагов, таких какUNICODE, если шаблон является строкой Юникод.
-
regex.groups -
Количество захватывающих групп в шаблоне.
-
regex.groupindex -
Словарь, сопоставляющий любые символические имена групп, определенные
(?P<id>), с номерами групп. Словарь пуст, если в шаблоне не использовались символические группы.
-
regex.pattern -
Строка шаблона, из которой был скомпилирован объект RE.
6.2.4. Объекты совпадений
Объекты совпадений всегда имеют булево значение 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 возвращает 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()породил этот экземпляр совпадения.
6.2.5. Примеры регулярных выражений
6.2.5.1. Проверка на пару
В этом примере мы будем использовать следующую вспомогательную функцию, чтобы отображать объекты совпадения немного более элегантно:
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» — карты с соответствующими значениями.
Чтобы проверить, является ли данная строка действительной рукой, можно сделать следующее:
def displaymatch(match):
if match is None:
return None
return '<Match: %r, groups=%r>' % (match.group(), match.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'
6.2.5.2. Эмуляция scanf()
В Python пока нет эквивалента scanf(). Регулярные выражения обычно более мощные, хотя и более громоздкие, чем строки форматирования scanf(). В таблице ниже приведены приблизительные соответствия между разделителями форматирования scanf() и регулярными выражениями.
| Регулярное выражение |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Для извлечения имени файла и чисел из строки, например
/usr/sbin/sendmail - 0 errors, 4 warnings
используйте строку форматирования scanf(), как
%s - %d errors, %d warnings
Эквивалентное регулярное выражение будет
(\S+) - (\d+) errors, (\d+) warnings
6.2.5.3. search() и match()
Python предоставляет две разные базовые операции, основанные на регулярных выражениях: re.match() проверяет соответствие только в начале строки, а re.search() проверяет соответствие в любой части строки (так делает Perl по умолчанию).
Например:
>>> re.match("c", "abcdef") # No match
>>> re.search("c", "abcdef") # Match
<_sre.SRE_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
<_sre.SRE_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
<_sre.SRE_Match object; span=(4, 5), match='X'>
6.2.5.4. Создание телефонной книги
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']]
6.2.5.5. Обработка текста
sub() заменяет каждое вхождение шаблона строкой или результатом функции. В этом примере показано использование search() с функцией для «обработки» текста или случайного изменения порядка всех символов в каждом слове предложения, за исключением первого и последнего:
>>> 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.'
6.2.5.6. Поиск всех наречий
findall() находит все вхождения шаблона, а не только первое, как search(). Например, если автор хочет найти все наречия в тексте, он может использовать findall() следующим образом:
>>> text = "He was carefully disguised but captured quickly by police." >>> re.findall(r"\w+ly", text) ['carefully', 'quickly']
6.2.5.7. Поиск всех наречий и их позиций
Если требуется больше информации о всех совпадениях шаблона, чем соответствующий текст, 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
6.2.5.8. Символьная запись
Символьная запись (r"text") поддерживает регулярные выражения. Без неё каждый обратный слэш ('\') в регулярном выражении необходимо было бы предварять ещё одним для экранирования. Например, две следующие строки кода функционально идентичны:
>>> re.match(r"\W(.)\1\W", " ff ")
<_sre.SRE_Match object; span=(0, 4), match=' ff '>
>>> re.match("\\W(.)\\1\\W", " ff ")
<_sre.SRE_Match object; span=(0, 4), match=' ff '>
Когда нужно сопоставить буквенный обратный слэш, его необходимо экранировать в регулярном выражении. С использованием символьной записи, это означает r"\\". Без символьной записи необходимо использовать "\\\\", что делает следующие строки кода функционально идентичными:
>>> re.match(r"\\", r"\\")
<_sre.SRE_Match object; span=(0, 1), match='\\'>
>>> re.match("\\\\", r"\\")
<_sre.SRE_Match object; span=(0, 1), match='\\'>
6.2.5.9. Написание токенизатора
Токенизатор (или сканер) анализирует строку, чтобы категоризировать группы символов. Это полезный первый шаг в написании компилятора или интерпретатора.
Категории текста задаются регулярными выражениями. Этот метод заключается в объединении их в единое основное регулярное выражение и итерации по последовательным совпадениям:
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.6/library/re.html