Каковы были бы последствия вставки положительного 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 и ^
затем неправильно совпадает с началом подстроки, а не с исходной строкой).
Предполагая, что ваша библиотека 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 может быть активирован флагом u
в шаблоне, переданном функции preg_*
, или путем указания (*UTF)
, (*UTF8)
, (*UTF16)
, (*UTF32)
глаголов в начале шаблона.
В режиме UTF, класс символов []
и метасимвол точки .
будет соответствовать одной кодовой точке в пределах допустимого диапазона символов Юникода и не является суррогатом. Поскольку одна кодовая точка может быть закодирована в 1-4 байта в UTF-8, и из-за схемы кодирования UTF-8 невозможно использовать конструкцию символьного класса для соответствия одному байту для значений в диапазоне от 0x80 до 0xFF ,
В то время как \C
специально разработан для соответствия одному блоку данных (который является одним байтом в UTF-8) независимо от того, включен ли режим UTF, он не поддерживается в конструкции look-behind в режиме UTF.
Я не знаю, действительно ли кто-то компилирует 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
[…]
- Метафактор точки соответствует одному символу 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
смещения. Добавьте якоря или некоторые другие мягкие анкеры, которые выполняют выравнивание начала.