7

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

我更喜欢 preg_replace 而不是 str_replace。这是一个示例代码:

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

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

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

4

4 回答 4

9

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

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

键盘

它破坏字符串的原因是因为对于 RegEx 引擎,您的替换字符20(space) 或e3 80 80(IDEOGRAPHIC SPACE) 不被视为两个字符,而是单独的bytes20和.e380

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

至于导致 � (REPLACEMENT CHARACTER) 的修饰,我们可以看到发生这种情况,因为该字节e3在字符串中的位置更远。该e3字节是三字节长的日文字符的起始字节,例如e3 83 a9(KATAKANA LETTER RA)。当该前导e3被替换为20(空格)时,它不再成为有效的 UTF-8 序列。

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

于 2012-12-19T06:22:12.893 回答
2

为避免其他问题,还请考虑将内部编码显式设置为您的 mb_* 函数解决方案:

mb_internal_encoding("UTF-8");
于 2012-12-19T06:32:00.740 回答
1

深入研究文档总是好的。我发现 preg_* 相关函数没有针对多字节字符进行优化。相反,应该使用 mb_ereg_* 和 mb_* 函数。我通过将代码重构为以下内容解决了这个小问题:

$keywords = 'ラメ単色';
$pattern = " "/*ascii 空格*/ . " "/*多字节空格*/;
$关键字=修剪(
    mb_ereg_replace("[{$pattern}]+", ' ',urldecode($keywords))); //输出:'ラメ単色'

一样的谢谢!

于 2012-12-19T06:22:04.093 回答
-1

用这个

$keywords = preg_replace('/\s+/', ' ',urldecode($keywords));
于 2012-12-19T06:30:50.320 回答