Zamiana z callbackiem przez wyrażenia regularne w PHP

Załóżmy, że mamy następujący ciąg znaków:

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

Załóżmy, że chcemy znaleźć wszystkie konstrukcje typu liczba+liczba= i sprawić, aby po znaku równości pojawił się wynik dodawania.

Do rozwiązania podobnego zadania wygodnie jest użyć funkcji preg_replace_callback, która działa analogicznie do funkcji preg_replace - znajduje i zastępuje według wyrażenia regularnego, ale pozwala wykonywać dodatkowe manipulacje ze znalezionymi fragmentami.

Pierwszym parametrem funkcja przyjmuje wyrażenie regularne, drugim - na co zamieniamy, trzecim - ciąg znaków, w którym dokonywana jest zamiana.

Przy tym w drugim parametrze należy przekazać funkcję-callback, która zostanie wywołana dla każdego znalezionego dopasowania.

Pierwszym parametrem callbacka należy określić zmienną, do której będzie trafiać znaleziony element. Ta zmienna będzie reprezentować tablicę grup przechwytujących znalezionego dopasowania.

Spróbujmy w praktyce. Napiszmy kod, który złapie nasze podciągi, przy czym umieszczając pierwszą liczbę w pierwszej grupie przechwytującej, a drugą - w drugiej:

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

W rezultacie nasz var_dump zadziała trzy razy, kolejno wypisując następujące elementy:

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

Idziemy dalej. Każde dopasowanie zostanie zastąpione przez to, co zwróci callback za pomocą return. Dla przykładu zamieńmy każdy z szukanych podciągów na znak '!':

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

A teraz zamieńmy każdy podciąg na sumę pary liczb w nim:

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; // wypisze '5 8 13'
?>

Okazuje się, że nasze zadanie jest prawie rozwiązane. Pozostaje sprawić, aby przed sumą liczb pozostawał szukany podciąg. W tym celu będziemy wstawiać przed sumą zawartość zerowej grupy przechwytującej:

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; // wypisze '2+3=5 3+5=8 7+8=13'
?>
Задание 1

Dany jest ciąg znaków:

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

Zamień wszystkie liczby w ciągu na ich kwadraty.

Oczekiwany wynik:

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

Dany jest ciąg znaków:

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

Przekształć wszystkie daty na format dzień.miesiąc.rok.

Задание 3

Dany jest ciąg znaków:

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

Zwiększ wszystkie ceny o 10%.