Последствия вставки положительного поиска в произвольное регулярное выражение для имитации смещения байтов

Каковы были бы последствия вставки положительного lookbehind для n-байтов (?<=\C{n}) в начало любого произвольного регулярного выражения, особенно при использовании для операций замены?

По крайней мере, в PHP функции соответствия регулярному выражению preg_match и preg_match_all позволяют начинать сопоставление после заданного смещения байта. В любой из других функций PCRE PHP нет соответствующей функции – вы можете указать ограничение на количество замен, выполняемых preg_replace например, но не на то, что совпадения замен должны появляться после n-байтов.

Очевидно, что некоторые (давайте назовем их тривиальными) последствиями для производительности и удобочитаемости, но будут ли какие-либо (нетривиальные) воздействия, например, совпадения становятся несоответствиями (за исключением случаев, когда они не смещены на n байтов), или замены становятся неверными ?

Некоторые примеры:

/some expression/ становится /(?<=\C{4})some expression/ для 4-байтового смещения

/(this) has (groups)/i становится /(?<=\C{2})(this) has (groups)/i для 2-байтового смещения

Насколько я могу судить, и из ограниченных тестов, которые я выполнил, добавление в этот lookbehind эффективно имитирует этот параметр смещения и не вмешивается в какие-либо другие lookbehinds, замены или другие шаблоны управления; но я тоже не специалист по Regex.

Я пытаюсь определить, есть ли какие-либо возможные последствия для создания функций замены / фильтрации, вставив n-байтовый lookbehind в шаблоны. Он должен работать так же, как работает параметр смещения функции смещения, поэтому просто выполнение выражения в отношении substr( $subject, $offset ) не будет работать по тем же причинам, что и не для preg_match (в первую очередь, оно отсекает любые lookbehinds и ^ затем неправильно совпадает с началом подстроки, а не с исходной строкой).

Короткий ответ

В режиме, отличном от UTF, библиотека UTF-8

Предполагая, что ваша библиотека PCRE, связанная с PHP, скомпилирована как 8-битная библиотека (UTF-8) , затем в режиме без UTF

 \C 

эквивалентно

 [\x00-\xff] 

а также

 (?s:.) 

Любой из них может использоваться в качестве замены для поля offset в preg_match и preg_match_all .

В режиме, отличном от UTF, все они соответствуют 1 единице данных, которая составляет 1 байт в 8-битной (UTF-8) библиотеке PCRE, и они соответствуют всем 256 возможным различным значениям.

В UTF-режиме библиотека UTF-8

Режим UTF может быть активирован флагом u в шаблоне, переданном функции preg_* , или путем указания (*UTF) , (*UTF8) , (*UTF16) , (*UTF32) глаголов в начале шаблона.

В режиме UTF, класс символов [] и метасимвол точки . будет соответствовать одной кодовой точке в пределах допустимого диапазона символов Юникода и не является суррогатом. Поскольку одна кодовая точка может быть закодирована в 1-4 байта в UTF-8, и из-за схемы кодирования UTF-8 невозможно использовать конструкцию символьного класса для соответствия одному байту для значений в диапазоне от 0x80 до 0xFF ,

В то время как \C специально разработан для соответствия одному блоку данных (который является одним байтом в UTF-8) независимо от того, включен ли режим UTF, он не поддерживается в конструкции look-behind в режиме UTF.

Библиотека UTF-16 и UTF-32

Я не знаю, действительно ли кто-то компилирует 16-битную или 32-разрядную библиотеку PCRE, включает ее в библиотеку PHP и фактически заставляет ее работать. Если кто-нибудь знает, что такая сборка широко используется в дикой природе, пожалуйста, пингуйте меня. На самом деле я понятия не имею, как строка и смещение от PHP передаются в API C API PCRE, в зависимости от того, какой результат функции preg_* может отличаться.

Подробнее

На уровне API C API библиотеки PCRE вы можете работать только с блоком данных, который находится в 8-битных единицах для 8-битной библиотеки, в 16-разрядных устройствах для 16-разрядной библиотеки и 32-разрядных устройствах для 32-разрядной библиотеки ,

Для 8-битной библиотеки (UTF-8) 1 блок данных имеет 8-битный или 1 байт, поэтому не существует большого препятствия для задания смещения в байтах, как в качестве параметра для функции, так и в виде конструкции регулярного выражения.

Конструкции регулярных выражений

В режиме, отличном от UTF, класс символов [] , точка . и \C соответствует точно 1 единицам данных.

  • \C соответствует 1 единице данных, независимо от режима UTF или не UTF. Однако он не может использоваться в режиме просмотра в режиме UTF.

    СОПУТЬ ЕДИНИЦУ ДАННЫХ

    Вне класса символов последовательность escape \C соответствует любому одному блоку данных, независимо от того, установлен ли режим UTF.

  • . соответствует 1 единицам данных в режиме, отличном от UTF.

    Общие комментарии о режимах UTF

    […]

    1. Метафактор точки соответствует одному символу UTF вместо одного блока данных.
  • Класс символов соответствует 1 единице данных в режиме, отличном от UTF. В документации явно не указано это, но это подразумевается в формулировке.

    КВАДРАТНЫЕ КРЕПЛЕНИЯ И ХАРАКТЕРНЫЕ КЛАССЫ

    […]

    Класс символов соответствует одному символу объекта. В режиме UTF символ может содержать более одного блока данных.

    Тот же вывод можно найти, посмотрев верхний предел синтаксиса \x{hh...} чтобы указать символ шестнадцатеричным кодом в режиме, отличном от UTF. При тестировании последнее предложение о суррогате, похоже, не относится к не-UTF-режиму.

    Символы, которые задаются с использованием восьмеричных или шестнадцатеричных чисел, ограничены определенными значениями следующим образом:

      8-bit non-UTF mode less than 0x100 8-bit UTF-8 mode less than 0x10ffff and a valid codepoint 16-bit non-UTF mode less than 0x10000 16-bit UTF-16 mode less than 0x10ffff and a valid codepoint 32-bit non-UTF mode less than 0x100000000 32-bit UTF-32 mode less than 0x10ffff and a valid codepoint 

    Недопустимыми кодовыми точками Unicode являются диапазон от 0xd800 до 0xdfff (так называемые «суррогатные» кодовые точки) и 0xffef.

офсет

Все введенные и возвращенные смещения указаны в количестве блоков данных:

Строка, которая будет соответствовать pcre_exec()

Строка subject передается pcre_exec() как указатель subject , длина по length и начальное смещение в startoffset . Единицами для length и startoffset являются байты для 8-битной библиотеки, 16-разрядные элементы данных для 16-битной библиотеки и 32-разрядные элементы данных для 32-битной библиотеки.

Как pcre_exec() возвращает захваченные подстроки

[…]

Когда совпадение выполнено успешно, информация об захваченных подстроках возвращается парами целых чисел, начиная с начала ovector и продолжая до двух третей своей длины. Первый элемент каждой пары устанавливается на смещение первого символа в подстроке, а второй устанавливается на смещение первого символа после конца подстроки. Эти значения всегда являются выключенными блоками данных, даже в режиме UTF.

Вы можете попробовать /(?<=[\x00-\xFF]{n})some expression/ для 'n'- byte смещения. Добавьте якоря или некоторые другие мягкие анкеры, которые выполняют выравнивание начала.