php - 在 PHP 中检测 Unicode 字符范围

标签 php unicode utf-8 character-encoding

晚上,

有谁知道在 PHP 中检测字符串的 Unicode 范围的最快方法是什么?我以为 PHP 中会有一些东西可以做到这一点,但我找不到任何东西。理想情况下,我想要的是一个函数,它会说“John Jones”100% 是拉丁语或“Jones језик”是 50% 拉丁语和 50% 西里尔语。

您可以在 ReEx 中使用如下所示的内容来完成此操作:

strA = 'John Jones';
$strB = 'Српски језик';
$strC = 'Հայաստանի Հանրապետություն';
preg_match( '~[\p{Cyrillic}\p{Common}]+~u', $strB, $res );

但这需要检查每个范围,这似乎不是一个好主意。或者,您可以获取每个字符的 unicode 值并检查它所在的范围。但我想有人已经做了类似的事情。

编辑

为了更多地了解为什么这可能有用,正如评论中指出的,有些人有时会混合视觉上相同的拉丁字符和西里尔字符。例如这是用西里尔文“С”搜索克罗地亚,其余部分用拉丁文搜索:

https://www.google.am/search?q=%22%D0%A1roatia%22&aq=f&oq=%22%D0%A1roatia%22

再次使用完整拉丁语搜索,您将得到大约 100,000,000 个结果,而不是 20,000 个。在这种情况下,需要根据文本上下文来替换适当的字符。此类检测有用的一个很好的例子是使用西里尔字母绕过脏话过滤器的人。

最佳答案

我已经做了一些事情。这将检测每个字符的范围。我一开始只输入了亚美尼亚语、拉丁语和俄语。如果其他人有此需要,您需要从以下来源找到 detectorRanges 函数的字符范围: http://jrgraphix.net/r/Unicode/我想看看是否有更好的方法来完成这部分。确保范围内的所有字母字符均为小写。

mb_internal_encoding("UTF-8");
echo header( "Content-Type: text/html;charset=UTF-8", true );

class DetectUnicodeRanges
{
    function entityToUTF8( $number )
    {
        if( $number < 0 )
                return false;

        # Replace ASCII characters
        if( $number < 128 )
                return chr( $number );

        # Replace illegal Windows characters
        if( $number < 160 )
        {
            switch( $number )
            {
                case 128: $conversion = 8364; break;
                case 129: $conversion = 160; break;
                case 130: $conversion = 8218; break;
                case 131: $conversion = 402; break;
                case 132: $conversion = 8222; break;
                case 133: $conversion = 8230; break;
                case 134: $conversion = 8224; break;
                case 135: $conversion = 8225; break;
                case 136: $conversion = 710; break;
                case 137: $conversion = 8240; break;
                case 138: $conversion = 352; break;
                case 139: $conversion = 8249; break;
                case 140: $conversion = 338; break;
                case 141: $conversion = 160; break;
                case 142: $conversion = 381; break;
                case 143: $conversion = 160; break;
                case 144: $conversion = 160; break;
                case 145: $conversion = 8216; break;
                case 146: $conversion = 8217; break;
                case 147: $conversion = 8220; break;
                case 148: $conversion = 8221; break;
                case 149: $conversion = 8226; break;
                case 150: $conversion = 8211; break;
                case 151: $conversion = 8212; break;
                case 152: $conversion = 732; break;
                case 153: $conversion = 8482; break;
                case 154: $conversion = 353; break;
                case 155: $conversion = 8250; break;
                case 156: $conversion = 339; break;
                case 157: $conversion = 160; break;
                case 158: $conversion = 382; break;
                case 159: $conversion = 376; break;
            }

            return $conversion;
        }

        if ( $number < 2048 )
                return chr( ($number >> 6 ) + 192 ) . chr( ( $number & 63 ) + 128 );
        if ( $number < 65536 )
                return chr( ( $number >> 12 ) + 224 ) . chr( ( ( $number >> 6 ) & 63 ) + 128 ) . chr( ( $number & 63 ) + 128 );
        if ( $number < 2097152 )
                return chr( ( $number >> 18 ) + 240 ) . chr( ( ( $number >> 12 ) & 63 ) + 128 ) . chr( ( ( $number >> 6 ) & 63 ) + 128 ) . chr( ( $number & 63 ) + 128 );

        return false;
    }

    function MBStrToHexes( $str )
    {        
        $str = mb_convert_encoding( $str, 'UCS-4BE' );
        $hexs = array();
        for( $i = 0; $i < mb_strlen( $str, 'UCS-4BE' ); $i++ )
        {        
            $s2 = mb_substr( $str, $i, 1, 'UCS-4BE' );                    
            $val = unpack( 'N', $s2 );
            $hexs[] = str_pad( dechex( $val[1] ), 4, 0, STR_PAD_LEFT );                
        }        
        return( $hexs );
    }

    function detectRanges( $str )
    {
        $hexes = $this->MBStrToHexes( $str );
        foreach( $hexes as $hex )
        {
            if( ( $hex >= '0041' ) && ( $hex <= '024f' ) )
                echo $this->entityToUTF8( hexdec($hex) ) . ' - Latin<br />';
            elseif( ( $hex >= '0400' ) && ( $hex <= '04ff' ) )
                echo $this->entityToUTF8( hexdec($hex) ) . ' - Cyrillic<br />';
            elseif( ( $hex >= '0530' ) && ( $hex <= '058f' ) )
                echo $this->entityToUTF8( hexdec($hex) ) . ' - Armenian<br />';
            else
                echo $this->entityToUTF8( $hex ) . ' - Some Other Range<br />';
        }
    }

}

#$strB = 'Cornelius Trow';
$strB = 'Cornelius Српски Հայաստանի';
#$strB = 'Հայաստանի Հանրապետություն';
echo 'Testing String: ' . $strB . '<br />';
$dur = new DetectUnicodeRanges();
$dur->detectRanges( $strB );

关于php - 在 PHP 中检测 Unicode 字符范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20713443/

相关文章:

转换到 LPCWSTR?

unicode - 如何处理 SDL 中的大写击键?

delphi - 如何在 Delphi 中使用 TXMLDocument 将 Ansi 转换为 UTF 8

encoding - 如何从 VBScript 中的单个字符获取 UTF-8 编码

php - 替换字符串中的 utf8 文字

php - 允许根据设置的权限编辑模型以及 Laravel 中模型的属性值

php - Doctrine 2 删除实体问题

python - PyCharm 调试器中的 UnicodeDecodeError

PHP imap_open 适用于 7.0.6 但不适用于 5.4.16

php - 使用数据库输入命名数组