Преобразовать строку в массив символов - многобайтовый - PullRequest
3 голосов
/ 21 апреля 2019

Предполагая, что в 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 ]

2 голосов
/ 21 апреля 2019

Просто передайте пустой шаблон с флагом 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.

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


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

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

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

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

1 голос
/ 21 апреля 2019

Это работает для меня, оно разбивает строку 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] => 出 )
...