Carattere Unicode nella stringa PHP


164

Questa domanda sembra imbarazzantemente semplice, ma non sono stato in grado di trovare una risposta.

Qual è il PHP equivalente alla seguente riga di codice C #?

string str = "\u1000";

In questo esempio viene creata una stringa con un singolo carattere Unicode il cui "valore numerico Unicode" è 1000 in esadecimale (4096 in decimale).

Cioè, in PHP, come posso creare una stringa con un singolo carattere Unicode il cui "valore numerico Unicode" è noto?



4
@diEcho: è solo per abbinare i caratteri Unicode, ma l'OP vuole creare questi caratteri.
Stefan Gehrig,


Risposte:


178

Poiché JSON supporta direttamente la \uxxxxsintassi, la prima cosa che mi viene in mente è:

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

Un'altra opzione sarebbe quella di utilizzare mb_convert_encoding()

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

oppure usa la mappatura diretta tra UTF-16BE (big endian) e il punto di codice Unicode:

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

9
JSON non è JavaScript.
Gumbo,

4
@Gumbo: lo so ma qui non fa alcuna differenza. Javascript e JSON supportano la \uxxxxsintassi Unicode in modo da poter utilizzare json_decodeper lavorare su una rappresentazione di stringhe JSON creata artificialmente. Ho modificato la formulazione per chiarirla.
Stefan Gehrig,

3
Ok, quindi la formulazione rigorosa di una risposta alla mia domanda è: $ str = json_decode ('"\ u1000"'); Grazie.
Telaclavo,

Ho provato echo json_decode('\u201B');Che si riferisce a una singola citazione ripristinata Tuttavia non funziona, il che significa che non c'è alcun output (anche se indirizzato a hd)
hek2mgl

4
Hai bisogno echo json_decode('"\u201B"');. Le virgolette doppie attorno al simbolo Unicode sono obbligatorie.
Stefan Gehrig,

162

PHP 7.0.0 ha introdotto la sintassi "Unicode codepoint escape" .

Ora è possibile scrivere facilmente caratteri Unicode usando una stringa tra virgolette doppie o una ereditaria , senza chiamare alcuna funzione.

$unicodeChar = "\u{1000}";

Questo può essere usato in questo modo: wordwrap($longLongText, 20, "\u{200B}", true);( spazio a larghezza zero è)
sanmai,

5
Credo che l'OP volesse questa risposta, non la risposta accettata. Ad ogni modo, quando ho cercato "Unicode in PHP", era perché volevo questa risposta, non la risposta accettata. Forse "\ u {abcd}" non esisteva alla prima domanda. In tal caso, la risposta accettata dovrebbe ora essere spostata.
Adam Chalcraft

23

Mi chiedo perché nessuno lo abbia ancora menzionato, ma puoi fare una versione quasi equivalente usando sequenze di escape in stringhe tra virgolette doppie :

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

La sequenza di caratteri corrispondente all'espressione regolare è un carattere in notazione esadecimale.

Esempio ASCII:

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

Ciao mondo!

Quindi, nel tuo caso, tutto ciò che devi fare è $str = "\x30\xA2";. Ma questi sono byte , non caratteri. La rappresentazione in byte del punto di codice Unicode coincide con il big endian UTF-16, quindi potremmo stamparlo direttamente come tale:

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

Se stai utilizzando una codifica diversa, dovrai modificare i byte di conseguenza (per lo più con una libreria, anche se possibile anche a mano).

Esempio di little endian UTF-16:

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

Esempio UTF-8:

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

C'è anche la packfunzione, ma puoi aspettarti che sia lento.


Perfetto per la copia / incolla di un carattere punto elenco (\ xE2 \ x80 \ xA2) potrebbe causare un errore di codifica UTF-8 nel documento di origine. Grazie.
jimp

21

PHP non conosce queste sequenze di escape Unicode. Ma poiché le sequenze di escape sconosciute rimangono inalterate, puoi scrivere la tua funzione che converte tali sequenze di escape Unicode:

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);
}

O con un'espressione di funzione anonima anziché create_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);
}

Il suo utilizzo:

$str = unicodeString("\u1000");

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

Anche questo funziona. Tuttavia, la soluzione json_decode () è molto più veloce (circa 50 volte).


Metodo semplice, elegante, diretto e totalmente sicuro. +10
andreszs,


3

Come menzionato da altri, PHP 7 introduce direttamente il supporto per la \usintassi Unicode.

Come menzionato anche da altri, l'unico modo per ottenere un valore di stringa da qualsiasi descrizione sensibile dei caratteri Unicode in PHP è convertirlo da qualcos'altro (ad esempio analisi JSON, analisi HTML o qualche altra forma). Ma questo ha un costo in termini di run-time.

Tuttavia, c'è un'altra opzione. Puoi codificare il personaggio direttamente in PHP con \xescape binario. La \xsintassi di escape è supportata anche in PHP 5 .

Ciò è particolarmente utile se si preferisce non inserire il carattere direttamente in una stringa attraverso la sua forma naturale. Ad esempio, se si tratta di un personaggio di controllo invisibile o di altri spazi difficili da rilevare.

Innanzitutto, un esempio di prova:

// 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)

Si noti che, come indicato da Pacerier in un'altra risposta, questo codice binario è unico per una codifica di caratteri specifici. Nell'esempio sopra, \xE2\x80\x8Aè la codifica binaria per U + 200A in UTF-8.

La prossima domanda è: come si arriva da U+200Aa \xE2\x80\x8A?

Di seguito è riportato uno script PHP per generare la sequenza di escape per qualsiasi carattere, basato su una stringa JSON, un'entità HTML o qualsiasi altro metodo dopo averlo utilizzato come stringa nativa.

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);

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.