我正在尝试使用preg_replace从字符串输入中消除日语全宽空格“
”,但最终会出现损坏的多字节字符串。
我更喜欢preg_replace而不是str_replace。 以下是示例代码:
$keywords = ' ラメ単色'; $keywords = str_replace(array(' ', ' '), ' ', urldecode($keywords)); // outputs :'ラメ単色' $keywords = preg_replace("@[ ]@", ' ',urldecode($keywords)); // outputs :'�� ��単色'
任何人都知道为什么会这样,以及如何解决这种情况?
答案 0 :(得分:8)
将u
标记添加到正则表达式中。这使得RegEx引擎将输入字符串视为UTF-8。
$keywords = preg_replace("@[ ]@u", ' ',urldecode($keywords));
// outputs :'ラメ単色'
它破坏字符串的原因是因为对于RegEx引擎,您的替换字符20
(空格)或e3 80 80
(IDEOGRAPHIC SPACE)不会被视为两个字符,而是单独的字节{{ 1}},20
和e3
。
当您查看要扫描的字符串的字节序列时,我们得到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));