Python Regex Search
Когда я впервые узнал о регулярных выражениях, я не оценил их силу. Но есть причина, по которой регулярные выражения пережили семь десятилетий технологического сбоя: программисты, понимающие регулярные выражения, имеют огромное преимущество при работе с текстовыми данными. Они могут написать в одной строке кода выражение, что занимает десятки других!
Как re.search() работает в Python?
Метод re.search(pattern, string) сопоставляет первое вхождение шаблона в строке и возвращает объект соответствия.
Спецификация :
re.search(pattern, string, flags=0)
Метод re.search() имеет до трех аргументов.
- pattern: шаблон регулярного выражения, который вы хотите сопоставить.
- string: строка, которую вы хотите найти для шаблона.
- flags(необязательный аргумент): более продвинутый модификатор, который позволяет вам настроить поведение функции.
Мы рассмотрим их более подробно позже.
Метод re.search() возвращает объект соответствия. Вы можете спросить (и это правильно):
Что такое объект соответствия?
Если регулярное выражение совпадает с частью вашей строки, с ней приходит много полезной информации: какова точная позиция соответствия? Какие группы регулярных выражений были сопоставлены и где?
Объект соответствия является простой оболочкой для этой информации. Некоторые методы регулярных выражений re-package в Python, такие как search()
, автоматически создают объект соответствия при первом сопоставлении с образцом.
На этом этапе вам не нужно детально исследовать объект соответствия. Просто знайте, что мы можем получить доступ к начальной и конечной позициям совпадения в строке, вызвав методы m.start()
и m.end()
для объекта соответствия m
:
m = re.search('h...o', 'hello world')
m.start()
# 0
m.end()
# 5
'hello world'[m.start():m.end()]
# 'hello'
В первой строке вы создаете объект m с помощью метода re.search(). Шаблон 'h… o
' совпадает в строке 'hello world' в начальной позиции 0. Вы используете начальную и конечную позиции для доступа к подстроке, которая соответствует шаблону.
Руководствуясь примером для re.search()
Сначала вы импортируете модуль re
и создаете текстовую строку для поиска шаблонов регулярных выражений:
import re
text = '''
Ha! let me see her: out, alas! he's cold:
Her blood is settled, and her joints are stiff;
Life and these lips have long been separated:
Death lies on her like an untimely frost
Upon the sweetest flower of all the field.
'''
Допустим, вы хотите найти в тексте строку «her»:
re.search('her', text)
#
Первый аргумент - образец, который нужно найти. В нашем случае это строка «her». Второй аргумент - это текст для анализа. Вы сохранили многострочную строку в переменной - так что вы берете ее в качестве второго аргумента.
Посмотрите на вывод: это объект соответствия! Объект match дает диапазон совпадения, то есть индексы начала и конца совпадения. Мы также можем напрямую получить доступ к этим границам, используя методы start()
и stop()
объекта match:
m = re.search('her', text)
m.start()
#20
m.end()
# 23
Проблема в том, что метод search()
извлекает только первое вхождение шаблона в строке. Если вы хотите найти все совпадения в строке, вы можете использовать метод findall() библиотеки re.
В чем разница между re.search() и re.findall()?
Существует два различия между методами re.search(pattern, string)
и re.findall(pattern, string)
:
re.search(pattern, string)
возвращает объект соответствия, аre.findall(pattern, string)
возвращает список совпадающих строк.re.search(pattern, string)
возвращает только первое совпадение в строке, аre.findall(pattern, string)
возвращает все совпадения в строке.
Оба можно увидеть в следующем примере:
text = 'Python is superior to Python'
re.search('Py...n', text)
#
re.findall('Py...n', text)
# ['Python', 'Python']
Строка «Python is superior to Python» содержит два вхождения «Python». Метод search()
возвращает только объект соответствия первого вхождения. Метод findall()
возвращает список всех вхождений.
В чем разница между re.search() и re.match()?
Методы re.search(pattern, string)
и re.match(pattern, string)
оба возвращают объект соответствия первого соответствия. Однако re.match()
пытается найти совпадение в начале строки, а re.search()
- в любом месте строки.
Вы можете увидеть эту разницу в следующем коде:
text = 'Slim Shady is my name'
re.search('Shady', text)
#
re.match('Shady', text)
# empty
Метод re.search()
извлекает совпадение подстроки 'Shady' как объект сопоставления. Но если вы используете метод re.match()
, совпадения и возвращаемого значения не будет, потому что подстрока 'Shady' не встречается в начале строки 'Slim Shady is my name'.
Как использовать необязательный аргумент flag?
Как вы видели в спецификации, метод search()
поставляется с необязательным третьим аргументом 'flag':
re.search(pattern, string, flags=0)
Какова цель аргумента flag?
Флаги позволяют вам управлять механизмом регулярных выражений. Поскольку регулярные выражения настолько мощны, они являются полезным способом включения и выключения определенных функций (например, игнорировать ли заглавные буквы при сопоставлении с регулярным выражением).
re.ASCII | Если вы не используете этот флаг, специальные символы регулярного выражения Python \w, \W, \b, \B, \d, \D, \s и \S будут соответствовать символам Юникода. Если вы используете этот флаг, эти специальные символы будут соответствовать только символам ASCII - как следует из названия. |
re.A | То же, что и re.ASCII |
re.DEBUG | Если вы используете этот флаг, Python выведет некоторую полезную информацию в оболочку, которая поможет вам отладить ваше регулярное выражение. |
re.IGNORECASE | Если вы используете этот флаг, механизм регулярных выражений выполнит сопоставление без учета регистра. Поэтому, если вы ищете [AZ], оно также будет соответствовать [az]. |
re.I | То же, что и re.IGNORECASE |
re.LOCALE | Не используйте этот флаг - никогда. Это устарело - идея заключалась в том, чтобы выполнять сопоставление без учета регистра в зависимости от вашей текущей локали. Но это не надежно. |
re.L | То же, что и re.LOCALE |
re.M | То же, что и re.MULTILINE |
re.DOTALL | Без использования этого флага точка regex '.' соответствует всем символам, кроме символа новой строки '\n'. Включите этот флаг, чтобы он действительно соответствовал всем символам, включая символ новой строки. |
re.S | То же, что и re.DOTALL |
re.VERBOSE | Чтобы улучшить читаемость сложных регулярных выражений, вы можете разрешить комментарии и (многострочное) форматирование самого регулярного выражения. Это возможно с этим флагом: все пробельные символы и строки, начинающиеся с символа «#», игнорируются в регулярном выражении. |
re.X | То же, что и re.VERBOSE |
text = 'Python is great!'
re.search('PYTHON', text, flags=re.IGNORECASE)
#
Хотя в вашем регулярном выражении 'PYTHON' прописные буквы, мы игнорируем заглавные буквы, используя флаг re.IGNORECASE.