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

Каковы были бы последствия вставки положительного 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 и ^ затем неправильно совпадает с началом подстроки, а не с исходной строкой).

Ответ 1

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

В режиме, отличном от 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.

Offset

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

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

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

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

[...]

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

Ответ 2

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