Рубрики
Без рубрики

Python Re группы

В этом руководстве объясняется все, что вам нужно знать о сопоставленных группах в пакете Python’s Re для регулярных выражений. Возможно, вы также прочитали термин «захватывающие группы», которые указывают на ту же концепцию. Когда вы прочитали по учебнику, вы также можете посмотреть видео-видео, где я объясню все простым способом: https://youtu.be/jwkciuqcdh4 … Python Re группы Подробнее »

Автор оригинала: Chris.

Это руководство объясняет все, что вам нужно знать о Соответствующие группы в Python’s Re Пакет Для регулярных выражений. Возможно, вы также прочитали термин “Группы захвата” Что указывает на ту же концепцию.

Как вы прочитали по учебнику, вы также можете посмотреть видео-видео, где я объясню все простым способом:

Связанная статья: Python Regex SuperPower – Ultimate Guide

Вы хотите освоить сверхдержаву Regeex? Проверьте мою новую книгу Самый умный способ изучать регулярные выражения в Python С инновационным 3-ступенчатым подходом для активного обучения: (1) Изучение книги главы, (2) Решите головоломки кода и (3) Смотреть воспроизведение главы видео.

Итак, начнем с основы:

Соответствующая группа ()

Что случилось подходящей группой?

Как вы используете скольи к структуре математических выражений, (2 + 2) * 2 против 2 + (2 * 2) Вы используете скольи к структуре Регулярные выражения Отказ Пример Regex, который делает это 'A (B | C)' Отказ Весь контент, заключенный в отверстие и закрытие скобок, называется Соответствующая группа (или Capture Group ). Вы можете иметь несколько соответствующих групп в одном Regex. И вы даже можете иметь иерархические подходящие группы, например 'A (B | (CD))' Отказ

Одним из больших преимуществ подходящей группы является то, что оно запечатлевает соответствующую подстроку. Вы можете получить его в других частях регулярного выражения или после анализа результата всего сопоставления Regex.

У даваем краткий пример для наиболее основного использования соответствующей группы – для структурирования Regex.

Скажи, что вы создаете Regex б? (а.) * С соответствующей группой (а.) Это соответствует всем шаблонам, начиная с нуля или одного вхождения символа 'b' и произвольное количество двухсистемных последовательностей, начинающихся с символа «А» Отказ Следовательно, строки «Бакакака» , «АААА» , '' (пустая строка), а «Хабабабабаб» Все соответствует вашему Regex.

Использование скобок для структурирования регулярного выражения интуитивно понятно и должно приходить к вам, потому что те же правила применяются как для арифметических операций. Тем не менее, есть более продвинутое использование групп Regex: поиск.

Вы можете получить соответствующий контент каждой соответствующей группы. Так что следующий вопрос естественно возникает:

Как получить первую подходящую группу?

Существует два сценария, когда вы хотите получить доступ к содержанию ваших сопоставленных групп:

  1. Доступ к соответствующей группе в шаблоне REGEX, чтобы повторно использовать частично сопоставленный текст из одной группы, где-то еще.
  2. Доступ к соответствующей группе после всей операции совпадения, чтобы проанализировать соответствующий текст в вашем Python Code.

В Первый случай Вы просто получите первую подходящую группу с \ номер Специальная последовательность. Например, чтобы получить первую подходящую группу, вы бы использовали \ 1 Специальная последовательность. Вот пример:

>>> import re
>>> re.search(r'(j.n) is \1','jon is jon')

Вы будете использовать эту функцию. Все остальные имена, которые также будут соответствовать шаблону).

Обратите внимание, что нумерация групп начинается с \ 1 а не с \ 0 – Редкое исключение из правила, которое в программировании все нумерация начинается с 0.

В Второй случай Вы хотите узнать содержимое первой группы после всего матча. Как ты это делаешь?

Ответ также прост: используйте m.group (0) Метод на Соответствующий объект м Отказ Вот пример:

>>> import re
>>> m = re.search(r'(j.n)','jon is jon')
>>> m.group(1)
'jon'

Нумерация работает последовательно с ранее введенным нумерацией группы Regex: начните с идентификатора 1 для доступа к содержимому первой группы.

Как получить все другие подходящие группы?

Опять же, есть два разных намерения, когда задают этот вопрос:

  1. Доступ к соответствующей группе в шаблоне REGEX, чтобы повторно использовать частично сопоставленный текст из одной группы, где-то еще.
  2. Доступ к соответствующей группе после всей операции совпадения, чтобы проанализировать соответствующий текст в вашем Python Code.

В Первый случай Вы используете специальную последовательность \ 2 Чтобы получить доступ к второй подходящей группе, \ 3 Чтобы получить доступ к третьей подходящей группе, и \ 99 Для доступа к девяносто девятой группе сопоставления.

Вот пример:

>>> import re
>>> re.search(r'(j..) (j..)\s+\2', 'jon jim jim')

>>> re.search(r'(j..) (j..)\s+\2', 'jon jim jon')
>>> 

Как видите, специальная последовательность \ 2 относится к соответствующему содержанию второй группы «Джим» Отказ

В Второй случай , вы также можете просто увеличить идентификатор, чтобы получить доступ к другим сопоставленным группам в вашем коде Python:

>>> import re
>>> m =  re.search(r'(j..) (j..)\s+\2', 'jon jim jim')
>>> m.group(0)
'jon jim jim'
>>> m.group(1)
'jon'
>>> m.group(2)
'jim'

Этот код также показывает интересную функцию: если вы используете идентификатор 0 в качестве аргумента для m.group (0) Метод, модуль Regex даст вам содержимое всего матча. Вы можете думать об этом, как первая группа, являющаяся весь матч.

Названные группы: (? P <имя> …) и)

Доступ к захваченной группе, используя обозначения \ номер Не всегда удобно, а иногда даже не возможен (например, если у вас есть более 99 групп в вашем Regex). Основным недостатком регулярных выражений является то, что они склонны к читанию. Поэтому важно знать о разных настройках для повышения читаемости.

Одной из таких оптимизаций является именованная группа. Это действительно только что: подходящая группа, которая захватывает часть матча, но с одним поворотом: у него есть имя. Теперь вы можете использовать это имя для доступа к захваченной группе в более позднем точке в вашем шаблоне регулярного выражения. Это может улучшить читаемость регулярного выражения.

import re
pattern = '(?P["\']).*(?P=quote)'
text = 'She said "hi"'
print(re.search(pattern, text))
# 

Код ищет подстроки, которые прилагаются в одну или двойную кавычки. Вы сначала сопоставьте открытие цитаты, используя Regex [». Сопоставьте закрытие цитаты одного и того же персонажа (одна или двойная цитата).

Не захватывающие группы (?: …)

В предыдущих примерах вы видели, как сопоставить и захватывать группы с круглыми скобками (...) Отказ Вы узнали, что каждый матч эта основной оператор группы захвачен так, чтобы вы могли получить его позже в Regex со специальными командами \ 1 , \ 2 , …, \ 99 или после матча на соответствующем объекте м С методом m.group (1) , M.Group (2) , и так далее.

Но что, если вам это не нужно? Что, если вам просто нужно сохранить шаблон Regex по порядку – но вы не хотите захватывать содержимое соответствующей группы?

Простое решение – это операция без захвата группы (?: ...) Отказ Вы можете использовать это так же, как операция по захвату группы (...) Отказ Вот пример:

>>>import re
>>> re.search('(?:python|java) is great', 'python is great. java is great.')

Незаключающая группа существует с единственной целью структурирования Regex. Вы не можете использовать его контент позже:

>>> m = re.search('(?:python|java) is great', 'python is great. java is great.')
>>> m.group(1)
Traceback (most recent call last):
  File "", line 1, in 
    m.group(1)
IndexError: no such group
>>> 

Если вы попытаетесь получить доступ к содержимому не захватывающую группу, двигатель REGEX бросит IndexError: нет такой группы Отказ

Конечно, есть прямая альтернатива без захватных групп. Вы можете просто использовать обычную (захват) группу, но не доступа к его содержимому. Лишь редко будет наказание на производительность захвата группы, которая не требуется, имеет какое-либо значимое влияние на ваше общее приложение.

Положительный lookahead (? = …)

Концепция lookahead – очень мощный, и любой продвинутый кодер должен знать это. Друг недавно сказал мне, что он написал сложное регулярное выражение, которое игнорирует порядок вхождений двух слов в данном тексте. Это сложная проблема и без концепции Lookahead, полученный код будет сложен и трудно понять. Тем не менее, концепция Lookahead делает эту проблему простой писать и прочитать.

Но первые вещи первыми: Как работает Ahead Assertion?

В нормальной обработке регулярных выражений, регулярное выражение сопоставляется слева направо. Двигатель Regex «потребляет» частично соответствующие подстроки. Потребляемая подстрока не может быть сопоставлена любой другой частью Regex.

Рисунок: Простой пример lookahead. Регулярный механизм экспрессии соответствует («потребляет») строку частично. Затем он проверяет, может ли оставшийся шаблон быть сопоставлен без надобрения его.

Думайте о утверждении Lookahead в качестве непоглощающего списка шаблонов. Двигатель REGEX идет слева направо – поиск шаблона. В каждой точке он имеет одну «текущую» положение для проверки, является ли эта позиция первой позиции оставшегося совпадения. Другими словами, двигатель REGEX пытается «потреблять» следующий символ как (частичное) совпадение шаблона.

Преимущество выражения Lookahead заключается в том, что он не потребляет ничего. Это просто «выглядит вперед», начиная с текущей позиции, следует ли сделать то, что теоретически соответствует образе узора. Если это не так, двигатель Regex не может двигаться дальше. Далее он «возврат» – что это просто модный способ сказать: он возвращается к предыдущему решению и пытается сопоставить что-то еще.

Положительный пример Lookahead: Как сопоставить два слова в произвольном порядке?

Что если вы хотите найти данный текст для шаблона A и Pattern B-но ни в одном порядке? Если оба шаблона появляются в любом месте строки, вся строка должна быть возвращена в виде совпадения.

Теперь это немного сложнее, потому что любая шаблон регулярных выражений заказывается слева направо. Простое решение состоит в том, чтобы использовать Ahead Assertion (?. * A) Чтобы проверить, появится ли Regeex A в любой точке строки. (Обратите внимание, что мы принимаем одну строку строки, поскольку шаблон. * По умолчанию не соответствует символу Newline.)

Давайте сначала посмотрим на минимальное решение для проверки двух шаблонов в любой точке строки (скажем, шаблоны «Привет» и «вы»).

>>> import re
>>> pattern = '(?=.*hi)(?=.*you)'
>>> re.findall(pattern, 'hi how are yo?')
[]
>>> re.findall(pattern, 'hi how are you?')
['']

В первом примере оба слова не появляются. Во втором примере они делают.

Давайте вернемся к выражению (? =. * Привет) (? =. * Вы), чтобы сопоставить строки, которые содержат как «HI», так и «вы». Почему это работает?

Причина в том, что выражения Lookahead не потребляют ничего. Вы сначала поищите произвольное количество персонажей. *, А затем слово привет. Но потому что двигатель Regex ничего не потреблял, это все еще в То же самое положение в начале строки Отказ Итак, вы можете повторить то же самое для этого слова.

Обратите внимание, что этот метод не заботится о порядке двух слов:

>>> import re
>>> pattern = '(?=.*hi)(?=.*you)'
>>> re.findall(pattern, 'hi how are you?')
['']
>>> re.findall(pattern, 'you are how? hi!')
['']

Независимо от того, какое слово «HI» или «Вы» появляются первым в тексте, двигатель Regex находит обоими.

Вы можете спросить: почему вывод пустой строки? Причина в том, что двигатель Regex не употреблял какой-либо характер. Он только что проверил поиск. Таким образом, простое решение – потреблять всех символов следующим образом:

>>> import re
>>> pattern = '(?=.*hi)(?=.*you).*'
>>> re.findall(pattern, 'you fly high')
['you fly high']

Теперь вся строка – это совпадение, потому что после проверки Lookahead с ‘(? =. * Привет) (? =. * Вы)’, вы также употребляете всю строку «. *».

Отрицательный oshead (?! …)

Отрицательный Lookaead работает так же, как положительный поиск, только проверяет, что данный рисунок Regex делает не происходят вперед из определенной позиции.

Вот пример:

>>> import re
>>> re.search('(?!.*hi.*)', 'hi say hi?')

Отрицательный образец Lookahead (?!. * Привет. *) гарантирует, что, идя вперед в строке, нет возникновения подстроки «Привет» Отказ Первая позиция, где это удерживает, это позиция 8 (сразу после второго 'h' ). Как и положительный поиск, негативное lookahead не потребляет любой символ, поэтому результат – пустая строка (которая является действительным совпадением шаблона).

Вы даже можете объединить несколько негативных Lookaeads, как это:

>>> re.search('(?!.*hi.*)(?!\?).', 'hi say hi?')

Вы ищете должность, где ни один «HI» не находится в Lookahead, и не подходит ли персонаж вопросительного знака немедленно. На этот раз мы потребляем произвольный характер, поэтому полученный матч является символом «Я» Отказ

Групповые флаги (? Ailmsux: …) и (? Ailmsux)

Вы можете управлять двигателем Regex с Флаги аргумент из Re.findall () , Re.Search () или Re.match () методы. Например, если вы не заботитесь о капитализации вашей подобранной подстроки, вы можете пройти Re.ignoRecase Флаг к Методы Regex :

>>> re.findall('PYTHON', 'python is great', flags=re.IGNORECASE)
['python']

Но использование глобального флага для всего регеляции не всегда является оптимальным. Что, если вы хотите игнорировать капитализацию только для определенного подреги?

Вы можете сделать это с флагами группы: a, i, l, m, s, u и x. Каждый флаг группы имеет свой смысл:

Синтаксис Имея в виду
a Если вы не используете этот флаг, специальные символы Regex Python \ W, \ W, \ b, \ b, \ d, \ d, \ s и \ s будут соответствовать символам Unicode. Если вы используете этот флаг, эти специальные символы будут соответствовать только символам ASCII – как указано имя.
i Если вы используете этот флаг, двигатель Regex будет выполнять совпадение в случае сопоставления. Поэтому, если вы ищете [A-Z], он также будет соответствовать [A-Z].
L Не используйте этот флаг – когда-либо. Он обесценился – идея состояла в том, чтобы выполнить сопоставление нечувствительности к регистру в зависимости от вашей текущей местности. Но это не надежно.
m Этот флаг включает в следующую функцию: начало строки Regex ‘^’ совпадает в начале каждой строки (а не только в начале строки). То же самое относится и к концу строки Regex ‘$’, который сейчас соответствует также в конце каждой строки в многострочной строке.
s Без использования этого флага точечное регулярное выражение. ‘ Соответствует всем персонажам, кроме символа Newline ‘\ N’. Переключите этот флаг, чтобы действительно сопоставить все символы, включая новенький символ.
x Чтобы улучшить читаемость сложных регулярных выражений, вы можете позволить комментариям и (многострочному) форматированию самого Regeex. Это возможно с этим флагом: все пробелы и строки, которые начинаются с символа «#», игнорируются в Regex.

Например, если вы хотите отключить дифференциацию капитализации, вы будете использовать Я Флаг следующим образом:

>>> re.findall('(?i:PYTHON)', 'python is great')
['python']

Вы также можете отключить капитализацию для всего регеляции с помощью «Глобального флага Группы» (? я) следующим образом:

>>> re.findall('(?i)PYTHON', 'python is great')
['python']

Куда пойти отсюда?

Резюме : Вы узнали о сопоставленных группах для структурирования Regex и Painture части соответствующего результата. Затем вы можете получить захваченные группы с \ номер Синтаксис в сам рисунок Regex и с m.group (i) Синтаксис в коде Python на более позднем этапе.

Чтобы узнать основные основы Python, ознакомьтесь с моим бесплатным академией электронной почты Python со многими продвинутыми курсами, включая видеоурок Regex в вашем почтовом ящике.

Присоединяйтесь к 20 000 амбициозных кодеров бесплатно!

Работая в качестве исследователя в распределенных системах, доктор Кристиан Майер нашел свою любовь к учению студентов компьютерных наук.

Чтобы помочь студентам достичь более высоких уровней успеха Python, он основал сайт программирования образования Finxter.com Отказ Он автор популярной книги программирования Python One-listers (Nostarch 2020), Coauthor of Кофе-брейк Python Серия самооставленных книг, энтузиаста компьютерных наук, Фрилансера и владелец одного из лучших 10 крупнейших Питон блоги по всему миру.

Его страсти пишут, чтение и кодирование. Но его величайшая страсть состоит в том, чтобы служить стремлению кодер через Finxter и помогать им повысить свои навыки. Вы можете присоединиться к его бесплатной академии электронной почты здесь.