Замяна с колбек чрез регулярни изрази в PHP

Нека имаме следния низ:

php<?php
  $str = '2+3= 3+5= 7+8=';
?>

Нека трябва да намерим всички конструкции от вида число+число= и да направим така, че след равното да се появи резултатът от събирането.

За решаването на подобна задача е удобно да се използва функцията preg_replace_callback, която работи аналогично на функцията preg_replace - намира и заменя чрез регулярен израз, но позволява извършването на допълнителни манипуляции с намерените части.

Първият параметър функцията приема регулярния израз, вторият - на какво заменяме, третият - низът, в който се извършва замяната.

При това във втория параметър трябва да се подаде функция-колбек, която ще бъде извикана за всяко намерено съвпадение.

Първият параметър на колбека трябва да се укаже променлива, в която ще попадне намереното. Тази променлива ще представлява масив от групи на намереното.

Нека опитаме на практика. Да напишем код, който да улови нашите поднизове, като същевременно сложи първото число в първата група, а второто - във втората:

php<?php
  $str = '2+3= 3+5= 7+8=';
  
  preg_replace_callback('#(\d+)\+(\d+)=#', function($match) {
    var_dump($match);
  }, $str);
?>

В резултат нашият var_dump ще сработи три пъти, като последователно ще изведе следното:

php['2+3=', '2', '3']
['3+5=', '3', '5']
['7+8=', '7', '7']

Продължаваме. Всяко съвпадение ще бъде заменено на това, което колбекът връща чрез return. Нека за пример заменим всеки от търсените поднизове със знака '!':

php<?php
  $str = '2+3= 3+5= 7+8=';
  
  $res = preg_replace_callback('#(\d+)\+(\d+)=#', function($match) {
    return '!';
  }, $str);
  
  echo $res; // ще изведе '! ! !'
?>

А сега нека заменим всеки подниз със сумата на двойката числа в него:

php<?php
  $str = '2+3= 3+5= 7+8=';
  
  $res = preg_replace_callback('#(\d+)\+(\d+)=#', function($match) {
    return $match[1] + $match[2];
  }, $str);
  
  echo $res; // ще изведе '5 8 13'
?>

Получава се, че нашата задача почти е решена. Остава да направим така, че пред сумата на числата да остава търсеният подниз. За това ще вмъкнем пред сумата съдържанието на нулевата група:

php<?php
  $str = '2+3= 3+5= 7+8=';
  
  $res = preg_replace_callback('#(\d+)\+(\d+)=#', function($match) {
    return $match[0] . ($match[1] + $match[2]);
  }, $str);
  
  echo $res; // ще изведе '2+3=5 3+5=8 7+8=13'
?>
Задание 1

Даден е низ:

php<?php
  $str = 'The numbers are 3, 7 and 12';
?>

Заменете всички числа в низа с техните квадрати.

Очакван резултат:

php'The numbers are 9, 49 and 144'
Задание 2

Даден е низ:

php<?php
  $str = '2023-01-15 2022-12-31 2024-05-20';
?>

Преобразувайте всички дати във формат ден.месец.година.

Задание 3

Даден е низ:

php<?php
  $str = 'Costs: $15, $20, $100';
?>

Увеличете всички цени с 10%.