Конструкции позиционной проверки обладают определенным сходством с метасимволами границ слов \b
, ^
и $
. Они тоже совпадают не с символами, а с позициями в тексте. Позиционная проверка носит гораздо более общий характер, чем специализированные метасимволы границ слов.
(?<=...)
- Должно совпасть слева (Позитивная ретроспективная проверка).(?<!...)
- Не должно совпасть слева (Негативная ретроспективная проверка).(?=...)
- Должно совпасть справа (Позитивная опережающая проверка).(?!...)
- Не должно совпасть справа (Негативная опережающая проверка).Одна из разновидностей позиционной проверки это опережающая проверка. Опережающая проверка анализирует текст, расположенный справа, и проверяет возможность совпадения подвыражения. Если совпадение возможно, проверка считается успешной.
Опережающая позиционная проверка может быть как позитивной, так и негативной:
(?=...)
, где ...
регулярное выражение, которое определяет проверяемую позицию справа от основного выражения. Например, подвыражение (?=\d)
совпадает в тех позициях, за которыми СЛЕДУЕТ какая либо одиночная цифра. (?!...)
. Например, подвыражение (?!\d)
совпадает в тех позициях, за которыми НЕ СЛЕДУЕТ какой либо одиночной цифры. Допустим что нам необходимо отобрать все файлы, кроме файлов с расширением .bat
. Шаблон регулярного выражения в этом случае будет выглядеть следующим образом:
re.match(r'.*[.](?!bat$)[^.]*$', file_name)
Негативная опережающая проверка (?!bat$)
означает: если выражение bat
не совпадает в указанной точке шаблона, то идет проверка остальной части шаблона. Если выражение bat$
совпало, то весь шаблон терпит неудачу. Знак $
- позиция в конце строки, необходим для того, чтобы были разрешены названия что-то вроде sample.batch
, где расширение только начинается bat
. Выражение [^.]*
гарантирует, что шаблон работает, когда в имени файла несколько точек.
Исключить другое расширение файла теперь легко. Для этого просто добавим другое расширение в негативную опережающую проверку. Следующий шаблон исключает имена файлов, оканчивающиеся на bat
или exe
:
re.match(r'.*[.](?!bat$|exe$)[^.]*$', file_name)
Также существует ретроспективная проверка, при которой текст анализируется в обратном направлении, к левому краю.
Ретроспективная позиционная проверка так же может быть как позитивной, так и негативной:
(?<=...)
, где ...
регулярное выражение, которое определяет проверяемую позицию слева от основного выражения. Например, подвыражение (?<=\d) совпадает в тех позициях, слева от которых НАХОДИТСЯ какая либо одиночная цифра, т. е. в позиции после цифры.(?<!...)
. Например, подвыражение (?<!\d) совпадает в тех позициях, слева от которых НЕ НАХОДИТСЯ какая либо одиночная цифра.Опережающая и ретроспективная позиционные проверки не "поглощают" текст. Это значит, что совпавший текст в позиционной проверке не учитывается в группах с захватом, следовательно не включаются в результат.
В примере требуется извлечь из текста частоту, издаваемую генератором и номер лаборатории.
>>> import re >>> text = 'В лаборатории N20 генератор выдает звук с частотой 862Гц' # частота генератора >>> match = re.search(r'(?<=\b)\d+(?!\d)', text) >>> match.group() # '862' # номер лаборатории >>> match = re.findall(r'(?<=N)\d+(?!\d)', text) >>> match # ['20']