从字符串PHP中删除多字节空格

时间:2012-12-19 06:10:55

标签: php regex utf-8 preg-replace multibyte

我正在尝试使用preg_replace从字符串输入中消除日语全宽空格“ ”,但最终会出现损坏的多字节字符串。

我更喜欢preg_replace而不是str_replace。 以下是示例代码:

$keywords = ' ラメ単色';
$keywords = str_replace(array(' ', ' '), ' ', urldecode($keywords)); // outputs :'ラメ単色'

$keywords = preg_replace("@[  ]@", ' ',urldecode($keywords)); // outputs :'�� ��単色'

任何人都知道为什么会这样,以及如何解决这种情况?

4 个答案:

答案 0 :(得分:8)

u标记添加到正则表达式中。这使得RegEx引擎将输入字符串视为UTF-8。

$keywords = preg_replace("@[  ]@u", ' ',urldecode($keywords));
// outputs :'ラメ単色'

CodePad

它破坏字符串的原因是因为对于RegEx引擎,您的替换字符20(空格)或e3 80 80(IDEOGRAPHIC SPACE)不会被视为两个字符,而是单独的字节{{ 1}},20e3

当您查看要扫描的字符串的字节序列时,我们得到80。我们知道第一个字符是一个IDEOGRAPHIC SPACE,但由于PHP将其视为一个字节序列,它会单独替换前四个字节,因为它们匹配正则表达式引擎正在扫描的各个字节。

对于导致 (REPLACEMENT CHARACTER)的重整,我们可以看到这种情况发生,因为字符串e3 80 80 e3 83 a9 e3 83 a1 e5 8d 98 e8 89 b2在字符串中进一步出现。 e3字节是三字节长日语字符的起始字节,例如e3(KATAKANA LETTER RA)。当前导e3 83 a9替换为e3(空格)时,它不再成为有效的UTF-8序列。

当您启用20标志时,RegEx引擎会将字符串视为UTF-8,并且不会基于每个字节处理字符类中的字符。

答案 1 :(得分:2)

为避免其他问题,还可以考虑将内部编码明确设置为mb_ *函数解决方案:

mb_internal_encoding("UTF-8");

答案 2 :(得分:1)

总是很好地深入了解文档。我发现preg_ *相关函数没有针对mulitbyte charaacter进行优化。而是应该使用mb_ereg_ *和mb_ *函数。我通过重构代码来解决这个小问题:

$keywords = ' ラメ単色';
$pattern = " "/*ascii whitespace*/ . " "/*multi-byte whitespace*/;
$keywords = trim(
    mb_ereg_replace("[{$pattern}]+", ' ',urldecode($keywords))); // outputs:'ラメ単色' 

非常感谢!

答案 3 :(得分:-1)

使用此

$keywords = preg_replace('/\s+/', ' ',urldecode($keywords));