Mb strpos: примеры (PHP)

Функция 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 8+)
<?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 соответствует реальной кодировке строк.

Использование offset за пределами строки
<?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
<?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
<?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
<?php
$text = 'Я ???? и ты ????';
$pos = mb_strpos($text, '????');
echo $pos; // 2 (пробел и 'Я' занимают 0 и 1 позицию)
?>
2
Использование с функциями для работы со строками
Пример php
<?php
$text = 'Пример строки для извлечения подстроки';
$needle = 'для';
$pos = mb_strpos($text, $needle);
if ($pos !== false) {
    $substring = mb_substr($text, $pos + mb_strlen($needle));
    echo $substring; // ' извлечения подстроки'
}
?>
 извлечения подстроки
Поиск с учетом регистра (сравнение с mb_stripos)
Пример php
<?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)

Аналоги в других языках

Python
text = 'Привет, мир!'
pos = text.find('мир')
print(pos)  # 8
8

Метод str.find() в Python по умолчанию работает с Unicode. Аналогом точного соответствия mb_strpos является именно find(), а не index() (который выбрасывает исключение при отсутствии подстроки).

JavaScript
let text = 'Привет, мир!';
let pos = text.indexOf('мир');
console.log(pos); // 8
8

Метод String.prototype.indexOf() в JavaScript также работает с Unicode (UTF-16). Особенность: не поддерживает параметр offset в символах для перескакивания, как в PHP.

MySQL
SELECT INSTR('Привет, мир!', 'мир') AS position;
position: 9

Функция INSTR() в MySQL возвращает позицию в байтах, а не в символах, для кодировки UTF-8 это может дать другой результат. Для корректной работы с символами нужно использовать функции, учитывающие многобайтовость, например, в сочетании с CHAR_LENGTH.

PHP mb_strpos function comments

En
Mb strpos Find position of first occurrence of string in a string