Bri*_*rth 10 php regex regex-lookarounds
将n个字节的正向lookbehind插入(?<=\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)/i2字节的偏移量
据我所知,并且从我运行的有限测试中,添加这个lookbehind有效地模拟了这个偏移参数,并且不会混淆任何其他的lookbehinds,替换或其他控制模式; 但我也不是Regex的专家.
我试图通过将n字节lookbehind插入模式来确定是否有可能对构建替换/过滤器函数扩展产生影响.它应该像匹配函数的偏移参数一样工作 - 因此简单地运行表达式substr( $subject, $offset )将不会出于与其不相同的原因preg_match(最明显的是它会切断任何外观,^然后错误地匹配子字符串的开头,不是原来的字符串).
假设您的PHP捆绑的PCRE库被编译为8位库(UTF-8),那么在非UTF模式下
\C
Run Code Online (Sandbox Code Playgroud)
相当于
[\x00-\xff]
Run Code Online (Sandbox Code Playgroud)
和
(?s:.)
Run Code Online (Sandbox Code Playgroud)
它们中的任何一个都可以在后视中用作offset现场preg_match和preg_match_all功能的替代品.
在非UTF模式下,它们都匹配1个数据单元,即8位(UTF-8)PCRE库中的1个字节,它们匹配所有256个可能的不同值.
UTF模式可以通过激活u标志传递给图案preg_*的功能,或者通过指定(*UTF),(*UTF8),(*UTF16),(*UTF32)在模式的始动词.
在UTF模式下,字符类[]和点元字符.将匹配Unicode字符的有效范围内的一个代码点,而不是代理项.由于UTF-8中的一个代码点可以编码为1到4个字节,并且由于UTF-8的编码方案,因此不可能使用字符类构造来匹配0x80到0xFF范围内的值的单个字节.
虽然\C专门设计为匹配一个数据单元(UTF-8中的一个字节),无论UTF模式是否打开,但在UTF模式下的后视构造中不支持它.
我不知道是否有人实际编译16位或32位PCRE库,将其包含在PHP库中并实际使其工作.如果有人知道这种构建在野外广泛使用,请ping我.我实际上不知道如何将PHP的字符串和偏移量传递给PCRE的C API,具体取决于preg_*函数的结果可能有所不同.
在PCRE库的C API级别,您只能使用数据单元,对于8位库为8位单元,对于16位库为16位单元,对于32位库为32位单元.
对于8位库(UTF-8),1个数据单元是8位或1个字节,因此指定偏移量(无论是作为参数还是作为正则表达式构造)都没有太大的障碍.
在非UTF模式下,字符类[],点.和\C正好匹配1个数据单元.
\C匹配1个数据单元,无论是UTF模式还是非UTF模式.但它不能用于UTF模式的后视.
匹配单个数据单元
在字符类之外,转义序列
\C匹配任何一个数据单元,无论是否设置了UTF模式.
. 在非UTF模式下匹配1个数据单元.
关于UTF模式的一般评论
[...]
- 点元字符匹配一个UTF字符而不是单个数据单元.
字符类在非UTF模式下匹配1个数据单元.文档没有明确说明这一点,但措辞暗示了这一点.
SQUARE BRACKETS和CHARACTER CLASSES
[...]
字符类匹配主题中的单个字符.在UTF模式下,字符可以是多于一个数据单元.
通过查看\x{hh...}语法的上限可以达到相同的结论,以在非UTF模式下通过十六进制代码指定字符.通过测试,关于代理的最后一个条款似乎不适用于非UTF模式.
使用八进制或十六进制数字指定的字符仅限于某些值,如下所示:
Run Code Online (Sandbox Code Playgroud)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()主题字符串
pcre_exec()作为指针传入subject,长度为inlength,起始偏移量为startoffset. 8位库的单位length和startoffset字节数,16位库的16位数据项和32位库的32位数据项.
如何
pcre_exec()返回捕获的子串[...]
当匹配成功时,有关捕获的子串的信息将以整数对的形式返回,从ovector的开头开始,最多持续长度的三分之二.每对中的第一个元素设置为子字符串中第一个字符的偏移量,第二个元素设置为子字符串结尾后第一个字符的偏移量.即使在UTF模式下,这些值也始终是数据单元偏移量.