Pithon. Регулярные выражения
Регулярные выражения есть во многих языках: JavaScript, PHP, C#. Даже для 1С есть внешние компоненты, позволяющие работать с регулярными выражениями. Но в Python существует еще и ряд разных фишек для работы с регулярными выражениями, в частности, кроме поиска и сопоставления, в этом языке есть функции, которые, например, позволяют разбить строку по заданному шаблону. Более того, в Python есть функция, которая позволяет компилировать регулярные выражения.
Для тех, кто не в курсе, что такое регулярные выражения. Допустим, пользователь вводит номер телефона. И этот номер должен быть заполнен по следующим правилам:
- Начинается с восьмёрки
- Потом идет код города в скобках, от 1 до 5 цифр.
- Затем через пробел номер абонента, допускается разделять цифры знаком «-» (тире)
Необходимо проверить корректность ввода. Вот такой код позволит выявить достаточно много ошибок при вводе телефонных номеров:
import re result = re.match(r'^8 \(\d{1,5}\) \d{1}\d|-$', '8 (3412) 12-34-56') if result==None: print("НЕВЕРНО") else: print ("Корректный номер")
Программа будет «ругаться», если номер телефона начинается не с восьмёрки, пропущены пробелы или скобки, в коде горда слишком много цифр (больше 5) или в скобках вообще нет цифр, если номер телефона начинается не с цифры. То есть, вот так уже нельзя: ‘8 (3412) -12-34-56’.
Правда, программа посчитает корректными и вот такие номера: ‘8 (3412) 12—34-56’, ‘8 (3412) 12-34-56ввв’. Но, для понимания, что такое регулярные выражения, хватит и этого простого примера. Давайте разберём его.
Сначала мы импортируем библиотеку для работы с регулярными выражениями:
import re
В ней есть функция match, которая выполняет сопоставление строки с шаблоном. Если ни одного сопоставления не найдено, программа возвращает константу None. Теперь о самом шаблоне. Восьмерку мы задаём явно, пробел тоже. А вот скобка является специальным символом, поэтому ее нужно экранировать знаком «\». Знак «\d» обозначает, что тут должна стоять цифра. В фигурных скобках «{1,5}» — задано количество данных, от и до. В нашем случае запись «\d{1,5}» Означает, что должно идти от 1 до 5-ти цифр. Затем опять скобка и пробел: «\) «. После него одна цифра «d{1}». Обратите внимание, что «до» — не задано, значит, задано точно количество символов, не больше не меньше. В данном случае — это одна цифра, чтобы номер не мог начинаться с тире. Ну а потом идет либо цифра, либо тире: «\d|-«. Знак «|» обозначает «или».
А теперь запустим вот такой пример:
import re result = re.match(r'Мама', 'Мама мыла раму') if result!=None: print(result.group(0)) else: print("Не найдено")
Программа напечатает: «Мама».
А если вот так:
import re result = re.match(r'мыла', 'Мама мыла раму') if result!=None: print(result.group(0)) else: print("Не найдено")
То скажет: «не найдено». Функция math может находить шаблоны только в начале строки.
А вот функция serach ищет совпдаения по всей строке:
import re result = re.search(r'мыла', 'Мама мыла раму') if result!=None: print(result.group(0)) else: print("Не найдено")
Функция search хоть и ищет по всей строке, но возвращает только первое найденное совпадение.
А вот функция findall возвращает весь список найденных совпадений. Следующий пример вернет списко корректных идентификаторов (начинается с буквы, а потом может идти сколько угодно букв и цифр):
import re s="var1 var2 1var var3 2var 123 ThisIsVariable" result = re.findall(r'[a-zA-Z]{1}[a-zA-Z0-9]+', s) print(result)
Вот результат ее работы: [‘var1’, ‘var2’, ‘var’, ‘var3’, ‘var’, ‘ThisIsVariable’]. Обратите внимание, что «1var» не является корректным идентификатором, но «var» — является, поэтому именно «var» и попал в список. О таких нюансах следует помнить и быть очень осторожным с регулярными выражениями.
Есть в библиотеке для работы с регулярными выражениями и уже знакомый вам split (см. прошлый урок). Он делает тоже самое, что и split обычной — разбивает строку, согласно разделителям. Только в качестве разделителя тут шаблон регулярного выражения. Например:
import re s="Это разные слова, словосочетания. Предложения" result = re.split(r' |\.|\,', s) print(result)
Программа вернет: «[‘Это’, ‘разные’, ‘слова’, », ‘словосочетания’, », ‘Предложения’]».
Если после запятой или точки буте пропущен пробел, то данная функция также корректно разделит ее. Сравните с функцией split строки:
import re s="Это разные слова,словосочетания. Предложения" result = re.split(r' |\.|\,', s) print(result) print(s.split())
Результат работы программы:
[‘Это’, ‘разные’, ‘слова’, ‘словосочетания’, », ‘Предложения’]
[‘Это’, ‘разные’, ‘слова,словосочетания.’, ‘Предложения’]
Теперь решим некоторые задачки.
Задача 1. Извлечь даты из строки
Решение.
import re s='sdfsd 34.3456 12.05.2007, SWERW 56-4532 11.11.2011, ABC 67+8945 12.01.2009' result = re.findall(r'\d{2}\.\d{2}\.\d{4}', s) print(result)
Результат работы программы: [‘12.05.2007’, ‘11.11.2011’, ‘12.01.2009’]
Задача 2. Извлечь из строки года, которые в датах.
Решение. Это задача по сложнее, но, благодаря регулярным выражением, есть очень красивое решение:
import re s='sdfsd 34.3456 12.05.2007, SWERW 56-4532 11.11.2011, ABC 67+8945 12.01.2009' result = re.findall(r'\d{2}\.\d{2}\.(\d{4})', s) print(result)
Результат: [‘2007’, ‘2011’, ‘2009’].
Небольшое пояснение: в круглых скобках выражение, которое надо вернуть. Все остальное при возврате игнорится, хотя учитывается при поиске. Если мы сделаем вот так:
import re s='sdfsd 34.3456 12.05.2007, SWERW 56-4532 11.11.2011, ABC 67+8945 12.01.2009' result = re.findall(r'\d{4}', s) print(result)
То программа вернет много лишнего: [‘3456’, ‘2007’, ‘4532’, ‘2011’, ‘8945’, ‘2009’]
Задача 3. Дана строка, в которой есть адреса электронной почты. Вернуть список доменов.
Решение.
import re s='abc.test@gmail.com, xyz@test.in, test.first@analyticsvidhya.com, first.test@rest.biz' result = re.findall(r'@(\w+.\w+)', s) print(result)
Результат: [‘gmail.com’, ‘test.in’, ‘analyticsvidhya.com’, ‘rest.biz’]
Задача 4. Вернуть список слов.
Решение. Хотя мы это делали выше, но есть более красивое решение:
s="Это разные слова,словосочетания. Предложения" result = re.findall(r'\w+', s) print(result)
Результат: [‘Это’, ‘разные’, ‘слова’, ‘словосочетания’, ‘Предложения’]
Задача 5. Вернуть список слов русского языка, начинающихся на гласную:
Решение.
s="Это разные слова,словосочетания. Предложения. Какие-то начинаються на гласную, например, яблоко" result = re.findall(r'\b[аеёиоуыэюяАЕЁИОУЫЭЯ]\w+', s) print(result)
Результат: [‘Это’, ‘яблоко’]
Comments
So empty here ... leave a comment!