Преобразовать строку в массив символов - многобайтовый

Предполагая, что в 2019 году каждое решение, которое не является UNICODE-безопасным, является неправильным. Каков наилучший способ преобразования строки в массив символов UNICODE в PHP?

Очевидно, это означает, что доступ к байтам с синтаксисом скобок является неправильным, а также использование str_split:

$arr = str_split($text);

Из примера ввода, как:

$string = '先éé€‍ ‍❤️‍';

Я жду:

array(16) {


[0]=>
  string(3) "先"
  [1]=>
  string(2) "é"
  [2]=>
  string(1) "e"
  [3]=>
  string(2) "́"
  [4]=>
  string(3) "€"
  [5]=>
  string(4) ""
  [6]=>
  string(4) ""
  [7]=>
  string(4) ""
  [8]=>
  string(3) "‍"
  [9]=>
  string(1) " "
  [10]=>
  string(4) ""
  [11]=>
  string(3) "‍"
  [12]=>
  string(3) "❤"
  [13]=>
  string(3) "️"
  [14]=>
  string(3) "‍"
  [15]=>
  string(4) ""
}

2 ответа

Решение

Просто передайте пустой шаблон с PREG_SPLIT_NO_EMPTY флаг. В противном случае вы можете написать шаблон с \X (точка Unicode) и \K (перезапустите матч с полной строкой). Я включу mb_split() вызов и preg_match_all() призыв к полноте.

Код: ( Демо)

$string='先秦兩漢';
var_export(preg_split('~~u', $string, 0, PREG_SPLIT_NO_EMPTY));
echo "\n---\n";
var_export(preg_split('~\X\K~u', $string, 0, PREG_SPLIT_NO_EMPTY));
echo "\n---\n";
var_export(preg_split('~\X\K(?!$)~u', $string));
echo "\n---\n";
var_export(mb_split('\X\K(?!$)', $string));
echo "\n---\n";
var_export(preg_match_all('~\X~u', $string, $out) ? $out[0] : []);

Вся продукция::

array (
  0 => '先',
  1 => '秦',
  2 => '兩',
  3 => '漢',
)

С https://www.regular-expressions.info/unicode.html:

Как подобрать одну графему Unicode

Совпадение одной графемы, независимо от того, кодируется ли она как одна кодовая точка или как несколько кодовых точек с использованием комбинированных меток, легко в Perl, PCRE, PHP, Boost, Ruby 2.0, Java 9 и приложениях Just Great Software: просто используйте \ ИКС.

Вы можете считать \X версией Unicode точки. Однако есть одно отличие: \X всегда соответствует символам разрыва строки, тогда как точка не соответствует символам разрыва строки, если вы не включите точку, соответствующую режиму соответствия новой строки.


ОБНОВЛЕНИЕ, DHarman обратил мое внимание, что mb_str_split() теперь доступен с PHP7.4.

Параметр длины по умолчанию для новой функции равен 1, поэтому в этом случае параметр длины может быть опущен.

https://wiki.php.net/rfc/mb_str_split

Демо Дхармана: https://3v4l.org/M85Fi/rfc

Это работает для меня, он разбивает строку Unicode в массив символов:

//
// split at all position not after the start: ^
// and not before the end: $, with unicode modifier
// u (PCRE_UTF8).
//
$arr = preg_split("/(?<!^)(?!$)/u", $text);

Например:

<?php
//
$text = "堆栈溢出";

$arr = preg_split("/(?<!^)(?!$)/u", $text);

echo '<html lang="fr">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
</head>
<body>
';

print_r($arr);

echo '</body>
</html>
';
?>

В браузере это выдает это:

Array ( [0] => 堆 [1] => 栈 [2] => 溢 [3] => 出 )
Другие вопросы по тегам