代码之家  ›  专栏  ›  技术社区  ›  Ian Baget

php多字节str_replace?

  •  12
  • Ian Baget  · 技术社区  · 16 年前

    我试着在PHP中做重音字符替换,但是得到了很坏的结果,我猜是因为我使用的是UTF-8字符串,StryEnter不能正确地处理多字节字符串。

    $accents_search     = array('á','à','â','ã','ª','ä','å','Á','À','Â','Ã','Ä','é','è',
    'ê','ë','É','È','Ê','Ë','í','ì','î','ï','Í','Ì','Î','Ï','œ','ò','ó','ô','õ','º','ø',
    'Ø','Ó','Ò','Ô','Õ','ú','ù','û','Ú','Ù','Û','ç','Ç','Ñ','ñ'); 
    
    $accents_replace    = array('a','a','a','a','a','a','a','A','A','A','A','A','e','e',
    'e','e','E','E','E','E','i','i','i','i','I','I','I','I','oe','o','o','o','o','o','o',
    'O','O','O','O','O','u','u','u','U','U','U','c','C','N','n'); 
    
    $str = str_replace($accents_search, $accents_replace, $str);
    

    我得到的结果:

    Ørjan Nilsen -> �orjan Nilsen
    

    预期结果:

    Ørjan Nilsen -> Orjan Nilsen
    

    编辑:我已经把我的内部字符处理程序设置为UTF-8(根据MbInInLalEnEnCONDIGN()),$STR的值是UTF-8,所以从我可以看出,涉及的所有字符串都是UTF-8。str_replace()是否检测到字符集并正确使用它们?

    4 回复  |  直到 13 年前
        1
  •  5
  •   phsiao    16 年前

    由于输入编码和文件编码不匹配,看起来字符串没有被替换。

        2
  •  18
  •   dav    13 年前

    根据php文档 str_replace 函数是二进制安全的,这意味着它可以处理。 UTF-8 编码文本没有任何数据丢失。

        3
  •  3
  •   mermshaus    16 年前

    可以使用 Unicode normalization form D (NFD)和Unicode字符属性。

    nfd将类似“umlaut”的内容从“带分音符的拉丁文小写字母u”(这是一个字母)转换为“拉丁文小写字母u”(字母)和“组合分音符”(不是字母)。

    header('Content-Type: text/plain; charset=utf-8');
    
    $test = implode('', array('á','à','â','ã','ª','ä','å','Á','À','Â','Ã','Ä','é','è',
    'ê','ë','É','È','Ê','Ë','í','ì','î','ï','Í','Ì','Î','Ï','œ','ò','ó','ô','õ','º','ø',
    'Ø','Ó','Ò','Ô','Õ','ú','ù','û','Ú','Ù','Û','ç','Ç','Ñ','ñ'));
    
    $test = Normalizer::normalize($test, Normalizer::FORM_D);
    
    // Remove everything that's not a "letter" or a space (e.g. diacritics)
    // (see http://de2.php.net/manual/en/regexp.reference.unicode.php)
    $pattern = '/[^\pL ]/u';
    
    echo preg_replace($pattern, '', $test);
    

    输出:

    aaaaªaaAAAAAeeeeEEEEiiiiIIIIœooooºøØOOOOuuuUUUcCNn
    

    normalizer类是 PECL intl package . (算法本身并不复杂,但需要加载大量字符映射afaik。我写了一篇 PHP implementation 不久前。)

    (我迟了两个月才补充这一点,因为我认为这是一种尚未广为人知的好技术。)

        4
  •  2
  •   Gumbo    15 年前

    尝试此函数定义:

    if (!function_exists('mb_str_replace')) {
        function mb_str_replace($search, $replace, $subject) {
            if (is_array($subject)) {
                foreach ($subject as $key => $val) {
                    $subject[$key] = mb_str_replace((string)$search, $replace, $subject[$key]);
                }
                return $subject;
            }
            $pattern = '/(?:'.implode('|', array_map(create_function('$match', 'return preg_quote($match[0], "/");'), (array)$search)).')/u';
            if (is_array($search)) {
                if (is_array($replace)) {
                    $len = min(count($search), count($replace));
                    $table = array_combine(array_slice($search, 0, $len), array_slice($replace, 0, $len));
                    $f = create_function('$match', '$table = '.var_export($table, true).'; return array_key_exists($match[0], $table) ? $table[$match[0]] : $match[0];');
                    $subject = preg_replace_callback($pattern, $f, $subject);
                    return $subject;
                }
            }
            $subject = preg_replace($pattern, (string)$replace, $subject);
            return $subject;
        }
    }
    
    推荐文章