Главная страница
Навигация по странице:

  • Модуль для работы с регулярными выражениями

  • (ms) – в случае встраивания флагов в само регулярное выражение. Модуль для работы с регулярными выражениями539

  • Синтаксис Описание

  • (\w+)\s+\1(!\w) .Следует также отметить, что в конце регулярного выражения вместо(!\w) можно было бы использовать проверку на границу слова \b

  • Программирование на Python 3. Руководство издательство СимволПлюс


    Скачать 3.74 Mb.
    НазваниеРуководство издательство СимволПлюс
    Дата10.11.2022
    Размер3.74 Mb.
    Формат файлаpdf
    Имя файлаПрограммирование на Python 3.pdf
    ТипРуководство
    #780382
    страница63 из 74
    1   ...   59   60   61   62   63   64   65   66   ...   74
    (?(quote)(?P=quote)) # закрывающая кавычка (если была открывающая кавычка)
    [^>]*? # любые атрибуты, следующие за src
    > # конец тега
    Сохраняющей группе с именем файла было присвоено имя "image"
    (этой группе соответствует порядковый номер 2).
    Конечно, существует более простая, но менее очевидная альтернатива:
    src=(["']?)([^"'>]+)\1
    . Здесь, если имеется символ открывающей ка
    вычки, он сохраняется в группе 1, далее идут символы, следующие за открывающей кавычкой. Если в определении атрибута открывающая кавычка отсутствовала, попрежнему будет считаться, что для груп
    пы 1 было найдено совпадение – совпадение с пустой строкой, так как кавычка считается необязательной (ее квантификатор означает ноль или более совпадений); в этом случае обратной ссылке также будет со
    ответствовать пустая строка.
    Наконец, механизм регулярных выражений в языке Py
    thon предоставляет возможность устанавливать флаги,
    влияющие на работу регулярных выражений. Обычно флаги устанавливаются посредством их передачи функ
    ции re.compile() в виде дополнительных параметров, но иногда гораздо удобнее устанавливать их непосредствен
    но в регулярных выражениях. Установка флагов выпол
    няется простой синтаксической конструкцией (?flags),
    где flags – один или несколько следующих флагов: a (то же самое, что передача флага re.ASCII), i (re.IGNORECASE),
    m
    (re.MULTILINE), s (re.DOTALL) и x (re.VERBOSE).
    1
    При таком
    1
    В языке Python используются те же символы флагов, что и в механизме ре
    гулярных выражений языка Perl, поэтому символ s обозначает флаг re.DO
    TALL
    , а символ x – флаг re.VERBOSE.
    Флаги регулярных выражений, стр. 535

    538
    Глава 12. Регулярные выражения способе использования флаги должны помещаться в начало регуляр
    ного выражения. Эта конструкция не участвует в поиске совпадений –
    она используется только для установки флагов.
    Модуль для работы
    с регулярными выражениями
    Модуль re обеспечивает два способа работы с регулярными выраже
    ниями. Один из них заключается в использовании функций, перечис
    ленных в табл. 12.5, которым в виде первого аргумента передается ре
    гулярное выражение. Каждая функция преобразует регулярное выра
    жение во внутренний формат – этот процесс называется компиляцией,
    а затем выполняет свою работу. Это очень удобно для однократного применения регулярного выражения, но если одно и то же регулярное выражение требуется применить несколько раз, можно избежать из
    лишних затрат на компиляцию при каждом использовании, скомпи
    лировав выражение всего один раз с помощью функции re.compile().
    После этого можно вызывать методы скомпилированного регулярного выражения столько раз, сколько потребуется. Методы скомпилиро
    ванных регулярных выражений перечислены в табл. 12.6.
    match = re.search(r"#[\dAFaf]{6}\b", text)
    Этот фрагмент программного кода демонстрирует порядок использова
    ния функции из модуля re. Данному регулярному выражению соот
    ветствует определение цвета в формате HTML (например, #C0C0AB). Ес
    ли совпадение будет найдено, функция re.search() вернет объект сов
    падения; в противном случае она вернет значение None. Методы объек
    тов совпадений перечислены в табл. 12.7.
    Если предполагается несколько раз использовать одно и то же регу
    лярное выражение, его можно скомпилировать один раз и использо
    вать скомпилированное регулярное выражение везде, где только по
    требуется:
    color_re = re.compile(r"#[\dAFaf]{6}\b")
    match = color_re.search(text)
    Как уже отмечалось выше, мы используем «сырые» строки, чтобы избе
    жать необходимости дублировать символы обратного слеша. Это регу
    лярное выражение можно записать иначе, использовав в нем символь
    ный класс [\dAF] и передав флаг re.IGNORECASE функции re.compile()
    в виде последнего аргумента, или использовать регулярное выраже
    ние (?i)#[\dA F]{6}\b, которое начинается с установки флага, делаю
    щего регулярное выражение нечувствительным к регистру символов.
    Если требуется установить более одного флага, их можно объединять с помощью оператора ИЛИ (|) – например, re.MULTILINE|re.DOTALL, или
    (?ms) –
    в случае встраивания флагов в само регулярное выражение.

    Модуль для работы с регулярными выражениями
    539
    Таблица 12.5. Функции модуля регулярных выражений
    Синтаксис
    Описание
    re.compile(
    r, f)
    Возвращает скомпилированное регулярное выражение r с установленными флагами f, если они были заданы re.escape(s)
    Возвращает строку s, в которой все неалфавитноцифровые символы экранированы символом обратного слеша, то есть возвращает строку, не содержащую специальных символов регулярных выражений re.findall(
    r, s, f)
    Возвращает все неперекрывающиеся совпадения с регуляр
    ным выражением r в строке s (с учетом флагов f, если они заданы). Если регулярное выражение содержит сохраняю
    щие группы, для каждого совпадения возвращается кортеж с сохраненными фрагментами re.finditer(
    r, s, f)
    Возвращает объект совпадения для каждого неперекрываю
    щегося совпадения с регулярным выражением r в строке s
    (с учетом флагов f, если они заданы)
    re.match(
    r, s, f)
    Возвращает объект совпадения, если совпадение с регуляр
    ным выражением r находится в начале строки s (с учетом флагов f, если они заданы); в противном случае возвращает
    None re.search(
    r, s, f)
    Возвращает объект совпадения, если совпадение с регуляр
    ным выражением r обнаруживается в любом месте строки s
    (с учетом флагов f, если они заданы); в противном случае возвращает None re.split(
    r, s, m)
    Возвращает список строк, который создается в результате разбиения строки s по каждому совпадению с регулярным выражением r. Количество разбиений не превышает m (если аргумент m не задан, выполняется столько разбиений,
    сколько возможно). Если регулярное выражение содержит сохраняющие группы, они включаются в список между час
    тями, полученными в результате разбиения re.sub(
    r, x,
    s, m)
    Возвращает копию строки s, в которой каждое (но не более
    m
    , если задано) совпадение с регулярным выражением r за
    мещается значением аргумента x, который может быть строкой или функцией – описание приводится в тексте re.subn(
    r, x,
    s, m)
    То же самое, что и функция re.sub(), за исключением того,
    что она возвращает кортеж из двух элементов – со строкой результата и количеством выполненных подстановок

    540
    Глава 12. Регулярные выражения
    Таблица 12.6. Методы объекта регулярного выражения
    Синтаксис
    Описание
    rx.findall
    (s, start, end)
    Возвращает все неперекрывающиеся совпадения с регуляр
    ным выражением в строке s (или в срезе start:end строки).
    Если регулярное выражение содержит сохраняющие груп
    пы, для каждого совпадения возвращается кортеж с сохра
    ненными фрагментами rx.finditer
    (s, start, end)
    Возвращает объект совпадения для каждого неперекры
    вающегося совпадения в строке s (или в срезе start:end
    строки)
    rx.flags
    Возвращает флаги, которые были установлены при компи
    ляции регулярного выражения rx.groupindex
    Словарь, ключами которого являются имена сохраняющих групп, а значениями – номера групп. Пустой, если имена не используются rx.match
    (s, start, end)
    Возвращает объект совпадения, если совпадение с регуляр
    ным выражением находится в начале строки s (или в начале среза start:end строки); в противном случае возвращает None rx.pattern
    Строка, из которой была получена скомпилированная вер
    сия регулярного выражения rx.search
    (s, start, end)
    Возвращает объект совпадения, если совпадение с регуляр
    ным выражением обнаруживается в любом месте строки s
    (или в любом месте в срезе start:end строки); в противном случае возвращает None rx.split(s, m)
    Возвращает список строк, который создается в результате разбиения строки s по каждому совпадению с регулярным выражением. Количество разбиений не превышает m (если аргумент m не задан, выполняется столько разбиений,
    сколько возможно). Если регулярное выражение содержит сохраняющие группы, они включаются в список между частями, полученными в результате разбиения rx.sub(x, s, m)
    Возвращает копию строки s, в которой каждое (но не более
    m
    , если задано) совпадение с регулярным выражением заме
    щается значением аргумента x, который может быть стро
    кой или функцией, – описание приводится в тексте rx.subn(x, s, m)
    То же самое, что и метод rx.sub(), за исключением того, что этот метод возвращает кортеж из двух элементов – со стро
    кой результата и количеством выполненных подстановок

    Модуль для работы с регулярными выражениями
    541
    Таблица 12.7. Методы и атрибуты объекта совпадения
    Синтаксис
    Описание
    m.end(g)
    Возвращает конечную позицию совпадения в тексте для группы g, если таковая указана (или для группы 0, соответ
    ствующей совпадению со всем регулярным выражением);
    если группа не участвовала в совпадении, возвращается –1
    m.endpos
    Позиция конца поиска (конец текста или значение аргумен
    та end в методах или функциях match() или search())
    m.expand(s)
    Возвращает строку s, в которой номера и имена сохраняю
    щих групп (\1, \2, \g и подобные им) замещаются соот
    ветствующими сохраненными фрагментами m.group(g,
    ...)
    Возвращает фрагмент, сохраненный в нумерованной или именованной группе g; если указано более одной группы,
    возвращается кортеж соответствующих сохраненных фраг
    ментов (совпадению со всем регулярным выражением соот
    ветствует группа 0)
    m.groupdict(
    default)
    Возвращает словарь имен всех именованных сохраняющих групп, в котором ключами являются имена групп, а значе
    ниями – сохраненные фрагменты; если указан аргумент de
    fault
    , его значение возвращается для групп, не участвовав
    ших в совпадении m.groups(
    default)
    Возвращает кортеж всех сохраняющих групп, начиная с 1;
    если указан аргумент default, его значение возвращается для групп, не участвовавших в совпадении m.lastgroup
    Имя сохраняющей группы с наибольшим порядковым номе
    ром, для которой имеется совпадение, или None, если таких групп нет или если именованные группы не использовались m.lastindex
    Номер последней сохраняющей группы, для которой имеет
    ся совпадение, или None, если таких групп нет m.pos
    Начальная позиция поиска (начало текста или значение ар
    гумента start в методах или функциях match() или search())
    m.re
    Объект регулярного выражения, который воспроизвел этот объект совпадения m.span(g)
    Возвращает начальную и конечную позиции совпадения в тексте для группы g, если таковая указана (или для груп
    пы 0, соответствующей совпадению со всем регулярным вы
    ражением); если группа не участвовала в совпадении, воз
    вращается (–1, –1)
    m.start(g)
    Возвращает начальную позицию совпадения в тексте для группы g, если таковая указана (или для группы 0, соответ
    ствующей совпадению со всем регулярным выражением);
    если группа не участвовала в совпадении, возвращается –1
    m.string
    Строка, которая была передана функциям или методам match()
    или search()

    542
    Глава 12. Регулярные выражения
    Мы завершим этот раздел обзором нескольких примеров и начнем с тех регулярных выражений, которые демонстрировались в предыдущих разделах, чтобы проиллюстрировать применение наиболее часто ис
    пользуемых функций из модуля re. Начнем с регулярного выражения,
    отыскивающего повторяющиеся слова:
    double_word_re = re.compile(r"\b(?P\w+)\s+(?P=word)(?!\w)",
    re.IGNORECASE)
    for match in double_word_re.finditer(text):
    print("{0} is duplicated".format(match.group("word")))
    Здесь используется немного более сложная версия по сравнению с той,
    что мы видели выше. Регулярное выражение начинается с границы слова (чтобы гарантировать, что совпадение будет начинаться с начала слова), затем следует максимально длинное соответствие одному или более символам «слова», затем следует один или более пробельных символов, затем следует то же самое слово еще раз, но при условии, что за вторым вхождением слова не следует какойлибо символ «слова».
    Если предположить, что поиск выполняется в тексте «win in vain», то
    без
    первой проверки было бы получено одно соответствие и два сохра
    нения: w vain
    . Наличие проверки на границу слова гарантирует,
    что первое слово в совпадении будет целым словом, в результате в этом тексте не будет найдено совпадений, и ничего не будет сохраняться,
    так как здесь нет повторяющихся слов. Аналогично, если предполо
    жить, что поиск выполняется в тексте «one and and two let’s say», то
    без
    последней проверки было бы найдено два совпадения и выполнено два сохранения: one and two let’ say
    . Опережающая проверка га
    рантирует, что второе слово в совпадении будет целым словом, в ре
    зультате в этом тексте будет найдено одно совпадение и выполнено од
    но сохранение: one and two let’s say
    Цикл for выполняет итерации по всем объектам совпадений, возвра
    щаемых методом finditer(), и мы используем метод group() для получе
    ния фрагментов текста, сохраненных в группах. Точно так же мы могли бы использовать вызов group(1) (хотя это было бы менее понятно тому,
    кто будет сопровождать такой программный код) – в этом случае нам потребовалось бы отказаться от применения именованной сохраняю
    щей группы и использовать регулярное выражение (\w+)\s+\1(?!\w).
    Следует также отметить, что в конце регулярного выражения вместо
    (?!\w)
    можно было бы использовать проверку на границу слова \b.
    Другим регулярным выражением, представленным выше, было регу
    лярное выражение, отыскивающее имена файлов в тегах изображений в документах HTML. Ниже показано, как при компиляции регулярно
    го выражения можно добавить флаги, чтобы оно не было чувствитель
    но к регистру символов, и поддерживается возможность вставлять комментарии:
    image_re = re.compile(r"""
    and

    Модуль для работы с регулярными выражениями
    543
    [^>]*? # другие атрибуты src= # начало атрибута src
    (?P["'])? # необязательная открывающая кавычка
    (?P[^"'>]+) # имя файла изображения
    (?(quote)(?P=quote)) # закрывающая кавычка
    [^>]*? # другие атрибуты
    > # конец тега """, re.IGNORECASE|re.VERBOSE)
    image_files = []
    for match in image_re.finditer(text):
    image_files.append(match.group("image"))
    Здесь мы снова использовали метод finditer() для получения всех най
    денных совпадений и метод group() объектов совпадений – для извле
    чения сохраненного текста. Поскольку регистр символов имеет значе
    ние только для выражений img и src, мы могли бы отбросить флаг re.IGNORECASE
    и использовать выражения [Ii][Mm][Gg] и [Ss][Rr][Cc].
    Это сделало бы регулярное выражение более трудным для чтения, но,
    возможно, более быстрым, так как при поиске совпадений не будет требоваться преобразовывать его символы в верхний или нижний ре
    гистр. Однако, скорее всего, разницу в скорости можно будет заметить только при обработке больших объемов текста.
    Одна из типичных задач заключается в том, чтобы взять документ в формате HTML и вывести только обычный текст, содержащийся в нем. Естественно, это можно сделать с применением одного из парсе
    ров, входящих в состав Python, но с помощью регулярных выражений можно создать очень простой инструмент. Чтобы реализовать это, не
    обходимо решить три задачи: удалить все теги, заменить сущности символами, которые они представляют, и вставить пустые строки, от
    деляющие параграфы. Ниже приводится функция (взята из програм
    мы html2text.py), которая делает эту работу:
    def html2text(html_text):
    def char_from_entity(match):
    code = html.entities.name2codepoint.get(match.group(1), 0xFFFD)
    return chr(code)
    text = re.sub(r"", "", html_text) #1
    text = re.sub(r"<[Pp][^>]*?(?!", "\n\n", text) #2
    text = re.sub(r"<[^>]*?>", "", text) #3
    text = re.sub(r"&#(\d+);", lambda m: chr(int(m.group(1))), text)
    text = re.sub(r"&([AZaz]+);", char_from_entity, text) #5
    text = re.sub(r"\n(?:[ \xA0\t]+\n)+", "\n", text) #6
    return re.sub(r"\n\n+", "\n\n", text.strip()) #7
    Первому регулярному выражению соответствуют ком
    ментарии HTML, включая теги HTML, вложенные в них. Функция re.sub()
    замещает все найденные совпадения указанным текстом –
    просто удаляет совпадения, если в качестве замены используется пус
    тая строка, как в данном случае. (Имеется возможность определить

    544
    Глава 12. Регулярные выражения максимальное количество совпадений, передав дополнительно целое число в виде последнего аргумента.)
    Обратите внимание, что здесь выполняется поиск совпадений мини
    мальной длины, чтобы гарантировать, что в каждом удаляемом совпа
    дении будет только один комментарий; в противном случае мы могли бы удалить все, что находится между началом первого комментария и концом последнего.
    Функция re.sub() не принимает никаких флагов в виде аргументов,
    вследствие этого символ . в регулярном выражении означает «любой символ за исключением символа перевода строки», поэтому мы долж
    ны выполнять поиск . или \n. Отыскивать эти совпадения следует с ис
    пользованием оператора выбора, а не с помощью символьного класса,
    так как внутри символьных классов точка интерпретируется букваль
    но – как символ точки. Как вариант в начало регулярного выражения можно было бы добавить флаг, например (?s), или скомпи
    лировать регулярное выражение с флагом re.DOTALL; в этом случае ре
    гулярное выражение можно было бы упростить до .
    Второму регулярному выражению
    1   ...   59   60   61   62   63   64   65   66   ...   74


    написать администратору сайта