Документация Python неофициальный перевод

re.md

1513 строк · 88.2 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.4/library/re.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 6.2. [`re`](https://python-all.ru/3.4/library/re.html#module-re) – Операции с регулярными выражениями89Этот модуль предоставляет операции сопоставления с регулярными выражениями, аналогичные тем, что есть в Perl.1011И паттерны, и искомые строки могут быть как строками Unicode, так и 8-битными строками. Однако строки Unicode и 8-битные строки нельзя смешивать: нельзя сопоставить строку Unicode с байтовым паттерном или наоборот; аналогично, при запросе замены строка замены должна быть того же типа, что и паттерн, и искомая строка.1213В регулярных выражениях обратная косая черта (`'\'`) используется для обозначения специальных форм или чтобы разрешить использование специальных символов без их специального значения. Это противоречит использованию того же символа в Python для той же цели в строковых литералах; например, чтобы сопоставить буквальную обратную косую черту, возможно, придётся написать `'\\\\'` в строке шаблона, потому что регулярное выражение должно быть `\\`, а каждую обратную косую черту нужно выразить как `\\` внутри обычного строкового литерала Python.1415Решение – использовать raw-строки Python для паттернов регулярных выражений; обратная косая черта не обрабатывается особым образом в строковом литерале с префиксом `'r'`. Так что `r"\n"` – это двухсимвольная строка, содержащая `'\'` и `'n'`, в то время как `"\n"` – односимвольная строка, содержащая символ новой строки. Обычно паттерны записывают в коде Python с использованием этой raw-нотации.1617Важно отметить, что большинство операций с регулярными выражениями доступны как функции уровня модуля и методы [*скомпилированных регулярных выражений*](https://python-all.ru/3.4/library/re.html#re-objects). Функции – это ярлыки, которые не требуют предварительной компиляции объекта regex, но не имеют некоторых параметров тонкой настройки.1819## 6.2.1. Синтаксис регулярных выражений2021Регулярное выражение (или RE) задаёт набор строк, которым оно соответствует; функции в этом модуле позволяют проверить, соответствует ли конкретная строка заданному регулярному выражению (или соответствует ли заданное регулярное выражение конкретной строке – что одно и то же).2223Регулярные выражения можно объединять для получения новых регулярных выражений; если *A* и *B* – регулярные выражения, то *AB* тоже регулярное выражение. В общем, если строка *p* соответствует *A*, а другая строка *q* соответствует *B*, то строка *pq* будет соответствовать AB. Это верно, если только *A* или *B* не содержат операций с низким приоритетом, граничных условий между *A* и *B* или нумерованных обращений к группам. Таким образом, сложные выражения легко строятся из более простых примитивных выражений, подобных описанным здесь. Подробнее о теории и реализации регулярных выражений см. книгу Фридла, указанную выше, или почти любой учебник по построению компиляторов.2425Далее следует краткое объяснение формата регулярных выражений. Для получения дополнительной информации и более доступного изложения обратитесь к [*руководству по регулярным выражениям*](https://python-all.ru/3.4/howto/regex.html#regex-howto).2627Регулярные выражения могут содержать как специальные, так и обычные символы. Большинство обычных символов, например `'A'`, `'a'` или `'0'`, – это простейшие регулярные выражения: они просто соответствуют сами себе. Можно объединять обычные символы, так что `last` соответствует строке `'last'`. (В остальной части этого раздела мы будем записывать регулярные выражения `таким специальным стилем`, обычно без кавычек, а строки для поиска – `'в одинарных кавычках'`.)2829Некоторые символы, такие как `'|'` или `'('`, являются специальными. Специальные символы либо обозначают классы обычных символов, либо влияют на то, как интерпретируются окружающие их регулярные выражения. Строки паттернов регулярных выражений не могут содержать нулевые байты, но можно указать нулевой байт с помощью нотации `\number`, например `'\x00'`.3031Специальные символы:3233**`'.'`**3435(Точка.) В режиме по умолчанию соответствует любому символу, кроме перевода строки. Если указан флаг3637[`DOTALL`](https://python-all.ru/3.4/library/re.html#re.DOTALL)3839, соответствует любому символу, включая перевод строки.4041**`'^'`**4243(Циркумфлекс.) Соответствует началу строки, а в режиме4445[`MULTILINE`](https://python-all.ru/3.4/library/re.html#re.MULTILINE)4647также соответствует позиции сразу после каждого перевода строки.4849**`'$'`**5051Соответствует концу строки или позиции перед символом новой строки в конце строки, а в режиме5253[`MULTILINE`](https://python-all.ru/3.4/library/re.html#re.MULTILINE)5455также соответствует перед переводом строки.5657`foo`5859соответствует и 'foo', и 'foobar', а регулярное выражение6061`foo$`6263соответствует только 'foo'. Ещё интереснее: поиск6465`foo.$`6667в6869`'foo1\nfoo2\n'`7071обычно находит 'foo2', но в режиме7273[`MULTILINE`](https://python-all.ru/3.4/library/re.html#re.MULTILINE)7475– 'foo1'; поиск одного7677`$`7879в8081`'foo\n'`8283найдёт два (пустых) совпадения: одно перед переводом строки, и одно в конце строки.8485**`'*'`**8687Заставляет результирующее регулярное выражение соответствовать 0 или более повторениям предшествующего выражения, захватывая максимально возможное количество повторений.8889`ab*`9091будет соответствовать 'a', 'ab' или 'a', за которым следует любое количество 'b'.9293**`'+'`**9495Заставляет результирующее регулярное выражение соответствовать 1 или более повторениям предшествующего выражения.9697`ab+`9899будет соответствовать 'a', за которым следует любое ненулевое количество 'b'; одному 'a' оно не соответствует.100101**`'?'`**102103Заставляет результирующее регулярное выражение соответствовать 0 или 1 повторению предшествующего выражения.104105`ab?`106107будет соответствовать либо 'a', либо 'ab'.108109**`*?`, `+?`, `??`**110111Квантификаторы112113`'*'`114115,116117`'+'`118119и120121`'?'`122123являются124125*жадными*126127; они захватывают максимально возможный текст. Иногда такое поведение нежелательно; если регулярное выражение128129`<.*>`130131применить к строке132133`'<H1>title</H1>'`134135, оно совпадет со всей строкой, а не только с136137`'<H1>'`138139. Добавление140141`'?'`142143после квантификатора заставляет его выполнять сопоставление в144145*нежадном*146147или148149*минимальном*150151режиме; при этом будет захвачено152153*наименьшее количество*154155символов. Используя156157`.*?`158159в предыдущем выражении, мы получим соответствие только160161`'<H1>'`162163.164165**`{m}`**166167Указывает, что должно быть сопоставлено ровно168169*m*170171копий предшествующего регулярного выражения; если совпадений меньше, всё регулярное выражение не срабатывает. Например,172173`a{6}`174175будет соответствовать ровно шести символам176177`'a'`178179, но не пяти.180181**`{m,n}`**182183Заставляет результирующее регулярное выражение соответствовать от184185*m*186187до188189*n*190191повторений предшествующего выражения, пытаясь захватить максимальное количество повторений. Например,192193`a{3,5}`194195будет соответствовать от 3 до 5 символов196197`'a'`198199. Пропуск200201*m*202203задаёт нижнюю границу, равную нулю, а пропуск204205*n*206207– бесконечную верхнюю границу. Например,208209`a{4,}b`210211будет соответствовать212213`aaaab`214215или тысяче символов216217`'a'`218219, за которыми следует220221`b`222223, но не224225`aaab`226227. Запятая не может быть опущена, иначе модификатор будет спутан с ранее описанной формой.228229**`{m,n}?`**230231Заставляет результирующее регулярное выражение соответствовать от232233*m*234235до236237*n*238239повторений предшествующего выражения, пытаясь захватить как можно240241*меньше*242243повторений. Это нежадная версия предыдущего квантификатора. Например, на 6-символьной строке244245`'aaaaaa'`246247выражение248249`a{3,5}`250251совпадет с 5 символами252253`'a'`254255, тогда как256257`a{3,5}?`258259– только с 3.260261**`'\'`**262263Либо экранирует специальные символы (позволяя сопоставлять такие символы, как `'*'`, `'?'` и т.д.), либо обозначает специальную последовательность; специальные последовательности рассматриваются ниже.264265Если вы не используете сырую строку для выражения шаблона, помните, что Python также использует обратную косую черту как escape-последовательность в строковых литералах; если escape- последовательность не распознаётся парсером Python, обратная косая черта и следующий за ней символ включаются в результирующую строку. Однако если Python распознает результирующую последовательность, обратную косую черту следует удвоить. Это сложно и трудно для понимания, поэтому настоятельно рекомендуется использовать сырые строки для всех, кроме самых простых выражений.266267**`[]`**268269Используется для обозначения набора символов. В наборе:270271- Символы можно перечислять по отдельности, например `[amk]` будет соответствовать `'a'`, `'m'` или `'k'`.272- Диапазоны символов можно задавать, указывая два символа и разделяя их `'-'`, например `[a-z]` будет соответствовать любой строчной букве ASCII, `[0-5][0-9]` – всем двузначным числам от `00` до `59`, а `[0-9A-Fa-f]` – любой шестнадцатеричной цифре. Если `-` экранирован (например `[a\-z]`) или стоит первым или последним символом (например `[a-]`), он будет соответствовать литералу `'-'`.273- Специальные символы теряют своё специальное значение внутри наборов. Например, `[(+*)]` будет соответствовать любому из литеральных символов `'('`, `'+'`, `'*'` или `')'`.274- Классы символов, такие как `\w` или `\S` (определены ниже), также допускаются внутри набора, хотя символы, которым они соответствуют, зависят от того, активен ли режим [`ASCII`](https://python-all.ru/3.4/library/re.html#re.ASCII) или [`LOCALE`](https://python-all.ru/3.4/library/re.html#re.LOCALE).275- Символы, не входящие в диапазон, можно сопоставить с помощью *дополнения* набора. Если первый символ набора – `'^'`, то будут сопоставлены все символы, которые *не* входят в набор. Например, `[^5]` совпадет с любым символом, кроме `'5'`, а `[^^]` – с любым символом, кроме `'^'`. `^` не имеет специального значения, если он не первый символ в наборе.276- Чтобы найти символ `']'` внутри набора, поставьте перед ним обратную косую черту или поместите его в начало набора. Например, `[()[\]{}]` и `[]()[{}]` оба соответствуют круглой скобке.277278**`'|'`**279280`A|B`281282, где A и B могут быть произвольными регулярными выражениями, создает регулярное выражение, которое будет соответствовать либо A, либо B. Таким способом можно разделять произвольное количество регулярных выражений с помощью283284`'|'`285286. Это можно использовать и внутри групп (см. ниже). При сканировании целевой строки выражения, разделенные287288`'|'`289290, пробуются слева направо. Когда один паттерн полностью совпадает, эта ветвь принимается. Это означает, что как только291292`A`293294совпадает,295296`B`297298больше не проверяется, даже если оно дало бы более длинное совпадение. Другими словами, оператор299300`'|'`301302никогда не бывает жадным. Чтобы сопоставить литерал303304`'|'`305306, используйте307308`\|`309310или заключите его в символьный класс, например311312`[|]`313314.315316**`(...)`**317318Соответствует любому регулярному выражению внутри скобок и обозначает начало и конец группы; содержимое группы можно получить после выполнения сопоставления, а также сопоставить позже в строке с помощью специальной последовательности319320`\number`321322, описанной ниже. Чтобы сопоставить литералы323324`'('`325326или327328`')'`329330, используйте331332`\(`333334или335336`\)`337338, или заключите их в символьный класс:339340`[(] [)]`341342.343344**`(?...)`**345346Это нотация расширения (347348`'?'`349350после351352`'('`353354в противном случае не имеет смысла). Первый символ после355356`'?'`357358определяет значение и дальнейший синтаксис конструкции. Расширения обычно не создают новую группу;359360`(?P<name>...)`361362– единственное исключение из этого правила. Ниже перечислены поддерживаемые в настоящее время расширения.363364**`(?aiLmsux)`**365366(Одна или несколько букв из набора `'a'`, `'i'`, `'L'`, `'m'`, `'s'`, `'u'`, `'x'`.) Группа соответствует пустой строке; буквы устанавливают соответствующие флаги: [`re.A`](https://python-all.ru/3.4/library/re.html#re.A) (только ASCII), [`re.I`](https://python-all.ru/3.4/library/re.html#re.I) (игнорировать регистр), [`re.L`](https://python-all.ru/3.4/library/re.html#re.L) (зависит от локали), [`re.M`](https://python-all.ru/3.4/library/re.html#re.M) (многострочный), [`re.S`](https://python-all.ru/3.4/library/re.html#re.S) (точка соответствует всему) и [`re.X`](https://python-all.ru/3.4/library/re.html#re.X) (подробный) для всего регулярного выражения. (Флаги описаны в разделе [*Содержание модуля*](https://python-all.ru/3.4/library/re.html#contents-of-module-re).) Это полезно, если нужно включить флаги в состав регулярного выражения, а не передавать аргумент *flag* в функцию [`re.compile()`](https://python-all.ru/3.4/library/re.html#re.compile).367368Обратите внимание, что флаг `(?x)` изменяет способ разбора выражения. Он должен быть указан первым в строке выражения или после одного или нескольких пробельных символов. Если перед флагом есть непробельные символы, результат не определён.369370**`(?:...)`**371372Незапоминающая версия обычных круглых скобок. Совпадает с любым регулярным выражением внутри скобок, но подстрока, совпавшая с группой,373374*не может*375376быть извлечена после выполнения сопоставления или использована для ссылки позже в шаблоне.377378**`(?P<name>...)`**379380Аналогично обычным круглым скобкам, но подстрока, совпавшая с группой, доступна по символическому имени группы *name*. Имена групп должны быть допустимыми идентификаторами Python, и каждое имя группы должно быть определено только один раз в регулярном выражении. Символическая группа также является нумерованной группой, как если бы группа не была именованной.381382Именованные группы можно использовать в трёх контекстах. Если паттерн имеет вид `(?P<quote>['"]).*?(?P=quote)` (т.е. соответствует строке, заключённой в одинарные или двойные кавычки):383384| Контекст ссылки на группу «quote» | Способы ссылки на нее |385| --- | --- |386| в том же самом шаблоне | `(?P=quote)` (как показано) `\1` |387| при обработке объекта сопоставления `m` | `m.group('quote')` `m.end('quote')` (и т.д.) |388| в строке, передаваемой в аргумент `repl` функции `re.sub()` | `\g<quote>` `\g<1>` `\1` |389390**`(?P=name)`**391392Обратная ссылка на именованную группу; соответствует любому тексту, который был найден ранее группой с именем393394*name*395396.397398**`(?#...)`**399400Комментарий; содержимое скобок просто игнорируется.401402**`(?=...)`**403404Совпадает, если405406`...`407408совпадает далее, но не поглощает ни одного символа строки. Это называется опережающей проверкой. Например,409410`Isaac (?=Asimov)`411412совпадёт с413414`'Isaac '`415416только если за ним следует417418`'Asimov'`419420.421422**`(?!...)`**423424Совпадает, если425426`...`427428не совпадает далее. Это отрицательная опережающая проверка. Например,429430`Isaac (?!Asimov)`431432совпадёт с433434`'Isaac '`435436только если за ним437438*не*439440следует441442`'Asimov'`443444.445446**`(?<=...)`**447448Совпадает, если текущей позиции в строке предшествует совпадение с `...`, которое заканчивается на текущей позиции. Это называется *положительной ретроспективной проверкой*. `(?<=abc)def` найдёт совпадение в `abcdef`, так как ретроспективная проверка отступит на 3 символа и проверит, совпадает ли вложенный шаблон. Вложенный шаблон должен соответствовать строкам только фиксированной длины, то есть `abc` или `a|b` допускаются, но `a*` и `a{3,4}` – нет. Ссылки на группы не поддерживаются, даже если они соответствуют строкам фиксированной длины. Обратите внимание, что шаблоны, начинающиеся с положительной ретроспективной проверки, не будут совпадать в начале искомой строки; скорее всего, потребуется использовать функцию [`search()`](https://python-all.ru/3.4/library/re.html#re.search), а не [`match()`](https://python-all.ru/3.4/library/re.html#re.match):449450```python451>>> import re452>>> m = re.search('(?<=abc)def', 'abcdef')453>>> m.group(0)454'def'455```456457Этот пример ищет слово, следующее за дефисом:458459```python460>>> m = re.search('(?<=-)\w+', 'spam-egg')461>>> m.group(0)462'egg'463```464465**`(?<!...)`**466467Совпадает, если текущей позиции в строке не предшествует совпадение с468469`...`470471. Это называется472473*отрицательной ретроспективной проверкой*474475. Как и положительные ретроспективные проверки, вложенный шаблон должен соответствовать только строкам фиксированной длины и не должен содержать ссылок на группы. Шаблоны, начинающиеся с отрицательной ретроспективной проверки, могут совпадать в начале искомой строки.476477**`(?(id/name)yes-pattern|no-pattern)`**478479Пытается применить480481`yes-pattern`482483, если группа с указанным484485*id*486487или488489*name*490491существует, и492493`no-pattern`494495– если нет.496497`no-pattern`498499необязателен и может быть опущен. Например,500501`(<)?(\w+@\w+(?:\.\w+)+)(?(1)>|$)`502503– это неудачный шаблон для проверки email, который совпадёт с504505`'<user@host.com>'`506507, а также с508509`'user@host.com'`510511, но не с512513`'<user@host.com'`514515и не с516517`'user@host.com>'`518519.520521Специальные последовательности состоят из `'\'` и символа из списка ниже. Если обычный символ отсутствует в списке, то результирующее РВ будет соответствовать второму символу. Например, `\$` соответствует символу `'$'`.522523**`\number`**524525Совпадает с содержимым группы с тем же номером. Группы нумеруются, начиная с 1. Например,526527`(.+) \1`528529совпадает с530531`'the 'the'`532533или534535`'55 55'`536537, но не с538539`'thethe'`540541(обратите внимание на пробел после группы). Эта специальная последовательность может использоваться только для совпадения с одной из первых 99 групп. Если первая цифра542543*числа*544545равна 0, или546547*число*548549состоит из 3 восьмеричных цифр, это будет интерпретироваться не как ссылка на группу, а как символ с восьмеричным значением550551*числа*552553. Внутри554555`'['`556557и558559`']'`560561класса символов все числовые escape-последовательности рассматриваются как символы.562563**`\A`**564565Совпадает только в начале строки.566567**`\b`**568569Совпадает с пустой строкой, но только в начале или конце слова. Слово определяется как последовательность буквенно-цифровых символов Unicode или символа подчёркивания, поэтому конец слова обозначается пробелом или не буквенно-цифровым символом Unicode, не являющимся подчёркиванием. Обратите внимание, что формально `\b` определяется как граница между символом `\w` и символом `\W` (или наоборот), или между `\w` и началом/концом строки. Это означает, что `r'\bfoo\b'` совпадает с `'foo'`, `'foo.'`, `'(foo)'`, `'bar foo baz'`, но не с `'foobar'` или `'foo3'`.570571По умолчанию используются буквенно-цифровые символы Unicode, но это можно изменить с помощью флага [`ASCII`](https://python-all.ru/3.4/library/re.html#re.ASCII). Внутри диапазона символов `\b` представляет символ backspace для совместимости со строковыми литералами Python.572573**`\B`**574575Совпадает с пустой строкой, но только когда она576577*не*578579находится в начале или конце слова. Это означает, что580581`r'py\B'`582583совпадает с584585`'python'`586587,588589`'py3'`590591,592593`'py2'`594595, но не с596597`'py'`598599,600601`'py.'`602603или604605`'py!'`606607.608609`\B`610611является противоположностью612613`\b`614615, поэтому символами слова являются буквенно-цифровые символы Unicode или подчёркивание, хотя это можно изменить с помощью флага616617[`ASCII`](https://python-all.ru/3.4/library/re.html#re.ASCII)618619.620621**`\d`**622623**Для шаблонов Unicode (str):**624625Совпадает с любой десятичной цифрой Unicode (то есть любым символом из категории Unicode \[Nd\]). Сюда входит626627`[0-9]`628629, а также многие другие цифровые символы. Если используется флаг630631[`ASCII`](https://python-all.ru/3.4/library/re.html#re.ASCII)632633, совпадает только634635`[0-9]`636637(но флаг влияет на всё регулярное выражение, поэтому в таких случаях лучше использовать явное638639`[0-9]`640641).642643**Для 8-битных (байтовых) шаблонов:**644645Соответствует любой десятичной цифре; это эквивалентно646647`[0-9]`648649.650651**`\D`**652653Совпадает с любым символом, не являющимся десятичной цифрой Unicode. Это противоположность654655`\d`656657. Если используется флаг658659[`ASCII`](https://python-all.ru/3.4/library/re.html#re.ASCII)660661, это становится эквивалентом662663`[^0-9]`664665(но флаг влияет на всё регулярное выражение, поэтому в таких случаях лучше использовать явное666667`[^0-9]`668669).670671**`\s`**672673**Для шаблонов Unicode (str):**674675Совпадает с пробельными символами Unicode (к которым относятся676677`[ \t\n\r\f\v]`678679, а также многие другие символы, например неразрывные пробелы, требуемые правилами типографики во многих языках). Если используется флаг680681[`ASCII`](https://python-all.ru/3.4/library/re.html#re.ASCII)682683, совпадает только684685`[ \t\n\r\f\v]`686687(но флаг влияет на всё регулярное выражение, поэтому в таких случаях лучше использовать явное688689`[ \t\n\r\f\v]`690691).692693**Для 8-битных (байтовых) шаблонов:**694695Совпадает с символами, считающимися пробельными в наборе символов ASCII; это эквивалентно696697`[ \t\n\r\f\v]`698699.700701**`\S`**702703Совпадает с любым символом, не являющимся пробельным символом Unicode. Это противоположность704705`\s`706707. Если используется флаг708709[`ASCII`](https://python-all.ru/3.4/library/re.html#re.ASCII)710711, это становится эквивалентом712713`[^ \t\n\r\f\v]`714715(но флаг влияет на всё регулярное выражение, поэтому в таких случаях лучше использовать явное716717`[^ \t\n\r\f\v]`718719).720721**`\w`**722723**Для шаблонов Unicode (str):**724725Совпадает с символами слова Unicode; сюда входят большинство символов, которые могут быть частью слова в любом языке, а также цифры и символ подчёркивания. Если используется флаг726727[`ASCII`](https://python-all.ru/3.4/library/re.html#re.ASCII)728729, совпадает только730731`[a-zA-Z0-9_]`732733(но флаг влияет на всё регулярное выражение, поэтому в таких случаях лучше использовать явное734735`[a-zA-Z0-9_]`736737).738739**Для 8-битных (байтовых) шаблонов:**740741Совпадает с символами, считающимися буквенно-цифровыми в наборе символов ASCII; это эквивалентно742743`[a-zA-Z0-9_]`744745.746747**`\W`**748749Соответствует любому символу, который не является символом слова Unicode. Это противоположность750751`\w`752753. Если используется флаг754755[`ASCII`](https://python-all.ru/3.4/library/re.html#re.ASCII)756757, это становится эквивалентом758759`[^a-zA-Z0-9_]`760761(но флаг влияет на всё регулярное выражение, поэтому в таких случаях использование явного762763`[^a-zA-Z0-9_]`764765может быть лучшим выбором).766767**`\Z`**768769Совпадение только в конце строки.770771Большинство стандартных управляющих последовательностей, поддерживаемых строковыми литералами Python, также принимаются синтаксическим анализатором регулярных выражений:772773```python774\a      \b      \f      \n775\r      \t      \u      \U776\v      \x      \\777```778779(Обратите внимание, что `\b` используется для обозначения границ слов и означает “backspace” только внутри символьных классов.)780781Управляющие последовательности `'\u'` и `'\U'` распознаются только в шаблонах Unicode. В байтовых шаблонах они не обрабатываются особым образом.782783Восьмеричные управляющие последовательности поддерживаются в ограниченной форме. Если первая цифра – 0, или если есть три восьмеричных цифры, это считается восьмеричной управляющей последовательностью. В противном случае это ссылка на группу. Как и в строковых литералах, восьмеричные управляющие последовательности всегда имеют длину не более трёх цифр.784785Изменено в версии 3.3: Добавлены управляющие последовательности `'\u'` и `'\U'`.786787> **См. также**788>789> **Mastering Regular Expressions**790>791> Книга по регулярным выражениям Джеффри Фридла, издательство O’Reilly. Второе издание книги вообще не охватывает Python, но первое издание очень подробно описывает написание хороших шаблонов регулярных выражений.792793## 6.2.2. Содержимое модуля794795Модуль определяет несколько функций, констант и одно исключение. Некоторые из функций являются упрощёнными версиями полнофункциональных методов для скомпилированных регулярных выражений. В большинстве нетривиальных приложений всегда используется скомпилированная форма.796797#### `re.compile(pattern, flags=0)`798799Компилирует шаблон регулярного выражения в объект регулярного выражения, который можно использовать для поиска совпадений с помощью его методов [`match()`](https://python-all.ru/3.4/library/re.html#re.regex.match) и [`search()`](https://python-all.ru/3.4/library/re.html#re.regex.search), описанных ниже.800801Поведение выражения можно изменить, указав значение *flags*. В качестве значений можно использовать любые из следующих переменных, комбинируя их с помощью побитового ИЛИ (оператор `|`).802803Последовательность804805```python806prog = re.compile(pattern)807result = prog.match(string)808```809810эквивалентна811812```python813result = re.match(pattern, string)814```815816но использование [`re.compile()`](https://python-all.ru/3.4/library/re.html#re.compile) и сохранение полученного объекта регулярного выражения для повторного использования более эффективно, когда выражение будет использоваться несколько раз в одной программе.817818> **Примечание**819>820> Скомпилированные версии последних шаблонов, переданных в [`re.compile()`](https://python-all.ru/3.4/library/re.html#re.compile) и функции сопоставления на уровне модуля, кэшируются, поэтому программы, которые используют лишь несколько регулярных выражений одновременно, не нужно беспокоиться о компиляции регулярных выражений.821822#### `re.A`823824#### `re.ASCII`825826Заставляет `\w`, `\W`, `\b`, `\B`, `\d`, `\D`, `\s` и `\S` выполнять сопоставление только из ASCII вместо полного сопоставления Unicode. Это имеет смысл только для шаблонов Unicode и игнорируется для байтовых шаблонов.827828Обратите внимание, что для обратной совместимости флаг `re.U` всё ещё существует (как и его синоним `re.UNICODE` и его встроенный аналог `(?u)`), но они избыточны в Python 3, так как сопоставление по умолчанию для строк выполняется с Unicode (а сопоставление Unicode не допускается для байтов).829830#### `re.DEBUG`831832Отображает отладочную информацию о скомпилированном выражении.833834#### `re.I`835836#### `re.IGNORECASE`837838Выполняет сопоставление без учёта регистра; выражения вроде `[A-Z]` будут соответствовать также и строчным буквам. На это не влияет текущая локаль, и оно работает с символами Unicode так, как и ожидается.839840#### `re.L`841842#### `re.LOCALE`843844Заставляет `\w`, `\W`, `\b`, `\B`, `\s` и `\S` зависеть от текущей локали. Использование этого флага не рекомендуется, так как механизм локали очень ненадёжен и в любом случае обрабатывает только одну «культуру» за раз; вместо этого следует использовать сопоставление Unicode, которое является стандартным в Python 3 для шаблонов Unicode (str).845846#### `re.M`847848#### `re.MULTILINE`849850При указании этого флага символ шаблона `'^'` совпадает с началом строки и с началом каждой строки (сразу после каждого перевода строки); а символ шаблона `'$'` совпадает с концом строки и с концом каждой строки (непосредственно перед каждым переводом строки). По умолчанию `'^'` совпадает только с началом строки, а `'$'` – только с концом строки и непосредственно перед переводом строки (если он есть) в конце строки.851852#### `re.S`853854#### `re.DOTALL`855856Заставляет специальный символ `'.'` совпадать с любым символом, включая перевод строки; без этого флага `'.'` будет совпадать с любым символом, *кроме* перевода строки.857858#### `re.X`859860#### `re.VERBOSE`861862Этот флаг позволяет писать регулярные выражения, которые выглядят аккуратнее и читаются проще: можно визуально разделять логические части шаблона и добавлять комментарии. Пробелы в шаблоне игнорируются, за исключением тех, что находятся внутри символьного класса или перед которыми стоит неэкранированный обратный слеш. Если строка содержит `#`, не находящийся в символьном классе и не предварённый неэкранированным обратным слешем, все символы от крайнего левого такого `#` до конца строки игнорируются.863864Это означает, что следующие два объекта регулярных выражений, которые сопоставляют десятичное число, функционально эквивалентны:865866```python867a = re.compile(r"""\d +  # the integral part868                   \.    # the decimal point869                   \d *  # some fractional digits""", re.X)870b = re.compile(r"\d+\.\d*")871```872873#### `re.search(pattern, string, flags=0)`874875Просматривает *string* в поисках первой позиции, где регулярное выражение *pattern* даёт совпадение, и возвращает соответствующий [*объект совпадения*](https://python-all.ru/3.4/library/re.html#match-objects). Возвращает `None`, если ни одна позиция в строке не соответствует шаблону; обратите внимание, что это отличается от поиска совпадения нулевой длины в какой-либо точке строки.876877#### `re.match(pattern, string, flags=0)`878879Если ноль или более символов в начале *string* соответствуют регулярному выражению *pattern*, возвращает соответствующий [*объект совпадения*](https://python-all.ru/3.4/library/re.html#match-objects). Возвращает `None`, если строка не соответствует шаблону; обратите внимание, что это отличается от совпадения нулевой длины.880881Обратите внимание, что даже в режиме [`MULTILINE`](https://python-all.ru/3.4/library/re.html#re.MULTILINE) функция [`re.match()`](https://python-all.ru/3.4/library/re.html#re.match) находит совпадение только в начале строки, а не в начале каждой строки.882883Если нужно найти совпадение в любом месте *string*, используйте [`search()`](https://python-all.ru/3.4/library/re.html#re.search) (см. также [*search() vs. match()*](https://python-all.ru/3.4/library/re.html#search-vs-match)).884885#### `re.fullmatch(pattern, string, flags=0)`886887Если вся *string* соответствует регулярному выражению *pattern*, возвращается соответствующий [*объект совпадения*](https://python-all.ru/3.4/library/re.html#match-objects). Возвращается `None`, если строка не соответствует шаблону; обратите внимание, что это отличается от совпадения нулевой длины.888889Новое в версии 3.4.890891#### `re.split(pattern, string, maxsplit=0, flags=0)`892893Разделяет *string* по вхождениям *pattern*. Если в *pattern* используются захватывающие круглые скобки, то текст всех групп в шаблоне также возвращается как часть результирующего списка. Если *maxsplit* не равно нулю, то происходит не более *maxsplit* разбиений, а остаток строки возвращается как последний элемент списка.894895```python896>>> re.split('\W+', 'Words, words, words.')897['Words', 'words', 'words', '']898>>> re.split('(\W+)', 'Words, words, words.')899['Words', ', ', 'words', ', ', 'words', '.', '']900>>> re.split('\W+', 'Words, words, words.', 1)901['Words', 'words, words.']902>>> re.split('[a-f]+', '0a3B9', flags=re.IGNORECASE)903['0', '3', '9']904```905906Если в разделителе есть захватывающие группы и он совпадает в начале строки, результат будет начинаться с пустой строки. То же самое относится и к концу строки:907908```python909>>> re.split('(\W+)', '...words, words...')910['', '...', 'words', ', ', 'words', '...', '']911```912913Таким образом, компоненты разделителя всегда находятся на одних и тех же относительных индексах в результирующем списке.914915Обратите внимание, что *split* никогда не разделяет строку по пустому совпадению шаблона. Например:916917```python918>>> re.split('x*', 'foo')919['foo']920>>> re.split("(?m)^$", "foo\n\nbar\n")921['foo\n\nbar\n']922```923924Изменено в версии 3.1: Добавлен необязательный аргумент flags.925926#### `re.findall(pattern, string, flags=0)`927928Возвращает все непересекающиеся совпадения *pattern* в *string*, в виде списка строк. Строка *string* сканируется слева направо, совпадения возвращаются в порядке обнаружения. Если в шаблоне присутствуют одна или несколько групп, возвращается список групп; если групп больше одной – список кортежей. Пустые совпадения включаются в результат, кроме случаев, когда они примыкают к началу другого совпадения.929930#### `re.finditer(pattern, string, flags=0)`931932Возвращает [*итератор*](https://python-all.ru/3.4/glossary.html#term-iterator), выдающий [*объекты совпадений*](https://python-all.ru/3.4/library/re.html#match-objects) по всем непересекающимся совпадениям регулярного выражения *pattern* в *string*. Строка *string* сканируется слева направо, совпадения возвращаются в порядке обнаружения. Пустые совпадения включаются в результат, кроме случаев, когда они примыкают к началу другого совпадения.933934#### `re.sub(pattern, repl, string, count=0, flags=0)`935936Возвращает строку, полученную заменой крайних левых непересекающихся вхождений *pattern* в *string* на замену *repl*. Если шаблон не найден, возвращается *string* без изменений. *repl* может быть строкой или функцией; если это строка, все обратные слеши в ней обрабатываются. То есть `\n` преобразуется в символ новой строки, `\r` – в возврат каретки и так далее. Неизвестные escape-последовательности, такие как `\j`, остаются без изменений. Обратные ссылки, такие как `\6`, заменяются подстрокой, соответствующей группе 6 в шаблоне. Например:937938```python939>>> re.sub(r'def\s+([a-zA-Z_][a-zA-Z_0-9]*)\s*\(\s*\):',940...        r'static PyObject*\npy_\1(void)\n{',941...        'def myfunc():')942'static PyObject*\npy_myfunc(void)\n{'943```944945Если *repl* – функция, она вызывается для каждого непересекающегося вхождения *pattern*. Функция принимает один аргумент – объект совпадения – и возвращает строку замены. Например:946947```python948>>> def dashrepl(matchobj):949...     if matchobj.group(0) == '-': return ' '950...     else: return '-'951>>> re.sub('-{1,2}', dashrepl, 'pro----gram-files')952'pro--gram files'953>>> re.sub(r'\sAND\s', ' & ', 'Baked Beans And Spam', flags=re.IGNORECASE)954'Baked Beans & Spam'955```956957Шаблон может быть строкой или объектом RE.958959Необязательный аргумент *count* – это максимальное количество заменяемых вхождений шаблона; *count* должен быть неотрицательным целым числом. Если опущено или равно нулю, заменяются все вхождения. Пустые совпадения шаблона заменяются только тогда, когда они не примыкают к предыдущему совпадению, поэтому `sub('x*', '-', 'abc')` возвращает `'-a-b-c-'`.960961В строковых аргументах *repl*, помимо escape-последовательностей символов и обратных ссылок, описанных выше, `\g<name>` использует подстроку, соответствующую группе с именем `name`, как определено синтаксисом `(?P<name>...)`. `\g<number>` использует соответствующий номер группы; `\g<2>` поэтому эквивалентно `\2`, но не является неоднозначным в замене такой как `\g<2>0`. `\20` было бы интерпретировано как ссылка на группу 20, а не как ссылка на группу 2, за которой следует литеральный символ `'0'`. Обратная ссылка `\g<0>` заменяет всей подстрокой, соответствующей регулярному выражению.962963Изменено в версии 3.1: Добавлен необязательный аргумент flags.964965#### `re.subn(pattern, repl, string, count=0, flags=0)`966967Выполняет ту же операцию, что и [`sub()`](https://python-all.ru/3.4/library/re.html#re.sub), но возвращает кортеж `(new_string, number_of_subs_made)`.968969Изменено в версии 3.1: Добавлен необязательный аргумент flags.970971#### `re.escape(string)`972973Экранирует все символы в шаблоне, кроме букв ASCII, цифр и `'_'`. Это полезно, если нужно сопоставить произвольную литеральную строку, которая может содержать метасимволы регулярных выражений.974975Изменено в версии 3.3: Символ `'_'` больше не экранируется.976977#### `re.purge()`978979Очищает кэш регулярных выражений.980981#### `exception re.error`982983Исключение возникает, когда строка, переданная одной из функций здесь, не является допустимым регулярным выражением (например, может содержать непарные скобки) или когда происходит другая ошибка во время компиляции или сопоставления. Это никогда не является ошибкой, если строка не содержит совпадений с шаблоном.984985## 6.2.3. Объекты регулярных выражений986987Скомпилированные объекты регулярных выражений поддерживают следующие методы и атрибуты:988989#### `regex.search(string[, pos[, endpos]])`990991Просматривает *string* в поиске позиции, где это регулярное выражение даёт совпадение, и возвращает соответствующий [*объект совпадения*](https://python-all.ru/3.4/library/re.html#match-objects). Возвращает `None`, если ни одна позиция в строке не соответствует шаблону; обратите внимание, что это отличается от нахождения совпадения нулевой длины в какой-то точке строки.992993Необязательный второй параметр *pos* задаёт индекс в строке, с которого начинается поиск; по умолчанию `0`. Это не полностью эквивалентно срезу строки; символ шаблона `'^'` сопоставляется с реальным началом строки и с позициями сразу после символа новой строки, но не обязательно с индексом, с которого должен начинаться поиск.994995Необязательный параметр *endpos* ограничивает, насколько далеко будет просматриваться строка; это будет так, как если бы строка имела длину *endpos* символов, поэтому для поиска совпадения будут просматриваться только символы от *pos* до `endpos - 1`. Если *endpos* меньше *pos*, совпадение не будет найдено; в противном случае, если *rx* – скомпилированный объект регулярного выражения, `rx.search(string, 0, 50)` эквивалентно `rx.search(string[:50], 0)`.996997```python998>>> pattern = re.compile("d")999>>> pattern.search("dog")     # Совпадение на индексе 01000<_sre.SRE_Match object; span=(0, 1), match='d'>1001>>> pattern.search("dog", 1)  # Совпадения нет; поиск не включает "d"1002```10031004#### `regex.match(string[, pos[, endpos]])`10051006Если ноль или более символов в *начале* *string* соответствуют этому регулярному выражению, возвращается соответствующий [*объект совпадения*](https://python-all.ru/3.4/library/re.html#match-objects). Возвращается `None`, если строка не соответствует шаблону; обратите внимание, что это отличается от совпадения нулевой длины.10071008Необязательные параметры *pos* и *endpos* имеют тот же смысл, что и для метода [`search()`](https://python-all.ru/3.4/library/re.html#re.regex.search).10091010```python1011>>> pattern = re.compile("o")1012>>> pattern.match("dog")      # Совпадения нет, так как "o" не в начале строки "dog".1013>>> pattern.match("dog", 1)   # Совпадение есть, так как "o" – второй символ строки "dog".1014<_sre.SRE_Match object; span=(1, 2), match='o'>1015```10161017Чтобы найти совпадение в любом месте *string*, используйте [`search()`](https://python-all.ru/3.4/library/re.html#re.regex.search) (см. также [*search() vs. match()*](https://python-all.ru/3.4/library/re.html#search-vs-match)).10181019#### `regex.fullmatch(string[, pos[, endpos]])`10201021Если вся *string* соответствует этому регулярному выражению, возвращается соответствующий [*объект совпадения*](https://python-all.ru/3.4/library/re.html#match-objects). Возвращается `None`, если строка не соответствует шаблону; обратите внимание, что это отличается от совпадения нулевой длины.10221023Необязательные параметры *pos* и *endpos* имеют тот же смысл, что и для метода [`search()`](https://python-all.ru/3.4/library/re.html#re.regex.search).10241025```python1026>>> pattern = re.compile("o[gh]")1027>>> pattern.fullmatch("dog")      # Совпадения нет, так как "o" не в начале строки "dog".1028>>> pattern.fullmatch("ogre")     # Совпадения нет, так как не вся строка совпала.1029>>> pattern.fullmatch("doggie", 1, 3)   # Совпадения в заданных пределах.1030<_sre.SRE_Match object; span=(1, 3), match='og'>1031```10321033Новое в версии 3.4.10341035#### `regex.split(string, maxsplit=0)`10361037Идентично функции [`split()`](https://python-all.ru/3.4/library/re.html#re.split), используя скомпилированный шаблон.10381039#### `regex.findall(string[, pos[, endpos]])`10401041Аналогично функции [`findall()`](https://python-all.ru/3.4/library/re.html#re.findall), использующей скомпилированный шаблон, но также принимает необязательные параметры *pos* и *endpos*, ограничивающие область поиска, как в [`match()`](https://python-all.ru/3.4/library/re.html#re.match).10421043#### `regex.finditer(string[, pos[, endpos]])`10441045Аналогично функции [`finditer()`](https://python-all.ru/3.4/library/re.html#re.finditer), использующей скомпилированный шаблон, но также принимает необязательные параметры *pos* и *endpos*, ограничивающие область поиска, как в [`match()`](https://python-all.ru/3.4/library/re.html#re.match).10461047#### `regex.sub(repl, string, count=0)`10481049Идентична функции [`sub()`](https://python-all.ru/3.4/library/re.html#re.sub), использующей скомпилированный шаблон.10501051#### `regex.subn(repl, string, count=0)`10521053Идентична функции [`subn()`](https://python-all.ru/3.4/library/re.html#re.subn), использующей скомпилированный шаблон.10541055#### `regex.flags`10561057Флаги сопоставления регулярного выражения. Это комбинация флагов, переданных в [`compile()`](https://python-all.ru/3.4/library/re.html#re.compile), любых `(?...)` встроенных флагов в шаблоне и неявных флагов, таких как `UNICODE`, если шаблон является строкой Unicode.10581059#### `regex.groups`10601061Количество захватываемых групп в шаблоне.10621063#### `regex.groupindex`10641065Словарь, сопоставляющий любые символьные имена групп, определённые с помощью `(?P<id>)`, с номерами групп. Словарь пуст, если в шаблоне не использовались символьные группы.10661067#### `regex.pattern`10681069Строка шаблона, из которой был скомпилирован объект RE.10701071## 6.2.4. Объекты совпадений10721073Объекты совпадения всегда имеют логическое значение `True`. Поскольку [`match()`](https://python-all.ru/3.4/library/re.html#re.regex.match) и [`search()`](https://python-all.ru/3.4/library/re.html#re.regex.search) возвращают `None`, когда совпадения нет, можно проверить наличие совпадения с помощью простого оператора `if`:10741075```python1076match = re.search(pattern, string)1077if match:1078    process(match)1079```10801081Объекты сопоставления поддерживают следующие методы и атрибуты:10821083#### `match.expand(template)`10841085Возвращает строку, полученную в результате замены обратной косой черты в шаблоне строки *template*, как это делает метод [`sub()`](https://python-all.ru/3.4/library/re.html#re.regex.sub). Экранированные последовательности, такие как `\n`, преобразуются в соответствующие символы, а числовые обратные ссылки (`\1`, `\2`) и именованные обратные ссылки (`\g<1>`, `\g<name>`) заменяются содержимым соответствующей группы.10861087#### `match.group([group1, ...])`10881089Возвращает одну или несколько подгрупп совпадения. Если аргумент один, результатом является одна строка; если аргументов несколько, результат – кортеж с одним элементом на каждый аргумент. Без аргументов *group1* по умолчанию равен нулю (возвращается всё совпадение). Если аргумент *groupN* равен нулю, соответствующее возвращаемое значение – вся сопоставленная строка; если он находится в диапазоне \[1..99\] включительно, это строка, соответствующая соответствующей группе в скобках. Если номер группы отрицателен или больше количества групп, определённых в шаблоне, возбуждается исключение [`IndexError`](https://python-all.ru/3.4/library/exceptions.html#IndexError). Если группа содержится в части шаблона, которая не совпала, соответствующий результат равен `None`. Если группа содержится в части шаблона, которая совпала несколько раз, возвращается последнее совпадение.10901091```python1092>>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")1093>>> m.group(0)       # Всё совпадение1094'Isaac Newton'1095>>> m.group(1)       # Первая группа в скобках.1096'Isaac'1097>>> m.group(2)       # Вторая группа в скобках.1098'Newton'1099>>> m.group(1, 2)    # Несколько аргументов дают кортеж.1100('Isaac', 'Newton')1101```11021103Если в регулярном выражении используется синтаксис `(?P<name>...)`, то аргументы *groupN* могут также быть строками, идентифицирующими группы по их имени. Если строковый аргумент не используется как имя группы в шаблоне, возбуждается исключение [`IndexError`](https://python-all.ru/3.4/library/exceptions.html#IndexError).11041105Довольно сложный пример:11061107```python1108>>> m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds")1109>>> m.group('first_name')1110'Malcolm'1111>>> m.group('last_name')1112'Reynolds'1113```11141115Именованные группы также можно указывать по их индексу:11161117```python1118>>> m.group(1)1119'Malcolm'1120>>> m.group(2)1121'Reynolds'1122```11231124Если группа совпадает несколько раз, доступно только последнее совпадение:11251126```python1127>>> m = re.match(r"(..)+", "a1b2c3")  # Совпадает 3 раза.1128>>> m.group(1)                        # Возвращает только последнее совпадение.1129'c3'1130```11311132#### `match.groups(default=None)`11331134Возвращает кортеж, содержащий все подгруппы совпадения, от 1 до количества групп в шаблоне. Аргумент *default* используется для групп, которые не участвовали в совпадении; по умолчанию он равен `None`.11351136Например:11371138```python1139>>> m = re.match(r"(\d+)\.(\d+)", "24.1632")1140>>> m.groups()1141('24', '1632')1142```11431144Если сделать десятичную точку и всё после неё необязательными, не все группы могут участвовать в совпадении. Эти группы по умолчанию будут равны `None`, если не указан аргумент *default*:11451146```python1147>>> m = re.match(r"(\d+)\.?(\d+)?", "24")1148>>> m.groups()      # Вторая группа по умолчанию – None.1149('24', None)1150>>> m.groups('0')   # Теперь вторая группа по умолчанию – '0'.1151('24', '0')1152```11531154#### `match.groupdict(default=None)`11551156Возвращает словарь, содержащий все *именованные* подгруппы совпадения, где ключом является имя подгруппы. Аргумент *default* используется для групп, которые не участвовали в совпадении; по умолчанию он равен `None`. Например:11571158```python1159>>> m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds")1160>>> m.groupdict()1161{'first_name': 'Malcolm', 'last_name': 'Reynolds'}1162```11631164#### `match.start([group])`11651166#### `match.end([group])`11671168Возвращает индексы начала и конца подстроки, сопоставленной с *group*; *group* по умолчанию равен нулю (означает всю сопоставленную подстроку). Возвращает `-1`, если *group* существует, но не участвовал в совпадении. Для объекта совпадения *m* и группы *g*, которая участвовала в совпадении, подстрока, сопоставленная группой *g* (эквивалент `m.group(g)`), – это11691170```python1171m.string[m.start(g):m.end(g)]1172```11731174Обратите внимание, что `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`](https://python-all.ru/3.4/library/exceptions.html#IndexError).11751176Пример, который удалит *remove\_this* из адресов электронной почты:11771178```python1179>>> email = "tony@tiremove_thisger.net"1180>>> m = re.search("remove_this", email)1181>>> email[:m.start()] + email[m.end():]1182'tony@tiger.net'1183```11841185#### `match.span([group])`11861187Для совпадения *m* возвращает кортеж из двух элементов `(m.start(group), m.end(group))`. Обратите внимание, что если *group* не участвовал в совпадении, результатом будет `(-1, -1)`. *group* по умолчанию равен нулю, то есть всё совпадение.11881189#### `match.pos`11901191The value of *pos* which was passed to the [`search()`](https://python-all.ru/3.4/library/re.html#re.regex.search) or [`match()`](https://python-all.ru/3.4/library/re.html#re.regex.match) method of a [*regex object*](https://python-all.ru/3.4/library/re.html#re-objects). This is the index into the string at which the RE engine started looking for a match.11921193#### `match.endpos`11941195Значение *endpos*, переданное методу [`search()`](https://python-all.ru/3.4/library/re.html#re.regex.search) или [`match()`](https://python-all.ru/3.4/library/re.html#re.regex.match) объекта [*регулярного выражения*](https://python-all.ru/3.4/library/re.html#re-objects). Это индекс в строке, за который движок регулярных выражений не выходит.11961197#### `match.lastindex`11981199Целочисленный индекс последней совпавшей захватывающей группы или `None`, если ни одна группа не совпала. Например, выражения `(a)b`, `((a)(b))` и `((ab))` будут иметь `lastindex == 1`, если применить к строке `'ab'`, а выражение `(a)(b)` будет иметь `lastindex == 2`, если применить к той же строке.12001201#### `match.lastgroup`12021203Имя последней совпавшей захватывающей группы или `None`, если у группы не было имени или если ни одна группа не совпала.12041205#### `match.re`12061207Объект регулярного выражения, метод [`match()`](https://python-all.ru/3.4/library/re.html#re.regex.match) или [`search()`](https://python-all.ru/3.4/library/re.html#re.regex.search) которого создал этот экземпляр совпадения.12081209#### `match.string`12101211Строка, переданная методу [`match()`](https://python-all.ru/3.4/library/re.html#re.regex.match) или [`search()`](https://python-all.ru/3.4/library/re.html#re.regex.search).12121213## 6.2.5. Примеры регулярных выражений12141215### 6.2.5.1. Проверка на пару12161217В этом примере используется следующая вспомогательная функция для более наглядного отображения объектов совпадения:12181219```python1220def displaymatch(match):1221    if match is None:1222        return None1223    return '<Match: %r, groups=%r>' % (match.group(), match.groups())1224```12251226Допустим, пишется программа для покера, где рука игрока представлена в виде строки из 5 символов, каждый символ обозначает карту: «a» – туз, «k» – король, «q» – дама, «j» – валет, «t» – десятка, а «2»–«9» – карты соответствующего достоинства.12271228Чтобы проверить, является ли заданная строка допустимой рукой, можно поступить следующим образом:12291230```python1231>>> valid = re.compile(r"^[a2-9tjqk]{5}$")1232>>> displaymatch(valid.match("akt5q"))  # Допустимо.1233"<Match: 'akt5q', groups=()>"1234>>> displaymatch(valid.match("akt5e"))  # Недопустимо.1235>>> displaymatch(valid.match("akt"))    # Недопустимо.1236>>> displaymatch(valid.match("727ak"))  # Допустимо.1237"<Match: '727ak', groups=()>"1238```12391240Та последняя рука, `"727ak"`, содержала пару, то есть две карты одного достоинства. Чтобы сопоставить это с помощью регулярного выражения, можно использовать обратные ссылки следующим образом:12411242```python1243>>> pair = re.compile(r".*(.).*\1")1244>>> displaymatch(pair.match("717ak"))     # Пара семёрок.1245"<Match: '717', groups=('7',)>"1246>>> displaymatch(pair.match("718ak"))     # Нет пар.1247>>> displaymatch(pair.match("354aa"))     # Пара тузов.1248"<Match: '354aa', groups=('a',)>"1249```12501251Чтобы узнать, из какой карты состоит пара, можно использовать метод [`group()`](https://python-all.ru/3.4/library/re.html#re.match.group) объекта совпадения следующим образом:12521253```python1254>>> pair.match("717ak").group(1)1255'7'12561257# Error because re.match() returns None, which doesn't have a group() method:1258>>> pair.match("718ak").group(1)1259Traceback (most recent call last):1260  File "<pyshell#23>", line 1, in <module>1261    re.match(r".*(.).*\1", "718ak").group(1)1262AttributeError: 'NoneType' object has no attribute 'group'12631264>>> pair.match("354aa").group(1)1265'a'1266```12671268### 6.2.5.2. Имитация scanf()12691270В Python пока нет аналога `scanf()`. Регулярные выражения в целом мощнее, хотя и более многословны, чем строки форматирования `scanf()`. В таблице ниже приведены более или менее эквивалентные соответствия между токенами формата `scanf()` и регулярными выражениями.12711272| `scanf()` Токен | Регулярное выражение |1273| --- | --- |1274| `%c` | `.` |1275| `%5c` | `.{5}` |1276| `%d` | `[-+]?\d+` |1277| `%e`, `%E`, `%f`, `%g` | `[-+]?(\d+(\.\d*)?\|\.\d+)([eE][-+]?\d+)?` |1278| `%i` | `[-+]?(0[xX][\dA-Fa-f]+\|0[0-7]*\|\d+)` |1279| `%o` | `[-+]?[0-7]+` |1280| `%s` | `\S+` |1281| `%u` | `\d+` |1282| `%x`, `%X` | `[-+]?(0[xX])?[\dA-Fa-f]+` |12831284Чтобы извлечь имя файла и числа из строки вида12851286```python1287/usr/sbin/sendmail - 0 errors, 4 warnings1288```12891290Можно использовать формат `scanf()`, например12911292```python1293%s - %d errors, %d warnings1294```12951296Эквивалентное регулярное выражение будет12971298```python1299(\S+) - (\d+) errors, (\d+) warnings1300```13011302### 6.2.5.3. Сравнение search() и match()13031304Python предлагает две разные базовые операции на основе регулярных выражений: [`re.match()`](https://python-all.ru/3.4/library/re.html#re.match) проверяет совпадение только в начале строки, а [`re.search()`](https://python-all.ru/3.4/library/re.html#re.search) проверяет совпадение в любом месте строки (именно так по умолчанию работает Perl).13051306Например:13071308```python1309>>> re.match("c", "abcdef")  # Нет совпадения.1310>>> re.search("c", "abcdef") # Совпадает.1311<_sre.SRE_Match object; span=(2, 3), match='c'>1312```13131314Регулярные выражения, начинающиеся с `'^'`, можно использовать с [`search()`](https://python-all.ru/3.4/library/re.html#re.search), чтобы ограничить совпадение началом строки:13151316```python1317>>> re.match("c", "abcdef")  # Нет совпадения.1318>>> re.search("^c", "abcdef") # Нет совпадения.1319>>> re.search("^a", "abcdef")  # Совпадает.1320<_sre.SRE_Match object; span=(0, 1), match='a'>1321```13221323Однако обратите внимание, что в режиме [`MULTILINE`](https://python-all.ru/3.4/library/re.html#re.MULTILINE) [`match()`](https://python-all.ru/3.4/library/re.html#re.match) совпадает только в начале строки, тогда как [`search()`](https://python-all.ru/3.4/library/re.html#re.search) с регулярным выражением, начинающимся с `'^'`, будет находить совпадение в начале каждой строки.13241325```python1326>>> re.match('X', 'A\nB\nX', re.MULTILINE)  # Нет совпадения.1327>>> re.search('^X', 'A\nB\nX', re.MULTILINE)  # Совпадает.1328<_sre.SRE_Match object; span=(4, 5), match='X'>1329```13301331### 6.2.5.4. Создание телефонной книги13321333[`split()`](https://python-all.ru/3.4/library/re.html#re.split) разбивает строку на список, используя переданный шаблон в качестве разделителя. Этот метод незаменим для преобразования текстовых данных в структуры данных, которые Python может легко читать и изменять, как показано в следующем примере, создающем телефонный справочник.13341335Сначала – входные данные. Обычно они берутся из файла, здесь мы используем синтаксис тройных кавычек:13361337```python1338>>> text = """Ross McFluff: 834.345.1254 155 Elm Street1339...1340... Ronald Heathmore: 892.345.3428 436 Finley Avenue1341... Frank Burger: 925.541.7625 662 South Dogwood Way1342...1343...1344... Heather Albrecht: 548.326.4584 919 Park Place"""1345```13461347Записи разделяются одним или несколькими символами новой строки. Теперь преобразуем строку в список, где каждая непустая строка будет отдельной записью:13481349```python1350>>> entries = re.split("\n+", text)1351>>> entries1352['Ross McFluff: 834.345.1254 155 Elm Street',1353'Ronald Heathmore: 892.345.3428 436 Finley Avenue',1354'Frank Burger: 925.541.7625 662 South Dogwood Way',1355'Heather Albrecht: 548.326.4584 919 Park Place']1356```13571358Наконец, каждая запись разбивается на список, содержащий имя, фамилию, номер телефона и адрес. Используется параметр `maxsplit` функции [`split()`](https://python-all.ru/3.4/library/re.html#re.split), потому что адрес содержит пробелы – наш разделитель:13591360```python1361>>> [re.split(":? ", entry, 3) for entry in entries]1362[['Ross', 'McFluff', '834.345.1254', '155 Elm Street'],1363['Ronald', 'Heathmore', '892.345.3428', '436 Finley Avenue'],1364['Frank', 'Burger', '925.541.7625', '662 South Dogwood Way'],1365['Heather', 'Albrecht', '548.326.4584', '919 Park Place']]1366```13671368Шаблон `:?` соответствует двоеточию после фамилии, поэтому оно не попадает в результирующий список. С помощью `maxsplit`, равного `4`, можно отделить номер дома от названия улицы:13691370```python1371>>> [re.split(":? ", entry, 4) for entry in entries]1372[['Ross', 'McFluff', '834.345.1254', '155', 'Elm Street'],1373['Ronald', 'Heathmore', '892.345.3428', '436', 'Finley Avenue'],1374['Frank', 'Burger', '925.541.7625', '662', 'South Dogwood Way'],1375['Heather', 'Albrecht', '548.326.4584', '919', 'Park Place']]1376```13771378### 6.2.5.5. Обработка текста13791380[`sub()`](https://python-all.ru/3.4/library/re.html#re.sub) заменяет каждое вхождение шаблона на строку или результат функции. В этом примере показано использование [`sub()`](https://python-all.ru/3.4/library/re.html#re.sub) с функцией для «изменения» (munge) текста, то есть перемешивания порядка всех символов в каждом слове предложения, кроме первого и последнего:13811382```python1383>>> def repl(m):1384...   inner_word = list(m.group(2))1385...   random.shuffle(inner_word)1386...   return m.group(1) + "".join(inner_word) + m.group(3)1387>>> text = "Professor Abdolmalek, please report your absences promptly."1388>>> re.sub(r"(\w)(\w+)(\w)", repl, text)1389'Poefsrosr Aealmlobdk, pslaee reorpt your abnseces plmrptoy.'1390>>> re.sub(r"(\w)(\w+)(\w)", repl, text)1391'Pofsroser Aodlambelk, plasee reoprt yuor asnebces potlmrpy.'1392```13931394### 6.2.5.6. Поиск всех наречий13951396[`findall()`](https://python-all.ru/3.4/library/re.html#re.findall) находит *все* вхождения шаблона, а не только первое, как [`search()`](https://python-all.ru/3.4/library/re.html#re.search). Например, если бы писателю потребовалось найти все наречия в тексте, он или она могли бы использовать [`findall()`](https://python-all.ru/3.4/library/re.html#re.findall) следующим образом:13971398```python1399>>> text = "He was carefully disguised but captured quickly by police."1400>>> re.findall(r"\w+ly", text)1401['carefully', 'quickly']1402```14031404### 6.2.5.7. Поиск всех наречий и их позиций14051406Если нужна более полная информация о всех совпадениях шаблона, чем просто текст совпадения, полезна функция [`finditer()`](https://python-all.ru/3.4/library/re.html#re.finditer), поскольку она возвращает [*объекты совпадений*](https://python-all.ru/3.4/library/re.html#match-objects), а не строки. Продолжая предыдущий пример: если бы писателю потребовалось найти все наречия *и их положения* в тексте, он или она мог бы использовать [`finditer()`](https://python-all.ru/3.4/library/re.html#re.finditer) следующим образом:14071408```python1409>>> text = "He was carefully disguised but captured quickly by police."1410>>> for m in re.finditer(r"\w+ly", text):1411...     print('%02d-%02d: %s' % (m.start(), m.end(), m.group(0)))141207-16: carefully141340-47: quickly1414```14151416### 6.2.5.8. Сырые строки14171418Сырые строки (`r"text"`) делают регулярные выражения читаемыми. Без них каждый обратный слеш (`'\'`) в регулярном выражении пришлось бы экранировать дополнительным слешем. Например, следующие две строки кода функционально идентичны:14191420```python1421>>> re.match(r"\W(.)\1\W", " ff ")1422<_sre.SRE_Match object; span=(0, 4), match=' ff '>1423>>> re.match("\\W(.)\\1\\W", " ff ")1424<_sre.SRE_Match object; span=(0, 4), match=' ff '>1425```14261427Если требуется сопоставить литеральный обратный слеш, его необходимо экранировать в регулярном выражении. В сырых строках это означает `r"\\"`. Без сырых строк придётся использовать `"\\\\"`, поэтому следующие строки кода функционально идентичны:14281429```python1430>>> re.match(r"\\", r"\\")1431<_sre.SRE_Match object; span=(0, 1), match='\\'>1432>>> re.match("\\\\", r"\\")1433<_sre.SRE_Match object; span=(0, 1), match='\\'>1434```14351436### 6.2.5.9. Написание токенизатора14371438[Токенизатор или сканер](https://python-all.ru/3.4/library/re.html) анализирует строку, чтобы разделить символы на группы. Это полезный первый шаг при написании компилятора или интерпретатора.14391440Категории текста задаются с помощью регулярных выражений. Метод заключается в том, чтобы объединить их в одно главное регулярное выражение и перебирать последовательные совпадения:14411442```python1443import collections1444import re14451446Token = collections.namedtuple('Token', ['typ', 'value', 'line', 'column'])14471448def tokenize(code):1449    keywords = {'IF', 'THEN', 'ENDIF', 'FOR', 'NEXT', 'GOSUB', 'RETURN'}1450    token_specification = [1451        ('NUMBER',  r'\d+(\.\d*)?'), # Целое или десятичное число.1452        ('ASSIGN',  r':='),          # Оператор присваивания.1453        ('END',     r';'),           # Терминатор инструкции.1454        ('ID',      r'[A-Za-z]+'),   # Идентификаторы.1455        ('OP',      r'[+\-*/]'),     # Арифметические операторы.1456        ('NEWLINE', r'\n'),          # Концы строк.1457        ('SKIP',    r'[ \t]+'),      # Пропускать пробелы и табуляции.1458        ('MISMATCH',r'.'),           # Любой другой символ.1459    ]1460    tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification)1461    line_num = 11462    line_start = 01463    for mo in re.finditer(tok_regex, code):1464        kind = mo.lastgroup1465        value = mo.group(kind)1466        if kind == 'NEWLINE':1467            line_start = mo.end()1468            line_num += 11469        elif kind == 'SKIP':1470            pass1471        elif kind == 'MISMATCH':1472            raise RuntimeError('%r unexpected on line %d' % (value, line_num))1473        else:1474            if kind == 'ID' and value in keywords:1475                kind = value1476            column = mo.start() - line_start1477            yield Token(kind, value, line_num, column)14781479statements = '''1480    IF quantity THEN1481        total := total + price * quantity;1482        tax := price * 0.05;1483    ENDIF;1484'''14851486for token in tokenize(statements):1487    print(token)1488```14891490Токенизатор выдаёт следующий результат:14911492```python1493Token(typ='IF', value='IF', line=2, column=4)1494Token(typ='ID', value='quantity', line=2, column=7)1495Token(typ='THEN', value='THEN', line=2, column=16)1496Token(typ='ID', value='total', line=3, column=8)1497Token(typ='ASSIGN', value=':=', line=3, column=14)1498Token(typ='ID', value='total', line=3, column=17)1499Token(typ='OP', value='+', line=3, column=23)1500Token(typ='ID', value='price', line=3, column=25)1501Token(typ='OP', value='*', line=3, column=31)1502Token(typ='ID', value='quantity', line=3, column=33)1503Token(typ='END', value=';', line=3, column=41)1504Token(typ='ID', value='tax', line=4, column=8)1505Token(typ='ASSIGN', value=':=', line=4, column=12)1506Token(typ='ID', value='price', line=4, column=15)1507Token(typ='OP', value='*', line=4, column=21)1508Token(typ='NUMBER', value='0.05', line=4, column=23)1509Token(typ='END', value=';', line=4, column=27)1510Token(typ='ENDIF', value='ENDIF', line=5, column=4)1511Token(typ='END', value=';', line=5, column=9)1512```1513