preg_replace_callback
Функция preg_replace_callback() в PHP выполняет поиск и замену по регулярному выражению с использованием callback-функции для вычисления замены.
Введение
preg_replace_callback() выполняет поиск и замену по регулярному выражению, однако вместо фиксированной строки замены вы передаёте callback-функцию, которая вызывается для каждого совпадения. Callback получает совпадение (и любые захватывающие группы) и возвращает текст для подстановки. Это позволяет вычислять замены с помощью реальной логики PHP — перевести слово в верхний регистр, прибавить 1 к числу, найти значение в таблице — что невозможно сделать с помощью обычной функции preg_replace().
Используйте её, когда замена зависит от того, что было найдено. Если замена является константой или простой обратной ссылкой вроде $1, лучше воспользоваться preg_replace(); если же нужен отдельный callback для каждого шаблона, обратитесь к preg_replace_callback_array().
Синтаксис
preg_replace_callback(
string|array $pattern,
callable $callback,
string|array $subject,
int $limit = -1,
int &$count = null,
int $flags = 0
): string|array|null| Параметр | Описание |
|---|---|
$pattern | Регулярное выражение (строка с разделителями) для поиска или массив шаблонов. |
$callback | Вызываемая функция, запускаемая для каждого совпадения. Получает массив совпадений и возвращает строку замены. |
$subject | Строка (или массив строк) для поиска и изменения. |
$limit | Максимальное количество замен на строку. -1 (по умолчанию) означает без ограничений. |
$count | Передаётся по ссылке; заполняется количеством выполненных замен. |
$flags | PREG_OFFSET_CAPTURE и/или PREG_UNMATCHED_AS_NULL, аналогично preg_match(). |
Функция возвращает изменённый subject или null при ошибке регулярного выражения. Первый аргумент callback — это массив $matches: $matches[0] содержит всё совпадение, а $matches[1], $matches[2], … — захватывающие группы, точно так же, как массив, заполняемый preg_match().
Базовый пример: перевод каждого слова в верхний регистр
Шаблон \w+ соответствует каждой последовательности словесных символов. Для каждого совпадения callback получает $matches[0] (слово) и возвращает его в верхнем регистре, который вставляется обратно в строку.
Работа с захватывающими группами
Скобки в шаблоне создают захватывающие группы, доступные через $matches[1], $matches[2] и т. д. В следующем примере мы прибавляем единицу к каждому числу в строке:
<?php
$subject = 'Room 12, floor 3, building 7';
$result = preg_replace_callback('/(\d+)/', function ($m) {
return (string) ((int) $m[1] + 1);
}, $subject);
echo $result;
// Room 13, floor 4, building 8Поскольку callback выполняет реальный код, приращение вычисляется для каждого совпадения — этого невозможно достичь со статической строкой замены.
Практический пример использования: маскировка конфиденциальных данных
Распространённая задача — частичное скрытие адресов электронной почты или номеров карт в журналах. Callback может решать, сколько каждого совпадения показывать:
<?php
$text = 'Contact: [email protected] or [email protected]';
$result = preg_replace_callback('/([\w.]+)@([\w.]+)/', function ($m) {
$name = $m[1];
$masked = $name[0] . str_repeat('*', max(strlen($name) - 1, 1));
return $masked . '@' . $m[2];
}, $text);
echo $result;
// Contact: a****@example.com or b**@test.orgПодсчёт и ограничение замен
Параметры $limit и $count позволяют ограничить количество обрабатываемых совпадений и узнать, сколько их было на самом деле:
<?php
$subject = 'a a a a a';
$result = preg_replace_callback('/a/', function ($m) {
return 'b';
}, $subject, 2, $count);
echo $result, "\n"; // b b a a a
echo $count; // 2Заменяются только первые два a, поскольку $limit равен 2, а $count сообщает количество выполненных замен.
preg_replace vs. preg_replace_callback
| Применение | Функция |
|---|---|
Фиксированный текст или обратная ссылка вроде $1 | preg_replace() |
| Замена, вычисляемая из совпадения | preg_replace_callback() |
| Отдельный callback для каждого шаблона | preg_replace_callback_array() |
Для поиска без замены обратитесь к preg_match() и preg_match_all(), а также к главе о регулярных выражениях PHP для изучения синтаксиса шаблонов.
Распространённые ошибки
- Всегда возвращайте строку. Возвращаемое значение callback приводится к строке и вставляется. Возврат
nullудаляет совпадение; забытыйreturnвставляет пустую строку. - Обращайтесь к правильному индексу.
$matches[0]— полное совпадение; группа 1 находится в$matches[1]. Ошибка на единицу здесь — самая частая ошибка. - Аккуратно с экранированием. В отличие от
preg_replace(), вы не пишете обратные ссылки$1/\1в результате — вы строите строку сами, поэтому в замене нечего экранировать. - Возврат
nullсамой функцией (не callback) сигнализирует об ошибке регулярного выражения, например о несовпадающем разделителе.
Заключение
preg_replace_callback() — правильный инструмент, когда замена должна быть вычислена, а не задана заранее. Функция сочетает мощь регулярных выражений с произвольной логикой PHP в callback, что делает её идеальной для преобразования, маскировки или пересчёта найденного текста. Для статических замен используйте preg_replace(), а для нескольких шаблонов одновременно — preg_replace_callback_array().