在任意正则表达式的开头插入n字节(?<=\C{n})
的正向lookbehind会产生什么后果,特别是在用于替换操作时?
至少在PHP中,正则表达式匹配函数preg_match
和preg_match_all
允许匹配在给定的字节偏移量之后开始。任何其他PCRE PHP函数都没有相应的功能 - 例如,您可以指定preg_replace
完成的替换次数的限制,但不能指定那些替换次数&#39;匹配必须在n字节之后发生。
显然会有一些(让它们称之为微不足道)对性能和可读性的影响,但会有任何(非平凡的)影响,比如匹配变为不匹配(除非它们没有被n个字节偏移)或替换变得格格不入?
一些例子:
对于4字节偏移量 /some expression/
变为/(?<=\C{4})some expression/
/(this) has (groups)/i
变为/(?<=\C{2})(this) has (groups)/i
据我所知,并且从我所运行的有限测试中,添加此外观有效地模拟了此偏移参数,并且不会混淆任何其他外观,替换或其他控制模式;但我也不是Regex的专家。
我试图通过将n字节lookbehind插入模式来确定是否可能对构建替换/过滤器函数扩展产生任何影响。它应该像匹配函数一样运行。偏移参数有效 - 所以简单地针对substr( $subject, $offset )
运行表达式的工作原因与preg_match
没有相同的原因(最明显的是它会切断任何外观和^
然后错误地匹配子字符串的开头,而不是原始字符串。)
答案 0 :(得分:6)
假设与PHP捆绑在一起的PCRE库编译为 8位库(UTF-8),则在非UTF模式下
\C
相当于
[\x00-\xff]
和
(?s:.)
其中任何一个都可以在后视中用作offset
和preg_match
函数中preg_match_all
字段的替换。
在非UTF模式下,它们都匹配1个数据单元,即8位(UTF-8)PCRE库中的1个字节,它们匹配所有256个不同的值。
UTF模式可以通过传递给u
函数的模式中的preg_*
标记激活,也可以通过指定(*UTF)
,(*UTF8)
,(*UTF16)
,{{ 1}}动词在模式的开头。
在UTF模式下,字符类(*UTF32)
和点元字符[]
将匹配Unicode字符的有效范围内的一个代码点,而不是代理项。由于UTF-8中的一个代码点可以编码为1到4个字节,并且由于UTF-8的编码方案,因此不可能使用字符类构造来匹配0x80到0xFF范围内的值的单个字节
虽然.
专门用于匹配一个数据单元(UTF-8中的一个字节),无论UTF模式是否打开,但在UTF模式下的后视结构中不支持它。
我不知道是否有人实际编译了16位或32位PCRE库,将其包含在PHP库中并实际使其工作。如果有人知道在野外使用广泛这样的构建,请ping我。我实际上不知道如何将PHP的字符串和偏移量传递给PCRE的C API,具体取决于\C
函数的结果可能不同。
在PCRE库的C API级别,您只能使用数据单元,对于8位库为8位单元,对于16位库为16位单元,对于32位为32位单元位库。
对于8位库(UTF-8),1个数据单元是8位或1个字节,因此指定偏移量(无论是作为参数还是作为正则表达式构造)都没有太大的障碍。
在非UTF模式下,字符类preg_*
,点[]
和.
恰好匹配1个数据单元。
\C
匹配1个数据单元,无论是UTF模式还是非UTF模式。但它不能用于UTF模式的后视。
匹配单个数据单元
在字符类之外,转义序列
\C
匹配任何一个数据 单位,是否设置了UTF模式。
\C
在非UTF模式下匹配1个数据单元。
关于UTF模式的一般评论
[...]
- 点元字符匹配一个UTF字符而不是单个字符 数据单位。
醇>
字符类在非UTF模式下匹配1个数据单元。文档没有明确说明这一点,但措辞暗示了这一点。
SQUARE BRACKETS和CHARACTER CLASSES
[...]
字符类匹配主题中的单个字符。在UTF中 模式,该字符可能不止一个数据单元。
通过查看.
语法的上限可以达到相同的结论,以在非UTF模式下通过十六进制代码指定字符。通过测试,关于代理的最后一个条款似乎并不适用于非UTF模式。
使用八进制或十六进制数字指定的字符是 限于某些值,如下:
\x{hh...}
无效的Unicode代码点是0xd800到0xdfff的范围(所以 - 叫&#34;代理&#34;代码点)和0xffef。
提供和返回的所有偏移量均以数据单位数:
匹配的字符串
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
主题字符串作为
pcre_exec()
中的指针传递给pcre_exec()
,asubject
中的长度和length
中的起始偏移量。单位为startoffset
和length
是8位库的字节,即16位数据 16位库的项目和32位的32位数据项 库。
startoffset
如何返回捕获的子字符串[...]
当匹配成功时,有关捕获的子串的信息是 从ovector开始,以整数对返回, 并且最多持续长度的三分之二。首先 每对的元素设置为a中第一个字符的偏移量 substring,第二个设置为第一个字符的偏移量 在子串结束后。这些值始终是数据单元 - 即使在UTF模式下也会设置。
答案 1 :(得分:1)
您可以尝试/(?<=[\x00-\xFF]{n})some expression/
获取'n' - byte
偏移量。添加锚点或其他一些开始对齐的软锚。