"\ U00ed" gibi Unicode kaçış dizilerinin kodunu uygun UTF-8 kodlu karakterlere nasıl çözebilirim?


100

PHP'de " \u00ed" - " í" gibi Unicode kaçış dizilerinin ve diğer tüm benzer oluşumların kodunu çözebilen bir işlev var mı ?

Burada benzer bir soru buldum ama işe yaramadı.

Yanıtlar:


175

Bunu dene:

$str = preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/', function ($match) {
    return mb_convert_encoding(pack('H*', $match[1]), 'UTF-8', 'UCS-2BE');
}, $str);

UTF-16 tabanlı C / C ++ / Java / Json tarzı olması durumunda:

$str = preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/', function ($match) {
    return mb_convert_encoding(pack('H*', $match[1]), 'UTF-8', 'UTF-16BE');
}, $str);

1
"\ U00ed" yi nereye koymalıyım?
Docstero

2
@Docstero: Normal ifade, \udört onaltılık basamaktan oluşan herhangi bir diziyle eşleşir .
Gumbo

9
Bu işlev, UCS-2'de temsil edilemeyecekleri için ek karakterlerle uğraşamaz.
Artefacto

3
@gumbo Bu işlevi nasıl çağırır veya kullanırsınız?
Demodave

3
Çıktımda bulduğum gibi burada yolumu buldum, ancak çıktıya json_encode () ile bakıyordum ve yeterince komik bir şekilde varsayılan json_encode () çıktıyı çöpe atacak, bu nedenle json_encode ($ theDict, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) kullanın;
Tom Andersen

72
print_r(json_decode('{"t":"\u00ed"}')); // -> stdClass Object ( [t] => í )

46
Nesne json_decode('"' . $text . '"')
sarıcısına

3
Teşekkürler. Bu , kabul edilen cevaptan ziyade STANDART YOL gibi görünüyor .
T.Todua

İlginç bir şekilde, bu aynı zamanda gülen yüzler gibi karmaşık varlıklar için de işe yarıyor ... json_decode('{"t":"\uD83D\uDE0A"}')is 😊
DynamicDan

2
@deceze $text, çift tırnak içerebilen gerçeği eklemelisiniz . Yani bir revize edilmiş versiyonu olacaktır: json_decode('"'.str_replace('"', '\\"', $text).'"'). Yardımınız için teşekkürler :-)
Yvan


11
$str = '\u0063\u0061\u0074'.'\ud83d\ude38';
$str2 = '\u0063\u0061\u0074'.'\ud83d';

// U+1F638
var_dump(
    "cat\xF0\x9F\x98\xB8" === escape_sequence_decode($str),
    "cat\xEF\xBF\xBD" === escape_sequence_decode($str2)
);

function escape_sequence_decode($str) {

    // [U+D800 - U+DBFF][U+DC00 - U+DFFF]|[U+0000 - U+FFFF]
    $regex = '/\\\u([dD][89abAB][\da-fA-F]{2})\\\u([dD][c-fC-F][\da-fA-F]{2})
              |\\\u([\da-fA-F]{4})/sx';

    return preg_replace_callback($regex, function($matches) {

        if (isset($matches[3])) {
            $cp = hexdec($matches[3]);
        } else {
            $lead = hexdec($matches[1]);
            $trail = hexdec($matches[2]);

            // http://unicode.org/faq/utf_bom.html#utf16-4
            $cp = ($lead << 10) + $trail + 0x10000 - (0xD800 << 10) - 0xDC00;
        }

        // https://tools.ietf.org/html/rfc3629#section-3
        // Characters between U+D800 and U+DFFF are not allowed in UTF-8
        if ($cp > 0xD7FF && 0xE000 > $cp) {
            $cp = 0xFFFD;
        }

        // https://github.com/php/php-src/blob/php-5.6.4/ext/standard/html.c#L471
        // php_utf32_utf8(unsigned char *buf, unsigned k)

        if ($cp < 0x80) {
            return chr($cp);
        } else if ($cp < 0xA0) {
            return chr(0xC0 | $cp >> 6).chr(0x80 | $cp & 0x3F);
        }

        return html_entity_decode('&#'.$cp.';');
    }, $str);
}

Teşekkür ederim. Bu ek karakterle çalışıyor gibi görünüyor, örneğin😍
c00000fd

3

Bu, ham UNICODE'u HTML ile değiştirmeye yönelik bir balyoz yaklaşımıdır. Bu çözümü koyacak başka bir yer görmedim, ancak başkalarının da bu sorunu yaşadığını varsayıyorum.

Başka bir şey yapmadan önce bu str_replace işlevini RAW JSON'a uygulayın .

function unicode2html($str){
    $i=65535;
    while($i>0){
        $hex=dechex($i);
        $str=str_replace("\u$hex","&#$i;",$str);
        $i--;
     }
     return $str;
}

Bu düşündüğünüz kadar uzun sürmeyecek ve bu HERHANGİ bir unicode'u HTML ile değiştirecektir.

JSON'da döndürülen unicode türlerini biliyorsanız, elbette bu azaltılabilir.

Örneğin, kodum çok sayıda ok ve dingbat unicode alıyordu. Bunlar 8448 ile 11263 arasında. Yani üretim kodum şöyle görünüyor:

$i=11263;
while($i>08448){
    ...etc...

Buraya yazarak Unicode bloklarına bakabilirsiniz: http://unicode-table.com/en/ Arapça veya Telegu ya da her neyse tercüme ettiğinizi biliyorsanız, bu kodları değiştirebilirsiniz, 65.000'in tamamını değil.

Aynı balyozu basit kodlamaya da uygulayabilirsiniz:

 $str=str_replace("\u$hex",chr($i),$str);

1

Bir çözüm de var:
http://www.welefen.com/php-unicode-to-utf8.html

function entity2utf8onechar($unicode_c){
    $unicode_c_val = intval($unicode_c);
    $f=0x80; // 10000000
    $str = "";
    // U-00000000 - U-0000007F:   0xxxxxxx
    if($unicode_c_val <= 0x7F){         $str = chr($unicode_c_val);     }     //U-00000080 - U-000007FF:  110xxxxx 10xxxxxx
    else if($unicode_c_val >= 0x80 && $unicode_c_val <= 0x7FF){         $h=0xC0; // 11000000
        $c1 = $unicode_c_val >> 6 | $h;
        $c2 = ($unicode_c_val & 0x3F) | $f;
        $str = chr($c1).chr($c2);
    } else if($unicode_c_val >= 0x800 && $unicode_c_val <= 0xFFFF){         $h=0xE0; // 11100000
        $c1 = $unicode_c_val >> 12 | $h;
        $c2 = (($unicode_c_val & 0xFC0) >> 6) | $f;
        $c3 = ($unicode_c_val & 0x3F) | $f;
        $str=chr($c1).chr($c2).chr($c3);
    }
    //U-00010000 - U-001FFFFF:  11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
    else if($unicode_c_val >= 0x10000 && $unicode_c_val <= 0x1FFFFF){         $h=0xF0; // 11110000
        $c1 = $unicode_c_val >> 18 | $h;
        $c2 = (($unicode_c_val & 0x3F000) >>12) | $f;
        $c3 = (($unicode_c_val & 0xFC0) >>6) | $f;
        $c4 = ($unicode_c_val & 0x3F) | $f;
        $str = chr($c1).chr($c2).chr($c3).chr($c4);
    }
    //U-00200000 - U-03FFFFFF:  111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
    else if($unicode_c_val >= 0x200000 && $unicode_c_val <= 0x3FFFFFF){         $h=0xF8; // 11111000
        $c1 = $unicode_c_val >> 24 | $h;
        $c2 = (($unicode_c_val & 0xFC0000)>>18) | $f;
        $c3 = (($unicode_c_val & 0x3F000) >>12) | $f;
        $c4 = (($unicode_c_val & 0xFC0) >>6) | $f;
        $c5 = ($unicode_c_val & 0x3F) | $f;
        $str = chr($c1).chr($c2).chr($c3).chr($c4).chr($c5);
    }
    //U-04000000 - U-7FFFFFFF:  1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
    else if($unicode_c_val >= 0x4000000 && $unicode_c_val <= 0x7FFFFFFF){         $h=0xFC; // 11111100
        $c1 = $unicode_c_val >> 30 | $h;
        $c2 = (($unicode_c_val & 0x3F000000)>>24) | $f;
        $c3 = (($unicode_c_val & 0xFC0000)>>18) | $f;
        $c4 = (($unicode_c_val & 0x3F000) >>12) | $f;
        $c5 = (($unicode_c_val & 0xFC0) >>6) | $f;
        $c6 = ($unicode_c_val & 0x3F) | $f;
        $str = chr($c1).chr($c2).chr($c3).chr($c4).chr($c5).chr($c6);
    }
    return $str;
}
function entities2utf8($unicode_c){
    $unicode_c = preg_replace("/\&\#([\da-f]{5})\;/es", "entity2utf8onechar('\\1')", $unicode_c);
    return $unicode_c;
}

1

json değerlerini düzeltin, u {xxx} 'den önce tüm + "" öğelerine eklenir

  $item = preg_replace_callback('/"(.+?)":"(u.+?)",/', function ($matches) {
        $matches[2] = preg_replace('/(u)/', '\u', $matches[2]);
            $matches[2] = preg_replace('/(")/', '&quot;', $matches[2]); 
            $matches[2] = json_decode('"' . $matches[2] . '"'); 
            return '"' . $matches[1] . '":"' . $matches[2] . '",';
        }, $item);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.