Αντικατάσταση με callback μέσω κανονικών εκφράσεων στην PHP
Ας υποθέσουμε ότι έχουμε την ακόλουθη συμβολοσειρά:
<?php
$str = '2+3= 3+5= 7+8=';
?>
Ας υποθέσουμε ότι πρέπει να βρούμε όλες τις κατασκευές της μορφής αριθμός+αριθμός= και να κάνουμε έτσι ώστε μετά το ίσον να εμφανίζεται το αποτέλεσμα της πρόσθεσης.
Για την επίλυση μιας τέτοιας εργασίας είναι βολικό να χρησιμοποιήσουμε
τη συνάρτηση preg_replace_callback, η οποία
λειτουργεί ανάλογα με τη συνάρτηση preg_replace
- βρίσκει και αντικαθιστά με βάση μια κανονική έκφραση,
αλλά επιτρέπει την εκτέλεση πρόσθετων χειρισμών
με τα κομμάτια που βρέθηκαν.
Ως πρώτη παράμετρο η συνάρτηση δέχεται την κανονική έκφραση, ως δεύτερη - με τι αντικαθιστούμε, ως τρίτη - τη συμβολοσειρά, στην οποία πραγματοποιείται η αντικατάσταση.
Σε αυτή την περίπτωση, στη δεύτερη παράμετρο θα πρέπει να περάσουμε μια συνάρτηση-callback, η οποία θα κληθεί για κάθε ταίριασμα που βρεθεί.
Ως πρώτη παράμετρο του callback πρέπει να ορίσουμε μια μεταβλητή, στην οποία θα πέφτει το που βρέθηκε. Αυτή η μεταβλητή θα είναι ένας πίνακας ομάδων καταλής (capturing groups) του ταιριάσματος.
Ας δοκιμάσουμε στην πράξη. Ας γράψουμε κώδικα, ο οποίος θα πιάσει τις υποσυμβολοσειρές μας, ενώ θα βάλει τον πρώτο αριθμό στην πρώτη ομάδα, και τον δεύτερο - στη δεύτερη:
<?php
$str = '2+3= 3+5= 7+8=';
preg_replace_callback('#(\d+)\+(\d+)=#', function($match) {
var_dump($match);
}, $str);
?>
Σαν αποτέλεσμα, το var_dump μας θα εκτελεστεί
τρεις φορές, εμφανίζοντας διαδοχικά τα ακόλουθα:
['2+3=', '2', '3']
['3+5=', '3', '5']
['7+8=', '7', '7']
Προχωράμε. Κάθε ταίριασμα θα αντικατασταθεί
με αυτό που επιστρέφει το callback μέσω return.
Ας αντικαταστήσουμε, για παράδειγμα, κάθε μία από τις αναζητημένες
υποσυμβολοσειρές με το σύμβολο '!':
<?php
$str = '2+3= 3+5= 7+8=';
$res = preg_replace_callback('#(\d+)\+(\d+)=#', function($match) {
return '!';
}, $str);
echo $res; // θα εμφανίσει '! ! !'
?>
Και τώρα ας αντικαταστήσουμε κάθε υποσυμβολοσειρά με το άθροισμα του ζευγαριού των αριθμών σε αυτή:
<?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
$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'
?>
Δίνεται μια συμβολοσειρά:
<?php
$str = 'The numbers are 3, 7 and 12';
?>
Αντικαταστήστε όλους τους αριθμούς στη συμβολοσειρά με τα τετράγωνά τους.
Αναμενόμενο αποτέλεσμα:
'The numbers are 9, 49 and 144'
Δίνεται μια συμβολοσειρά:
<?php
$str = '2023-01-15 2022-12-31 2024-05-20';
?>
Μετατρέψτε όλες τις ημερομηνίες στη μορφή ημέρα.μήνας.έτος.
Δίνεται μια συμβολοσειρά:
<?php
$str = 'Costs: $15, $20, $100';
?>
Αυξήστε όλες τις τιμές κατά 10%.