Php 从字符串中去掉多字节空白

Php 从字符串中去掉多字节空白,php,regex,utf-8,preg-replace,multibyte,Php,Regex,Utf 8,Preg Replace,Multibyte,我正在尝试使用preg_替换来消除日语的全宽空白“ “从一个字符串输入,但我最终得到一个损坏的多字节字符串 我更喜欢preg_替换而不是str_替换。 下面是一个示例代码: $keywords = ' ラメ単色'; $keywords = str_replace(array(' ', ' '), ' ', urldecode($keywords)); // outputs :'ラメ単色' $keywords = preg_replace("@[  ]@", ' ',urldecode($key

我正在尝试使用preg_替换来消除日语的全宽空白“
 “从一个字符串输入,但我最终得到一个损坏的多字节字符串

我更喜欢preg_替换而不是str_替换。 下面是一个示例代码:

$keywords = ' ラメ単色'; $keywords = str_replace(array(' ', ' '), ' ', urldecode($keywords)); // outputs :'ラメ単色' $keywords = preg_replace("@[  ]@", ' ',urldecode($keywords)); // outputs :'�� ��単色' $keywords='1 ラメ単色'; $keywords=str_replace(数组(“”,' '), ' ', urldecode($keywords));//输出:'ラメ単色' $keywords=preg_replace(@[ ]@", ' ',urldecode($keywords));//输出:'�� ��単色'
任何人都知道为什么会这样,以及如何补救这种情况吗?

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

$keywords = ' ラメ単色'; $pattern = " "/*ascii whitespace*/ . " "/*multi-byte whitespace*/; $keywords = trim( mb_ereg_replace("[{$pattern}]+", ' ',urldecode($keywords))); // outputs:'ラメ単色' $keywords='1 ラメ単色'; $pattern=”“/*ascii空格*/。” “/*多字节空格*/; $keywords=trim( mb_ereg_replace(“[{$pattern}]+”,“”,urldecode($keywords));//输出:'ラメ単色'
同样感谢!

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

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

它损坏字符串的原因是,对于正则表达式引擎,替换字符,
20
(空格)或
e3 80
(表意空格)不被视为两个字符,而是单独的字节
20
e3
80

当您查看要扫描的字符串的字节序列时,我们得到
e3 80 80 e3 83 a9 e3 83 a1 e5 8d 98 e8 89 b2
。我们知道第一个字符是表意空间,但由于PHP将其视为一个字节序列,它会单独替换前四个字节,因为它们与regex eng艾琳正在扫描

至于导致� (替换字符),我们可以看到这种情况,因为字节
e3
出现在字符串的后面。
e3
字节是三字节长的日文字符的起始字节,例如
e3 83 a9
(片假名字母RA)。当前面的
e3
替换为
20
(空格),它不再成为有效的UTF-8序列

当您启用
u
标志时,正则表达式引擎将字符串视为UTF-8,并且不会按每个字节处理字符类中的字符。

使用此选项

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

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

mb_internal_encoding("UTF-8");

$keywords
相同吗 ラメ単色'?是的,快速复制和编辑我将接受你的答案,因为它使用了我首选的preg__替换。mb_ereg_替换也可以完成任务。谢谢!这与OP想要删除的所有字符都不匹配。