Preg replace callback: примеры (PHP)

Работа с preg_replace_callback в PHP на примерах
Раздел: Регулярные выражения
preg_replace_callback(string|array $pattern, callable $callback, string|array $subject, int $limit = -1, int &$count = null, int $flags = 0): string|array|null

Функция preg_replace_callback

Назначение и применение

Функция preg_replace_callback в PHP выполняет поиск и замену текста с использованием регулярных выражений, где замена определяется результатом выполнения пользовательской callback-функции. Она применяется, когда замена зависит от найденных совпадений и требует дополнительной обработки.

Аргументы функции

Функция принимает до пяти параметров:

  • pattern - строка с регулярным выражением или массив таких строк.
  • callback - функция обратного вызова, которая получает массив совпадений и возвращает строку замены.
  • subject - строка или массив строк, в которых выполняется замена.
  • limit (необязательный) - максимальное количество замен. Значение -1 означает отсутствие ограничений.
  • count (необязательный) - переменная, в которую записывается количество выполненных замен.
  • flags (необязательный) - комбинация флагов: PREG_OFFSET_CAPTURE, PREG_UNMATCHED_AS_NULL.

Простые примеры использования

Базовый пример с числовыми значениями
<?php
$text = 'Цена: 100 и 200 долларов';
$result = preg_replace_callback('/\d+/', function($matches) {
    return $matches[0] * 1.1;
}, $text);
echo $result;
?>
Цена: 110 и 220 долларов
Использование именованных групп
<?php
$text = 'Иванов Иван, Петров Петр';
$result = preg_replace_callback('/(?P<last>\w+)\s+(?P<first>\w+)/', 
    function($matches) {
        return $matches['first'] . ' ' . $matches['last'];
    }, 
    $text
);
echo $result;
?>
Иван Иванов, Петр Петров

Альтернативные функции PHP

Выполняет простую замену по регулярному выражению без callback-функции. Используется, когда замена статична или определяется шаблоном.

Работает аналогично preg_replace, но возвращает только измененные элементы массива.

preg_match_all с обработкой

При сложной логике обработки иногда применяется комбинация preg_match_all и ручной обработки результатов.

Распространенные ошибки

Некорректный callback
<?php
$text = 'Пример текста';
// Неправильно: передана строка вместо callable
$result = preg_replace_callback('/\w+/', 'несуществующая_функция', $text);
?>
Warning: preg_replace_callback(): The callback is not callable
Изменение данных в callback
<?php
$text = 'Числа: 1, 2, 3';
$sum = 0;
$result = preg_replace_callback('/\d+/', function($matches) use (&$sum) {
    $sum += $matches[0]; // Побочный эффект
    return $matches[0];
}, $text);
// $sum теперь содержит 6
?>
Числа: 1, 2, 3 (но $sum = 6)

Изменения в новых версиях PHP

PHP 7.4

Добавлена возможность использовать стрелочные функции для callback, что упрощает запись.

PHP 8.0

Улучшена обработка ошибок при некорректных регулярных выражениях - теперь выбрасывается исключение TypeError.

PHP 8.2

Добавлена поддержка флага PREG_UNMATCHED_AS_NULL для более последовательного поведения с несовпадающими группами.

Расширенные примеры

Обработка вложенных конструкций
Пример php
<?php
function processMarkdown($text) {
    $pattern = '/\[([^\[\]]+)\]\(([^)]+)\)/';
    return preg_replace_callback($pattern, 
        function($matches) {
            return '<a href="' . htmlspecialchars($matches[2]) . '">' 
                   . htmlspecialchars($matches[1]) . '</a>';
        }, 
        $text
    );
}

$markdown = 'Ссылка [пример](https://example.com) в тексте';
echo processMarkdown($markdown);
?>
Ссылка <a href="https://example.com">пример</a> в тексте
Рекурсивная обработка с ограничением
Пример php
<?php
$text = '{{a{{b}}c}}';
$count = 0;
while (preg_match('/\{\{[^{}]*\}\}/', $text) && $count < 5) {
    $text = preg_replace_callback('/\{\{([^{}]*)\}\}/', 
        function($matches) {
            return '[' . strtoupper($matches[1]) . ']';
        }, 
        $text
    );
    $count++;
}
echo $text;
?>
[A[B]C]

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

Preg replace callback в Javascript

let text = 'Цена: 100 и 200 долларов';
let result = text.replace(/\d+/g, (match) => match * 1.1);
console.log(result);
Цена: 110 и 220 долларов

Preg replace callback в Python

import re
text = 'Цена: 100 и 200 долларов'
result = re.sub(r'\d+', lambda m: str(int(m.group()) * 1.1), text)
print(result)
Цена: 110.0 и 220.0 долларов

PHP preg_replace_callback function comments

En
Preg replace callback Perform a regular expression search and replace using a callback