PHP字符串中的Unicode字符


163

这个问题看起来很尴尬,但我一直找不到答案。

与下面的C#代码行等效的PHP是什么?

string str = "\u1000";

此示例创建一个带有单个Unicode字符的字符串,该字符串的“ Unicode数值”为十六进制的1000(十进制的4096)。

也就是说,在PHP中,如何创建一个具有“ Unicode数值”已知的Unicode字符的字符串?



4
@diEcho:仅用于匹配Unicode字符,但是OP希望针对这些字符进行创建。
Stefan Gehrig,


Answers:


178

因为JSON直接支持\uxxxx语法,所以我想到的第一件事是:

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

另一种选择是使用 mb_convert_encoding()

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

或利用UTF-16BE(大端)与Unicode代码点之间的直接映射:

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

9
JSON不是JavaScript。
浓汤

4
@Gumbo:我知道,但这在这里没有任何区别。Javascript和JSON支持\uxxxxUnicode语法,因此您可以使用它json_decode来人工创建的JSON字符串表示形式。我更改了措辞,但已将其澄清。
Stefan Gehrig

3
好的,所以对我的问题的一个答案的严格表达是:$ str = json_decode('“ \ u1000”'); 谢谢。
Telaclavo 2011年

我尝试过echo json_decode('\u201B');which指的是一个单引号,但是它不起作用,意味着没有输出(即使通过管道传递到hd
hek2mgl 2014年

4
你需要echo json_decode('"\u201B"');。unicode符号周围的双引号是必需的。
Stefan Gehrig 2014年

161

PHP 7.0.0引入了“ Unicode代码点转义”语法

现在,可以通过使用双引号Heredoc字符串轻松编写Unicode字符,而无需调用任何函数。

$unicodeChar = "\u{1000}";

这可用于像这样:wordwrap($longLongText, 20, "\u{200B}", true);零宽度的空间,它是)
sanmai

5
我相信OP需要这个答案,而不是被接受的答案。无论如何,当我搜索“ PHP中的Unicode”时,是因为我想要这个答案,而不是被接受的答案。首次提出此问题时,也许“ \ u {abcd}”不存在。如果是这样,现在应该移动接受的答案。
亚当·查尔克拉夫特

23

我想知道为什么还没有人提到这一点,但是您可以在双引号字符串中使用转义序列来做一个几乎等效的版本:

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

与正则表达式匹配的字符序列是十六进制字符。

ASCII示例:

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

你好,世界!

因此,对于您而言,您所需要做的就是$str = "\x30\xA2";。但是这些是字节,而不是字符。Unicode代码点的字节表示与UTF-16 big endian一致,因此我们可以这样直接打印出来:

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

如果您使用其他编码,则需要相应地更改字节(大多数情况下是通过库完成的,尽管也可以手动进行)。

UTF-16小尾数示例:

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

UTF-8示例:

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

也有该pack功能,但是您可以预期它会很慢。


当复制/粘贴项目符号字符(\ xE2 \ x80 \ xA2)可能导致源文档中的UTF-8编码错误时,此方法非常理想。谢谢。
jimp

21

PHP不知道这些Unicode转义序列。但是由于未知的转义序列不受影响,因此您可以编写自己的函数来转换此类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);
}

或使用匿名函数表达式代替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);
}

它的用法:

$str = unicodeString("\u1000");

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

这也可以。但是,json_decode()解决方案要快得多(大约50倍)。


简单,优雅,直接且完全安全的方法。+10
andreszs


3

正如其他人提到的,PHP 7 \u直接引入了对Unicode语法的支持。

正如其他人提到的那样,从PHP中任何明智的Unicode字符描述中获取字符串值的唯一方法是通过将其转换为其他内容(例如JSON解析,HTML解析或其他形式)。但这是以运行时性能成本为代价的。

但是,还有另一种选择。您可以使用\x二进制转义直接在PHP中对字符进行编码。该\x转义语法也支持PHP 5

如果您不想通过字符的自然形式直接在字符串中输入字符,这将特别有用。例如,如果它是一个不可见的控制字符,或其他难以检测到的空格。

首先,举一个例子:

// 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在另一个答案中提到的那样,此二进制代码对于特定的字符编码是唯一的。在上面的示例中,\xE2\x80\x8A是UTF-8中U + 200A的二进制编码。

接下来的问题是,你如何从中获取U+200A\xE2\x80\x8A

下面是一个PHP脚本,一旦您将其作为本机字符串,便可以根据JSON字符串,HTML实体或任何其他方法为任何字符生成转义序列。

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

回声unicode_to_textstring($ str);

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.