preg_split 对比 mb_split

preg_split vs mb_split

根据 PHP manual,PCRE 正则表达式的 u 修饰符为模式和主题字符串启用 UTF-8 支持。

考虑到这一点,使用带有 u 修饰符的 PCRE 表达式和相应的 mb_* 多字节字符串函数有什么区别吗? (假设所有字符串都是 UTF-8 编码。)


例如,考虑 preg_splitmb_split:两者

preg_split('/' . $pattern . '/u', $string);

mb_split($pattern, $string);

似乎return 相同的结果。那么,应该优先选择哪一个呢?这有关系吗?

只要您严格按照 UTF-8 工作,您都可以。如果您使用另一个 charset,那么建议使用 mb_split(),因为 PCRE 的 u 修饰符不允许您指定 charset,而是将字符串视为UTF-8.

关于扩展和长期生存能力,我建议从一开始就使用 mb_split(),以便在以后使用或需要 UTF-8 以外的东西时,您可以得到保障。

主要区别在于preg_函数使用pcre library, when the mb_ereg_ functions (including mb_split) use the oniguruma library(在2.0版本之前的ruby中使用)。

主要原因是oniguruma可以处理多种编码(ASCII, UTF-8, UTF-16BE, UTF-16LE, UTF-32BE, UTF-32LE, EUC-JP, EUC- TW, EUC-KR, EUC-CN, Shift_JIS, Big5, GB18030, KOI8-R, CP1251, ISO-8859-1, ISO-8859-2, ISO-8859-3, ISO-8859-4, ISO-8859-5、ISO-8859-6、ISO-8859-7、ISO-8859-8、ISO-8859-9、ISO-8859-10、ISO-8859-11、ISO-8859-13、ISO- 8859-14、ISO-8859-15、ISO-8859-16) 当 pcre 不能时。

请注意,许多可用于 mb_ 函数的编码如 mb_detect_encoding 不在此列表中(例如 UTF-7、ArmSCII-8、CP866)限制了 [=11 的相关性=] 功能。 (因为您需要先将字符串转换为受支持的编码,然后再将其转换回来。)

这两个正则表达式引擎或多或少具有相同的功能,但是您可以找到一些不同之处(并非详尽无遗):

Oniguruma 不支持:

  • 一个字母unicode shorthand字符class要写成没有大括号。
    例如:\pN被看作pN,你需要写:\p{N}
  • unicode字符classes: Xan, Xps, Xsp, Xwd
  • 字符中的非转义方括号 class:Oniguruma 将 [][] 视为两个空字符 classes,当 pcre 将字符 class 视为包含 ][
  • \K 功能
  • 换行序列的 \R 别名
  • 使用 Python 语法 (?P<name>...) 的命名组。只允许 (?<name>...)(?'name'...)
  • 使用 Oniguruma 语法以外的其他内容对引用进行分组:\g<name>(不允许使用 Perl 语法 (?&name)(?1)(?R))。
  • 回溯控制动词

PCRE 不支持:

  • 重复的命名组(默认)。您需要使用 (?J) 修饰符来开启此功能。
  • \k<...> 语法的编号反向引用。您可以写 \k<name> 但不能写 \k<1>\k<-1>.
  • 对特定嵌套级别的反向引用。 Oniguruma 可以使用 \k<name+n> 做到这一点,其中 n 是嵌套级别。


为了用点匹配换行符,Oniguruma 使用 m 修饰符,而 PCRE 使用 s 修饰符。 在 mb_ereg_ 函数中,点默认匹配换行符。 (所以默认情况下 m 修饰符是打开的)。

PCRE 使用 s 修饰符来匹配换行符和点。 m 修饰符在 PCRE 中的行为不同,它将 ^$ 锚点的含义从字符串的 "start" 和 "end" 更改为 "start"和行的 "end"。

对于 Oniguruma,这些锚点的含义不会改变,它们始终匹配行的开头和结尾。为了匹配字符串的限制,它使用 \A\z 也可用于 PCRE。

请注意,Oniguruma 已分叉为 Onigmo(在当前 Ruby 版本中使用)实现了更多 Perl 功能和句法元素,并且与 PCRE 更相似。