Работа со словами: функции и приёмы в PHP
Основные методы работы со словами в PHP
Наиболее эффективное решение для извлечения слов из строки на английском языке - встроенная функция str_word_count. Она возвращает массив слов или их количество, автоматически отбрасывая знаки препинания и учитывая только буквы.
$str = 'Hello world! This is a test.';
$words = str_word_count($str, 1);
print_r($words);
Array
(
[0] => Hello
[1] => world
[2] => This
[3] => is
[4] => a
[5] => test
)
Флаги функции: 0 (по умолчанию) - возвращает количество слов; 1 - массив слов; 2 - массив, где ключи - позиции начала слов. Для работы с дефисами или апострофами можно передать третий параметр - строку дополнительных символов, которые считаются частью слова, например str_word_count($str, 1, ''-'').
Типичная проблема: str_word_count не поддерживает кириллицу и другие многобайтовые кодировки без настройки локали. Решение - установить локаль через setlocale(LC_ALL, 'ru_RU.UTF-8') или использовать альтернативные методы, описанные ниже.
Как просто разбить строку на слова по пробелам?
Самый простой способ - использовать explode с разделителем пробел. Подходит для строк без лишних пробелов и знаков препинания.
$str = 'PHP is great';
$words = explode(' ', $str);
print_r($words);
Array
(
[0] => PHP
[1] => is
[2] => great
)
Проблемы: если в строке несколько пробелов подряд, образуются пустые элементы. Знаки препинания считаются частью слова. Решение - предварительно очищать строку или использовать регулярные выражения.
Как разделить строку на слова, игнорируя множественные пробелы?
Функция preg_split с шаблоном /\s+/ разбивает по одному или нескольким пробельным символам.
$str = ' PHP is great ';
$words = preg_split('/\s+/', trim($str));
print_r($words);
Array
(
[0] => PHP
[1] => is
[2] => great
)
Знаки препинания остаются прикреплёнными к словам. Для их удаления нужно расширить шаблон, например, /[^\p{L}]+/u.
Как извлечь слова на разных языках (кириллица, латиница)?
Использование preg_match_all с юникодной последовательностью \p{L} (любая буква) и модификатором u.
$str = 'Привет, world! Тест.';
preg_match_all('/\p{L}+/u', $str, $matches);
$words = $matches[0];
print_r($words);
Array
(
[0] => Привет
[1] => world
[2] => Тест
)
Проблема: слова с дефисами или апострофами (например, 'два-три' или 'don''t') не распознаются целиком. Решение - модифицировать шаблон: /[\p{L}''-]+/u.
Как подсчитать количество слов в строке?
Проще всего - str_word_count($str) для латиницы или count(preg_match_all('/\p{L}+/u', $str)) для юникода.
$str = 'Count words test';
echo str_word_count($str); // 3
3
Ошибка: при использовании str_word_count с кириллицей без локали вернёт 0. Всегда проверяйте локаль или применяйте юникодный подход.
Как проверить, содержится ли конкретное слово в строке?
Для точного совпадения (целое слово) используйте preg_match с границами слова \b.
$str = 'PHP is awesome';
if (preg_match('/\bPHP\b/', $str)) {
echo 'Слово найдено';
}
Слово найдено
Функция strpos найдёт слово внутри другого (например, 'PH' в 'PHP'). \b не работает с кириллицей в некоторых версиях PHP; альтернатива - использовать preg_match с /(?<=[\s\pP])PHP(?=[\s\pP])/u.
Как заменить одно слово на другое с учётом целостности?
Регулярное выражение с границами \b в preg_replace заменяет только целые слова.
$str = 'Old word and old buildings';
$newStr = preg_replace('/\bold\b/', 'new', $str);
echo $newStr; // 'new word and old buildings'
new word and old buildings
str_replace заменит часть слова (например, 'old' в 'buildings'). Всегда используйте границы слов для точной замены.
Как получить первое или последнее слово строки?
Можно разбить строку на слова функцией str_word_count и взять первый или последний элемент.
$str = 'First middle last';
$words = str_word_count($str, 1);
$first = $words[0] ?? '';
$last = end($words);
echo "Первое: $first, Последнее: $last";
Первое: First, Последнее: last
При использовании explode с непредсказуемым количеством пробелов можно получить пустые строки. Лучше применить array_values(array_filter(explode(' ', $str))).
// Пример 1: Извлечение слов с позициями и длиной (str_word_count с флагом 2)
$str = 'Hello world! This is a test.';
$wordsWithPos = str_word_count($str, 2);
foreach ($wordsWithPos as $pos => $word) {
echo "Слово '$word' на позиции $pos (длина " . strlen($word) . ")\n";
}
Слово 'Hello' на позиции 0 (длина 5) Слово 'world' на позиции 6 (длина 5) Слово 'This' на позиции 13 (длина 4) Слово 'is' на позиции 18 (длина 2) Слово 'a' на позиции 21 (длина 1) Слово 'test' на позиции 23 (длина 4)
// Пример 2: Подсчёт частоты слов и сортировка
$str = 'apple banana apple cherry banana apple';
$words = str_word_count(strtolower($str), 1);
$freq = array_count_values($words);
arsort($freq);
print_r($freq);
Array
(
[apple] => 3
[banana] => 2
[cherry] => 1
)
// Пример 3: Фильтрация слов по длине (больше 4 букв)
$str = 'PHP is a scripting language';
$words = str_word_count($str, 1);
$longWords = array_filter($words, function($w) { return strlen($w) > 4; });
print_r($longWords);
Array
(
[0] => scripting
[1] => language
)
// Пример 4: Извлечение слов, содержащих подстроку 'php'
$words = ['PHP', 'Hypertext', 'Preprocessor', 'phpstorm'];
$phpWords = preg_grep('/php/i', $words);
print_r($phpWords);
Array
(
[0] => PHP
[2] => Preprocessor
[3] => phpstorm
)
// Пример 5: Преобразование каждого слова в заглавную букву
$str = 'hello world from php';
$words = str_word_count($str, 1);
$capitalized = array_map('ucfirst', $words);
$newStr = implode(' ', $capitalized);
echo $newStr;
Hello World From Php
// Пример 6: Работа с многобайтовыми строками (разделение и удаление пустых)
$str = ' Привет мир! ';
$words = preg_split('/\s+/u', trim($str));
print_r($words);
Array
(
[0] => Привет
[1] => мир!
)
// Пример 7: Удаление стоп-слов из списка
$stopWords = ['and', 'or', 'the', 'a'];
$str = 'This is a book and a pen';
$words = str_word_count(strtolower($str), 1);
$filtered = array_diff($words, $stopWords);
echo implode(' ', $filtered);
this is book pen
// Пример 8: Извлечение слов с апострофами как одно целое
$str = "Don't stop the music";
preg_match_all("/[\w']+/u", $str, $matches);
print_r($matches[0]);
Array
(
[0] => Don't
[1] => stop
[2] => the
[3] => music
)