Pakeitimas su atgaliniu kvietimu naudojant reguliariąsias išraiškas PHP

Tarkime, kad turime tokią eilutę:

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

Tarkime, mums reikia rasti visas konstrukcijas, pavidalo skaičius+skaičius= ir padaryti taip, kad po lygybės ženklo atsirastų sudėties rezultatas.

Norint išspręsti tokią užduotį, patogu naudoti funkciją preg_replace_callback, kuri veikia analogiškai funkcijai preg_replace - randa ir pakeičia pagal reguliąją išraišką, bet leidžia atlikti papildomus veiksmus su rastomis dalimis.

Pirmuoju parametru funkcija priima reguliąją išraišką, antruoju - į ką keičiame, trečiuoju - eilutę, kurioje atliekamas pakeitimas.

Be to, antruoju parametru reikia perduoti funkciją-atgalinį-kvietimą, kuri bus iškviesta kiekvienam rastam atitikmeniui.

Pirmuoju atgalinio kvietimo parametru reikia nurodyti kintamąjį, į kurį pateks rasta dalis. Šis kintamasis bus masyvas rastų "kišenių" (angl. capture groups).

Pabandykime praktiškai. Parašykime kodą, kuris pagaus mūsų poeilutes, tuo pačiu įdėdamas pirmą skaičių į pirmą "kišenę", o antrajį - į antrą:

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

Dėl to mūsų var_dump suveiks tris kartus, paeiliui išvesdamas tai:

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

Toliau. Kiekvienas atitikmuo bus pakeistas tuo, ką atgalinis kvietimas grąžina per return. Pavyzdžiui, pakeiskime kiekvieną ieškomą poeilutę ženklu '!':

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

O dabar pakeiskime kiekvieną poeilutę į skaičių poros joje sumą:

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; // išves '5 8 13'
?>

Pasirodo, kad mūsų užduotis beveik išspręsta. Beliko pasidaryti taip, kad prieš sumą liktų ieškoma poeilutė. Tam įstatysime prieš sumą nulinei "kišenei" priklausančią reikšmę:

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

Duota eilutė:

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

Pakeiskite visus eilutės skaičius jų kvadratais.

Tikimasis rezultatas:

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

Duota eilutė:

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

Paverskite visas datas į formatą diena.mėnuo.metai.

Задание 3

Duota eilutė:

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

Padidinkite visas kainas 10%.