Книга: PyNEng
Назад: re.findall
Дальше: Флаги

re.compile

re.compile()

В Python есть возможность заранее скомпилировать регулярное выражение, а затем использовать его. Это особенно полезно в тех случаях, когда регулярное выражение много используется в скрипте.

Использование компилированного выражения может ускорить обработку, и, как правило, такой вариант удобней использовать, так как в программе разделяется создание регулярного выражения и его использование. Кроме того, при использовании функции re.compile создается объект RegexObject, у которого есть несколько дополнительных возможностей, которых нет в объекте MatchObject.

Для компиляции регулярного выражения используется функция re.compile:

In [52]: regex = re.compile('\d+ +\S+ +\w+ +\S+') 

Она возвращает объект RegexObject:

In [53]: regex Out[53]: re.compile(r'\d+ +\S+ +\w+ +\S+', re.UNICODE) 

У объекта RegexObject доступны такие методы и атрибуты:

In [55]: [ method for method in dir(regex) if not method.startswith('_')] Out[55]: ['findall',  'finditer',  'flags',  'fullmatch',  'groupindex',  'groups',  'match',  'pattern',  'scanner',  'search',  'split',  'sub',  'subn'] 

Обратите внимание, что у объекта Regex доступны методы search, match, finditer, findall. Это те же функции, которые доступны в модуле глобально, но теперь их надо применять к объекту.

Пример использования метода search:

In [67]: line = ' 100    a1b2.ac10.7000    DYNAMIC     Gi0/1'  In [68]: match = regex.search(line) 

Теперь search надо вызывать как метод объекта regex. И передать как аргумент строку.

Результатом будет объект Match:

In [69]: match Out[69]: <_sre.SRE_Match object; span=(1, 43), match='100    a1b2.ac10.7000    DYNAMIC     Gi0/1'>  In [70]: match.group() Out[70]: '100    a1b2.ac10.7000    DYNAMIC     Gi0/1' 

Пример компиляции регулярного выражения и его использования на примере разбора лог-файла (файл parse_log_compile.py):

import re  regex = re.compile('Host \S+ '                    'in vlan (\d+) '                    'is flapping between port '                    '(\S+) and port (\S+)')  ports = set()  with open('log.txt') as f:     for m in regex.finditer(f.read()):         vlan = m.group(1)         ports.add(m.group(2))         ports.add(m.group(3))  print('Петля между портами {} в VLAN {}'.format(', '.join(ports), vlan)) 

Это модифицированный пример с использованием finditer. Тут изменилось описание регулярного выражения:

regex = re.compile('Host \S+ '                    'in vlan (\d+) '                    'is flapping between port '                    '(\S+) and port (\S+)') 

И вызов finditer теперь выполняется как метод объекта regex:

    for m in regex.finditer(f.read()): 

Параметры, которые доступны только при использовании re.compile

При использовании функции re.compile в методах search, match, findall, finditer и fullmatch появляются дополнительные параметры:

  • pos - позволяет указывать индекс в строке, с которого надо начать искать совпадение
  • endpos - указывает, до какого индекса надо выполнять поиск

Их использование аналогично выполнению среза строки.

Например, таким будет результат без указания параметров pos, endpos:

In [75]: regex = re.compile(r'\d+ +\S+ +\w+ +\S+')  In [76]: line = ' 100    a1b2.ac10.7000    DYNAMIC     Gi0/1'  In [77]: match = regex.search(line)  In [78]: match.group() Out[78]: '100    a1b2.ac10.7000    DYNAMIC     Gi0/1' 

В этом случае указывается начальная позиция поиска:

In [79]: match = regex.search(line, 2)  In [80]: match.group() Out[80]: '00    a1b2.ac10.7000    DYNAMIC     Gi0/1' 

Указание начальной позиции аналогично срезу строки:

In [81]: match = regex.search(line[2:])  In [82]: match.group() Out[82]: '00    a1b2.ac10.7000    DYNAMIC     Gi0/1' 

И последний пример, с указанием двух индексов:

In [90]: line = ' 100    a1b2.ac10.7000    DYNAMIC     Gi0/1'  In [91]: regex = re.compile(r'\d+ +\S+ +\w+ +\S+')  In [92]: match = regex.search(line, 2, 40)  In [93]: match.group() Out[93]: '00    a1b2.ac10.7000    DYNAMIC     Gi' 

И аналогичный срез строки:

In [94]: match = regex.search(line[2:40])  In [95]: match.group() Out[95]: '00    a1b2.ac10.7000    DYNAMIC     Gi' 

В методах match, findall, finditer и fullmatch параметры pos и endpos работают аналогично.

Назад: re.findall
Дальше: Флаги