根据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);
似乎返回相同的结果。那么,应该首选哪一个?它甚至重要吗?
答案 0 :(得分:10)
主要区别在于preg_
函数使用pcre library,mb_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不支持:
\pN
被视为pN
,你需要写:\p{N}
[][]
和]
[
视为两个空字符类
\K
功能\R
别名(?P<name>...)
的命名组。仅允许(?<name>...)
或(?'name'...)
。\g<name>
(不允许使用Perl语法(?&name)
和(?1)
或(?R)
。PCRE不支持:
(?J)
修饰符来启用此功能。\k<...>
语法对后引用进行编号。您可以写\k<name>
但不能\k<1>
或\k<-1>
。\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
以外的其他内容时进行保护。