Mb strpos: примеры (PHP)
mb_strpos(string $haystack, string $needle, int $offset = 0, ?string $encoding = null): int|falseФункция mb_strpos
Функция mb_strpos выполняет поиск позиции первого вхождения подстроки в строке с учетом многобайтовых кодировок, таких как UTF-8. Использование этой функции необходимо, когда работа ведется с символами, занимающими более одного байта (кириллица, иероглифы, эмодзи). Обычная функция strpos может давать некорректные результаты для таких строк.
- haystack (string) – строка, в которой выполняется поиск.
- needle (string) – искомая подстрока. Если передается не строка, значение приводится к строке.
- offset (int) – необязательный параметр. Позиция в символах (не в байтах), с которой начинается поиск. Если указан отрицательный offset, отсчет идет с конца строки.
- encoding (string|null) – необязательный параметр. Кодировка строк. Если не указана или null, используется внутренняя кодировка, установленная mb_internal_encoding().
Основные примеры использования
<?php
$text = 'Привет, мир!';
$pos = mb_strpos($text, 'мир');
echo $pos; // 8
?>8
<?php
$text = 'абв абв';
$pos = mb_strpos($text, 'абв', 2);
echo $pos; // 4
?>4
<?php
$text = 'Пример текста для поиска';
$pos = mb_strpos($text, 'о', -10);
echo $pos; // 16 (позиция буквы 'о' в слове 'поиска')
?>16
<?php
$text = 'Hello, 世界!';
$pos = mb_strpos($text, '世', 0, 'UTF-8');
echo $pos; // 7
?>7
<?php
$text = 'Тестовый текст';
$pos = mb_strpos($text, 'нет');
var_dump($pos); // bool(false)
?>bool(false)
Похожие функции в PHP
- strpos – аналогичная функция, но работающая только с однобайтовыми кодировками (ASCII, Latin-1). Не подходит для UTF-8. Используется для простого текста на английском.
- mb_stripos – выполняет поиск без учета регистра символов. Полезен, когда регистр искомой подстроки неизвестен или неважен.
- str_starts_with (PHP 8) – проверяет, начинается ли строка с заданной подстроки. Работает с многобайтовыми строками корректно. Более читаемая альтернатива для проверки начала строки.
- str_contains (PHP 8) – проверяет, содержит ли строка заданную подстроку. Возвращает true/false, а не позицию. Удобна для простых проверок наличия подстроки.
Типичные ошибки
<?php
$text = 'Строка';
if (mb_strpos($text, 'С')) {
echo 'Найдено';
} else {
echo 'Не найдено';
}
?>Не найдено
Функция возвращает 0 при нахождении подстроки в начале строки, что трактуется как false при нестрогом сравнении. Нужно использовать строгое сравнение: if (mb_strpos($text, 'С') !== false).
<?php
$text = 'Текст в UTF-8';
$pos = mb_strpos($text, 'Т', 0, 'ISO-8859-1');
var_dump($pos);
?>bool(false) или неожиданное число
Указание неверной кодировки приводит к некорректному подсчету позиции или к false. Важно убедиться, что кодировка параметра encoding соответствует реальной кодировке строк.
<?php
$text = 'абв';
$pos = mb_strpos($text, 'в', 10);
var_dump($pos);
?>bool(false)
Если offset превышает длину строки, функция вернет false без предупреждения. Перед использованием стоит проверять длину строки функцией mb_strlen().
Изменения в новых версиях PHP
- В PHP 8.0 параметр needle теперь принимает только строки или объекты, приводимые к строке. Передача числа, null или массива вызовет TypeError. Раньше такие значения молчаливо преобразовывались.
- В PHP 8.0 параметр offset может быть отрицательным, что указывает на смещение от конца строки. Ранее отрицательные значения приводили к предупреждению и рассматривались как 0.
- В PHP 8.3 была улучшена производительность для некоторых частных случаев поиска подстрок.
Расширенные примеры
<?php
$text = 'Один два два три два';
$needle = 'два';
$offset = 0;
$positions = [];
while (($pos = mb_strpos($text, $needle, $offset)) !== false) {
$positions[] = $pos;
$offset = $pos + mb_strlen($needle);
}
print_r($positions);
?>Array
(
[0] => 5
[1] => 9
[2] => 17
)<?php
$text_utf8 = 'Строка в UTF-8';
$text_win1251 = iconv('UTF-8', 'Windows-1251', $text_utf8);
$pos1 = mb_strpos($text_utf8, 'в', 0, 'UTF-8');
$pos2 = mb_strpos($text_win1251, iconv('UTF-8', 'Windows-1251', 'в'), 0, 'Windows-1251');
echo "UTF-8 позиция: $pos1, Windows-1251 позиция: $pos2";
?>UTF-8 позиция: 7, Windows-1251 позиция: 6
Позиции различаются из-за разного размера символов в кодировках.
<?php
$text = 'Я ???? и ты ????';
$pos = mb_strpos($text, '????');
echo $pos; // 2 (пробел и 'Я' занимают 0 и 1 позицию)
?>2
<?php
$text = 'Пример строки для извлечения подстроки';
$needle = 'для';
$pos = mb_strpos($text, $needle);
if ($pos !== false) {
$substring = mb_substr($text, $pos + mb_strlen($needle));
echo $substring; // ' извлечения подстроки'
}
?>извлечения подстроки
<?php
$text = 'Привет Мир';
$pos1 = mb_strpos($text, 'мир'); // false
$pos2 = mb_stripos($text, 'мир'); // 8
echo "strpos: "; var_dump($pos1);
echo "stripos: "; var_dump($pos2);
?>strpos: bool(false) stripos: int(8)
Аналоги в других языках
text = 'Привет, мир!'
pos = text.find('мир')
print(pos) # 88
Метод str.find() в Python по умолчанию работает с Unicode. Аналогом точного соответствия mb_strpos является именно find(), а не index() (который выбрасывает исключение при отсутствии подстроки).
let text = 'Привет, мир!';
let pos = text.indexOf('мир');
console.log(pos); // 88
Метод String.prototype.indexOf() в JavaScript также работает с Unicode (UTF-16). Особенность: не поддерживает параметр offset в символах для перескакивания, как в PHP.
SELECT INSTR('Привет, мир!', 'мир') AS position;position: 9
Функция INSTR() в MySQL возвращает позицию в байтах, а не в символах, для кодировки UTF-8 это может дать другой результат. Для корректной работы с символами нужно использовать функции, учитывающие многобайтовость, например, в сочетании с CHAR_LENGTH.