re — Regular expression operations

Source code: Lib/re.py


Цей модуль забезпечує операції зіставлення регулярних виразів, подібні до тих, які є в Perl.

Both patterns and strings to be searched can be Unicode strings (str) as well as 8-bit strings (bytes). However, Unicode strings and 8-bit strings cannot be mixed: that is, you cannot match a Unicode string with a byte pattern or vice-versa; similarly, when asking for a substitution, the replacement string must be of the same type as both the pattern and the search string.

Regular expressions use the backslash character ('\') to indicate special forms or to allow special characters to be used without invoking their special meaning. This collides with Python’s usage of the same character for the same purpose in string literals; for example, to match a literal backslash, one might have to write '\\\\' as the pattern string, because the regular expression must be \\, and each backslash must be expressed as \\ inside a regular Python string literal. Also, please note that any invalid escape sequences in Python’s usage of the backslash in string literals now generate a DeprecationWarning and in the future this will become a SyntaxError. This behaviour will happen even if it is a valid escape sequence for a regular expression.

Рішення полягає у використанні необробленої рядкової нотації Python для шаблонів регулярних виразів; зворотні косі риски не обробляються жодним особливим чином у рядковому літералі з префіксом 'r'. Отже, r"\n" — це двосимвольний рядок, що містить '\' і 'n', тоді як "\n" є односимвольним рядком, що містить новий рядок. Зазвичай шаблони виражаються в коді Python за допомогою цієї необробленої рядкової нотації.

Важливо відзначити, що більшість операцій з регулярними виразами доступні як функції та методи на рівні модуля для компільованих регулярних виразів. Функції — це ярлики, які не потребують компіляції об’єкта регулярного виразу, але пропускають деякі параметри тонкого налаштування.

Дивись також

The third-party regex module, which has an API compatible with the standard library re module, but offers additional functionality and a more thorough Unicode support.

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

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

Регулярні вирази можна об’єднувати для створення нових регулярних виразів; якщо A і B є регулярними виразами, то AB також є регулярним виразом. Загалом, якщо рядок p відповідає A, а інший рядок q відповідає B, рядок pq відповідатиме AB. Це справедливо, якщо A або B не містять операції з низьким пріоритетом; граничні умови між A і B; або мають пронумеровані посилання на групи. Таким чином, складні вирази можна легко побудувати з простіших примітивних виразів, таких як описані тут. Щоб отримати детальну інформацію про теорію та реалізацію регулярних виразів, зверніться до книги Фрідла [Frie09] або майже до будь-якого підручника про побудову компілятора.

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

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

Деякі символи, наприклад '|' або '('', є спеціальними. Спеціальні символи або позначають класи звичайних символів, або впливають на інтерпретацію регулярних виразів навколо них.

Repetition qualifiers (*, +, ?, {m,n}, etc) cannot be directly nested. This avoids ambiguity with the non-greedy modifier suffix ?, and with other modifiers in other implementations. To apply a second repetition to an inner repetition, parentheses may be used. For example, the expression (?:a{6})* matches any multiple of six 'a' characters.

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

.

(Dot.) In the default mode, this matches any character except a newline. If the DOTALL flag has been specified, this matches any character including a newline.

^

(Caret.) Збігається з початком рядка, а в режимі 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“; воно не збігатиметься лише з «а».

?

Примушує результуюче RE відповідати 0 або 1 повторенням попереднього RE. ab? відповідатиме або „a“, або „ab“.

*?, +?, ??

The '*', '+', and '?' qualifiers are all greedy; they match as much text as possible. Sometimes this behaviour isn’t desired; if the RE <.*> is matched against '<a> b <c>', it will match the entire string, and not just '<a>'. Adding ? after the qualifier makes it perform the match in non-greedy or minimal fashion; as few characters as possible will be matched. Using the RE <.*?> will match only '<a>'.

{m}

Вказує, що точно m копій попереднього RE мають відповідати; менша кількість збігів призводить до того, що весь RE не збігається. Наприклад, a{6} відповідатиме рівно шести символам 'a', але не п’яти.

{m,n}

Примушує результуючий RE відповідати від m до n повторень попереднього RE, намагаючись зіставити якомога більше повторень. Наприклад, a{3,5} відповідатиме від 3 до 5 символів 'a'. Пропуск m визначає нижню межу нуля, а пропуск n визначає нескінченну верхню межу. Наприклад, a{4,}b відповідатиме 'aaaab' або тисячі символів 'a', після яких 'b', але не ' аааб''. Кому не можна опускати, інакше модифікатор можна сплутати з попередньо описаною формою.

{m,n}?

Causes the resulting RE to match from m to n repetitions of the preceding RE, attempting to match as few repetitions as possible. This is the non-greedy version of the previous qualifier. For example, on the 6-character string 'aaaaaa', a{3,5} will match 5 'a' characters, while a{3,5}? will only match 3 characters.

\

Або екранує спеціальні символи (дозволяючи вам зіставляти такі символи, як '*', '?'' і так далі), або сигналізує про спеціальну послідовність; спеціальні послідовності обговорюються нижче.

Якщо ви не використовуєте необроблений рядок для вираження шаблону, пам’ятайте, що Python також використовує зворотну косу риску як керуючу послідовність у рядкових літералах; якщо escape-послідовність не розпізнається синтаксичним аналізатором Python, зворотна коса риска та наступний символ включаються в результуючий рядок. Однак, якщо Python розпізнає отриману послідовність, зворотну косу риску слід повторити двічі. Це складно і важко зрозуміти, тому настійно рекомендується використовувати необроблені рядки для всіх виразів, крім найпростіших.

[]

Використовується для позначення набору символів. В комплекті:

  • Символи можуть бути перераховані окремо, напр. «[amk]» відповідатиме «a», «m» або «k».

  • Діапазони символів можна вказати, вказавши два символи та розділивши їх символом '-', наприклад, [a-z] відповідатиме будь-якій літері ASCII у нижньому регістрі, [0-5][0-9]. ] відповідатиме всім двозначним числам від 00 до 59, а [0-9A-Fa-f] відповідатиме будь-якій шістнадцятковій цифрі. Якщо - є екранованим (наприклад, [a\-z]) або якщо він розміщений як перший чи останній символ (наприклад [-a] або [a-] ), він відповідатиме літералу '-'.

  • Спеціальні символи втрачають своє особливе значення в наборах. Наприклад, [(+*)] відповідатиме будь-якому з літеральних символів '(', '+', '*' або ')'.

  • Character classes such as \w or \S (defined below) are also accepted inside a set, although the characters they match depends on whether ASCII or LOCALE mode is in force.

  • Символи, які не входять до діапазону, можуть бути зіставлені шляхом complementing набору. Якщо першим символом набору є '^', усі символи, яких не в наборі, будуть зіставлені. Наприклад, [^5] відповідатиме будь-якому символу, крім '5'', а [^^] відповідатиме будь-якому символу, крім '^'. ^ не має особливого значення, якщо це не перший символ у наборі.

  • To match a literal ']' inside a set, precede it with a backslash, or place it at the beginning of the set. For example, both [()[\]{}] and []()[{}] will both match a parenthesis.

  • У майбутньому може бути додано підтримку вкладених наборів і операцій із наборами, як у технічному стандарті Unicode #18. Це призведе до зміни синтаксису, тож для полегшення цієї зміни FutureWarning наразі буде викликано у неоднозначних випадках. Це включає в себе набори, що починаються з літерала '[' або містять літеральні послідовності символів '--', '&&', '~~' і '| |'. Щоб уникнути попередження, екрануйте їх зворотною скісною рискою.

Змінено в версії 3.7: FutureWarning викликається, якщо набір символів містить конструкції, які семантично зміняться в майбутньому.

|

A|B, де A і B можуть бути довільними RE, створює регулярний вираз, який відповідатиме A або B. Таким чином довільна кількість RE може бути розділена символом '|'. Це також можна використовувати всередині груп (див. нижче). Під час сканування цільового рядка RE, розділені '|', пробуються зліва направо. Якщо один шаблон повністю збігається, ця гілка приймається. Це означає, що як тільки A збігається, B більше не перевірятиметься, навіть якщо це призведе до довшого загального збігу. Іншими словами, оператор '|'' ніколи не є жадібним. Щоб відповідати літералу '|', використовуйте \| або вкладіть його в клас символів, як у [|].

(...)

Збігається з будь-яким регулярним виразом у дужках і вказує на початок і кінець групи; вміст групи може бути отриманий після того, як було виконано збіг, і може бути зіставлений пізніше в рядку за допомогою спеціальної послідовності \number, описаної нижче. Щоб зіставити літерали '(' або ')', використовуйте \( або \) або вкладіть їх у клас символів: [(] , [)].

(?...)

Це нотація розширення ('?'' після ' ('' не має значення інакше). Перший символ після '?'' визначає значення та подальший синтаксис Розширення зазвичай не створюють нову групу; (?P <name> ...) є єдиним винятком із цього правила. Нижче наведено наразі підтримувані розширення.

(?aiLmsux)

(One or more letters from the set 'a', 'i', 'L', 'm', 's', 'u', 'x'.) The group matches the empty string; the letters set the corresponding flags: re.A (ASCII-only matching), re.I (ignore case), re.L (locale dependent), re.M (multi-line), re.S (dot matches all), re.U (Unicode matching), and re.X (verbose), for the entire regular expression. (The flags are described in Зміст модуля.) This is useful if you wish to include the flags as part of the regular expression, instead of passing a flag argument to the re.compile() function. Flags should be used first in the expression string.

(?:...)

Версія звичайних круглих дужок без захоплення. Збігається з будь-яким регулярним виразом у дужках, але підрядок, який відповідає групі, неможливо отримати після виконання збігу або посилатися на нього пізніше в шаблоні.

(?aiLmsux-imsx:...)

(Zero or more letters from the set 'a', 'i', 'L', 'm', 's', 'u', 'x', optionally followed by '-' followed by one or more letters from the 'i', 'm', 's', 'x'.) The letters set or remove the corresponding flags: re.A (ASCII-only matching), re.I (ignore case), re.L (locale dependent), re.M (multi-line), re.S (dot matches all), re.U (Unicode matching), and re.X (verbose), for the part of the expression. (The flags are described in Зміст модуля.)

The letters 'a', 'L' and 'u' are mutually exclusive when used as inline flags, so they can’t be combined or follow '-'. Instead, when one of them appears in an inline group, it overrides the matching mode in the enclosing group. In Unicode patterns (?a:...) switches to ASCII-only matching, and (?u:...) switches to Unicode matching (default). In byte pattern (?L:...) switches to locale depending matching, and (?a:...) switches to ASCII-only matching (default). This override is only in effect for the narrow inline group, and the original matching mode is restored outside of the group.

Нове в версії 3.6.

Змінено в версії 3.7: Літери 'a', 'L' і 'u' також можна використовувати в групі.

(?P <name> ...)

Similar to regular parentheses, but the substring matched by the group is accessible via the symbolic group name name. Group names must be valid Python identifiers, and each group name must be defined only once within a regular expression. A symbolic group is also a numbered group, just as if the group were not named.

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

Контекст посилання на групу «цитата»

Способи посилання на нього

за таким самим шаблоном

  • (?P=quote) (як показано)

  • \1

під час обробки відповідного об’єкта m

  • m.group('quote')

  • m.end('quote') (і т.д.)

у рядку, переданому в аргумент repl re.sub()

  • \g <quote>

  • \g <1>

  • \1

(?P=name)

Зворотне посилання на іменовану групу; він відповідає будь-якому тексту, який відповідав попередній групі під назвою name.

(?#...)

коментар; вміст круглих дужок просто ігнорується.

(?=...)

Збігається, якщо ... збігається наступним, але не споживає жоден рядок. Це називається lookahead assertion. Наприклад, Isaac (?=Azimov) відповідатиме 'Isaac '', лише якщо за ним йде 'Azimov'.

(?!...)

Збігається, якщо ... не збігається наступним. Це негативне випереджальне твердження. Наприклад, Isaac (?!Azimov) відповідатиме 'Isaac '', лише якщо за ним не йде 'Azimov'.

(?<=...)

Збігається, якщо поточній позиції в рядку передує відповідність для ..., яка закінчується на поточній позиції. Це називається позитивним ретроспективним твердженням. (?<=abc)def знайде збіг у 'abcdef', оскільки огляд назад створить резервну копію 3 символів і перевірить, чи збігається шаблон, що міститься. Вміщений шаблон має збігатися лише з рядками певної фіксованої довжини, тобто допустимі abc або a|b, але a* і a{3,4} заборонені . Зауважте, що шаблони, які починаються з позитивних ретроспективних тверджень, не збігатимуться на початку рядка, що шукається; швидше за все, ви захочете використовувати функцію search(), а не функцію match():

>>> import re
>>> m = re.search('(?<=abc)def', 'abcdef')
>>> m.group(0)
'def'

У цьому прикладі шукається слово після дефіса:

>>> m = re.search(r'(?<=-)\w+', 'spam-egg')
>>> m.group(0)
'egg'

Змінено в версії 3.5: Додано підтримку групових посилань фіксованої довжини.

(?<!...)

Збігається, якщо поточній позиції в рядку не передує збіг для .... Це називається negative lookbehind assertion. Подібно до позитивних ретроспективних тверджень, шаблон, що міститься, повинен відповідати лише рядкам певної фіксованої довжини. Шаблони, які починаються з негативних ретроспективних тверджень, можуть збігатися на початку рядка, який шукається.

(?(id/name)yes-pattern|no-pattern)

Спробує знайти відповідність за допомогою yes-pattern, якщо група з заданим id або name існує, і за допомогою no-pattern, якщо вона не існує. no-pattern є необов’язковим і його можна опустити. Наприклад, ( <)?(\w+@\w+(?:\.\w+)+)(?(1)> |$) є поганим шаблоном відповідності електронної пошти, який збігатиметься з '<user@host.com>', а також 'user@host.com', але не з '<user@host.com' nor 'user@host.com> '.

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

\номер

Відповідає вмісту групи з тим самим номером. Групи нумеруються, починаючи з 1. Наприклад, (.+) \1 відповідає 'the' або '55 55', але не 'thethe' (примітка пробіл після групи). Цю спеціальну послідовність можна використовувати лише для відповідності одній із перших 99 груп. Якщо перша цифра числа дорівнює 0 або число складається з 3 вісімкових цифр, це не буде інтерпретовано як збіг групи, а як символ із вісімковим значенням число. Усередині '[' і ']' класу символів усі цифрові екрановані символи розглядаються як символи.

\A

Збігається лише на початку рядка.

\b

Matches the empty string, but only at the beginning or end of a word. A word is defined as a sequence of word characters. Note that formally, \b is defined as the boundary between a \w and a \W character (or vice versa), or between \w and the beginning/end of the string. This means that r'\bfoo\b' matches 'foo', 'foo.', '(foo)', 'bar foo baz' but not 'foobar' or 'foo3'.

By default Unicode alphanumerics are the ones used in Unicode patterns, but this can be changed by using the ASCII flag. Word boundaries are determined by the current locale if the LOCALE flag is used. Inside a character range, \b represents the backspace character, for compatibility with Python’s string literals.

\B

Matches the empty string, but only when it is not at the beginning or end of a word. This means that r'py\B' matches 'python', 'py3', 'py2', but not 'py', 'py.', or 'py!'. \B is just the opposite of \b, so word characters in Unicode patterns are Unicode alphanumerics or the underscore, although this can be changed by using the ASCII flag. Word boundaries are determined by the current locale if the LOCALE flag is used.

\d
Для шаблонів Unicode (str):

Matches any Unicode decimal digit (that is, any character in Unicode character category [Nd]). This includes [0-9], and also many other digit characters. If the ASCII flag is used only [0-9] is matched.

Для 8-бітових (байтових) шаблонів:

Matches any decimal digit; this is equivalent to [0-9].

\D

Matches any character which is not a decimal digit. This is the opposite of \d. If the ASCII flag is used this becomes the equivalent of [^0-9].

\s
Для шаблонів Unicode (str):

Matches Unicode whitespace characters (which includes [ \t\n\r\f\v], and also many other characters, for example the non-breaking spaces mandated by typography rules in many languages). If the ASCII flag is used, only [ \t\n\r\f\v] is matched.

Для 8-бітових (байтових) шаблонів:

Відповідає символам, які вважаються пробілами в наборі символів ASCII; це еквівалентно [ \t\n\r\f\v].

\S

Matches any character which is not a whitespace character. This is the opposite of \s. If the ASCII flag is used this becomes the equivalent of [^ \t\n\r\f\v].

\w
Для шаблонів Unicode (str):

Matches Unicode word characters; this includes most characters that can be part of a word in any language, as well as numbers and the underscore. If the ASCII flag is used, only [a-zA-Z0-9_] is matched.

Для 8-бітових (байтових) шаблонів:

Matches characters considered alphanumeric in the ASCII character set; this is equivalent to [a-zA-Z0-9_]. If the LOCALE flag is used, matches characters considered alphanumeric in the current locale and the underscore.

\W

Matches any character which is not a word character. This is the opposite of \w. If the ASCII flag is used this becomes the equivalent of [^a-zA-Z0-9_]. If the LOCALE flag is used, matches characters which are neither alphanumeric in the current locale nor the underscore.

\Z

Збігається лише в кінці рядка.

Most of the standard escapes supported by Python string literals are also accepted by the regular expression parser:

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

(Зауважте, що \b використовується для представлення меж слів і означає «backspace» лише всередині класів символів.)

'\u', '\U', and '\N' escape sequences are only recognized in Unicode patterns. In bytes patterns they are errors. Unknown escapes of ASCII letters are reserved for future use and treated as errors.

Вісімкові втечі включені в обмеженій формі. Якщо першою цифрою є 0 або є три вісімкові цифри, це вважається вісімковим екрануванням. В іншому випадку це посилання на групу. Що стосується рядкових літералів, вісімкові символи екранування завжди мають не більше трьох цифр.

Змінено в версії 3.3: Було додано керуючі послідовності '\u' і '\U'.

Змінено в версії 3.6: Невідомі вихідні символи, що складаються з '\' і літери ASCII, тепер є помилками.

Змінено в версії 3.8: The '\N{name}' escape sequence has been added. As in string literals, it expands to the named Unicode character (e.g. '\N{EM DASH}').

Зміст модуля

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

Змінено в версії 3.6: Константи прапорів тепер є екземплярами RegexFlag, який є підкласом enum.IntFlag.

re.compile(pattern, flags=0)

Скомпілюйте шаблон регулярного виразу в об’єкт регулярного виразу, який можна використовувати для зіставлення за допомогою його match(), search() та інших методів, описаних нижче .

The expression’s behaviour can be modified by specifying a flags value. Values can be any of the following variables, combined using bitwise OR (the | operator).

Послідовність

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

еквівалентно

result = re.match(pattern, string)

але використання re.compile() і збереження отриманого об’єкта регулярного виразу для повторного використання ефективніше, якщо вираз використовуватиметься кілька разів в одній програмі.

Примітка

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

re.A
re.ASCII

Make \w, \W, \b, \B, \d, \D, \s and \S perform ASCII-only matching instead of full Unicode matching. This is only meaningful for Unicode patterns, and is ignored for byte patterns. Corresponds to the inline flag (?a).

Note that for backward compatibility, the re.U flag still exists (as well as its synonym re.UNICODE and its embedded counterpart (?u)), but these are redundant in Python 3 since matches are Unicode by default for strings (and Unicode matching isn’t allowed for bytes).

re.DEBUG

Display debug information about compiled expression. No corresponding inline flag.

re.I
re.IGNORECASE

Perform case-insensitive matching; expressions like [A-Z] will also match lowercase letters. Full Unicode matching (such as Ü matching ü) also works unless the re.ASCII flag is used to disable non-ASCII matches. The current locale does not change the effect of this flag unless the re.LOCALE flag is also used. Corresponds to the inline flag (?i).

Note that when the Unicode patterns [a-z] or [A-Z] are used in combination with the IGNORECASE flag, they will match the 52 ASCII letters and 4 additional non-ASCII letters: „İ“ (U+0130, Latin capital letter I with dot above), „ı“ (U+0131, Latin small letter dotless i), „ſ“ (U+017F, Latin small letter long s) and „K“ (U+212A, Kelvin sign). If the ASCII flag is used, only letters „a“ to „z“ and „A“ to „Z“ are matched.

re.L
re.LOCALE

Make \w, \W, \b, \B and case-insensitive matching dependent on the current locale. This flag can be used only with bytes patterns. The use of this flag is discouraged as the locale mechanism is very unreliable, it only handles one «culture» at a time, and it only works with 8-bit locales. Unicode matching is already enabled by default in Python 3 for Unicode (str) patterns, and it is able to handle different locales/languages. Corresponds to the inline flag (?L).

Змінено в версії 3.6: re.LOCALE can be used only with bytes patterns and is not compatible with re.ASCII.

Змінено в версії 3.7: Compiled regular expression objects with the re.LOCALE flag no longer depend on the locale at compile time. Only the locale at matching time affects the result of matching.

re.M
re.MULTILINE

When specified, the pattern character '^' matches at the beginning of the string and at the beginning of each line (immediately following each newline); and the pattern character '$' matches at the end of the string and at the end of each line (immediately preceding each newline). By default, '^' matches only at the beginning of the string, and '$' only at the end of the string and immediately before the newline (if any) at the end of the string. Corresponds to the inline flag (?m).

re.S
re.DOTALL

Make the '.' special character match any character at all, including a newline; without this flag, '.' will match anything except a newline. Corresponds to the inline flag (?s).

re.X
re.VERBOSE

This flag allows you to write regular expressions that look nicer and are more readable by allowing you to visually separate logical sections of the pattern and add comments. Whitespace within the pattern is ignored, except when in a character class, or when preceded by an unescaped backslash, or within tokens like *?, (?: or (?P<...>. When a line contains a # that is not in a character class and is not preceded by an unescaped backslash, all characters from the leftmost such # through the end of the line are ignored.

Це означає, що два наступних об’єкти регулярного виразу, які відповідають десятковому числу, функціонально однакові:

a = re.compile(r"""\d +  # the integral part
                   \.    # the decimal point
                   \d *  # some fractional digits""", re.X)
b = re.compile(r"\d+\.\d*")

Відповідає вбудованому прапору (?x).

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

Scan through string looking for the first location where the regular expression pattern produces a match, and return a corresponding match object. Return None if no position in the string matches the pattern; note that this is different from finding a zero-length match at some point in the string.

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

If zero or more characters at the beginning of string match the regular expression pattern, return a corresponding match object. Return None if the string does not match the pattern; note that this is different from a zero-length match.

Зауважте, що навіть у режимі MULTILINE re.match() збігатиметься лише на початку рядка, а не на початку кожного рядка.

Якщо ви хочете знайти збіг будь-де в string, використовуйте натомість search() (див. також search() проти match()).

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

If the whole string matches the regular expression pattern, return a corresponding match object. Return None if the string does not match the pattern; note that this is different from a zero-length match.

Нове в версії 3.4.

re.split(pattern, string, maxsplit=0, flags=0)

Розділіть рядок на входження шаблону. Якщо в шаблоні використовуються дужки для захоплення, тоді текст усіх груп у шаблоні також повертається як частина результуючого списку. Якщо maxsplit відмінний від нуля, відбувається не більше ніж maxsplit, а залишок рядка повертається як останній елемент списку.

>>> re.split(r'\W+', 'Words, words, words.')
['Words', 'words', 'words', '']
>>> re.split(r'(\W+)', 'Words, words, words.')
['Words', ', ', 'words', ', ', 'words', '.', '']
>>> re.split(r'\W+', 'Words, words, words.', 1)
['Words', 'words, words.']
>>> re.split('[a-f]+', '0a3B9', flags=re.IGNORECASE)
['0', '3', '9']

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

>>> re.split(r'(\W+)', '...words, words...')
['', '...', 'words', ', ', 'words', '...', '']

Таким чином, компоненти роздільників завжди знаходяться за однаковими відносними індексами в списку результатів.

Порожні збіги для шаблону розділяють рядок лише тоді, коли вони не суміжні з попереднім порожнім збігом.

>>> re.split(r'\b', 'Words, words, words.')
['', 'Words', ', ', 'words', ', ', 'words', '.']
>>> re.split(r'\W*', '...words...')
['', '', 'w', 'o', 'r', 'd', 's', '', '']
>>> re.split(r'(\W*)', '...words...')
['', '...', '', '', 'w', '', 'o', '', 'r', '', 'd', '', 's', '...', '', '', '']

Змінено в версії 3.1: Додано необов’язковий аргумент flags.

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

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

Повертає всі неперекриваючі збіги шаблону в рядку у вигляді списку рядків або кортежів. Рядок сканується зліва направо, і збіги повертаються в порядку знайдення. Порожні збіги включаються в результат.

Результат залежить від кількості груп захоплення в шаблоні. Якщо груп немає, поверніть список рядків, які відповідають повному шаблону. Якщо існує рівно одна група, поверніть список рядків, які відповідають цій групі. Якщо присутні кілька груп, поверніть список кортежів рядків, які відповідають групам. Незахоплюючі групи не впливають на форму результату.

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

Return an iterator yielding match objects over all non-overlapping matches for the RE pattern in string. The string is scanned left-to-right, and matches are returned in the order found. Empty matches are included in the result.

Змінено в версії 3.7: Непорожні збіги тепер можуть починатися одразу після попереднього порожнього збігу.

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

Повертає рядок, отриманий шляхом заміни крайніх лівих неперекриваючих входжень pattern у string на заміну repl. Якщо шаблон не знайдено, рядок повертається без змін. 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{'

If repl is a function, it is called for every non-overlapping occurrence of pattern. The function takes a single match object argument, and returns the replacement string. For example:

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

The pattern may be a string or a pattern object.

Необов’язковий аргумент 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: Unknown escapes in repl consisting of '\' and an ASCII letter now are errors.

Змінено в версії 3.7: Empty matches for the pattern are replaced when adjacent to a previous non-empty match.

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

Виконайте ту саму операцію, що й sub(), але поверніть кортеж (new_string, number_of_subs_made).

Змінено в версії 3.1: Додано необов’язковий аргумент flags.

Змінено в версії 3.5: Невідповідні групи замінюються порожнім рядком.

re.escape(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)

Exception raised when a string passed to one of the functions here is not a valid regular expression (for example, it might contain unmatched parentheses) or when some other error occurs during compilation or matching. It is never an error if a string contains no match for a pattern. The error instance has the following additional attributes:

msg

Неформатне повідомлення про помилку.

pattern

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

pos

Індекс у шаблоні, де не вдалося компілювати (може бути None).

lineno

Рядок, що відповідає pos (може бути None).

colno

Стовпець, що відповідає pos (може бути None).

Змінено в версії 3.5: Додані додаткові атрибути.

Об’єкти регулярного виразу

Compiled regular expression objects support the following methods and attributes:

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

Scan through string looking for the first location where this regular expression produces a match, and return a corresponding match object. Return None if no position in the string matches the pattern; note that this is different from finding a zero-length match at some point in the string.

Необов’язковий другий параметр 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]])

If zero or more characters at the beginning of string match this regular expression, return a corresponding match object. Return None if the string does not match the pattern; note that this is different from a zero-length match.

Необов’язкові параметри pos і endpos мають те саме значення, що й для методу search().

>>> pattern = re.compile("o")
>>> pattern.match("dog")      # No match as "o" is not at the start of "dog".
>>> pattern.match("dog", 1)   # Match as "o" is the 2nd character of "dog".
<re.Match object; span=(1, 2), match='o'>

Якщо ви хочете знайти збіг будь-де в string, використовуйте натомість search() (див. також search() проти match()).

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

If the whole string matches this regular expression, return a corresponding match object. Return None if the string does not match the pattern; note that this is different from a zero-length match.

Необов’язкові параметри pos і endpos мають те саме значення, що й для методу search().

>>> pattern = re.compile("o[gh]")
>>> pattern.fullmatch("dog")      # No match as "o" is not at the start of "dog".
>>> pattern.fullmatch("ogre")     # No match as not the full string matches.
>>> pattern.fullmatch("doggie", 1, 3)   # Matches within given limits.
<re.Match object; span=(1, 3), match='og'>

Нове в версії 3.4.

Pattern.split(string, maxsplit=0)

Ідентична функції split(), використовуючи скомпільований шаблон.

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

Подібно до функції findall(), використовує скомпільований шаблон, але також приймає додаткові параметри pos і endpos, які обмежують область пошуку, як для search().

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

Подібно до функції finditer(), яка використовує скомпільований шаблон, але також приймає додаткові параметри pos і endpos, які обмежують область пошуку, як для search().

Pattern.sub(repl, string, count=0)

Ідентична функції sub(), використовуючи скомпільований шаблон.

Pattern.subn(repl, string, count=0)

Ідентична функції subn(), використовуючи скомпільований шаблон.

Pattern.flags

The regex matching flags. This is a combination of the flags given to compile(), any (?...) inline flags in the pattern, and implicit flags such as UNICODE if the pattern is a Unicode string.

Pattern.groups

Кількість груп захоплення в шаблоні.

Pattern.groupindex

Словник, що відображає будь-які символічні назви груп, визначені (?P <id> ), на номери груп. Словник порожній, якщо в шаблоні не використовувалися символічні групи.

Pattern.pattern

Рядок шаблону, з якого було скомпільовано об’єкт шаблону.

Змінено в версії 3.7: Додано підтримку copy.copy() і copy.deepcopy(). Зкомпільовані об’єкти регулярного виразу вважаються атомарними.

Зіставте об’єкти

Об’єкти відповідності завжди мають логічне значення True. Оскільки match() і search() повертають None за відсутності збігу, ви можете перевірити, чи був збіг за допомогою простого оператора if: :

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

Match objects support the following methods and attributes:

Match.expand(template)

Return the string obtained by doing backslash substitution on the template string template, as done by the sub() method. Escapes such as \n are converted to the appropriate characters, and numeric backreferences (\1, \2) and named backreferences (\g<1>, \g<name>) are replaced by the contents of the corresponding group.

Змінено в версії 3.5: Невідповідні групи замінюються порожнім рядком.

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

Повертає одну або кілька підгруп збігу. Якщо є один аргумент, результатом буде один рядок; якщо є кілька аргументів, результатом є кортеж з одним елементом на аргумент. Без аргументів group1 за замовчуванням дорівнює нулю (повертається весь збіг). Якщо аргумент groupN дорівнює нулю, відповідним значенням, що повертається, є весь відповідний рядок; якщо він знаходиться у включному діапазоні [1..99], це рядок, що відповідає відповідній групі в дужках. Якщо номер групи є від’ємним або перевищує кількість груп, визначених у шаблоні, виникає виняток IndexError. Якщо група міститься в частині шаблону, яка не відповідає, відповідним результатом є None. Якщо група міститься в частині шаблону, яка збігалася кілька разів, повертається останній збіг.

>>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")
>>> m.group(0)       # The entire match
'Isaac Newton'
>>> m.group(1)       # The first parenthesized subgroup.
'Isaac'
>>> m.group(2)       # The second parenthesized subgroup.
'Newton'
>>> m.group(1, 2)    # Multiple arguments give us a tuple.
('Isaac', 'Newton')

Якщо регулярний вираз використовує синтаксис (?P <name> ...), аргументи groupN також можуть бути рядками, що ідентифікують групи за назвою групи. Якщо рядковий аргумент не використовується як ім’я групи в шаблоні, виникає виняток IndexError.

Помірно складний приклад:

>>> m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds")
>>> m.group('first_name')
'Malcolm'
>>> m.group('last_name')
'Reynolds'

Іменовані групи також можна посилатися за їх індексом:

>>> m.group(1)
'Malcolm'
>>> m.group(2)
'Reynolds'

Якщо група збігається кілька разів, доступним буде лише останній збіг:

>>> m = re.match(r"(..)+", "a1b2c3")  # Matches 3 times.
>>> m.group(1)                        # Returns only the last match.
'c3'
Match.__getitem__(g)

Це ідентично m.group(g). Це дозволяє легше отримати доступ до окремої групи з матчу:

>>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")
>>> m[0]       # The entire match
'Isaac Newton'
>>> m[1]       # The first parenthesized subgroup.
'Isaac'
>>> m[2]       # The second parenthesized subgroup.
'Newton'

Нове в версії 3.6.

Match.groups(default=None)

Повертає кортеж, що містить усі підгрупи відповідності, від 1 до будь-якої кількості груп у шаблоні. Аргумент default використовується для груп, які не брали участі в матчі; за замовчуванням None.

Наприклад:

>>> m = re.match(r"(\d+)\.(\d+)", "24.1632")
>>> m.groups()
('24', '1632')

Якщо ми зробимо знак після коми необов’язковим, не всі групи можуть брати участь у матчі. Для цих груп за замовчуванням буде None, якщо не вказано аргумент default:

>>> m = re.match(r"(\d+)\.?(\d+)?", "24")
>>> m.groups()      # Second group defaults to None.
('24', None)
>>> m.groups('0')   # Now, the second group defaults to '0'.
('24', '0')
Match.groupdict(default=None)

Повертає словник, що містить усі іменовані підгрупи збігу, ключ яких містить назву підгрупи. Аргумент default використовується для груп, які не брали участі в матчі; за замовчуванням None. Наприклад:

>>> m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds")
>>> m.groupdict()
{'first_name': 'Malcolm', 'last_name': 'Reynolds'}
Match.start([group])
Match.end([group])

Повертає індекси початку та кінця підрядка, які відповідають групі; group за замовчуванням дорівнює нулю (це означає весь відповідний підрядок). Повертає -1, якщо група існує, але не брала участі в матчі. Для об’єкта збігу 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)). Зауважте, що якщо група не брала участі в матчі, це (-1, -1). група за замовчуванням дорівнює нулю, весь збіг.

Match.pos

Значення pos, яке було передано в метод search() або match() об’єкта regex. Це індекс у рядку, за яким механізм RE почав шукати збіг.

Match.endpos

Значення endpos, яке було передано в метод search() або match() об’єкта regex. Це індекс у рядку, за який механізм RE не виходить.

Match.lastindex

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

Match.lastgroup

Ім’я останньої відповідної групи захоплення або None, якщо група не мала назви, або якщо жодна група не була знайдена взагалі.

Match.re

Об’єкт регулярного виразу, чий метод match() або search() створив цей екземпляр відповідності.

Match.string

Рядок передається до match() або search().

Змінено в версії 3.7: Додано підтримку copy.copy() і copy.deepcopy(). Об’єкти відповідності вважаються атомарними.

Приклади регулярних виразів

Перевірка на пару

У цьому прикладі ми використаємо наступну допоміжну функцію, щоб відобразити об’єкти відповідності трохи витонченіше:

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

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

Щоб перевірити, чи даний рядок є правильною рукою, можна зробити наступне:

>>> valid = re.compile(r"^[a2-9tjqk]{5}$")
>>> displaymatch(valid.match("akt5q"))  # Valid.
"<Match: 'akt5q', groups=()>"
>>> displaymatch(valid.match("akt5e"))  # Invalid.
>>> displaymatch(valid.match("akt"))    # Invalid.
>>> displaymatch(valid.match("727ak"))  # Valid.
"<Match: '727ak', groups=()>"

Ця остання роздача, "727ak", містила пару або дві карти однакового значення. Щоб зіставити це з регулярним виразом, можна використовувати зворотні посилання як такі:

>>> pair = re.compile(r".*(.).*\1")
>>> displaymatch(pair.match("717ak"))     # Pair of 7s.
"<Match: '717', groups=('7',)>"
>>> displaymatch(pair.match("718ak"))     # No pairs.
>>> displaymatch(pair.match("354aa"))     # Pair of aces.
"<Match: '354aa', groups=('a',)>"

Щоб дізнатися, з якої карти складається пара, можна використати метод group() об’єкта відповідності таким чином:

>>> pair = 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 does not currently have an equivalent to scanf(). Regular expressions are generally more powerful, though also more verbose, than scanf() format strings. The table below offers some more-or-less equivalent mappings between scanf() format tokens and regular expressions.

scanf() Token

Регулярний вираз

%c

.

%5c

.{5}

%d

[-+]?\d+

%e, %E, %f, %g

[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?

%i

[-+]?(0[xX][\dA-Fa-f]+|0[0-7]*|\d+)

%o

[-+]?[0-7]+

%s

\S+

%u

\d+

%x, %X

[-+]?(0[xX])?[\dA-Fa-f]+

Щоб витягти назву файлу та номери з рядка на зразок

/usr/sbin/sendmail - 0 errors, 4 warnings

you would use a scanf() format like

%s - %d errors, %d warnings

Еквівалентним регулярним виразом буде:

(\S+) - (\d+) errors, (\d+) warnings

search() проти match()

Python offers two different primitive operations based on regular expressions: re.match() checks for a match only at the beginning of the string, while re.search() checks for a match anywhere in the string (this is what Perl does by default).

Наприклад:

>>> re.match("c", "abcdef")    # No match
>>> re.search("c", "abcdef")   # Match
<re.Match object; span=(2, 3), match='c'>

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

>>> re.match("c", "abcdef")    # No match
>>> re.search("^c", "abcdef")  # No match
>>> re.search("^a", "abcdef")  # Match
<re.Match object; span=(0, 1), match='a'>

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

>>> re.match('X', 'A\nB\nX', re.MULTILINE)  # No match
>>> re.search('^X', 'A\nB\nX', re.MULTILINE)  # Match
<re.Match object; span=(4, 5), match='X'>

Створення телефонної книги

split() розбиває рядок на список, розділений переданим шаблоном. Цей метод є безцінним для перетворення текстових даних у структури даних, які можна легко читати та змінювати Python, як показано в наступному прикладі створення телефонної книги.

По-перше, ось вхідні дані. Зазвичай він може надходити з файлу, тут ми використовуємо синтаксис рядка в потрійних лапках

>>> text = """Ross McFluff: 834.345.1254 155 Elm Street
...
... Ronald Heathmore: 892.345.3428 436 Finley Avenue
... Frank Burger: 925.541.7625 662 South Dogwood Way
...
...
... Heather Albrecht: 548.326.4584 919 Park Place"""

Записи розділені одним або кількома символами нового рядка. Тепер ми перетворюємо рядок на список, у якому кожен непорожній рядок має окремий запис:

>>> entries = re.split("\n+", text)
>>> entries
['Ross McFluff: 834.345.1254 155 Elm Street',
'Ronald Heathmore: 892.345.3428 436 Finley Avenue',
'Frank Burger: 925.541.7625 662 South Dogwood Way',
'Heather Albrecht: 548.326.4584 919 Park Place']

Нарешті, розділіть кожен запис на список із іменем, прізвищем, номером телефону та адресою. Ми використовуємо параметр maxsplit split(), тому що в адресі є пробіли, наш шаблон поділу:

>>> [re.split(":? ", entry, 3) for entry in entries]
[['Ross', 'McFluff', '834.345.1254', '155 Elm Street'],
['Ronald', 'Heathmore', '892.345.3428', '436 Finley Avenue'],
['Frank', 'Burger', '925.541.7625', '662 South Dogwood Way'],
['Heather', 'Albrecht', '548.326.4584', '919 Park Place']]

Шаблон :? відповідає двокрапці після прізвища, щоб він не зустрічався в списку результатів. За допомогою maxsplit 4 ми можемо відокремити номер будинку від назви вулиці:

>>> [re.split(":? ", entry, 4) for entry in entries]
[['Ross', 'McFluff', '834.345.1254', '155', 'Elm Street'],
['Ronald', 'Heathmore', '892.345.3428', '436', 'Finley Avenue'],
['Frank', 'Burger', '925.541.7625', '662', 'South Dogwood Way'],
['Heather', 'Albrecht', '548.326.4584', '919', 'Park Place']]

Перебирання тексту

sub() замінює кожне входження шаблону рядком або результатом функції. У цьому прикладі демонструється використання sub() із функцією для «переміщення» тексту або випадкового порядку всіх символів у кожному слові речення, за винятком першого та останнього символів:

>>> def repl(m):
...     inner_word = list(m.group(2))
...     random.shuffle(inner_word)
...     return m.group(1) + "".join(inner_word) + m.group(3)
>>> text = "Professor Abdolmalek, please report your absences promptly."
>>> re.sub(r"(\w)(\w+)(\w)", repl, text)
'Poefsrosr Aealmlobdk, pslaee reorpt your abnseces plmrptoy.'
>>> re.sub(r"(\w)(\w+)(\w)", repl, text)
'Pofsroser Aodlambelk, plasee reoprt yuor asnebces potlmrpy.'

Знайти всі прислівники

findall() відповідає всім входженням шаблону, а не лише першому, як це робить search(). Наприклад, якщо автор хоче знайти всі прислівники в якомусь тексті, він може використати findall() у такий спосіб:

>>> text = "He was carefully disguised but captured quickly by police."
>>> re.findall(r"\w+ly\b", text)
['carefully', 'quickly']

Знайти всі прислівники та їх позиції

If one wants more information about all matches of a pattern than the matched text, finditer() is useful as it provides match objects instead of strings. Continuing with the previous example, if a writer wanted to find all of the adverbs and their positions in some text, they would use finditer() in the following manner:

>>> 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"текст") зберігає регулярні вирази нормальними. Без нього кожен зворотний слеш ('\') у регулярному виразі повинен був би мати префікс іншим, щоб уникнути його. Наприклад, два наступних рядки коду функціонально ідентичні:

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

Якщо потрібно зіставити літеральний зворотний слеш, його потрібно екранувати у регулярному виразі. У необробленому рядковому записі це означає r"\\". Без нотації необробленого рядка потрібно використовувати "\\\\", роблячи наступні рядки коду функціонально ідентичними:

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

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

Токенизатор або сканер аналізує рядок, щоб класифікувати групи символів. Це корисний перший крок у написанні компілятора чи інтерпретатора.

Текстові категорії вказуються регулярними виразами. Техніка полягає в тому, щоб об’єднати їх у єдиний основний регулярний вираз і виконати цикл послідовних збігів:

from typing import NamedTuple
import re

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

def tokenize(code):
    keywords = {'IF', 'THEN', 'ENDIF', 'FOR', 'NEXT', 'GOSUB', 'RETURN'}
    token_specification = [
        ('NUMBER',   r'\d+(\.\d*)?'),  # Integer or decimal number
        ('ASSIGN',   r':='),           # Assignment operator
        ('END',      r';'),            # Statement terminator
        ('ID',       r'[A-Za-z]+'),    # Identifiers
        ('OP',       r'[+\-*/]'),      # Arithmetic operators
        ('NEWLINE',  r'\n'),           # Line endings
        ('SKIP',     r'[ \t]+'),       # Skip over spaces and tabs
        ('MISMATCH', r'.'),            # Any other character
    ]
    tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification)
    line_num = 1
    line_start = 0
    for mo in re.finditer(tok_regex, code):
        kind = mo.lastgroup
        value = mo.group()
        column = mo.start() - line_start
        if kind == 'NUMBER':
            value = float(value) if '.' in value else int(value)
        elif kind == 'ID' and value in keywords:
            kind = value
        elif kind == 'NEWLINE':
            line_start = mo.end()
            line_num += 1
            continue
        elif kind == 'SKIP':
            continue
        elif kind == 'MISMATCH':
            raise RuntimeError(f'{value!r} unexpected on line {line_num}')
        yield Token(kind, value, line_num, column)

statements = '''
    IF quantity THEN
        total := total + price * quantity;
        tax := price * 0.05;
    ENDIF;
'''

for token in tokenize(statements):
    print(token)

Токенізатор видає такий вихід:

Token(type='IF', value='IF', line=2, column=4)
Token(type='ID', value='quantity', line=2, column=7)
Token(type='THEN', value='THEN', line=2, column=16)
Token(type='ID', value='total', line=3, column=8)
Token(type='ASSIGN', value=':=', line=3, column=14)
Token(type='ID', value='total', line=3, column=17)
Token(type='OP', value='+', line=3, column=23)
Token(type='ID', value='price', line=3, column=25)
Token(type='OP', value='*', line=3, column=31)
Token(type='ID', value='quantity', line=3, column=33)
Token(type='END', value=';', line=3, column=41)
Token(type='ID', value='tax', line=4, column=8)
Token(type='ASSIGN', value=':=', line=4, column=12)
Token(type='ID', value='price', line=4, column=15)
Token(type='OP', value='*', line=4, column=21)
Token(type='NUMBER', value=0.05, line=4, column=23)
Token(type='END', value=';', line=4, column=27)
Token(type='ENDIF', value='ENDIF', line=5, column=4)
Token(type='END', value=';', line=5, column=9)
Frie09

Фрідл, Джеффрі. Освоєння регулярних виразів. 3rd ed., O’Reilly Media, 2009. Третє видання книги більше не охоплює Python взагалі, але перше видання охоплювало написання хороших шаблонів регулярних виразів дуже детально.