re
— Операции с регулярными выражениями¶
Исходный код: Lib/re/
Этот модуль предоставляет операции сопоставления регулярных выражений, аналогичные тем, которые можно найти в Perl.
Как шаблоны, так и строки для поиска могут быть строками в Юникоде (str
), а также 8-разрядными строками (bytes
). Однако строки в Юникоде и 8-разрядные строки нельзя смешивать: то есть вы не можете сопоставить строку в Юникоде с шаблоном в байтах или наоборот; аналогично, при запросе замены строка замены должна быть того же типа, что и шаблон, и строка поиска.
Регулярные выражения используют символ обратной косой черты ('\'
) для обозначения специальных форм или для того, чтобы разрешить использование специальных символов без указания их специального значения. Это противоречит использованию Python одного и того же символа для одной и той же цели в строковых литералах; например, чтобы соответствовать обратной косой черте литерала, возможно, придется написать '\\\\'
в качестве строки шаблона, поскольку регулярное выражение должно быть \\
, и каждый обратная косая черта должна быть выражена как \\
внутри обычного строкового литерала Python. Также, пожалуйста, обратите внимание, что любые недопустимые escape-последовательности при использовании обратной косой черты в строковых литералах в Python теперь генерируют DeprecationWarning
, а в будущем это станет SyntaxError
. Такое поведение будет происходить, даже если это допустимая escape-последовательность для регулярного выражения.
Решение состоит в том, чтобы использовать необработанную строковую нотацию Python для шаблонов регулярных выражений; обратные косые черты не обрабатываются каким-либо особым образом в строковом литерале с префиксом 'r'
. Таким образом, r"\n"
- это двухсимвольная строка, содержащая '\'
и 'n'
, в то время как "\n"
- это односимвольная строка, содержащая новую строку. Обычно шаблоны будут выражены в коде Python с использованием этой необработанной строковой нотации.
Важно отметить, что большинство операций с регулярными выражениями доступны в виде функций и методов на уровне модуля в compiled regular expressions. Функции - это ярлыки, которые не требуют предварительной компиляции объекта regex, но не позволяют настроить некоторые параметры тонкой настройки.
См.также
Сторонний модуль regex, который имеет API, совместимый с модулем стандартной библиотеки re
, но предлагает дополнительную функциональность и более полную поддержку Unicode.
Синтаксис регулярных выражений¶
Регулярное выражение (или RE) определяет набор строк, который ему соответствует; функции в этом модуле позволяют вам проверить, соответствует ли конкретная строка заданному регулярному выражению (или если данное регулярное выражение соответствует определенной строке, что в конечном итоге одно и то же).
Регулярные выражения могут быть объединены для формирования новых регулярных выражений; если A и B оба являются регулярными выражениями, то AB также является регулярным выражением. В общем случае, если строка p соответствует A, а другая строка q соответствует B, строка pq будет соответствовать AB. Это справедливо, если только A или B не содержат операций с низким приоритетом, граничных условий между A и B или не содержат нумерованных ссылок на группы. Таким образом, сложные выражения могут быть легко построены из более простых примитивных выражений, подобных описанным здесь. Для получения подробной информации о теории и реализации регулярных выражений обратитесь к удобной книге [Frie09] или практически к любому учебнику по построению компилятора.
Ниже приводится краткое объяснение формата регулярных выражений. Для получения дополнительной информации и более удобного представления обратитесь к Руководство по использованию регулярных выражений.
Регулярные выражения могут содержать как специальные, так и обычные символы. Большинство обычных символов, таких как 'A'
, 'a'
, или '0'
, являются простейшими регулярными выражениями; они просто совпадают сами с собой. Вы можете объединять обычные символы, чтобы last
соответствовал строке 'last'
. (В оставшейся части этого раздела мы будем писать RE в this special style
, обычно без кавычек, и строки, которые необходимо сопоставить 'in single quotes'
.)
Некоторые символы, такие как '|'
или '('
, являются специальными. Специальные символы либо обозначают классы обычных символов, либо влияют на интерпретацию связанных с ними регулярных выражений.
Операторы повторения или кванторы (*
, +
, ?
, {m,n}
, и т.д.) Не могут быть вложены напрямую. Это позволяет избежать двусмысленности с суффиксом-модификатором ?
и с другими модификаторами в других реализациях. Чтобы применить второе повторение к внутреннему повторению, можно использовать круглые скобки. Например, выражение (?:a{6})*
соответствует любому символу, кратному шести 'a'
.
Специальными символами являются:
.
(Точка.) В режиме по умолчанию это значение соответствует любому символу, кроме новой строки. Если указан флаг
DOTALL
, оно соответствует любому символу, включая новую строку.
^
(Каретка.) Соответствует началу строки, а в режиме
MULTILINE
также совпадает сразу после каждой новой строки.
$
Совпадает с концом строки или непосредственно перед новой строкой в конце строки, а в режиме
MULTILINE
также совпадает перед новой строкой.foo
соответствует как „foo“, так и „foobar“, в то время как регулярное выражениеfoo$
соответствует только „foo“. Что еще более интересно, поискfoo.$
в'foo1\nfoo2\n'
обычно соответствует „foo2“, но „foo1“ в режимеMULTILINE
; поиск единственного$
в'foo\n'
приведет к найдите два (пустых) совпадения: одно непосредственно перед новой строкой и одно в конце строки.
*
Приводит к тому, что результирующий RE соответствует 0 или более повторениям предыдущего RE, столько повторений, сколько возможно.
ab*
будет соответствовать буквам «a», «ab» или «a», за которыми следует любое количество букв «b».
+
Приводит к тому, что результирующий RE соответствует 1 или более повторениям предыдущего RE.
ab+
будет соответствовать «a», за которым следует любое ненулевое число «b»; оно не будет соответствовать только «a».
?
Приводит к тому, что результирующий RE соответствует 0 или 1 повторению предыдущего RE.
ab?
будет соответствовать либо «a», либо «ab».
*?
,+?
,??
Все кванторы
'*'
,'+'
, и'?'
равны greedy; они соответствуют максимально возможному объему текста. Иногда такое поведение нежелательно; если RE<.*>
сопоставляется с'<a> b <c>'
, то он будет соответствовать всей строке, а не только'<a>'
. Добавление?
после квантора позволяет выполнить сопоставление в виде non-greedy или minimal; будет сопоставлено как можно меньше символов. Использование здесь<.*?>
будет соответствовать только'<a>'
.
*+
,++
,?+
Как и кванторы
'*'
,'+'
, и'?'
, те, к которым добавляется'+'
, также совпадают как можно больше раз. Однако, в отличие от истинно жадных кванторов, они не позволяют выполнить обратный поиск, если следующее за ними выражение не соответствует. Они известны как possessive кванторы. Например,a*a
будет соответствовать'aaaa'
, потому чтоa*
будет соответствовать всем 4'a'
s, но когда встречается последний'a'
, выражение имеет вид выполняется обратный поиск, так что в итогеa*
оказывается равным сумме из 3'a'
, а четвертому'a'
соответствует итоговое'a'
. Однако, когдаa*+a
используется для сопоставления с'aaaa'
,a*+
будет соответствовать всем 4'a'
, но когда в последнем'a'
не удается найти больше символов для совпадать, выражение не может быть восстановлено и, следовательно, не будет соответствовать.x*+
,x++
иx?+
эквивалентны(?>x*)
,(?>x+)
и(?>x?)
соответственно.Добавлено в версии 3.11.
{m}
Указывает, что должно совпадать ровно m копий предыдущего RE; меньшее количество совпадений приведет к несоответствию всего RE. Например,
a{6}
будет соответствовать ровно шести'a'
символам, но не пяти.{m,n}
Приводит к тому, что результирующий RE соответствует от m до n повторений предыдущего RE, пытаясь сопоставить как можно больше повторений. Например,
a{3,5}
будет соответствовать от 3 до 5'a'
символов. Пропуск m указывает на нижнюю границу, равную нулю, а пропуск n указывает на бесконечную верхнюю границу. Например,a{4,}b
будет соответствовать'aaaab'
или тысяче'a'
символов, за которыми следует'b'
, но не'aaab'
. Запятую нельзя опускать, иначе модификатор можно было бы спутать с ранее описанной формой.{m,n}?
Приводит к тому, что результирующий RE соответствует от m до * n* повторений предыдущего RE, пытаясь сопоставить как можно меньшее количество повторений. Это не жадная версия предыдущего квантификатора. Например, в 6-символьной строке
'aaaaaa'
,a{3,5}
будет соответствовать 5'a'
символам, в то время какa{3,5}?
будет соответствовать только 3 символам.{m,n}+
Приводит к тому, что результирующий RE соответствует от m до * n* повторений предыдущего RE, пытаясь сопоставить как можно больше повторений, не устанавливая никаких точек возврата. Это притяжательная версия приведенного выше квантора. Например, в 6-символьной строке
'aaaaaa'
,a{3,5}+aa
попытайтесь сопоставить 5'a'
символов, тогда потребуется еще 2'a'
s, потребуется больше символов, чем доступно, и, таким образом завершится неудачей, в то время какa{3,5}aa
будет совпадать сa{3,5}
, захватив 5, затем 4'a'
s путем обратного отслеживания, а затем последние 2'a'
s будут сопоставлены с окончательнымиaa
в шаблоне.x{m,n}+
эквивалентно(?>x{m,n})
.Добавлено в версии 3.11.
\
Либо экранирует специальные символы (позволяя вам сопоставлять символы типа
'*'
,'?'
, и т.д.), либо указывает на специальную последовательность; специальные последовательности обсуждаются ниже.Если вы не используете необработанную строку для выражения шаблона, помните, что Python также использует обратную косую черту в качестве управляющей последовательности в строковых литералах; если управляющая последовательность не распознается синтаксическим анализатором Python, обратная косая черта и последующий символ включаются в результирующую строку. Однако, если Python распознает результирующую последовательность, обратная косая черта должна быть повторена дважды. Это сложно и труднодоступно для понимания, поэтому настоятельно рекомендуется использовать необработанные строки для всех выражений, кроме самых простых.
[]
Используется для обозначения набора символов. В наборе:
Символы могут быть указаны отдельно, например,
[amk]
будет соответствовать'a'
,'m'
, или'k'
.
Диапазоны символов можно указать, введя два символа и разделив их символом
'-'
, например,[a-z]
будет соответствовать любой строчному алфавиту ASCII,[0-5][0-9]
будет соответствовать всем двузначным числам из00
к59
, а[0-9A-Fa-f]
будет соответствовать любой шестнадцатеричной цифре. Если-
экранирован (например,[a\-z]
) или если он помещен в качестве первого или последнего символа (например,[-a]
или[a-]
), он будет соответствовать литералу'-'
.Специальные символы теряют свое особое значение внутри наборов. Например,
[(+*)]
будет соответствовать любому из буквенных символов'('
,'+'
,'*'
, или')'
.
Классы символов, такие как
\w
или\S
(определение приведено ниже), также принимаются внутри набора, хотя символы, которым они соответствуют, зависят от используемых флагов.
Символы, которые не входят в диапазон, могут быть сопоставлены с помощью complementing набора. Если первым символом набора является
'^'
, все символы, которые не входят в набор, будут сопоставлены. Например,[^5]
будет соответствовать любому символу, кроме'5'
, а[^^]
будет соответствовать любому символу, кроме'^'
.^
не имеет особого значения, если это не первый символ в наборе.Чтобы сопоставить литерал
']'
внутри набора, поставьте перед ним обратную косую черту или поместите его в начало набора. Например, как[()[\]{}]
, так и[]()[{}]
будут соответствовать правой скобке, а также левой скобке, фигурным скобкам и круглым скобкам в скобках.
В будущем может быть добавлена поддержка вложенных наборов и операций с заданиями, как в Unicode Technical Standard #18. Это изменит синтаксис, поэтому для облегчения этого изменения в неоднозначных случаях на данный момент будет использоваться
FutureWarning
. Это включает в себя наборы, начинающиеся с литерала'['
или содержащие литеральные последовательности символов'--'
,'&&'
,'~~'
, и'||'
. Чтобы избежать появления предупреждения, закройте их обратной косой чертой.
Изменено в версии 3.7:
FutureWarning
вызывается, если набор символов содержит конструкции, которые будут семантически изменены в будущем.
|
A|B
, где A и B могут быть произвольными значениями, создает регулярное выражение, которое будет соответствовать либо A, либо B. Таким образом, произвольное количество значений может быть разделено символом'|'
. Это также можно использовать внутри групп (см. ниже). При сканировании целевой строки слева направо пробуются строки, разделенные'|'
. Когда один шаблон полностью совпадает, эта ветвь принимается. Это означает, что как только A совпадет, B не будет проверяться в дальнейшем, даже если это приведет к более длительному общему совпадению. Другими словами, оператор'|'
никогда не бывает жадным. Чтобы сопоставить литерал'|'
, используйте\|
или заключите его в символьный класс, как в[|]
.
(...)
Соответствует любому регулярному выражению, заключенному в круглые скобки, и указывает начало и конец группы; содержимое группы может быть извлечено после выполнения сопоставления и может быть сопоставлено позже в строке с помощью специальной последовательности
\number
, описанной ниже. Чтобы сопоставить литералы'('
или')'
, используйте\(
или\)
или заключите их в символьный класс:[(]
,[)]
.
(?...)
Это обозначение расширения (
'?'
, следующее за'('
, в противном случае не имеет смысла). Первый символ после'?'
определяет значение и дальнейший синтаксис конструкции. Расширения обычно не создают новую группу;(?P<name>...)
является единственным исключением из этого правила. Ниже приведены поддерживаемые в настоящее время расширения.(?aiLmsux)
(Одна или несколько букв из набора
'a'
,'i'
,'L'
,'m'
,'s'
,'u'
,'x'
.) Группа соответствует пустой строке; буквы устанавливают соответствующие флаги для всего регулярного выражения:re.A
(соответствие только ASCII)re.I
(регистр игнорируется)re.L
(зависит от языкового стандарта)re.M
(многострочный)re.S
(точка совпадает со всеми)re.U
(соответствие Юникоду)re.X
(подробный)
(Флаги описаны в разделе Содержимое модуля.) Это полезно, если вы хотите включить флаги как часть регулярного выражения вместо передачи аргумента flag функции
re.compile()
. Флаги должны использоваться первыми в строке выражения.Изменено в версии 3.11: Эта конструкция может быть использована только в начале выражения.
(?:...)
Версия обычных круглых скобок, не содержащая перехвата. Соответствует любому регулярному выражению, заключенному в круглые скобки, но подстрока, соответствующая группе *, не может быть извлечена после выполнения сопоставления или ссылки на нее позже в шаблоне.
(?aiLmsux-imsx:...)
(Ноль или более букв из набора
'a'
,'i'
,'L'
,'m'
,'s'
,'u'
,'x'
, за которыми необязательно следует'-'
, за которыми следует одна или более букв из набора'i'
,'m'
,'s'
,'x'
.) Буквы устанавливают или снимают соответствующие флажки для данной части выражения:re.A
(соответствие только ASCII)re.I
(регистр игнорируется)re.L
(зависит от языкового стандарта)re.M
(многострочный)re.S
(точка совпадает со всеми)re.U
(соответствие Юникоду)re.X
(подробный)
(Флаги описаны в разделе Содержимое модуля.)
Буквы
'a'
,'L'
и'u'
являются взаимоисключающими при использовании в качестве встроенных флагов, поэтому их нельзя комбинировать или использовать после'-'
. Вместо этого, когда один из них появляется во встроенной группе, он переопределяет режим сопоставления во вложенной группе. В шаблонах Юникода(?a:...)
переключается на соответствие только ASCII, а(?u:...)
- на соответствие Юникоду (по умолчанию). В шаблонах bytes(?L:...)
переключается на сопоставление, зависящее от языка, а(?a:...)
переключается на сопоставление только в формате ASCII (по умолчанию). Это переопределение действует только для узкой встроенной группы, и исходный режим сопоставления восстанавливается за пределами группы.Добавлено в версии 3.6.
Изменено в версии 3.7: Буквы
'a'
,'L'
и'u'
также могут быть использованы в группе.(?>...)
Пытается сопоставить
...
, как если бы это было отдельное регулярное выражение, и в случае успеха продолжает сопоставлять остальную часть следующего за ним шаблона. Если последующий шаблон не соответствует, стек может быть развернут только до точки * перед*(?>...)
, потому что после завершения выражение, известное как atomic group, отбрасывает все точки стека внутри себя. Таким образом,(?>.*).
никогда не будет соответствовать чему-либо, потому что сначала.*
будет соответствовать всем возможным символам, затем, когда не останется ничего, чему можно было бы соответствовать, последний.
не будет соответствовать. Поскольку в атомной группе не сохранены точки стека и перед ней нет точки стека, все выражение, таким образом, не будет соответствовать друг другу.Добавлено в версии 3.11.
(?P<name>...)
Аналогично обычным скобкам, но подстрока, соответствующая группе, доступна через символическое имя группы name. Имена групп должны быть действительными идентификаторами Python, и каждое имя группы должно быть определено только один раз в регулярном выражении. Символическая группа также является пронумерованной, как если бы у нее не было имени.
На именованные группы можно ссылаться в трех контекстах. Если шаблон равен
(?P<quote>['"]).*?(?P=quote)
(т.е. соответствует строке, заключенной в одинарные или двойные кавычки).:Контекст ссылки на группу «цитата»
Способы ссылки на него
в том же самом шаблоне
(?P=quote)
(как показано на рисунке)\1
при обработке объекта сопоставления m
m.group('quote')
m.end('quote')
(и т.д.)
в строке, передаваемой в аргумент repl типа
re.sub()
\g<quote>
\g<1>
\1
Не рекомендуется, начиная с версии 3.11: Сгруппируйте имя, содержащее символы вне диапазона ASCII (
b'\x00'
-b'\x7f'
) в шаблонахbytes
.
(?P=name)
Обратная ссылка на именованную группу; она соответствует любому тексту, который был сопоставлен более ранней группе с именем name.
(?#...)
Комментарий; содержимое круглых скобок просто игнорируется.
(?=...)
Совпадает, если
...
соответствует следующей, но не использует ни одной строки. Это называется lookahead assertion. Например,Isaac (?=Asimov)
будет соответствовать'Isaac '
только в том случае, если за ним следует'Asimov'
.
(?!...)
Совпадает, если
...
не соответствует следующему. Это negative lookahead assertion. Например,Isaac (?!Asimov)
будет соответствовать'Isaac '
только в том случае, если за ним не следует'Asimov'
.
(?<=...)
Совпадает, если текущей позиции в строке предшествует значение
...
, которое заканчивается в текущей позиции. Это называется a positive lookbehind assertion.(?<=abc)def
будет найдено совпадение в'abcdef'
, поскольку поисковая система создаст резервную копию 3 символов и проверит, совпадает ли содержащийся в них шаблон. Содержащийся в нем шаблон должен соответствовать только строкам некоторой фиксированной длины, что означает, чтоabc
илиa|b
допустимы, ноa*
иa{3,4}
- нет. Обратите внимание, что шаблоны, которые начинаются с положительных утверждений lookbehind, не будут совпадать в начале искомой строки; скорее всего, вы захотите использовать функциюsearch()
, а не функциюmatch()
:>>> import re >>> m = re.search('(?<=abc)def', 'abcdef') >>> m.group(0) 'def'
В этом примере выполняется поиск слова, следующего за дефисом:
>>> m = re.search(r'(?<=-)\w+', 'spam-egg') >>> m.group(0) 'egg'
Изменено в версии 3.5: Добавлена поддержка групповых ссылок фиксированной длины.
(?<!...)
Совпадает, если текущей позиции в строке не предшествует значение
...
. Это называется negative lookbehind assertion. Аналогично утверждениям о положительном просмотре, содержащийся шаблон должен соответствовать только строкам некоторой фиксированной длины. Шаблоны, которые начинаются с отрицательных утверждений lookbehind, могут совпадать в начале искомой строки.
(?(id/name)yes-pattern|no-pattern)
Будет предпринята попытка сопоставления с
yes-pattern
, если группа с заданным идентификатором или именем существует, и сno-pattern
, если ее нет.no-pattern
является необязательным и может быть опущен. Например,(<)?(\w+@\w+(?:\.\w+)+)(?(1)>|$)
- это плохой шаблон для сопоставления электронной почты, который будет совпадать с'<user@host.com>'
, а также с'user@host.com'
, но не с'<user@host.com'
и не с'user@host.com>'
.Не рекомендуется, начиная с версии 3.11: Идентификатор группы*, содержащий все, что угодно, кроме цифр ASCII. Название группы*, содержащее символы, не входящие в диапазон ASCII (
b'\x00'
-b'\x7f'
) в заменяющих строкахbytes
.
Специальные последовательности состоят из '\'
и символа из списка ниже. Если обычный символ не является цифрой ASCII или буквой ASCII, то результирующий RE будет соответствовать второму символу. Например, \$
соответствует символу '$'
.
\number
Совпадает с содержимым группы с таким же номером. Группы нумеруются, начиная с 1. Например,
(.+) \1
соответствует'the the'
или'55 55'
, но не'thethe'
(обратите внимание на пробел после группы). Эта специальная последовательность может использоваться только для сопоставления с одной из первых 99 групп. Если первая цифра в number равна 0 или number состоит из 3 восьмеричных цифр, это будет интерпретироваться не как совпадение группы, а как символ с восьмеричным значением number. Внутри'['
и']'
символьного класса все числовые экранирующие элементы обрабатываются как символы.
\A
Совпадает только в начале строки.
\b
Совпадает с пустой строкой, но только в начале или конце слова. Слово определяется как последовательность символов word. Обратите внимание, что формально
\b
определяется как граница между\w
и\W
символами (или наоборот), или между\w
и началом или концом строки. Это означает, чтоr'\bat\b'
соответствует'at'
,'at.'
,'(at)'
, и'as at ay'
, но не'attempt'
или'atlas'
.Символами слов по умолчанию в шаблонах Unicode (str) являются буквенно-цифровые символы Unicode и символ подчеркивания, но это можно изменить, используя флаг
ASCII
. Границы слов определяются текущим языковым стандартом, если используется флагLOCALE
.Примечание
Внутри диапазона символов
\b
обозначает символ обратного пробела для совместимости со строковыми литералами Python.
\B
Соответствует пустой строке, но только в том случае, если она не находится в начале или конце слова. Это означает, что
r'at\B'
соответствует'athens'
,'atom'
,'attorney'
,, но не'at'
,'at.'
, или'at!'
.\B
является противоположностью\b
, поэтому символы word в шаблонах Unicode (str) являются буквенно-цифровыми символами Unicode или символом подчеркивания, хотя это можно изменить, используя флагASCII
. Границы слов определяются текущим языковым стандартом, если используется флагLOCALE
.
\d
- Для шаблонов Unicode (str):
Соответствует любой десятичной цифре Юникода (то есть любому символу в категории символов Юникода) [Nd]). Сюда входит
[0-9]
, а также многие другие цифровые символы.Соответствует
[0-9]
, если используется флагASCII
.- Для 8-битных (байтовых) шаблонов:
Соответствует любой десятичной цифре в наборе символов ASCII; это эквивалентно
[0-9]
.
\D
Соответствует любому символу, который не является десятичной цифрой. Это противоположно
\d
.Соответствует
[^0-9]
, если используется флагASCII
.
\s
- Для шаблонов Unicode (str):
Соответствует пробельным символам Юникода (которые включают в себя
[ \t\n\r\f\v]
, а также многие другие символы, например неразрывные пробелы, предусмотренные правилами типографики во многих языках).Соответствует
[ \t\n\r\f\v]
, если используется флагASCII
.- Для 8-битных (байтовых) шаблонов:
Соответствует символам, которые считаются пробелами в наборе символов ASCII; это эквивалентно
[ \t\n\r\f\v]
.
\S
Соответствует любому символу, который не является пробельным. Это противоположно
\s
.Соответствует
[^ \t\n\r\f\v]
, если используется флагASCII
.
\w
- Для шаблонов Unicode (str):
Соответствует символам слов в кодировке Unicode; сюда входят все буквенно-цифровые символы в кодировке Unicode (как определено в
str.isalnum()
), а также символ подчеркивания (_
).Соответствует
[a-zA-Z0-9_]
, если используется флагASCII
.- Для 8-битных (байтовых) шаблонов:
Соответствует символам, которые считаются буквенно-цифровыми в наборе символов ASCII; это эквивалентно
[a-zA-Z0-9_]
. Если используется флагLOCALE
, соответствует символам, которые считаются буквенно-цифровыми в текущем языковом стандарте, и символу подчеркивания.
\W
Соответствует любому символу, который не является символом слова. Это противоположно
\w
. По умолчанию соответствует символам без подчеркивания (_
), для которыхstr.isalnum()
возвращаетFalse
.Соответствует
[^a-zA-Z0-9_]
, если используется флагASCII
.Если используется флаг
LOCALE
, то он соответствует символам, которые в текущей локали не являются ни буквенно-цифровыми, ни символом подчеркивания.
\Z
Совпадает только в конце строки.
Большинство стандартных экранирующих функций, поддерживаемых строковыми литералами Python, также принимаются анализатором регулярных выражений:
\a \b \f \n
\N \r \t \u
\U \v \x \\
(Обратите внимание, что \b
используется для обозначения границ слов и означает «обратное пространство» только внутри классов символов.)
'\u'
, '\U'
, и '\N'
управляющие последовательности распознаются только в шаблонах Unicode (str). В шаблонах bytes они являются ошибками. Неизвестные управляющие последовательности букв ASCII зарезервированы для дальнейшего использования и рассматриваются как ошибки.
Восьмеричные переходы используются в ограниченном количестве. Если первая цифра равна 0 или если в ней три восьмеричные цифры, это считается восьмеричным переходом. В противном случае это ссылка на группу. Что касается строковых литералов, восьмеричные значения всегда имеют длину не более трех цифр.
Изменено в версии 3.3: Добавлены управляющие последовательности '\u'
и '\U'
.
Изменено в версии 3.6: Неизвестные значения, состоящие из '\'
и буквы ASCII, теперь являются ошибками.
Изменено в версии 3.8: Добавлена управляющая последовательность '\N{name}'
. Как и в строковых литералах, она расширяется до именованного символа Юникода (например, '\N{EM DASH}'
).
Содержимое модуля¶
Модуль определяет несколько функций, констант и исключение. Некоторые из функций являются упрощенными версиями полнофункциональных методов для скомпилированных регулярных выражений. Большинство нетривиальных приложений всегда используют скомпилированную форму.
Флаги¶
Изменено в версии 3.6: Константы флага теперь являются экземплярами RegexFlag
, который является подклассом enum.IntFlag
.
- class re.RegexFlag¶
Класс
enum.IntFlag
, содержащий параметры регулярных выражений, перечисленные ниже.Добавлено в версии 3.11: - added to
__all__
- re.A¶
- re.ASCII¶
Сделайте так, чтобы
\w
,\W
,\b
,\B
,\d
,\D
,\s
и\S
выполняли сопоставление только с ASCII вместо полного сопоставления с Unicode. Это имеет смысл только для шаблонов Unicode (str) и игнорируется для шаблонов bytes.Соответствует встроенному флагу
(?a)
.
- re.DEBUG¶
Отображать отладочную информацию о скомпилированном выражении.
Нет соответствующего встроенного флага.
- re.I¶
- re.IGNORECASE¶
Выполняйте сопоставление без учета регистра; выражения типа
[A-Z]
также будут соответствовать строчным буквам. Полное соответствие Юникоду (например,Ü
соответствиеü
) также работает, если только не используется флагASCII
для отключения совпадений, отличных от ASCII. Текущая локаль не изменяет действие этого флага, если только также не используется флагLOCALE
.Соответствует встроенному флагу
(?i)
.Обратите внимание, что когда шаблоны Юникода
[a-z]
или[A-Z]
используются в сочетании с флагомIGNORECASE
, они будут соответствовать 52 буквам ASCII и 4 дополнительным буквам, отличным от ASCII: „I“ (U+0130, латиница заглавная буква I с точкой над ней), «и» (U+0131, латинская строчная буква i без точки), «ſ» (U+017F, латинская строчная буква s) и «К» (U+212A, знак Кельвина). Если используется флагASCII
, совпадают только буквы от «a» до «z» и от «A» до «Z».
- re.L¶
- re.LOCALE¶
Установите соответствие
\w
,\W
,\b
,\B
и без учета регистра в зависимости от текущего языкового стандарта. Этот флаг можно использовать только с шаблонами байтов.Соответствует встроенному флагу
(?L)
.Предупреждение
Этот флажок не рекомендуется использовать; вместо этого рассмотрите возможность сопоставления с Юникодом. Механизм языковых стандартов очень ненадежен, поскольку он одновременно обрабатывает только одну «культуру» и работает только с 8-разрядными языками. Сопоставление с Юникодом включено по умолчанию для шаблонов Unicode (str) и позволяет обрабатывать различные локали и языки.
Изменено в версии 3.7: Скомпилированные объекты регулярных выражений с флагом
LOCALE
больше не зависят от языкового стандарта во время компиляции. Только языковой стандарт во время сопоставления влияет на результат сопоставления.
- re.M¶
- re.MULTILINE¶
Если указано, то символ шаблона
'^'
совпадает в начале строки и в начале каждой строки (непосредственно после каждой новой строки); а символ шаблона'$'
совпадает в конце строки и в конце каждой строки (непосредственно перед каждой новой строкой). По умолчанию'^'
соответствует только началу строки, а'$'
- только концу строки и непосредственно перед новой строкой (если таковая имеется) в конце строки.Соответствует встроенному флагу
(?m)
.
- re.NOFLAG¶
Указывает, что флаг не применяется, значение равно
0
. Этот флаг может использоваться как значение по умолчанию для ключевого аргумента функции или как базовое значение, которое будет условно сопоставлено с другими флагами. Пример использования в качестве значения по умолчанию:def myfunc(text, flag=re.NOFLAG): return re.match(text, flag)
Добавлено в версии 3.11.
- re.S¶
- re.DOTALL¶
Сделайте так, чтобы специальный символ
'.'
соответствовал любому символу вообще, включая перевод строки; без этого флага'.'
будет соответствовать чему угодно, кроме перевода строки.Соответствует встроенному флагу
(?s)
.
- re.U¶
- re.UNICODE¶
В Python 3 символы Unicode по умолчанию совпадают с шаблонами
str
. Таким образом, этот флаг является избыточным, не имеет эффекта и сохраняется только для обеспечения обратной совместимости.Смотрите
ASCII
, чтобы ограничить сопоставление символами ASCII.
- re.X¶
- re.VERBOSE¶
Этот флаг позволяет вам писать регулярные выражения, которые выглядят приятнее и более удобочитаемы, позволяя визуально разделять логические разделы шаблона и добавлять комментарии. Пробелы в шаблоне игнорируются, за исключением случаев, когда они используются в символьном классе, или когда им предшествует неэкранированная обратная косая черта, или в токенах типа
*?
,(?:
или(?P<...>
. Например,(? :
и* ?
недопустимы. Когда строка содержит символ#
, который не относится к классу символов и перед которым не стоит неэкранированная обратная косая черта, все символы, начиная с крайнего левого символа#
и заканчивая концом строки, игнорируются.Это означает, что два следующих объекта регулярного выражения, соответствующие десятичному числу, функционально равны:
a = re.compile(r"""\d + # the integral part \. # the decimal point \d * # some fractional digits""", re.X) b = re.compile(r"\d+\.\d*")
Соответствует встроенному флагу
(?x)
.
Функции¶
- re.compile(pattern, flags=0)¶
Скомпилируйте шаблон регулярного выражения в regular expression object, который можно использовать для сопоставления с помощью его
match()
,search()
и других методов, описанных ниже.Поведение выражения можно изменить, указав значение flags. Значениями могут быть любые переменные flags, объединенные с помощью побитового ИЛИ (оператор
|
).Последовательность действий
prog = re.compile(pattern) result = prog.match(string)
эквивалентно
result = re.match(pattern, string)
но использование
re.compile()
и сохранение результирующего объекта регулярного выражения для повторного использования более эффективно, когда выражение будет использоваться несколько раз в одной программе.Примечание
Скомпилированные версии самых последних шаблонов, передаваемые в
re.compile()
, и функции сопоставления на уровне модуля кэшируются, поэтому программам, которые используют только несколько регулярных выражений одновременно, не нужно беспокоиться о компиляции регулярных выражений.
- re.search(pattern, string, flags=0)¶
Просмотрите string в поисках первого места, где регулярное выражение pattern выдает совпадение, и верните соответствующий
Match
. ВозвращаетNone
, если ни одна позиция в строке не соответствует шаблону; обратите внимание, что это отличается от поиска совпадения нулевой длины в некоторой точке строки.
- re.match(pattern, string, flags=0)¶
Если ноль или более символов в начале строки string соответствуют шаблону регулярного выражения *, верните соответствующий
Match
. ВернитеNone
, если строка не соответствует шаблону; обратите внимание, что это отличается от совпадения с нулевой длиной.Обратите внимание, что даже в режиме
MULTILINE
значениеre.match()
будет совпадать только в начале строки, а не в начале каждой строки.Если вы хотите найти совпадение в любом месте string, используйте вместо этого
search()
(смотрите также поиск() и сопоставление()).
- re.fullmatch(pattern, string, flags=0)¶
Если вся строка соответствует шаблону *регулярного выражения, верните соответствующий
Match
. ВернитеNone
, если строка не соответствует шаблону; обратите внимание, что это отличается от совпадения нулевой длины.Добавлено в версии 3.4.
- re.split(pattern, string, maxsplit=0, flags=0)¶
Разделите string на вхождения в pattern. Если в pattern используются фиксирующие круглые скобки, то текст всех групп в шаблоне также возвращается как часть результирующего списка. Если значение maxsplit не равно нулю, то происходит самое большее разделение maxsplit, и оставшаяся часть строки возвращается в качестве последнего элемента списка.
>>> re.split(r'\W+', 'Words, words, words.') ['Words', 'words', 'words', ''] >>> re.split(r'(\W+)', 'Words, words, words.') ['Words', ', ', 'words', ', ', 'words', '.', ''] >>> re.split(r'\W+', 'Words, words, words.', 1) ['Words', 'words, words.'] >>> re.split('[a-f]+', '0a3B9', flags=re.IGNORECASE) ['0', '3', '9']
Если в разделителе есть группы захвата и они совпадают в начале строки, результат будет начинаться с пустой строки. То же самое относится и к концу строки:
>>> re.split(r'(\W+)', '...words, words...') ['', '...', 'words', ', ', 'words', '...', '']
Таким образом, компоненты-разделители всегда находятся в списке результатов с одинаковыми относительными индексами.
Пустые совпадения для шаблона разделяют строку только в том случае, если они не примыкают к предыдущему пустому совпадению.
>>> re.split(r'\b', 'Words, words, words.') ['', 'Words', ', ', 'words', ', ', 'words', '.'] >>> re.split(r'\W*', '...words...') ['', '', 'w', 'o', 'r', 'd', 's', '', ''] >>> re.split(r'(\W*)', '...words...') ['', '...', '', '', 'w', '', 'o', '', 'r', '', 'd', '', 's', '...', '', '', '']
Изменено в версии 3.1: Добавлен необязательный аргумент flags.
Изменено в версии 3.7: Добавлена поддержка разбиения по шаблону, который может соответствовать пустой строке.
- re.findall(pattern, string, flags=0)¶
Возвращает все непересекающиеся совпадения pattern в string в виде списка строк или кортежей. Строка* сканируется слева направо, и совпадения возвращаются в том порядке, в котором они были найдены. В результат включаются пустые совпадения.
Результат зависит от количества групп захвата в шаблоне. Если групп нет, верните список строк, соответствующих всему шаблону. Если есть только одна группа, верните список строк, соответствующих этой группе. Если имеется несколько групп, верните список кортежей строк, соответствующих группам. Группы, не включенные в список, не влияют на форму результата.
>>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest') ['foot', 'fell', 'fastest'] >>> re.findall(r'(\w+)=(\d+)', 'set width=20 and height=10') [('width', '20'), ('height', '10')]
Изменено в версии 3.7: Непустые матчи теперь могут начинаться сразу после предыдущего пустого матча.
- re.finditer(pattern, string, flags=0)¶
Возвращает значение iterator, в результате чего
Match
объекты в целом совпадают с непересекающимися объектами для повторной проверки шаблона в строке. Строка* сканируется слева направо, и совпадения возвращаются в том порядке, в котором они были найдены. Пустые совпадения включаются в результат.Изменено в версии 3.7: Непустые матчи теперь могут начинаться сразу после предыдущего пустого матча.
- re.sub(pattern, repl, string, count=0, flags=0)¶
Возвращает строку, полученную путем замены крайних левых непересекающихся вхождений pattern в string на замену repl. Если шаблон не найден, string возвращается без изменений. repl может быть строкой или функцией; если это строка, то обрабатываются все экранирующие обратные косые черты в ней. То есть
\n
преобразуется в один символ новой строки,\r
- в символ возврата каретки и т.д. Неизвестные значения символов ASCII зарезервированы для дальнейшего использования и рассматриваются как ошибки. Другие неизвестные варианты выхода, такие как\&
, оставлены в покое. Обратные ссылки, такие как\6
, заменяются подстрокой, соответствующей группе 6 в шаблоне. Например:>>> re.sub(r'def\s+([a-zA-Z_][a-zA-Z_0-9]*)\s*\(\s*\):', ... r'static PyObject*\npy_\1(void)\n{', ... 'def myfunc():') 'static PyObject*\npy_myfunc(void)\n{'
Если repl - это функция, то она вызывается при каждом непересекающемся появлении pattern. Функция принимает единственный аргумент
Match
и возвращает строку замены. Например:>>> def dashrepl(matchobj): ... if matchobj.group(0) == '-': return ' ' ... else: return '-' >>> re.sub('-{1,2}', dashrepl, 'pro----gram-files') 'pro--gram files' >>> re.sub(r'\sAND\s', ' & ', 'Baked Beans And Spam', flags=re.IGNORECASE) 'Baked Beans & Spam'
Шаблон может быть строкой или
Pattern
.Необязательный аргумент count - это максимальное количество вхождений шаблона, которое необходимо заменить; count должно быть неотрицательным целым числом. Если оно опущено или равно нулю, все вхождения будут заменены. Пустые совпадения для шаблона заменяются только в том случае, если они не совпадают с предыдущим пустым совпадением, поэтому
sub('x*', '-', 'abxd')
возвращает'-a-b--d-'
.В аргументах repl строкового типа, в дополнение к описанным выше экранирующим символам и обратным ссылкам,
\g<name>
будет использоваться подстрока, соответствующая группе с именемname
, как определено синтаксисом(?P<name>...)
.\g<number>
использует соответствующий номер группы;\g<2>
, следовательно, эквивалентно\2
, но не является двусмысленным при замене, такой как\g<2>0
.\20
, будет интерпретироваться как ссылка к группе 20, а не к группе 2, за которой следует буквенный символ'0'
. Обратная ссылка\g<0>
заменяет всю подстроку, соответствующую RE.Изменено в версии 3.1: Добавлен необязательный аргумент flags.
Изменено в версии 3.5: Несовпадающие группы заменяются пустой строкой.
Изменено в версии 3.6: Неизвестные значения в шаблоне, состоящем из
'\'
и буквы ASCII, теперь являются ошибками.Изменено в версии 3.7: Неизвестные значения в repl, состоящие из
'\'
и буквы ASCII, теперь являются ошибками.Изменено в версии 3.7: Пустые совпадения для шаблона заменяются, если они находятся рядом с предыдущим непустым совпадением.
Не рекомендуется, начиная с версии 3.11: Идентификатор группы*, содержащий все, что угодно, кроме цифр ASCII. Название группы*, содержащее символы, не входящие в диапазон ASCII (
b'\x00'
-b'\x7f'
) в заменяющих строкахbytes
.
- re.subn(pattern, repl, string, count=0, flags=0)¶
Выполните ту же операцию, что и с
sub()
, но верните кортеж(new_string, number_of_subs_made)
.Изменено в версии 3.1: Добавлен необязательный аргумент flags.
Изменено в версии 3.5: Несовпадающие группы заменяются пустой строкой.
- re.escape(pattern)¶
Экранируйте специальные символы в pattern. Это полезно, если вы хотите сопоставить произвольную строку-литерал, в которой могут содержаться метасимволы регулярных выражений. Например:
>>> print(re.escape('https://www.python.org')) https://www\.python\.org >>> legal_chars = string.ascii_lowercase + string.digits + "!#$%&'*+-.^_`|~:" >>> print('[%s]+' % re.escape(legal_chars)) [abcdefghijklmnopqrstuvwxyz0123456789!\#\$%\&'\*\+\-\.\^_`\|\~:]+ >>> operators = ['+', '-', '*', '/', '**'] >>> print('|'.join(map(re.escape, sorted(operators, reverse=True)))) /|\-|\+|\*\*|\*
Эта функция не должна использоваться для замены строки в
sub()
иsubn()
, следует экранировать только обратную косую черту. Например:>>> digits_re = r'\d+' >>> sample = '/usr/sbin/sendmail - 0 errors, 12 warnings' >>> print(re.sub(digits_re, digits_re.replace('\\', r'\\'), sample)) /usr/sbin/sendmail - \d+ errors, \d+ warnings
Изменено в версии 3.3: Символ
'_'
больше не экранируется.Изменено в версии 3.7: Экранируются только те символы, которые могут иметь особое значение в регулярном выражении. В результате,
'!'
,'"'
,'%'
,"'"
,','
,'/'
,':'
,';'
,'<'
,'='
,'>'
,'@'
, и"`"
больше не экранируются.
- re.purge()¶
Очистите кэш регулярных выражений.
Исключения¶
- exception re.error(msg, pattern=None, pos=None)¶
Исключение возникает, когда строка, передаваемая в одну из приведенных здесь функций, не является допустимым регулярным выражением (например, она может содержать несоответствующие круглые скобки) или когда во время компиляции или сопоставления возникает какая-либо другая ошибка. Это никогда не будет ошибкой, если строка не содержит соответствия шаблону. Экземпляр error имеет следующие дополнительные атрибуты:
- msg¶
Неформатированное сообщение об ошибке.
- pattern¶
Шаблон регулярного выражения.
- pos¶
Индекс в pattern, где произошла ошибка компиляции (может быть
None
).
- lineno¶
Строка, соответствующая pos (может быть
None
).
- colno¶
Столбец, соответствующий pos (может быть
None
).
Изменено в версии 3.5: Добавлены дополнительные атрибуты.
Объекты регулярных выражений¶
- class re.Pattern¶
Скомпилированный объект регулярного выражения, возвращаемый с помощью
re.compile()
.Изменено в версии 3.9:
re.Pattern
поддерживает[]
для указания кода Unicode (str) или байтового шаблона. Смотрите Общий тип псевдонима.
- Pattern.search(string[, pos[, endpos]])¶
Просмотрите string в поисках первого места, где это регулярное выражение приводит к совпадению, и верните соответствующий
Match
. ВозвращаетNone
, если ни одна позиция в строке не соответствует шаблону; обратите внимание, что это отличается от поиска совпадения нулевой длины в некоторой точке строки.Необязательный второй параметр pos задает индекс в строке, с которой должен начинаться поиск; по умолчанию он равен
0
. Это не совсем эквивалентно разделению строки на части; символ шаблона'^'
совпадает в реальном начале строки и в позициях сразу после новой строки, но не обязательно в индексе, с которого должен начинаться поиск.Необязательный параметр endpos ограничивает диапазон поиска строки; это будет выглядеть так, как если бы строка была длиной в endpos символов, поэтому поиск совпадения будет производиться только по символам от pos до
endpos - 1
. Если значение endpos меньше значения pos, совпадение найдено не будет; в противном случае, если rx является скомпилированным объектом регулярного выражения,rx.search(string, 0, 50)
эквивалентноrx.search(string[:50], 0)
.>>> pattern = re.compile("d") >>> pattern.search("dog") # Match at index 0 <re.Match object; span=(0, 1), match='d'> >>> pattern.search("dog", 1) # No match; search doesn't include the "d"
- Pattern.match(string[, pos[, endpos]])¶
Если ноль или более символов в начале строки соответствуют этому регулярному выражению, возвращает соответствующий
Match
. ВозвращаетNone
, если строка не соответствует шаблону; обратите внимание, что это отличается от совпадения с нулевой длиной.Необязательные параметры pos и endpos имеют то же значение, что и для метода
search()
.>>> pattern = re.compile("o") >>> pattern.match("dog") # No match as "o" is not at the start of "dog". >>> pattern.match("dog", 1) # Match as "o" is the 2nd character of "dog". <re.Match object; span=(1, 2), match='o'>
Если вы хотите найти совпадение в любом месте string, используйте вместо этого
search()
(смотрите также поиск() и сопоставление()).
- Pattern.fullmatch(string[, pos[, endpos]])¶
Если вся строка соответствует этому регулярному выражению, верните соответствующий
Match
. ВернитеNone
, если строка не соответствует шаблону; обратите внимание, что это отличается от совпадения нулевой длины.Необязательные параметры pos и endpos имеют то же значение, что и для метода
search()
.>>> pattern = re.compile("o[gh]") >>> pattern.fullmatch("dog") # No match as "o" is not at the start of "dog". >>> pattern.fullmatch("ogre") # No match as not the full string matches. >>> pattern.fullmatch("doggie", 1, 3) # Matches within given limits. <re.Match object; span=(1, 3), match='og'>
Добавлено в версии 3.4.
- Pattern.findall(string[, pos[, endpos]])¶
Аналогично функции
findall()
, использующей скомпилированный шаблон, но также принимающей необязательные параметры pos и endpos, которые ограничивают область поиска, как дляsearch()
.
- Pattern.finditer(string[, pos[, endpos]])¶
Аналогично функции
finditer()
, использующей скомпилированный шаблон, но также принимающей необязательные параметры pos и endpos, которые ограничивают область поиска, как дляsearch()
.
- Pattern.subn(repl, string, count=0)¶
Идентична функции
subn()
, использующей скомпилированный шаблон.
- Pattern.flags¶
Соответствующие флаги регулярных выражений. Это комбинация флагов, присвоенных
compile()
, любых встроенных флагов(?...)
в шаблоне и неявных флагов, таких какUNICODE
, если шаблон представляет собой строку в Юникоде.
- Pattern.groups¶
Количество групп захвата в шаблоне.
- Pattern.groupindex¶
Словарь, отображающий любые символьные имена групп, определенные с помощью
(?P<id>)
, в номера групп. Словарь пуст, если в шаблоне не использовались символьные группы.
- Pattern.pattern¶
Строка шаблона, из которой был скомпилирован объект pattern.
Изменено в версии 3.7: Добавлена поддержка copy.copy()
и copy.deepcopy()
. Скомпилированные объекты регулярных выражений считаются атомарными.
Сопоставлять объекты¶
Соответствующие объекты всегда имеют логическое значение True
. Поскольку match()
и search()
возвращают None
при отсутствии совпадения, вы можете проверить, было ли совпадение, с помощью простого оператора if
:
match = re.search(pattern, string)
if match:
process(match)
- class re.Match¶
Сопоставьте объект, возвращенный успешными
match
es иsearch
es.Изменено в версии 3.9:
re.Match
поддерживает[]
для указания соответствия Юникоду (str) или байтам. Смотрите Общий тип псевдонима.
- Match.expand(template)¶
Возвращает строку, полученную путем подстановки обратной косой черты в строку шаблона template, как это делается методом
sub()
. Управляющие символы, такие как\n
, преобразуются в соответствующие символы, а числовые обратные ссылки (\1
,\2
) и именованные обратные ссылки (\g<1>
,\g<name>
) заменяются на содержимое соответствующей группы. Обратная ссылка\g<0>
будет заменена на полное совпадение.Изменено в версии 3.5: Несовпадающие группы заменяются пустой строкой.
- Match.group([group1, ...])¶
Возвращает одну или несколько подгрупп соответствия. Если аргумент один, результатом будет одна строка; если аргументов несколько, результатом будет кортеж с одним элементом в аргументе. Без аргументов значение group1 по умолчанию равно нулю (возвращается полное соответствие). Если аргумент groupN равен нулю, то соответствующим возвращаемым значением является вся соответствующая строка; если он находится в диапазоне включений [1..99], то это строка, соответствующая группе, заключенной в круглые скобки. Если номер группы отрицательный или больше, чем количество групп, определенных в шаблоне, возникает исключение
IndexError
. Если группа содержится в части шаблона, которая не соответствует, то соответствующим результатом будетNone
. Если группа содержится в части шаблона, которая совпадала несколько раз, возвращается последнее совпадение.>>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist") >>> m.group(0) # The entire match 'Isaac Newton' >>> m.group(1) # The first parenthesized subgroup. 'Isaac' >>> m.group(2) # The second parenthesized subgroup. 'Newton' >>> m.group(1, 2) # Multiple arguments give us a tuple. ('Isaac', 'Newton')
Если в регулярном выражении используется синтаксис
(?P<name>...)
, аргументами groupN также могут быть строки, идентифицирующие группы по их названию. Если строковый аргумент не используется в шаблоне в качестве имени группы, возникает исключениеIndexError
.Умеренно сложный пример:
>>> m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds") >>> m.group('first_name') 'Malcolm' >>> m.group('last_name') 'Reynolds'
На именованные группы также можно ссылаться по их индексу:
>>> m.group(1) 'Malcolm' >>> m.group(2) 'Reynolds'
Если группа совпадает несколько раз, доступно только последнее совпадение:
>>> m = re.match(r"(..)+", "a1b2c3") # Matches 3 times. >>> m.group(1) # Returns only the last match. 'c3'
- Match.__getitem__(g)¶
Это аналогично
m.group(g)
. Это упрощает доступ к отдельной группе из совпадения:>>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist") >>> m[0] # The entire match 'Isaac Newton' >>> m[1] # The first parenthesized subgroup. 'Isaac' >>> m[2] # The second parenthesized subgroup. 'Newton'
Также поддерживаются именованные группы:
>>> m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Isaac Newton") >>> m['first_name'] 'Isaac' >>> m['last_name'] 'Newton'
Добавлено в версии 3.6.
- Match.groups(default=None)¶
Возвращает кортеж, содержащий все подгруппы совпадения, от 1 до любого количества групп в шаблоне. Аргумент default используется для групп, которые не участвовали в совпадении; по умолчанию он равен
None
.Например:
>>> m = re.match(r"(\d+)\.(\d+)", "24.1632") >>> m.groups() ('24', '1632')
Если мы сделаем десятичный знак и все, что после него, необязательными, не все группы смогут участвовать в сопоставлении. По умолчанию для этих групп будет установлено значение
None
, если не указан аргумент default:>>> m = re.match(r"(\d+)\.?(\d+)?", "24") >>> m.groups() # Second group defaults to None. ('24', None) >>> m.groups('0') # Now, the second group defaults to '0'. ('24', '0')
- Match.groupdict(default=None)¶
Возвращает словарь, содержащий все именованные подгруппы в соответствии с именем подгруппы. Аргумент default используется для групп, которые не участвовали в сопоставлении; по умолчанию он равен
None
. Например:>>> m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds") >>> m.groupdict() {'first_name': 'Malcolm', 'last_name': 'Reynolds'}
- Match.start([group])¶
- Match.end([group])¶
Возвращает индексы начала и конца подстроки, совпадающей с group; значение group по умолчанию равно нулю (что означает всю совпадающую подстроку). Возвращает
-1
, если group существует, но не участвовала в совпадении. Для совпадающего объекта m и группы g, которые внесли свой вклад в совпадение, подстрока, соответствующая группе g (эквивалентнаяm.group(g)
), равнаm.string[m.start(g):m.end(g)]
Обратите внимание, что
m.start(group)
будет равноm.end(group)
, если group соответствует пустой строке. Например, после того, какm = re.search('b(c?)', 'cba')
,m.start(0)
равно 1,m.end(0)
равно 2,m.start(1)
иm.end(1)
равны 2, аm.start(2)
вызывает исключениеIndexError
.Пример, который удалит remove_this с адресов электронной почты:
>>> email = "tony@tiremove_thisger.net" >>> m = re.search("remove_this", email) >>> email[:m.start()] + email[m.end():] 'tony@tiger.net'
- Match.span([group])¶
Для совпадения m верните кортеж из 2 элементов
(m.start(group), m.end(group))
. Обратите внимание, что если group не участвовала в совпадении, то это(-1, -1)
. Значение group по умолчанию равно нулю, то есть соответствует всему совпадению.
- Match.pos¶
Значение pos, которое было передано в
search()
илиmatch()
методу regex object. Это индекс строки, по которому поисковик начал искать соответствие.
- Match.endpos¶
Значение endpos, которое было передано в
search()
илиmatch()
методу regex object. Это индекс строки, за пределы которого движок заходить не будет.
- Match.lastindex¶
Целочисленный индекс последней сопоставленной группы захвата или
None
, если ни одна группа не была сопоставлена вообще. Например, выражения(a)b
,((a)(b))
, и((ab))
будут иметь значениеlastindex == 1
, если они применяются к строке'ab'
, в то время как выражение(a)(b)
будет иметь значениеlastindex == 2
, если оно применяется к той же строке.
- Match.lastgroup¶
Имя последней сопоставленной группы захвата или
None
, если у группы не было имени, или если ни одна группа не была сопоставлена вообще.
- Match.re¶
regular expression object, чей метод
match()
илиsearch()
создал этот соответствующий экземпляр.
Изменено в версии 3.7: Добавлена поддержка copy.copy()
и copy.deepcopy()
. Объекты соответствия считаются атомарными.
Примеры регулярных выражений¶
Проверка наличия пары¶
В этом примере мы будем использовать следующую вспомогательную функцию для более изящного отображения соответствующих объектов:
def displaymatch(match):
if match is None:
return None
return '<Match: %r, groups=%r>' % (match.group(), match.groups())
Предположим, вы пишете покерную программу, в которой комбинация игрока представлена в виде строки из 5 символов, каждый символ которой обозначает карту: «a» - туз, «k» - король, «q» - дама, «j» - валет, «t» - 10 и «2» через «9», обозначающую карту с таким значением.
Чтобы проверить, является ли данная строка допустимой комбинацией, можно сделать следующее:
>>> valid = re.compile(r"^[a2-9tjqk]{5}$")
>>> displaymatch(valid.match("akt5q")) # Valid.
"<Match: 'akt5q', groups=()>"
>>> displaymatch(valid.match("akt5e")) # Invalid.
>>> displaymatch(valid.match("akt")) # Invalid.
>>> displaymatch(valid.match("727ak")) # Valid.
"<Match: '727ak', groups=()>"
Эта последняя комбинация, "727ak"
, содержала пару или две карты одинакового достоинства. Чтобы сопоставить это с регулярным выражением, можно было бы использовать обратные ссылки как таковые:
>>> pair = re.compile(r".*(.).*\1")
>>> displaymatch(pair.match("717ak")) # Pair of 7s.
"<Match: '717', groups=('7',)>"
>>> displaymatch(pair.match("718ak")) # No pairs.
>>> displaymatch(pair.match("354aa")) # Pair of aces.
"<Match: '354aa', groups=('a',)>"
Чтобы узнать, из какой карты состоит пара, можно использовать метод group()
объекта match следующим образом:
>>> pair = re.compile(r".*(.).*\1")
>>> pair.match("717ak").group(1)
'7'
# Error because re.match() returns None, which doesn't have a group() method:
>>> pair.match("718ak").group(1)
Traceback (most recent call last):
File "<pyshell#23>", line 1, in <module>
re.match(r".*(.).*\1", "718ak").group(1)
AttributeError: 'NoneType' object has no attribute 'group'
>>> pair.match("354aa").group(1)
'a'
Имитация scanf()¶
В настоящее время в Python нет эквивалента scanf()
. Регулярные выражения, как правило, более мощные, хотя и более подробные, чем строки формата scanf()
. В таблице ниже приведены некоторые более или менее эквивалентные сопоставления между токенами формата c:func:!scanf и регулярными выражениями.
:токен c:func:!scanf |
обычное выражение |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Чтобы извлечь имя файла и номера из строки, подобной
/usr/sbin/sendmail - 0 errors, 4 warnings
вы бы использовали формат a scanf()
, например
%s - %d errors, %d warnings
Эквивалентным регулярным выражением было бы следующее
(\S+) - (\d+) errors, (\d+) warnings
поиск() и сопоставление()¶
Python предлагает различные примитивные операции, основанные на регулярных выражениях:
re.match()
проверяет соответствие только в начале строкиre.search()
проверяет соответствие в любом месте строки (это то, что Perl делает по умолчанию)re.fullmatch()
проверяет соответствие всей строки
Например:
>>> re.match("c", "abcdef") # No match
>>> re.search("c", "abcdef") # Match
<re.Match object; span=(2, 3), match='c'>
>>> re.fullmatch("p.*n", "python") # Match
<re.Match object; span=(0, 6), match='python'>
>>> re.fullmatch("r.*n", "python") # No match
Регулярные выражения, начинающиеся с '^'
, можно использовать с search()
, чтобы ограничить совпадение в начале строки:
>>> re.match("c", "abcdef") # No match
>>> re.search("^c", "abcdef") # No match
>>> re.search("^a", "abcdef") # Match
<re.Match object; span=(0, 1), match='a'>
Однако обратите внимание, что в режиме MULTILINE
match()
совпадает только в начале строки, тогда как при использовании search()
с регулярным выражением, начинающимся с '^'
, будет совпадать в начале каждой строки.
>>> re.match("X", "A\nB\nX", re.MULTILINE) # No match
>>> re.search("^X", "A\nB\nX", re.MULTILINE) # Match
<re.Match object; span=(4, 5), match='X'>
Создание телефонной книги¶
split()
разбивает строку на список, разделенный переданным шаблоном. Этот метод незаменим для преобразования текстовых данных в структуры данных, которые могут быть легко прочитаны и изменены с помощью Python, как показано в следующем примере создания телефонной книги.
Во-первых, вот входные данные. Обычно они могут быть получены из файла, здесь мы используем синтаксис строки в тройных кавычках
>>> text = """Ross McFluff: 834.345.1254 155 Elm Street
...
... Ronald Heathmore: 892.345.3428 436 Finley Avenue
... Frank Burger: 925.541.7625 662 South Dogwood Way
...
...
... Heather Albrecht: 548.326.4584 919 Park Place"""
Записи разделены одной или несколькими новыми строками. Теперь мы преобразуем строку в список, в котором каждая непустая строка содержит свою собственную запись:
>>> entries = re.split("\n+", text)
>>> entries
['Ross McFluff: 834.345.1254 155 Elm Street',
'Ronald Heathmore: 892.345.3428 436 Finley Avenue',
'Frank Burger: 925.541.7625 662 South Dogwood Way',
'Heather Albrecht: 548.326.4584 919 Park Place']
Наконец, разделите каждую запись на список с именем, фамилией, номером телефона и адресом. Мы используем параметр maxsplit
из split()
, потому что в адресе есть пробелы, что соответствует нашему шаблону разделения:
>>> [re.split(":? ", entry, 3) for entry in entries]
[['Ross', 'McFluff', '834.345.1254', '155 Elm Street'],
['Ronald', 'Heathmore', '892.345.3428', '436 Finley Avenue'],
['Frank', 'Burger', '925.541.7625', '662 South Dogwood Way'],
['Heather', 'Albrecht', '548.326.4584', '919 Park Place']]
Шаблон :?
совпадает с двоеточием после фамилии, поэтому он не отображается в списке результатов. Используя maxsplit
вместо 4
, мы могли бы отделить номер дома от названия улицы:
>>> [re.split(":? ", entry, 4) for entry in entries]
[['Ross', 'McFluff', '834.345.1254', '155', 'Elm Street'],
['Ronald', 'Heathmore', '892.345.3428', '436', 'Finley Avenue'],
['Frank', 'Burger', '925.541.7625', '662', 'South Dogwood Way'],
['Heather', 'Albrecht', '548.326.4584', '919', 'Park Place']]
Редактирование текста¶
sub()
заменяет каждое появление шаблона строкой или результатом функции. В этом примере показано использование sub()
с функцией «munge» текста или рандомизации порядка расположения всех символов в каждом слове предложения, за исключением первого и последнего символов:
>>> def repl(m):
... inner_word = list(m.group(2))
... random.shuffle(inner_word)
... return m.group(1) + "".join(inner_word) + m.group(3)
>>> text = "Professor Abdolmalek, please report your absences promptly."
>>> re.sub(r"(\w)(\w+)(\w)", repl, text)
'Poefsrosr Aealmlobdk, pslaee reorpt your abnseces plmrptoy.'
>>> re.sub(r"(\w)(\w+)(\w)", repl, text)
'Pofsroser Aodlambelk, plasee reoprt yuor asnebces potlmrpy.'
Поиск всех наречий¶
findall()
соответствует всем вхождениям шаблона, а не только первому, как search()
. Например, если автор хотел найти все наречия в каком-либо тексте, он мог бы использовать findall()
следующим образом:
>>> text = "He was carefully disguised but captured quickly by police."
>>> re.findall(r"\w+ly\b", text)
['carefully', 'quickly']
Поиск всех наречий и их позиций¶
Если кому-то нужно больше информации обо всех совпадениях шаблона, чем о совпадающем тексте, finditer()
полезен, поскольку он предоставляет Match
объекты вместо строк. Продолжая предыдущий пример, если бы автор хотел найти все наречия * и их позиции* в каком-либо тексте, он бы использовал finditer()
следующим образом:
>>> text = "He was carefully disguised but captured quickly by police."
>>> for m in re.finditer(r"\w+ly\b", text):
... print('%02d-%02d: %s' % (m.start(), m.end(), m.group(0)))
07-16: carefully
40-47: quickly
Необработанная строковая нотация¶
Запись в виде необработанной строки (r"text"
) позволяет сохранить логичность регулярных выражений. Без нее каждая обратная косая черта ('\'
) в регулярном выражении должна была бы иметь другой префикс, чтобы избежать ее. Например, две следующие строки кода функционально идентичны:
>>> re.match(r"\W(.)\1\W", " ff ")
<re.Match object; span=(0, 4), match=' ff '>
>>> re.match("\\W(.)\\1\\W", " ff ")
<re.Match object; span=(0, 4), match=' ff '>
Если требуется сопоставить буквальную обратную косую черту, она должна быть экранирована в регулярном выражении. При использовании необработанной строковой записи это означает r"\\"
. Без использования необработанной строковой записи необходимо использовать "\\\\"
, что делает следующие строки кода функционально идентичными:
>>> re.match(r"\\", r"\\")
<re.Match object; span=(0, 1), match='\\'>
>>> re.match("\\\\", r"\\")
<re.Match object; span=(0, 1), match='\\'>
Написание токенизатора¶
A tokenizer or scanner анализирует строку для классификации групп символов. Это полезный первый шаг при написании компилятора или интерпретатора.
Текстовые категории задаются с помощью регулярных выражений. Метод заключается в объединении их в одно основное регулярное выражение и циклическом просмотре последовательных совпадений:
from typing import NamedTuple
import re
class Token(NamedTuple):
type: str
value: str
line: int
column: int
def tokenize(code):
keywords = {'IF', 'THEN', 'ENDIF', 'FOR', 'NEXT', 'GOSUB', 'RETURN'}
token_specification = [
('NUMBER', r'\d+(\.\d*)?'), # Integer or decimal number
('ASSIGN', r':='), # Assignment operator
('END', r';'), # Statement terminator
('ID', r'[A-Za-z]+'), # Identifiers
('OP', r'[+\-*/]'), # Arithmetic operators
('NEWLINE', r'\n'), # Line endings
('SKIP', r'[ \t]+'), # Skip over spaces and tabs
('MISMATCH', r'.'), # Any other character
]
tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification)
line_num = 1
line_start = 0
for mo in re.finditer(tok_regex, code):
kind = mo.lastgroup
value = mo.group()
column = mo.start() - line_start
if kind == 'NUMBER':
value = float(value) if '.' in value else int(value)
elif kind == 'ID' and value in keywords:
kind = value
elif kind == 'NEWLINE':
line_start = mo.end()
line_num += 1
continue
elif kind == 'SKIP':
continue
elif kind == 'MISMATCH':
raise RuntimeError(f'{value!r} unexpected on line {line_num}')
yield Token(kind, value, line_num, column)
statements = '''
IF quantity THEN
total := total + price * quantity;
tax := price * 0.05;
ENDIF;
'''
for token in tokenize(statements):
print(token)
Токенизатор выдает следующий результат:
Token(type='IF', value='IF', line=2, column=4)
Token(type='ID', value='quantity', line=2, column=7)
Token(type='THEN', value='THEN', line=2, column=16)
Token(type='ID', value='total', line=3, column=8)
Token(type='ASSIGN', value=':=', line=3, column=14)
Token(type='ID', value='total', line=3, column=17)
Token(type='OP', value='+', line=3, column=23)
Token(type='ID', value='price', line=3, column=25)
Token(type='OP', value='*', line=3, column=31)
Token(type='ID', value='quantity', line=3, column=33)
Token(type='END', value=';', line=3, column=41)
Token(type='ID', value='tax', line=4, column=8)
Token(type='ASSIGN', value=':=', line=4, column=12)
Token(type='ID', value='price', line=4, column=15)
Token(type='OP', value='*', line=4, column=21)
Token(type='NUMBER', value=0.05, line=4, column=23)
Token(type='END', value=';', line=4, column=27)
Token(type='ENDIF', value='ENDIF', line=5, column=4)
Token(type='END', value=';', line=5, column=9)
Фридл, Джеффри. Освоение регулярных выражений. 3-е изд., O’Reilly Media, 2009. В третьем издании книги больше не рассматривается Python, но в первом издании очень подробно описывалось написание хороших шаблонов регулярных выражений.