Jac*_*iuk 1 php regex unicode utf-8 character-encoding
我有一个杂乱的数据库,其中包含世界各地许多机构的名称.
我想显示它们,包括国家字符,但没有无效字符 - 在firefox中显示为unicode数字.
如何过滤掉它们?
数据库具有utf8编码,但是某些字符串插入了错误的编码或者源代码中已经混乱.
我不想修复数据库 - 它太大了.我想过滤掉它 - "看不见了"
我想过滤掉它
你的数据有一个未指定的编码/字符集.这是一个很大的问题.
您可以先尝试将其转换为utf-8
然后删除所有不可打印的字符:
$str = iconv('utf-8', 'utf-8//ignore', $str);
echo preg_replace('/[^\pL\pN\pP\pS\pZ]/u', '', $str);
Run Code Online (Sandbox Code Playgroud)
问题是,该iconv
功能只能尝试.它会丢弃任何无效的字符序列.从PHP 5.4开始,如果指定的输入编码无效,它将删除完整的字符串.
从PHP 5.3开始,您将看到一个警告,即输入字符串的编码无效.
你可以先删除所有无效的utf-8
字节序列来解决这个问题:
$str = valid_utf8_bytes($str);
echo preg_replace('/[^\pL\pN\pP\pS\pZ]/u', '', $str);
/**
* get valid utf-8 byte squences
*
* take over all matching bytes, drop an invalid sequence until first
* non-matching byte.
*
* @param string $str
* @return string
*/
function valid_utf8_bytes($str)
{
$return = '';
$length = strlen($str);
$invalid = array_flip(array("\xEF\xBF\xBF" /* U-FFFF */, "\xEF\xBF\xBE" /* U-FFFE */));
for ($i=0; $i < $length; $i++)
{
$c = ord($str[$o=$i]);
if ($c < 0x80) $n=0; # 0bbbbbbb
elseif (($c & 0xE0) === 0xC0) $n=1; # 110bbbbb
elseif (($c & 0xF0) === 0xE0) $n=2; # 1110bbbb
elseif (($c & 0xF8) === 0xF0) $n=3; # 11110bbb
elseif (($c & 0xFC) === 0xF8) $n=4; # 111110bb
else continue; # Does not match
for ($j=++$n; --$j;) # n bytes matching 10bbbbbb follow ?
if ((++$i === $length) || ((ord($str[$i]) & 0xC0) != 0x80))
continue 2
;
$match = substr($str, $o, $n);
if ($n === 3 && isset($invalid[$match])) # test invalid sequences
continue;
$return .= $match;
}
return $return;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4907 次 |
最近记录: |