Caractère Unicode dans la chaîne PHP

164

Cette question a l'air d'une simplicité embarrassante, mais je n'ai pas pu trouver de réponse.

Quel est l'équivalent PHP de la ligne de code C # suivante?

string str = "\u1000";

Cet exemple crée une chaîne avec un seul caractère Unicode dont la «valeur numérique Unicode» est 1 000 en hexadécimal (4 096 en décimal).

Autrement dit, en PHP, comment puis-je créer une chaîne avec un seul caractère Unicode dont la "valeur numérique Unicode" est connue?

Telaclavo
la source
4
@diEcho: c'est uniquement pour faire correspondre les caractères Unicode, mais l'OP veut créer pour ces caractères.
Stefan Gehrig

Réponses:

178

Étant donné que JSON prend directement en charge la \uxxxxsyntaxe, la première chose qui me vient à l'esprit est:

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

Une autre option serait d'utiliser mb_convert_encoding()

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

ou utilisez le mappage direct entre UTF-16BE (big endian) et le codet Unicode:

echo mb_convert_encoding("\x10\x00", 'UTF-8', 'UTF-16BE');
Stefan Gehrig
la source
9
JSON n'est pas JavaScript.
Gumbo
4
@Gumbo: Je le sais mais cela ne fait aucune différence ici. Javascript ainsi que JSON prennent en charge la \uxxxxsyntaxe Unicode afin que vous puissiez l'utiliser json_decodepour travailler sur une représentation de chaîne JSON créée artificiellement. J'ai cependant changé le libellé pour clarifier cela.
Stefan Gehrig
3
Ok, donc la formulation stricte d'une réponse à ma question est: $ str = json_decode ('"\ u1000"'); Je vous remercie.
Telaclavo
J'ai essayé echo json_decode('\u201B');ce qui fait référence à une seule citation inversée.Cependant, cela ne fonctionne pas, ce qui signifie aucune sortie (même si elle est canalisée hd)
hek2mgl
4
Vous avez besoin echo json_decode('"\u201B"');. Les guillemets doubles autour du symbole Unicode sont obligatoires.
Stefan Gehrig
162

PHP 7.0.0 a introduit la syntaxe "Unicode codepoint escape" .

Il est désormais possible d'écrire facilement des caractères Unicode en utilisant une chaîne entre guillemets ou une chaîne heredoc , sans appeler aucune fonction.

$unicodeChar = "\u{1000}";
Trou noir
la source
Cela peut être utilisé comme ceci: wordwrap($longLongText, 20, "\u{200B}", true);( espace de largeur zéro )
sanmai
5
Je crois que le PO voulait cette réponse, pas la réponse acceptée. En tout cas, quand j'ai cherché "Unicode en PHP", c'était parce que je voulais cette réponse, pas la réponse acceptée. Peut-être que "\ u {abcd}" n'existait pas lorsque cette question a été posée pour la première fois. Si tel est le cas, la réponse acceptée doit maintenant être déplacée.
Adam Chalcraft
23

Je me demande pourquoi personne n'a encore mentionné cela, mais vous pouvez faire une version presque équivalente en utilisant des séquences d'échappement entre guillemets doubles :

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

La séquence de caractères correspondant à l'expression régulière est un caractère en notation hexadécimale.

Exemple ASCII:

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

Bonjour le monde!

Donc, pour votre cas, tout ce que vous avez à faire est $str = "\x30\xA2";. Mais ce sont des octets , pas des caractères. La représentation en octets du point de code Unicode coïncide avec le big endian UTF-16, nous pouvons donc l'imprimer directement en tant que tel:

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

Si vous utilisez un encodage différent, vous devrez modifier les octets en conséquence (principalement avec une bibliothèque, bien que possible à la main aussi).

Exemple de petit boutiste UTF-16:

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

Exemple UTF-8:

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

Il y a aussi la packfonction, mais vous pouvez vous attendre à ce qu'elle soit lente.

Pacerier
la source
Parfait lorsque copier / coller un caractère puce (\ xE2 \ x80 \ xA2) peut entraîner une erreur de codage UTF-8 dans le document source. Je vous remercie.
jimp
21

PHP ne connaît pas ces séquences d'échappement Unicode. Mais comme les séquences d'échappement inconnues ne sont pas affectées, vous pouvez écrire votre propre fonction qui convertit ces séquences d'échappement 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);
}

Ou avec une expression de fonction anonyme au lieu 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);
}

Son utilisation:

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

Cela fonctionne aussi. Cependant, la solution json_decode () est beaucoup plus rapide (environ 50 fois).

flori
la source
Méthode simple, élégante, directe et totalement sécurisée. +10
andreszs
7

Essayez Portable UTF-8 :

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

Tous fonctionnent exactement de la même manière. Vous pouvez obtenir le point de code d'un caractère avec utf8_ord(). En savoir plus sur Portable UTF-8 .

Hamid Sarfraz
la source
3

Comme mentionné par d'autres, PHP 7 introduit \udirectement le support de la syntaxe Unicode.

Comme d'autres l'ont également mentionné, la seule façon d'obtenir une valeur de chaîne à partir de toute description de caractère Unicode sensée en PHP, est de la convertir à partir de quelque chose d'autre (par exemple l'analyse JSON, l'analyse HTML ou une autre forme). Mais cela a un coût d'exécution.

Cependant, il existe une autre option. Vous pouvez encoder le caractère directement en PHP avec \xéchappement binaire. La \xsyntaxe d'échappement est également prise en charge dans PHP 5 .

Ceci est particulièrement utile si vous préférez ne pas saisir le caractère directement dans une chaîne sous sa forme naturelle. Par exemple, s'il s'agit d'un caractère de contrôle invisible ou d'un autre espace difficile à détecter.

Tout d'abord, un exemple de preuve:

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

Notez que, comme mentionné par Pacerier dans une autre réponse, ce code binaire est unique à un codage de caractères spécifique. Dans l'exemple ci-dessus,\xE2\x80\x8A est le codage binaire pour U + 200A en UTF-8.

La question suivante est de savoir comment passer de U+200Aà\xE2\x80\x8A ?

Vous trouverez ci-dessous un script PHP pour générer la séquence d'échappement pour n'importe quel caractère, basée sur une chaîne JSON, une entité HTML ou toute autre méthode une fois que vous l'avez en tant que chaîne native.

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
la source
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
la source