Опубликован: 14.06.2015 | Доступ: свободный | Студентов: 4655 / 500 | Длительность: 21:48:00
Авторские права: Creative Commons Attribution 3.0
Самостоятельная работа 11:

Регулярные выражения

< Самостоятельная работа 1 || Самостоятельная работа 11: 12345

23.2. Извлечение данных с помощью регулярных выражений

Для выделения данных из строки Питон предоставляет метод findall(), извлекающий все подстроки, соответствующие регулярному выражению. Пусть мы хотим извлечь всё, что похоже на адрес электронной почты, из любой строки, независимо от ее формата. Например, мы хотим извлечь e-mail адрес из любой из следующих строк:

From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008
Return-Path: <postmaster@collab.sakaiproject.org>
for <source@collab.sakaiproject.org>;
Received: (from apache@localhost)
Author: stephen.marquard@uct.ac.za
  

Не хотелось бы писать отдельный код для каждого типа строк, разбирая по-своему каждую строку. Приведенная ниже программа использует метод findall() для нахождения всех строк с e-mail адресом и извлечения одного или нескольких адресов из таких строк.

import re
s = 'Hello from csev@umich.edu to cwen@iupui.edu about the meeting @2PM'
lst = re.findall('\S+@\S+', s)
print lst
  

Метод findall() производит поиск регулярного выражения в строке, переданной ему в качестве второго аргумента, и возвращает список всех ее подстрок, которые выглядят как e-mail адреса. Мы используем специальную двухсимвольную последовательность \S длины 2, которая сопоставляется любому непробельному (non-whitespace) символу. На выходе программы получим:

['csev@umich.edu', 'cwen@iupui.edu']

Сопоставляя регулярное выражение, мы находим все подстроки, имеющие хотя бы один непробельный символ, за которым следует символ @, после которого в свою очередь идет один или более непробельный символ. Шаблон "\S+" аналогично сопоставляется максимально длинной последовательности непробельных символов (это называют "жадным" поведением в регулярных выражениях).

Регулярное выражение сопоставляется дважды (csev@umich.edu и cwen@iupui.edu), но оно не соответствует подстроке "@2PM", поскольку перед символом @ нет непробельных символов. Мы можем использовать это регулярное выражение в программе, читающей все строки в файле и печатающей всё, что выглядит как e-mail адрес:

import re
hand = open('mbox-short.txt')
for line in hand:
line = line.rstrip()
x = re.findall('\S+@\S+', line)
if len(x) > 0 :
print x
  

Из каждой прочитанной строки извлекаются все подстроки, соответствующие нашему регулярному выражению. Поскольку метод findall() возвращает список, достаточно проверить, что число его элементов больше нуля, чтобы напечатать строки, содержащие e-mail адреса.

Применив программу к файлу mbox.txt, получим следующий результат:

['wagnermr@iupui.edu']
['cwen@iupui.edu']
['<postmaster@collab.sakaiproject.org>']
['<200801032122.m03LMFo4005148@nakamura.uits.iupui.edu>']
['<source@collab.sakaiproject.org>;']
['<source@collab.sakaiproject.org>;']
['<source@collab.sakaiproject.org>;']
['apache@localhost)']
['source@collab.sakaiproject.org;']
  

Некоторые из этих e-mail адресов содержат некорректные символы "<" или ";" в начале либо конце. Укажем, что нас интересует лишь часть строки, начинающаяся и заканчивающаяся буквой или цифрой. Для этого используем другую возможность, предоставляемую регулярными выражениями. Квадратные скобки в них применяются для указания множества допустимых символов, используемых при сопоставлении. В этом смысле шаблон "\S" соответствует множеству всех непробельных символов. Теперь мы более явно укажем множество сопоставляемых символов.

Вот наше новое регулярное выражение:

[a-zA-Z0-9]\S*@\S*[a-zA-Z]

Оно несколько сложнее, теперь уже видно, почему регулярные выражения можно считать самостоятельным языком. Данное регулярное выражение означает, что мы ищем подстроки, начинающиеся с одиночной строчной буквы, прописной буквы или цифры "[a-zA-Z0-9]", за которой следует ноль или более непробельных символов "\S*", дальше идет символ @, потом ноль или более непробельных символов "\S*" и в конце строчная или прописная буква. Отметим, что мы заменили "+ " на "* " для указания нуля или более непробельных символов, поскольку фрагмент " [a-zA-Z0-9] " уже представляет собой один непробельный символ.

Помните, что "* " или "+ " применяются к одному символу, стоящему непосредственно слева от звездочки или плюса. Если мы используем это выражение в нашей программе, выходные данные будут более чистыми:

import re
hand = open('mbox-short.txt')
for line in hand:
line = line.rstrip()
x = re.findall('[a-zA-Z0-9]\S+@\S+[a-zA-Z]', line)
if len(x) > 0 :
print x
['wagnermr@iupui.edu']
['cwen@iupui.edu']
['postmaster@collab.sakaiproject.org']
['200801032122.m03LMFo4005148@nakamura.uits.iupui.edu']
['source@collab.sakaiproject.org']
['source@collab.sakaiproject.org']
['source@collab.sakaiproject.org']
['apache@localhost']
  

Отметим, что из строк, содержащих фрагмент "source@collab.sakaiproject.org", наше регулярное выражение исключило два символа в конце строки (">;"). Это произошло потому, что, добавив фрагмент "[a-zA-Z]" в конец нашего регулярного выражения, мы указали, что подстрока, которая сопоставляется регулярному выражению, обязательно должна заканчиваться буквой. Поэтому сопоставление заканчивается, как только мы доходим до символа ">" в конце "sakaiproject.org>;" – на последней "сопоставимой" букве (в данном случае "g"). Также отметим, что каждая строчка вывода программы представляет собой одноэлементный список Питона, единственным элементом которого является строка.

< Самостоятельная работа 1 || Самостоятельная работа 11: 12345
Ксения Шошина
Ксения Шошина

курс Программирование на Python

Илья Кизилов
Илья Кизилов

В лекции приводится программа для сортировки слов по их длинне. В коде ошибка. Я исправил так:

def sort_by_length(words):

words = words.split()

t = []

for word in words:

t.append((len(word), word))

t.sort(reverse=True)

res = []

for length, word in t:

res.append(word)

return res

print(sort_by_length(words))

 

Кто ещё как сделал?

 

Андрей Милых
Андрей Милых
Россия, г. Донской Тульской области, Средняя школа № 12, 1987
evgeny koblov
evgeny koblov
Россия, Нижний Новгород