С помощью уже упоминавшегося класса IntlBreakIterator можно легко выделить из текста хеш-теги. Для этого создадим итератор не по предложениям, а по словам с помощью: createWordInstance. Итерация с помощью IntlBreakIterator выдаёт смещения границ слов, что в данном случае не очень удобно. Поэтому воспользуемся методом IntlBreakIterator::getPartsIterator. Он создаёт ещё один итератор, который возвращает уже непосредственно сами слова. Далее, когда встретится символ # (он в режиме WordInstance считается отдельным словом), запоминаем этот факт и следующее слово обрабатываем как хеш-тег.
Вот пример кода:
function getHashTags($text) {
$breaker =IntlBreakIterator::createWordInstance('ru_RU');
$breaker->setText($text);
$iterator = $breaker->getPartsIterator();
$hashtags = array();
$mode = false;
// теперь в $item будут сами слова, а не их смещения
foreach ($iterator as $item) {
// выставляем $mode в TRUE, если следующее слово нужно обработать как хеш-тег
if ($item==='#') $mode=true;
elseif ($mode && trim($item) && mb_strlen($item)>1) { // ряд дополнительных проверок, чтобы в хеш-теги не попадал мусор
$hashtags[] = mb_strtolower($item);
// обработка закочена, поэтому сбрасываем $mode до тех пор, пока не попадётся новый символ #
$mode = false;
}
else $mode=false;
}
return $hashtags;
}
Проверка mb_strlen($item)>1 нужна для отработки случаев вида #! #;,так как в этом случае знаки препинания рассматриваются как отдельные слова. Кроме того, хештеги из одной буквы обычно не имеют смысла.

- Перово, Москва, Россия
- me@4xpro.ru
- XXXXPro
Новости сайта в Telegram
t.me/4x_proКомпьютерное
Выделение хештегов из текста

Автоматическое создание анонса текста на PHP

При создании скриптов для новостей или блогов часто требуется автоматически сформировать анонс из нескольких первых предложений полного текста, не превышающий определённой длины. Типичный подход для этих целей — это выделить с помощью mb_substr начальную часть текста нужной длины, а потом обрезать получившуюся часть до последней точки.
Но не все знают, что с версии 5.5 в PHP в модуле intl предусмотрен специальный класс IntlBreakIterator, который позволяет решать эту задачу более эффективно. У него есть несколько статических методов для создания итераторов, позволяющих выделять границы отдельных символов (createCharacterInstance), слов (createTitleInstance и createWordInstance, первый выделяет слова с включением пробелов и знаков препинания после них, второй — рассматривает пробелы и знаки препинания как отдельные слова) и целых предложений (createSentenceInstance). Для нашей задачи потребуется последний.
Далее всё просто: создаём экземпляр этого класса, передаём ему текст и получаем смещение конца ближайшего предложения с помощью методов preceding (ближайшая граница до нужной длины) и following (ближайшая граница после):
$test = 'Это тестовый текст. Текст длинный! И с многоточиями… Но нужно лишь только несколько начальных предложений. ';
// задаём длину анонса
$max_length = 80;
// создаём экземпляр класса и указываем локаль для русского языка
$breaker =IntlBreakIterator::createSentenceInstance('ru_RU');
// задаём текст для обработки
$breaker->setText($test);
// получаем ближайшую границу предложения перед указанной в $max_length позицией
$offset = $breaker->preceding($max_length);
// если оказалось, что первое предложение больше требуемой длины, берём его целиком, иначе анонс будет пустым
if ($offset==0) $breaker->following($max_length);
// выделяем начало текста
$summary = substr($test,0,$offset);
// выводим то, что получилось
print $summary;
Важно: IntlBreakIterator возвращает смещения в байтах, поэтому для выделения строки нужно использовать substr, а не mb_substr!