发布日期:2018-03-26
如何从字符串中删除非UTF-8字符?+ 查看更多
如何从字符串中删除非UTF-8字符?
+ 查看更多
发布日期:2018-03-10 15:46
分类:PHP
浏览次数:477
我有一个问题是关于如何从字符串中删除无法正确显示的非UTF-8字符。例如0x97、0x61、0x6C、0x6F这些十六进制表示的字符。
删除它们的最佳方法是什么?正则表达式还是其他方法?
删除它们的最佳方法是什么?正则表达式还是其他方法?
回答:
如下是使用正则表达式的方法:
$regex = <<<'END'/ ( (?: [\x00-\x7F] # single-byte sequences 0xxxxxxx | [\xC0-\xDF][\x80-\xBF] # double-byte sequences 110xxxxx 10xxxxxx | [\xE0-\xEF][\x80-\xBF]{2} # triple-byte sequences 1110xxxx 10xxxxxx * 2 | [\xF0-\xF7][\x80-\xBF]{3} # quadruple-byte sequence 11110xxx 10xxxxxx * 3 ){1,100} # ...one or more times ) | . # anything else /x END; preg_replace($regex, '$1', $text);该方法可以搜索UTF-8序列并将它们放入到组1中。它还会匹配出那些不被确认为UTF-8序列的一部分的单字节符号,但是不会捕获它们。将组1中捕获到的全部内容都替换到$regex中。这样就有效的去除了所有的无效字节。
可以通过将无效字节编码成UTF-8字符来修复字符串。
但是如果产生的错误是随机的,那么可能会遗留下一些奇怪的符号。
$regex = <<<'END' / ( (?: [\x00-\x7F] # single-byte sequences 0xxxxxxx | [\xC0-\xDF][\x80-\xBF] # double-byte sequences 110xxxxx 10xxxxxx | [\xE0-\xEF][\x80-\xBF]{2} # triple-byte sequences 1110xxxx 10xxxxxx * 2 | [\xF0-\xF7][\x80-\xBF]{3} # quadruple-byte sequence 11110xxx 10xxxxxx * 3 ){1,100} # ...one or more times ) | ( [\x80-\xBF] ) # invalid byte in range 10000000 - 10111111 | ( [\xC0-\xFF] ) # invalid byte in range 11000000 - 11111111 /x END; function utf8replacer($captures) { if ($captures[1] != "") { // Valid byte sequence. Return unmodified. return $captures[1]; } elseif ($captures[2] != "") { // Invalid byte of the form 10xxxxxx. // Encode as 11000010 10xxxxxx. return "\xC2".$captures[2]; } else { // Invalid byte of the form 11xxxxxx. // Encode as 11000011 10xxxxxx. return "\xC3".chr(ord($captures[3])-64); } } preg_replace_callback($regex, "utf8replacer", $text);
注意: !empty(x) 可以匹配非空值("0" 被认为是空值).
x != "" 可以匹配非空值,包括 "0".
x !== "" 可以匹配任何值,除了 "".
在这里,使用x != "" 似乎是最好的方法。
x != "" 可以匹配非空值,包括 "0".
x !== "" 可以匹配任何值,除了 "".
在这里,使用x != "" 似乎是最好的方法。