preg_split与mb_split比较

8
根据PHP手册,PCRE正则表达式的u修饰符可以为模式和主题字符串启用UTF-8支持。
考虑到这一点,使用带有u修饰符的PCRE表达式和相应的mb_*多字节字符串函数之间是否有任何区别?(假设所有字符串都是UTF-8编码。)
例如,考虑preg_splitmb_split:两者均可用于分割字符串。
preg_split('/' . $pattern . '/u', $string);

并且

mb_split($pattern, $string);

它们似乎返回相同的结果。那么,哪一个应该优先使用?甚至有必要吗?


1
我会说这基本上和比较preg_matchstrpos用于静态字符串搜索是一样的。 - Niet the Dark Absol
1
为什么 strpos 不支持正则表达式呢?或者我对此有误解吗? - emkey08
1
当字符串是常量而不是正则表达式时,使用静态字符串搜索。 - Niet the Dark Absol
@NiettheDarkAbsol preg_split / mb_split 都是用于正则表达式的,所以我不理解 preg_match / strpos 的类比。 - fusion3k
哦。糟糕。那就不理我吧。 - Niet the Dark Absol
2个回答

11
主要区别在于preg_函数使用pcre库,而mb_ereg_函数(包括mb_split)使用oniguruma库(用于ruby 2.0之前的版本)。
The main reason is that oniguruma can deal with multiple encodings (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) when pcre can't.
Note that a lot of encodings available for mb_ functions like mb_detect_encoding are not in this list (UTF-7, ArmSCII-8, CP866 for example) limiting the relevance of mb_ereg_ functions. (Since you need to convert the string to a supported encoding before working on it, and to convert it back after.)
这两个正则表达式引擎基本上具有相同的功能,但仍然存在一些差异(并非详尽无遗):
Oniguruma 不支持:
  • 单字节Unicode简写字符类的书写方式不需要花括号。例如:\pN应被视为pN,您需要写成:\p{N}
  • Unicode字符类:Xan、Xps、Xsp、Xwd
  • 字符类中的非转义方括号:Oniguruma将[][]视为两个空字符类,而PCRE则将其视为包含][的字符类
  • \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修饰符来匹配换行符与点号。在PCRE中,m修饰符的行为不同,它将^$锚从字符串的“开头”和“结尾”更改为行的“开头”和“结尾”。
使用Oniguruma时,这些锚的含义不会改变,它们始终匹配行的开头和结尾。为了匹配字符串的限制,它还使用\A\z,这也可用于PCRE。
请注意,Oniguruma已被分叉为Onigmo(用于当前的Ruby版本),它实现了更多的Perl功能和语法元素,并且更类似于PCRE。

2
只要您严格使用 UTF-8,则两者都可以。如果您使用其他 charset,则建议使用 mb_split(),因为 PCRE 的 u 修饰符不允许您指定 charset,而是将字符串视为 UTF-8

关于扩展性和长期可行性,我建议从一开始就使用 mb_split(),这样在需要使用或使用除 UTF-8 以外的内容时,您也会得到保障。


你是不是指的是 mb_split 而不是 preg_split?你可以使用 mb_regex_encoding 来设置编码,然后再使用 mb_* 函数。 - emkey08

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接