Αντικατάσταση με callback μέσω κανονικών εκφράσεων στην PHP

Ας υποθέσουμε ότι έχουμε την ακόλουθη συμβολοσειρά:

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

Ας υποθέσουμε ότι πρέπει να βρούμε όλες τις κατασκευές της μορφής αριθμός+αριθμός= και να κάνουμε έτσι ώστε μετά το ίσον να εμφανίζεται το αποτέλεσμα της πρόσθεσης.

Για την επίλυση μιας τέτοιας εργασίας είναι βολικό να χρησιμοποιήσουμε τη συνάρτηση preg_replace_callback, η οποία λειτουργεί ανάλογα με τη συνάρτηση preg_replace - βρίσκει και αντικαθιστά με βάση μια κανονική έκφραση, αλλά επιτρέπει την εκτέλεση πρόσθετων χειρισμών με τα κομμάτια που βρέθηκαν.

Ως πρώτη παράμετρο η συνάρτηση δέχεται την κανονική έκφραση, ως δεύτερη - με τι αντικαθιστούμε, ως τρίτη - τη συμβολοσειρά, στην οποία πραγματοποιείται η αντικατάσταση.

Σε αυτή την περίπτωση, στη δεύτερη παράμετρο θα πρέπει να περάσουμε μια συνάρτηση-callback, η οποία θα κληθεί για κάθε ταίριασμα που βρεθεί.

Ως πρώτη παράμετρο του callback πρέπει να ορίσουμε μια μεταβλητή, στην οποία θα πέφτει το που βρέθηκε. Αυτή η μεταβλητή θα είναι ένας πίνακας ομάδων καταλής (capturing groups) του ταιριάσματος.

Ας δοκιμάσουμε στην πράξη. Ας γράψουμε κώδικα, ο οποίος θα πιάσει τις υποσυμβολοσειρές μας, ενώ θα βάλει τον πρώτο αριθμό στην πρώτη ομάδα, και τον δεύτερο - στη δεύτερη:

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']

Προχωράμε. Κάθε ταίριασμα θα αντικατασταθεί με αυτό που επιστρέφει το callback μέσω 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%.