Сообщить об ошибке.

Опережающая и ретроспективная проверка позиции в RegExp.

Конструкции позиционной проверки обладают определенным сходством с метасимволами границ слов \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']