Иероглифы на камне
Перевод статьи «Python Regular Expression».
Сегодня мы хотим поговорить о регулярных выражениях в Python. Пожалуй, стоит начать с определения. Регулярные выражения, иногда называемые re, regex или regexp, представляют собой последовательности символов, составляющие шаблоны, соответствия которым ищутся в строке или тексте. Для работы с regexp в Python есть встроенный модуль re.
Обычное использование регулярного выражения:
search and find)findall)split)sub)Регулярное выражение – это комбинация символов и метасимволов. Из метасимволов доступны следующие:
\ используется для игнорирования специального значения символа[] указывает на класс символов. Например: [a-z] — все буквы латинского алфавита в нижнем регистре, [a-zA-Z0-9] — все буквы в обоих регистрах плюс цифры^ соответствует началу текста$ обозначает конец текста. соответствует любому символу, кроме символа новой строки? обозначает одно или ноль вхождений| означает ИЛИ (совпадение с любым из символов, разделенных им)* любое количество вхождений (включая 0 вхождений)+ одно и более вхождений{} указывает на несколько совпадений предыдущего RE.() отделяет группу в регулярном выраженииОбратная косая черта (backslash) \ используется в сочетании с другими символами и тогда приобретает особые значения. Если же необходимо использовать backslash просто как символ, без учета специального значения, его нужно «экранировать» еще одной обратной косой чертой – \\. Что касается специальных значений:
\d соответствует любой десятичной цифре, это то же самое, что и [0-9]\D соответствует любому нечисловому символу\s соответствует любому пробельному символу\S соответствует любому не пробельному символу\w соответствует любому буквенно-числовому символу; это то же самое, что и [a-zA-Z0-9_].\W соответствует любому не буквенно-числовому символу.Мы разобрали основы регулярных выражений (подробнее про них вы можете почитать тут). Теперь давайте посмотрим, какие методы доступны в модуле re.
Этот метод возвращает совпадающую часть строки и останавливается сразу же, как находит первое совпадение. Таким образом, его можно использовать для проверки выражения, а не для извлечения данных.
Синтаксис: re.search(шаблон, строка)
Возвращаемое значение может быть либо подстрокой, соответствующей шаблону, либо None, если такой подстроки не окажется.
Давайте разберем пример: поищем в строке месяц и число.
import re
regexp = r"([a-zA-Z]+) (\d+)"
match = re.search(regexp, "My son birthday is on July 20")
if match != None:
print("Match at index %s, %s" % (match.start(), match.end())) #This provides index of matched string
print("Full match: %s" % (match.group(0)))
print("Month: %s" % (match.group(1)))
print("Day: %s" % (match.group(2)))
else:
print("The given regex pattern does not match") Этот метод ищет и возвращает первое совпадение. Но надо учесть, что он проверяет соответствие только в начале строки.
Синтаксис: re.match(шаблон, строка)
Возвращаемое значение, как и в search(), может быть либо подстрокой, соответствующей шаблону, либо None, если желаемый результат не найден.
Теперь давайте посмотрим на пример. Проверим, совпадает ли строка с шаблоном.
import re
regexp = r"([a-zA-Z]+) (\d+)"
match = re.match(regexp, "July 20")
if match == None:
print("Not a valid date")
else:
print("Given string: %s" % (match.group()))
print("Month: %s" % (match.group(1)))
print("Day: %s" % (match.group(2))) Рассмотрим другой пример. Здесь «July 20» находится не в начале строки, поэтому результатом кода будет «Not a valid date»
import re
regexp = r"([a-zA-Z]+) (\d+)"
match = re.match(regexp, "My son birthday is on July 20")
if match == None:
print("Not a valid date")
else:
print("Given string: %s" % (match.group()))
print("Month: %s" % (match.group(1)))
print("Day: %s" % (match.group(2))) Этот метод возвращает все совпадения с шаблоном, которые встречаются в строке. При этом строка проверяется от начала до конца. Совпадения возвращаются в том порядке, в котором они идут в исходной строке.
Синтаксис: re.findall(шаблон, строка)
Возвращаемое значение может быть либо списком строк, совпавших с шаблоном, либо пустым списком, если совпадений не нашлось.
Рассмотрим пример. Используем регулярное выражение для поиска чисел в исходной строке.
import re string = "Bangalore pincode is 560066 and gulbarga pincode is 585101" regexp = '\d+' match = re.findall(regexp, string) print(match)
Или другой пример. Теперь нам нужно найти в заданном тексте номер мобильного телефона. То есть, в данном случае, нам нужно десятизначное число.
import re
string = "Bangalore office number 1234567891, My number is 8884278690, emergency contact 3456789123 invalid number 898883456"
regexp = '\d{10}' # Регулярное выражение, соответствующее числу из ровно 10 цифр
match = re.findall(regexp, string)
print(match) С помощью этого метода регулярные выражения компилируются в объекты шаблона и могут использоваться в других методах. Рассмотрим это на примере поиска совпадений с шаблоном.
import re
e = re.compile('[a-e]')
print(e.findall("I born at 11 A.M. on 20th July 1989"))
e = re.compile('\d') # \d - эквивалент [0-9].
print(e.findall("I born at 11 A.M. on 20th July 1989"))
p = re.compile('\d+') # группа из одной или более цифр
print(p.findall("I born at 11 A.M. on 20th July 1989"))
# Результат:
# ['b', 'a']
# ['1', '1', '2', '0', '1', '9', '8', '9']
# ['11', '20', '1989'] Данный метод разделяет строку по заданному шаблону. Если шаблон найден, оставшиеся символы из строки возвращаются в виде результирующего списка. Более того, мы можем указать максимальное количество разделений для нашей строки.
Синтаксис: re.split(шаблон, строка, maxsplit = 0)
Возвращаемое значение может быть либо списком строк, на которые была разделена исходная строка, либо пустым списком, если совпадений с шаблоном не нашлось.
Рассмотрим, как работает данный метод, на примере.
import re
# '\W+' совпадает с символами или группой символов, не являющихся буквами или цифрами
# разделение по запятой ',' или пробелу ' '
print(re.split('\W+', 'Good, better , Best'))
print(re.split('\W+', "Book's books Books"))
# Здесь ':', ' ' ,',' - не буквенно-цифровые символы, по которым происходит разделение
print(re.split('\W+', 'Born On 20th July 1989, at 11:00 AM'))
# '\d+' означает цифры или группы цифр
# Разделение происходит по '20', '1989', '11', '00'
print(re.split('\d+', 'Born On 20th July 1989, at 11:00 AM'))
# Указано максимальное количество разделений - 1
print(re.split('\d+', 'Born On 20th July 1989, at 11:00 AM', maxsplit=1))
# Результат:
# ['Good', 'better', 'Best']
# ['Book', 's', 'books', 'Books']
# ['Born', 'On', '20th', 'July', '1989', 'at', '11', '00', 'AM']
# ['Born On ', 'th July ', ', at ', ':', ' AM']
# ['Born On ', 'th July 1989, at 11:00 AM'] Здесь значение «sub» — это сокращение от substring, т.е. подстрока. В данном методе исходный шаблон сопоставляется с заданной строкой и, если подстрока найдена, она заменяется параметром repl.
Кроме того, у метода есть дополнительные аргументы. Это count, счетчик, в нем указывается, сколько раз заменяется регулярное выражение. А также flag, в котором мы можем указать флаг регулярного выражения (например, re.IGNORECASE)
Синтаксис: re.sub(шаблон, repl, строка, count = 0, flags = 0)
В результате работы кода возвращается либо измененная строка, либо исходная.
Посмотрим на работу метода на следующем примере.
import re
# Шаблон 'lly' встречается в строке в "successfully" и "DELLY"
print(re.sub('lly', '#$', 'doctor appointment booked successfully in DELLY'))
# Благодаря использованию флага регистр игнорируется, и 'lly' находит два совпадения
# Когда совпадения найдены, 'lly' заменяется на '~*' в "successfully" и "DELLY".
print(re.sub('lly', '#$', 'doctor appointment booked successfully in DELLY', flags=re.IGNORECASE))
# Чувствительность к регистру: 'lLY' не находит совпадений, и ничего в строке не будет заменено
print(re.sub('lLY', '#$', 'doctor appointment booked successfully in DELLY'))
# С count = 1 заменяется только одно совпадение с шаблоном
print(re.sub('lly', '#$', 'doctor appointment booked successfully in DELLY', count=1, flags=re.IGNORECASE)) Функциональность subn() во всех отношениях такая же, как и sub(). Единственная разница – это формат вывода. subn() возвращает кортеж, содержащий общее количество замен и новую строку.
Синтаксис: re.subn(шаблон, repl, строка, count = 0, flags = 0)
Рассмотрим такой пример.
import re
print(re.subn('lly', '#$', 'doctor appointment booked successfully in DELLY'))
t = re.subn('lly', '#$', 'doctor appointment booked successfully in DELLY', flags=re.IGNORECASE)
print(t)
print(len(t))
# Это даст такой же вывод, как и sub()
print(t[0]) Этот метод возвращает строку с обратной косой чертой \ перед каждым не буквенно-числовым символом. Это полезно, если мы хотим сопоставить произвольную буквенную строку, которая может содержать метасимволы регулярного выражения.
Синтаксис: re.escape(строка)
Чтобы лучше понять принцип работы метода, рассмотрим следующий пример.
import re
# Здесь из не буквенно-цифровых символов есть только пробелы.
print(re.escape("doctor appointment booked successfully at 1PM"))
# Здесь есть , ' ', '^', '-', '[]', '\' - все эти символы не относятся к буквенно-цифровым
print(re.escape("He asked what is this [0-9], I said \t ^Numberic class")) Сегодня мы поговорили о регулярных выражениях в Python и о том, что необходимо для их понимания в любом приложении. Мы изучили различные методы и метасимволы, присутствующие в регулярных выражениях Python, на примерах.
Если вы ищете работу на Python, на Talanto.work сейчас есть варианты для junior, middle, senior…
Рынок Python-вакансий большой, но удобным его назвать сложно. Формально вакансий много, однако в реальном поиске…
Срезы в Python — это больше, чем a[2:7]. В статье — быстрый разбор полезных приёмов:…
В этой статье мы рассмотрим возведение в степень в Python с помощью различных методов, от…
Дубликаты в списке Python — частая проблема. В статье показано, как быстро убрать повторы, в…
Услуга виртуального хостинга на SpaceWeb позволяет арендовать часть сервера (shared-сервера) и разместить на нём свой…