如何拆分英文字母、数字和汉字?

How to split English letters, numbers and Chinese characters?

为了更好地说明问题,我将陈述几个输入以及所需的输出:

所以基本上,输入的字符串可以有白色space也可以没有,而且英文字母、数字和汉字的顺序是未知的,可以出现不止一次。

我发现这个可以在没有汉字的情况下完成工作(参考:Splitting string containing letters and numbers):

$array = preg_split("/(,?\s+)|((?<=[a-z])(?=\d))|((?<=\d)(?=[a-z]))/i", $str);

我能大致理解上面的正则表达式:

  1. (,?\s+) - 被白色 spaces 分割,所以
  2. (?<=[a-z])(?=\d) - 如果数字紧跟在字母之后,将它们分开
  3. (?<=\d)(?=[a-z]) - 如果字母紧跟在数字之后,将它们分开

所以我天真地想:我总共需要做3件事:

  1. 如果数字紧跟在字母或汉字之后,将它们分开
  2. 如果字母紧跟在数字或汉字之后,将它们分开
  3. 如果一个汉字紧跟在一个字母或数字之后,将它们分开

为了实现1,我是这样想的:

(?<=[a-z\x4E00-\x9FA5])(?=\d)

其中\x4E00-\x9FA5是匹配汉字。但这行不通!

要以明确的方式做到这一点,您可以使用:

$result = preg_split('~(?<!\p{Latin})(?=\p{Latin})|(?<!\p{Han})(?=\p{Han})|(?<![0-9])(?=[0-9])~u', $str, -1, PREG_SPLIT_NO_EMPTY);

(在每个边界上拆分字符串)。请注意,如果您只有三种字符,则可以删除其中一种边界(您想要的那种)。

如果要从结果中删除空格,可以将所有内容放在非捕获组中并在模式开头添加 \s*

然而,使用 preg_match_all 可能会以更少的努力得到相同的结果:

if (preg_match_all('~\p{Latin}+|\p{Han}+|[0-9]+~u', $str, $matches))
    $result = $matches[0];

u 修饰符强制正则表达式引擎将字符串读取为 UTF8 字符串。