preg_split vs mb_split

时间:2016-03-20 15:38:04

标签: php regex split pcre

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

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

例如,请考虑preg_split vs mb_split:两者

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

mb_split($pattern, $string);

似乎返回相同的结果。那么,应该首选哪一个?它甚至重要吗?

2 个答案:

答案 0 :(得分:10)

主要区别在于preg_函数使用pcre librarymb_ereg_函数(包括mb_split)使用oniguruma library(之前在ruby中使用)版本2.0)。

主要原因是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)限制了mb_ereg_的相关性功能。 (因为您需要在处理之前将字符串转换为支持的编码,然后将其转换回来。)

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

Oniguruma不支持:

  • 一个字母的unicode速记字符类,没有大括号。例如:\pN被视为pN,你需要写:\p{N}
  • unicode字符类:Xan,Xps,Xsp,Xwd
  • 字符类中的非转义方括号:当pcre看到包含[][]]
  • 的字符类时,Oniguruma将[视为两个空字符类
  • \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是巢级别。


为了使换行符与点匹配,当PCRE使用m修饰符时,Oniguruma使用s修饰符。 在mb_ereg_函数中,默认情况下,点与新行匹配。 (因此默认情况下m修饰符处于启用状态。)

PCRE使用s修饰符将换行符与点匹配。 m修饰符在PCRE中的行为有所不同,它改变了^$锚点的含义来自&#34; start&#34;和&#34;结束&#34;字符串到&#34;开始&#34;和&#34;结束&#34;这条线。

使用Oniguruma,这些锚点的含义不会改变,它们始终匹配线条的起点和终点。为了匹配字符串的限制,它使用了PCRE也可以使用\A\z

请注意,Oniguruma已被分叉以提供Onigmo(在当前的Ruby版本中使用),它实现了更多的Perl功能和语法元素,而且更类似于PCRE。

答案 1 :(得分:2)

只要您严格按照UTF-8工作,您就可以了。如果您使用其他charset,则建议使用mb_split(),因为带有PCRE的u修饰符不允许您指定charset,而是将字符串视为UTF-8

关于缩放和长期可行性,我建议您从一开始就使用mb_split(),以便在未来使用UTF-8以外的其他内容时进行保护。