Zamiana z callbackiem przez wyrażenia regularne w PHP
Załóżmy, że mamy następujący ciąg znaków:
<?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
$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:
['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
$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
$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
$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'
?>
Dany jest ciąg znaków:
<?php
$str = 'The numbers are 3, 7 and 12';
?>
Zamień wszystkie liczby w ciągu na ich kwadraty.
Oczekiwany wynik:
'The numbers are 9, 49 and 144'
Dany jest ciąg znaków:
<?php
$str = '2023-01-15 2022-12-31 2024-05-20';
?>
Przekształć wszystkie daty na format dzień.miesiąc.rok.
Dany jest ciąg znaków:
<?php
$str = 'Costs: $15, $20, $100';
?>
Zwiększ wszystkie ceny o 10%.