Как я могу получить правильную позицию слова в тексте UTF-8?

У меня есть простой код PHP, чтобы получить предложения текста и жирным шрифтом конкретного слова.

Прежде всего я получаю массив со словами, которые я хочу, и их положение в тексте.

$all_words = str_word_count($text, 2, 'åæéø');

// $words is an array with the words that I want find.
$words_found = array();
foreach ($all_words as $pos => $word_found) {
  foreach ($words as $word) {
    if ($word == strtolower($word_found)) {
      $words_found[$pos] = $word_found;
      break;
    }
  }
}

Тогда для каждого слова в $words_found Я получаю часть текста со словом в середине.

$length = 90;
foreach ($words_found as $offset => $word) {
  $word_length = strlen($word);

  $start = $offset - $length;
  $last_start = $start + $length + $word_length;

  $first_part = substr($text, $start, $length);
  $last_part = substr($text, $last_start, $length);

  $sentence = $first_part . '<b>' . $word . '</b>' . $last_part;
}

Он отлично работает, за исключением того, что текст UTF-8 текст с датскими символами (текст). Так когда $first_part или же $last_part начинается с символа Юникода, строка susbtr пуста.

я знаю mb_substr функция, поэтому я заменяю свой код с ним.

$word_length = mb_strlen($word, 'UTF-8');
$first_part = mb_substr($text, $start, $length, 'UTF-8');
$last_part = mb_substr($text, $last_start, $length, 'UTF-8');

Но с этой функцией (mb_substr) положение слова ($offsetнеправильно, новые подстроки ($sentence) не соответствует, как должно быть.

Существует ли что-то вроде mb_str_word_count? Как я могу получить правильное положение слов?

2 ответа

Решение

Я пробую решение @Mario Johnathan, но оно не сработало для меня.

Наконец, я получаю решение самостоятельно: я использую не многобайтовые функции, такие как substr и положение, данное str_word_countи решение заключается в изменении первой подстроки, если первый символ является датским.

$first_part_aux = str_split(trim($first_part));

if (!ctype_alpha($first_part_aux[0])) {
  for ($i = 1; $i < count($first_part_aux); $i++) {
    if (ctype_alpha($first_part_aux[$i])) {
      $start = $start + $i;
      $length = $length - $i;

      $first_part = substr($text, $start, $length);

      break;
    }
  }
}

Попробуйте использовать регулярные выражения с границами слов

$string = 'That this notpink a or pink blue red dark.';
$regex = '/\bpink\b/';
preg_match($regex, $string, $match, PREG_OFFSET_CAPTURE);
$pos = $match[0][1];
echo $pos;

Редактировать:

Если вам не нравится регулярное выражение, вы можете сопоставить слово с полосами, используя пробел

if(stripos($string, 'pink ') === 0)
    $pos = 0;
else if(stripos($string, ' pink') !== false)
    $pos = stripos($string, ' pink') + 1;
else
    $pos = stripos($string, ' pink ') + 1;
Другие вопросы по тегам