Carácter Unicode en cadena PHP

164

Esta pregunta parece vergonzosamente simple, pero no he podido encontrar una respuesta.

¿Cuál es el equivalente de PHP a la siguiente línea de código C #?

string str = "\u1000";

Esta muestra crea una cadena con un solo carácter Unicode cuyo "valor numérico Unicode" es 1000 en hexadecimal (4096 en decimal).

Es decir, en PHP, ¿cómo puedo crear una cadena con un solo carácter Unicode cuyo "valor numérico Unicode" sea conocido?

Telaclavo
fuente
44
@diEcho: eso es solo para hacer coincidir los caracteres Unicode, pero el OP quiere crear a esos caracteres.
Stefan Gehrig

Respuestas:

178

Como JSON admite directamente la \uxxxxsintaxis, lo primero que se me ocurre es:

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

Otra opción sería usar mb_convert_encoding()

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

o utilice la asignación directa entre UTF-16BE (big endian) y el punto de código Unicode:

echo mb_convert_encoding("\x10\x00", 'UTF-8', 'UTF-16BE');
Stefan Gehrig
fuente
9
JSON no es JavaScript.
Gumbo
44
@Gumbo: Lo sé, pero no hace ninguna diferencia aquí. Javascript y JSON son compatibles con la \uxxxxsintaxis Unicode, por lo que puede utilizarla json_decodepara trabajar en una representación de cadena JSON creada artísticamente. Sin embargo, cambié la redacción para aclarar eso.
Stefan Gehrig
3
Ok, entonces la formulación estricta de una respuesta a mi pregunta es: $ str = json_decode ('"\ u1000"'); Gracias.
Telaclavo
Intenté echo json_decode('\u201B');Lo que se refiere a una sola cita revertida Sin embargo, no funciona, lo que significa que no hay salida (incluso si se canaliza a hd)
hek2mgl
44
Es necesario echo json_decode('"\u201B"');. Las comillas dobles alrededor del símbolo Unicode son obligatorias.
Stefan Gehrig
162

PHP 7.0.0 ha introducido la sintaxis "escape de punto de código Unicode" .

Ahora es posible escribir caracteres Unicode fácilmente utilizando una cadena entre comillas dobles o heredoc , sin llamar a ninguna función.

$unicodeChar = "\u{1000}";
Agujero negro
fuente
Esto se puede usar así: wordwrap($longLongText, 20, "\u{200B}", true);( espacio de ancho cero es)
sanmai
55
Creo que el OP quería esta respuesta, no la respuesta aceptada. En cualquier caso, cuando busqué "Unicode en PHP", fue porque quería esta respuesta, no la respuesta aceptada. Quizás "\ u {abcd}" no existía cuando se hizo esta pregunta por primera vez. Si es así, la respuesta aceptada ahora debe ser movida.
Adam Chalcraft
23

Me pregunto por qué nadie ha mencionado esto todavía, pero puedes hacer una versión casi equivalente usando secuencias de escape en cadenas dobles :

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

La secuencia de caracteres que coincide con la expresión regular es un carácter en notación hexadecimal.

Ejemplo ASCII:

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

Hola Mundo!

Entonces, para su caso, todo lo que necesita hacer es $str = "\x30\xA2";. Pero estos son bytes , no caracteres. La representación de bytes del punto de código Unicode coincide con UTF-16 big endian, por lo que podríamos imprimirlo directamente como tal:

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

Si está usando una codificación diferente, necesitará alterar los bytes en consecuencia (principalmente hecho con una biblioteca, aunque también es posible a mano).

UTF-16 pequeño ejemplo endian:

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

UTF-8 ejemplo:

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

También existe la packfunción, pero puede esperar que sea lenta.

Pacerier
fuente
Perfecto para cuando copiar / pegar un carácter de viñeta (\ xE2 \ x80 \ xA2) podría provocar un error de codificación UTF-8 en el documento fuente. Gracias.
jimp
21

PHP no conoce estas secuencias de escape Unicode. Pero como las secuencias de escape desconocidas no se ven afectadas, puede escribir su propia función que convierta tales secuencias de 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 una expresión de función anónima en lugar de 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);
}

Su uso:

$str = unicodeString("\u1000");
Gumbo
fuente
10
html_entity_decode('&#x30a8;', 0, 'UTF-8');

Esto tambien funciona. Sin embargo, la solución json_decode () es mucho más rápida (alrededor de 50 veces).

flori
fuente
Método simple, elegante, directo y totalmente seguro. +10
andreszs
7

Prueba Portable UTF-8 :

$str = utf8_chr( 0x1000 );
$str = utf8_chr( '\u1000' );
$str = utf8_chr( 4096 );

Todos funcionan exactamente de la misma manera. Puede obtener el punto de código de un personaje con utf8_ord(). Lea más sobre Portable UTF-8 .

Hamid Sarfraz
fuente
3

Como lo mencionaron otros, PHP 7 introduce soporte para la \usintaxis Unicode directamente.

Como también mencionaron otros, la única forma de obtener un valor de cadena a partir de cualquier descripción sensible de caracteres Unicode en PHP, es convirtiéndolo de otra cosa (por ejemplo, análisis JSON, análisis HTML o alguna otra forma). Pero esto tiene un costo de rendimiento en tiempo de ejecución.

Sin embargo, hay otra opción. Puede codificar el carácter directamente en PHP con \xescape binario. La \xsintaxis de escape también es compatible con PHP 5 .

Esto es especialmente útil si prefiere no ingresar el carácter directamente en una cadena a través de su forma natural. Por ejemplo, si se trata de un carácter de control invisible u otro espacio en blanco difícil de detectar.

Primero, un ejemplo de prueba:

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

Tenga en cuenta que, como mencionó Pacerier en otra respuesta, este código binario es exclusivo de una codificación de caracteres específica. En el ejemplo anterior, \xE2\x80\x8Aes la codificación binaria para U + 200A en UTF-8.

La siguiente pregunta es, ¿cómo llegas de U+200Aa \xE2\x80\x8A?

A continuación se muestra un script PHP para generar la secuencia de escape para cualquier carácter, basado en una cadena JSON, una entidad HTML o cualquier otro método una vez que lo tiene como una cadena 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
Timo Tijhof
fuente
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);

chings228
fuente