Чтобы помочь вам лучше разобраться в рассматриваемой теме, ниже приводятся несколько коротких примеров сценариев, демонстрирующих простые, но показательные формы шаблонов. Комментарии в примере 19.3 описывают осуществляемые операции; смотрите по табл. 19.1, какие операторы здесь используются. Если что-то для вас все равно останется непонятным, попробуйте выполнить инструкции из этих сценариев в интерактивной оболочке и вместо start() вызывать метод group(0), чтобы видеть, какие строки соответствуют шаблонам.
Пример 19.3. PP4E\Lang\re-basics.py
литералы, множества, диапазоны, альтернативы и экранированные последовательности
все тесты здесь выводят число 2: смещение, где найдено совпадение
import re # единственный, необходимый сейчас
pattern, string = "A.C.", "xxABCDxx" # неспец. символы соотв. сами себе matchobj = re.search(pattern, string) # ‘.’ означает один любой символ if matchobj: # search возвращ. объект соотв. или None
print(matchobj.start()) # start — смещение совпадения
pattobj = re.compile("A.*C.*") # ‘R*’ — ноль или более совпадений
matchobj = pattobj.search("xxABCDxx") # compile возвращает объект шаблона if matchobj: # patt.search возвращ. объект соотв.
print(matchobj.start())
# наборы выбора
print(re.search(" *A.C[DE][D-F][~G-ZE]G\t+ ?", "..ABCDEFG\t..").start())
# альтернативы: R1|R2 означает R1 или R2
print(re.search("(A|X)(B|Y)(C|Z)D", "..AYCD..").start()) # проверяем каждый
# символ
print(re.search("(?:A|X)(?:B|Y)(?:C|Z)D","..AYCD..").start()) # без сохр. print(re.search("A|XB|YC|ZD", "..AYCD..").start()) # совпадет только A!
print(re.search("(A|XB|YC|ZD)YCD", "..AYCD..").start()) # лишь первый символ
# границы слов
print(re.search(r"\bABCD", "..ABCD ").start()) # \b означает границу слова
print(re.search(r"ABCD\b", "..ABCD ").start()) # используйте r’…’
# для экранирования ‘\’
Обратите внимание на наличие нескольких способов выполнить поиск совпадения с использованием re: вызовом функций поиска модуля и посредством создания компилированных объектов шаблонов. В любом случае в результате можно получить объект соответствия. Все вызовы функции print в этом сценарии выводят результат 2 — смещение в строке, по которому было найдено соответствие с шаблоном. Например, в первом тесте шаблону A.C. соответствует подстрока ABCD со смещением 2 в проверяемой строке (то есть после начальных символов xx):
C:\…\PP4E\Lang> python re-basic.py
2
…8 других двоек опущено…
В примере 19.4 части строк шаблонов, заключенные в круглые скобки, образуют груп пы — части строки, которым они соответствуют, будут доступны после выполнения поиска.
Пример 19.4. PP4E\Lang\re-groups.py
группы: извлечение подстрок, соответствующих частям
регулярных выражений в ‘()’
группы обозначаются номерами позиций, но конструкция (?P<name>R) позволяет присваивать им символические имена
import re
patt = re.compile("A(.)B(.)C(.)") # сохраняет 3 подстроки
mobj = patt.match("A0B1C2") # группы ‘()’, 1..n
print(mobj.group(1), mobj.group(2), mobj.group(3)) # group() возвр. подстр
patt = re.compile("A(.*)B(.*)C(.*)") mobj = patt.match("A000B111C222") print(mobj.groups())
print(re.search("(A|X)(B|Y)(C|Z)D", "..AYCD..").groups())
print(re.search("(?P<a>A|X)(?P<b>B|Y)(?P<c>C|Z)D", "..AYCD..").groupdict())
patt = re.compile(r"[\t ]*#\s*define\s*([a-z0-9_]*)\s*(.*)")
mobj = patt.search(" # define spam 1 + 2 + 3") # поиск инструкций #define
print(mobj.groups()) # \s — пробельный символ
Например, в первом тесте имеются три группы (.), каждая из которых соответствует одному символу и сохраняет найденный символ — метод group возвращает найденные совпадения. Во втором тесте группы (.*) соответствуют любому числу символов и сохраняют их. В третьем и четвертом тестах показано, как можно группировать альтернативы по позициям и именам, а последний шаблон здесь соответствует строкам с инструкциями #define языка C — подробнее об этом чуть ниже:
C:\…\PP4E\Lang> python re-groups.py 0 1 2
(‘000’, ‘111’, ‘222’)
(‘A’, ‘Y’, ‘C’)
{‘a’: ‘A’, ‘c’: ‘C’, ‘b’: ‘Y’}
(‘spam‘, ‘1 + 2 + 3’)
Наконец, кроме поиска совпадений и извлечения подстрок, в модуле re есть средства замены строк (пример 19.5).
Пример 19.5. PP4E\Lang\re-subst.py
"замена: замещает совпадения с шаблоном в строке"
import re
print(re.sub(‘[ABC]’, ‘*’, ‘XAXAXBXBXCXC’))
print(re.sub(‘[ABC]_’, ‘*’, ‘XA-XA_XB-XB_XC-XC_’)) # замещает символ + _ print(re.sub(‘(.) spam’, ‘spam\\1’, ‘x spam, y spam’)) # обратная ссылка
# на группу (или r») def mapper(matchobj):
return ‘spam’ + matchobj.group(1)
print(re.sub(‘(.) spam’, mapper, ‘x spam, y spam’)) # функция отображения
В первом тесте заменяются все символы, присутствующие в наборе, — вслед за ними должен следовать символ подчеркивания. Последние два теста иллюстрируют обратные ссылки на группы и функцию отображения, используемую при выполнении операции замены. Обратите внимание, что конструкцию \1 необходимо экранировать, как \\1, из-за правил оформления строк в языке Python — точно так же можно было бы использовать r’spam\1′. Дополнительные примеры замены и разбиения строк смотрите в тестах в интерактивной оболочке в этом разделе выше.
C:\…\PP4E\Lang> python re-subst.py
X*X*X*X*X*X*
XA-X*XB-X*XC-X*
spamx, spamy spamx, spamy
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, II том, 2011