PHP dizesinde Unicode karakter


164

Bu soru utanç verici derecede basit görünüyor, ancak bir cevap bulamadım.

Aşağıdaki C # kod satırına eşdeğer PHP nedir?

string str = "\u1000";

Bu örnek, "Unicode sayısal değeri" onaltılı olarak 1000 (ondalık olarak 4096) olan tek bir Unicode karakteri olan bir dize oluşturur.

Yani, PHP'de, "Unicode sayısal değeri" bilinen tek bir Unicode karakteri olan bir dize nasıl oluşturabilirim?



4
@diEcho: Bu yalnızca Unicode karakterleri eşleştirmek içindir, ancak OP bu karakterlere oluşturmak istiyor.
Stefan Gehrig


Yanıtlar:


178

JSON doğrudan \uxxxxsözdizimini desteklediğinden aklıma ilk gelen şey:

$unicodeChar = '\u1000';
echo json_decode('"'.$unicodeChar.'"');

Başka bir seçenek kullanmak mb_convert_encoding()

echo mb_convert_encoding('က', 'UTF-8', 'HTML-ENTITIES');

veya UTF-16BE (big endian) ile Unicode kod noktası arasındaki doğrudan eşlemeyi kullanın:

echo mb_convert_encoding("\x10\x00", 'UTF-8', 'UTF-16BE');

9
JSON JavaScript değildir.
Gumbo

4
@ Gumbo: Bunu biliyorum ama burada bir fark yaratmıyor. Javascript ve JSON, yapay olarak oluşturulmuş bir JSON dizesi temsili üzerinde çalışmak için \uxxxxkullanabileceğiniz Unicode sözdizimini destekler json_decode. Bunu açıklığa kavuşturmak için ifadeleri değiştirdim.
Stefan Gehrig

3
Tamam, sorumun bir cevabının katı formülasyonu: $ str = json_decode ('"\ u1000"'); Teşekkür ederim.
Telaclavo

Ben denedim echo json_decode('\u201B');Hangi tek bir tek tırnak alıntı Ancak çalışmıyor, yani hiçbir çıkış anlamına gelir ( hd
piped

4
Gerek echo json_decode('"\u201B"');. Unicode sembolü etrafındaki çift tırnak işaretleri zorunludur.
Stefan Gehrig

162

PHP 7.0.0 "Unicode kod noktası kaçış" sözdizimini tanıttı .

Artık herhangi bir işlevi çağırmadan çift ​​tırnaklı veya bir yorumlu dize kullanarak Unicode karakterleri kolayca yazmak mümkündür .

$unicodeChar = "\u{1000}";

Bu şu şekilde kullanılabilir: wordwrap($longLongText, 20, "\u{200B}", true);( sıfır genişlikli alan )
sanmai

5
OP'nin bu cevabı istediğine inanıyorum, kabul edilen cevabı değil. Her halükarda, "PHP Unicode" aradığımda, bunun nedeni kabul edilen cevabı değil, bu cevabı istediğimden kaynaklanıyordu. Belki bu soru ilk sorulduğunda "\ u {abcd}" yoktu. Öyleyse, kabul edilen cevap şimdi taşınmalıdır.
Adam Chalcraft

23

Acaba neden kimse bundan bahsetmedi, ancak çift ​​tırnaklı dizelerde kaçış dizileri kullanarak neredeyse eşdeğer bir sürüm yapabilirsiniz :

\x[0-9A-Fa-f]{1,2}

Normal ifadeyle eşleşen karakter sırası, onaltılık gösterimdeki bir karakterdir.

ASCII örneği:

<?php
    echo("\x48\x65\x6C\x6C\x6F\x20\x57\x6F\x72\x6C\x64\x21");
?>

Selam Dünya!

Yani davanız için tek yapmanız gereken $str = "\x30\xA2";. Ama bunlar bayt , karakter değil. Unicode kod noktasının bayt temsili UTF-16 büyük endian ile çakışır, böylece doğrudan bu şekilde yazdırabiliriz:

<?php
    header('content-type:text/html;charset=utf-16be');
    echo("\x30\xA2");
?>

Farklı bir kodlama kullanıyorsanız, baytları buna göre değiştirmeniz gerekir (mümkünse elle de olsa bir kütüphane ile yapılır).

UTF-16 küçük endian örneği:

<?php
    header('content-type:text/html;charset=utf-16le');
    echo("\xA2\x30");
?>

UTF-8 örneği:

<?php
    header('content-type:text/html;charset=utf-8');
    echo("\xE3\x82\xA2");
?>

Ayrıca packişlevi var, ancak yavaş olmasını bekleyebilirsiniz.


Bir madde işareti karakterini (\ xE2 \ x80 \ xA2) kopyalarken / yapıştırırken kaynak belgede UTF-8 kodlama hatasına neden olabilir. Teşekkür ederim.
jimp

21

PHP bu Unicode kaçış dizilerini bilmiyor. Ancak bilinmeyen kaçış dizileri etkilenmediğinden, bu tür Unicode kaçış dizilerini dönüştüren kendi işlevinizi yazabilirsiniz:

function unicodeString($str, $encoding=null) {
    if (is_null($encoding)) $encoding = ini_get('mbstring.internal_encoding');
    return preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/u', create_function('$match', 'return mb_convert_encoding(pack("H*", $match[1]), '.var_export($encoding, true).', "UTF-16BE");'), $str);
}

Veya yerine anonim işlev ifadesiylecreate_function :

function unicodeString($str, $encoding=null) {
    if (is_null($encoding)) $encoding = ini_get('mbstring.internal_encoding');
    return preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/u', function($match) use ($encoding) {
        return mb_convert_encoding(pack('H*', $match[1]), $encoding, 'UTF-16BE');
    }, $str);
}

Kullanımı:

$str = unicodeString("\u1000");

10
html_entity_decode('&#x30a8;', 0, 'UTF-8');

Bu da işe yarıyor. Ancak json_decode () çözümü çok daha hızlıdır (yaklaşık 50 kez).


Basit, zarif, anlaşılır ve tamamen güvenli bir yöntem. +10
andreszs


3

Başkaları tarafından belirtildiği gibi, PHP 7, \u doğrudan Unicode sözdizimi .

Başkaları tarafından da belirtildiği gibi, PHP'deki herhangi bir makul Unicode karakter açıklamasından bir dize değeri elde etmenin tek yolu, bunu başka bir şeyden (örn. JSON ayrıştırma, HTML ayrıştırma veya başka bir form) dönüştürmektir. Ancak bu, çalışma zamanı performans maliyetiyle gelir.

Ancak, başka bir seçenek daha var. \xİkili kaçış ile karakteri doğrudan PHP'de kodlayabilirsiniz . \xKaçış sözdizimi de olan PHP desteklenen 5 .

Bu, karakteri doğal biçimiyle doğrudan bir dizeye girmemeyi tercih ediyorsanız özellikle yararlıdır. Örneğin, görünmez bir kontrol karakteri veya boşlukları tespit etmek zorsa.

İlk olarak, bir kanıt örneği:

// Unicode Character 'HAIR SPACE' (U+200A)
$htmlEntityChar = "&#8202;";
$realChar = html_entity_decode($htmlEntityChar);
$phpChar = "\xE2\x80\x8A";
echo 'Proof: ';
var_dump($realChar === $phpChar); // bool(true)

Pacerier tarafından başka bir cevapta belirtildiği gibi, bu ikili kodun belirli bir karakter kodlamasına özgü olduğunu unutmayın. Yukarıdaki örnekte, \xE2\x80\x8AUTF-8'de U + 200A için ikili kodlama verilmiştir.

Bir sonraki soru, nasıl alırım edilir U+200Aiçin \xE2\x80\x8A?

Aşağıda, yerel bir dize olarak bir kez varsa, bir JSON dizesi, HTML varlığı veya başka bir yöntemi temel alan herhangi bir karakter için kaçış dizisi oluşturmak için bir PHP komut dosyası bulunmaktadır.

function str_encode_utf8binary($str) {
    /** @author Krinkle 2018 */
    $output = '';
    foreach (str_split($str) as $octet) {
        $ordInt = ord($octet);
        // Convert from int (base 10) to hex (base 16), for PHP \x syntax
        $ordHex = base_convert($ordInt, 10, 16);
        $output .= '\x' . $ordHex;
    }
    return $output;
}

function str_convert_html_to_utf8binary($str) {
    return str_encode_utf8binary(html_entity_decode($str));
}
function str_convert_json_to_utf8binary($str) {
    return str_encode_utf8binary(json_decode($str));
}

// Example for raw string: Unicode Character 'INFINITY' (U+221E)
echo str_encode_utf8binary('∞') . "\n";
// \xe2\x88\x9e

// Example for HTML: Unicode Character 'HAIR SPACE' (U+200A)
echo str_convert_html_to_utf8binary('&#8202;') . "\n";
// \xe2\x80\x8a

// Example for JSON: Unicode Character 'HAIR SPACE' (U+200A)
echo str_convert_json_to_utf8binary('"\u200a"') . "\n";
// \xe2\x80\x8a

0
function unicode_to_textstring($str){

    $rawstr = pack('H*', $str);

    $newstr =  iconv('UTF-16BE', 'UTF-8', $rawstr);
    return $newstr;
}

msg = '67714eac99c500200054006f006b0079006f002000530074006100740069006f006e003a0020';

echo unicode_to_textstring ($ str);

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.