Regularne izraze uporabljamo za iskanje po besedilih. Z regex v nizu znakov iščemo določen vzorec, če je ta prisoten kot rezultat prejmemo TRUE sicer FALSE.
npr: preg_match("/Luka/", $besedilo); #rezultat je TRUE/FALSE
Z regex lahko tudi iščemo dele niza in ga poljubno menjamo (search&replace.)
Zadeva je zelo uporabna pri preverjanju in čiščenju odprtih vnosov uporabnikov spletnih aplikacij.
Kako v PHP torej izgleda regularen izraz? PHP ga prepozna če je zapisan "/takole/"
Sedaj pa k primerom. V spremenljivko z imenom $besedilo bomo vnesli niz znakov.
Najprej si pripravimo besedilo, v katerem bomo iskali vzorce:
<?php $besedilo = "Moje ime je Toni, Toni Res."; echo '<b>' . $besedilo . '</b>'; ?>
preg_match() vrne vrednost 0 ali 1.
<?php
echo preg_match("/Toni/", $besedilo);
?>
V praksi funkcijo največkrat uporabimo v kombinaciji z if:
<?php
if (preg_match("/Toni/", $besedilo)){
echo "Toni was here!";
}
?>
Če želimo iskanje razbremeniti razlik med velikimi in malimi črkami, regexu dodamo modifikator i, na primer /Toni/i.
<?php
if (preg_match("/toni/i", $besedilo)){
echo "Toni was here!";
}
?>
Funkciji lahko dodamo še tretji parameter. Vanj PHP shrani najdeni zadetek.
<?php
if (preg_match("/Toni/", $besedilo, $polje)){
print_r($polje);
}
?>
preg_match() vrne samo prvi zadetek, če je iskani niz prisoten. Če želimo poiskati vse zadetke, uporabimo funkcijo preg_match_all().
<?php
if (preg_match_all("/Toni/", $besedilo, $polje)){
print_r($polje);
}
?>
Z oklepaji lahko označimo skupine. Tako lahko posebej zajamemo del zadetka.
<?php
if (preg_match_all("/To(ni)/", $besedilo, $polje)){
print_r($polje);
}
?>
Izpišimo še vsebino polja, ki ga dobimo kot rezultat iskanja:
<?php
if (preg_match_all("/To(ni)/", $besedilo, $polje)){
echo $polje[0][0] . "<br>";
echo $polje[1][1] . "<br>";
}
?>
Za zamenjavo besedila uporabimo preg_replace().
<?php
$besedilo2 = preg_replace("/Toni/", "Luka", $besedilo);
echo $besedilo2;
?>
Za razbijanje besedila na več delov z uporabo izbranega niza znakov uporabimo funkcijo preg_split($regex, $string).
<?php
$besedilo3 = "html, css, javascript, php";
echo $besedilo3;
echo "<br>";
$jeziki = preg_split("/,/", $besedilo3);
print_r($jeziki);
?>
Do zdaj smo regularne izraze uporabljali na enem nizu znakov. V PHP-ju pa lahko regex uporabimo tudi za iskanje znotraj polja.
Za to uporabimo funkcijo preg_grep(). Ta pregleda vse elemente polja in vrne samo tiste, ki ustrezajo podanemu regularnemu izrazu.
<?php
print_r($jeziki);
echo "<br>";
$output = preg_grep('/h[tp]/', $jeziki);
print_r($output);
?>
preg_grep() preišče vse elemente polja./h[tp]/ pomeni: poišči niz, v katerem se pojavi črka h, za njo pa t ali p.Regularni izrazi uporabljajo posebne znake (metaznake), s katerimi opišemo vzorce za iskanje.
. – katerikoli znak^ – začetek niza$ – konec niza
<?php
$besedilo = "Moje ime je Toni, Toni Res.";
echo preg_match("/Toni/", $besedilo);
echo preg_match("/./", $besedilo);
echo preg_match("/(o|e)/", $besedilo);
echo preg_match("/(a|N)/", $besedilo);
?>
<?php
$besedilo2 = "Moje ime je Toni, Toni";
preg_match_all("/Toni/", $besedilo2, $polje);
print_r($polje);
preg_match_all("/Toni$/", $besedilo2, $polje);
print_r($polje);
preg_match_all("/^.*$/", $besedilo2, $polje);
print_r($polje);
?>
Nekateri znaki imajo v regexu poseben pomen, zato jih moramo zapisati z escape znakom \, če jih želimo iskati dobesedno:
\. → pika (.)\$ → znak $\^ → znak ^\\ → poševnica \V nizu znakov Moje $ime ^ je Toni, Toni, bi radi poiskali $ime
<?php
$besedilo3 = "Moje \$ime ^ je Toni, Toni";
preg_match_all("/\\$.../", $besedilo3, $polje);
print_r($polje);
?>
Z oglatimi oklepaji določimo množico znakov:
<?php
echo preg_match("/[abc]/", $besedilo);
echo preg_match("/[ijk]/", $besedilo);
echo preg_match("/[^Na]/", $besedilo);
echo preg_match("/[a-c]/", $besedilo);
echo preg_match("/[a-zA-Z]/", $besedilo);
echo preg_match("/[0-9]/", $besedilo);
?>
\d – števke\w – črke, številke, _\s – presledki
<?php
preg_match_all("/\\$\\w\\D\\S/", $besedilo3, $polje);
print_r($polje);
?>
<?php
echo preg_match("/MOj/i", $besedilo);
?>
Števniki določajo, kolikokrat se mora določen znak ali vzorec pojaviti.
{x} – natančno x-krat{x,y} – od x do y-krat{x,} – vsaj x-krat* – 0 ali večkrat+ – 1 ali večkrat? – 0 ali 1-kratNajprej preverimo, ali se v besedilu sploh pojavi velika črka T:
<?php
echo preg_match("/T/", $besedilo);
?>
V zavitih oklepajih lahko določimo, kolikokrat se mora znak ponoviti:
<?php
echo preg_match("/T{1}/", $besedilo) . "<br>";
echo preg_match("/T{2}/", $besedilo) . "<br>";
?>
Določimo lahko tudi spodnjo in zgornjo mejo:
<?php
echo preg_match("/T{0,1}/", $besedilo) . "<br>";
echo preg_match("/T{2,3}/", $besedilo) . "<br>";
echo preg_match("/T{1,}/", $besedilo) . "<br>";
?>
Znak * pomeni: ničkrat ali večkrat.
<?php
echo preg_match("/T*/", $besedilo) . "<br>";
preg_match_all("/T*/", $besedilo, $polje);
print_r($polje);
?>
Če želimo shraniti tudi znake, ki sledijo črki T, lahko uporabimo piko in števnik:
<?php
preg_match_all("/T.*/", $besedilo, $polje);
print_r($polje);
?>
Iskanje lahko tudi omejimo, na primer do črke e:
<?php
preg_match_all("/T.*e/", $besedilo, $polje);
print_r($polje);
?>
Znak + pomeni: enkrat ali večkrat.
<?php
preg_match_all("/T+/", $besedilo, $polje);
print_r($polje);
?>
Poglejmo še primer z drugim nizom:
<?php
$besedilo4 = "bat a 1000";
preg_match_all("/\s\w\s\d\d\d\d/", $besedilo4, $polje);
echo $polje[0][0];
echo "<hr>";
preg_match_all("/\D{3}/", $besedilo4, $polje);
print_r($polje);
?>
Nekateri števniki v regularnih izrazih so požrešni (greedy), kar pomeni, da poskušajo zajeti čim več znakov. Če jim dodamo vprašaj ?, postanejo leni (lazy) in zajamejo čim manj znakov.
Za primer malce predelajmo naše besedilo:
<?php $besedilo5 = "Moje 1ime2 je Toni, 1Toni2 Res."; echo $besedilo5 . "<br>"; ?>
Najprej primer za *, ki je požrešen (greedy) števnik:
<?php
preg_match_all("/1.*2/", $besedilo5, $polje);
print_r($polje);
?>
Izraz .* pomeni: zajemi karkoli in to naredi čim bolj na široko. Zato regex ujame vse od prve 1 do zadnje 2.
Če dodamo vprašaj in uporabimo *?, dobimo leni (lazy) števnik:
<?php
preg_match_all("/1.*?2/", $besedilo5, $polje);
print_r($polje);
?>
Izraz .*? pomeni: zajemi čim manj znakov, samo toliko, da se vzorec še ujema. Zato tukaj dobimo dva ločena zadetka.
Tak pristop je zelo uporaben, kadar iščemo vsebino znotraj določenih oznak.
<?php
$besedilo6 = "Trraraaa! <titl>Regularni izrazi v PHP</titl> Jeah.";
echo $besedilo6 . "<hr>";
preg_match_all("/<titl>.*?<\/titl>/", $besedilo6, $polje);
print_r($polje);
?>
.* je požrešen zapis in zajame čim več znakov..*? je leni zapis in zajame čim manj znakov.Z oklepaji () lahko v regularnem izrazu definiramo skupine. Na te skupine se lahko kasneje sklicujemo pri zamenjavi besedila.
Sklicujemo se z znakom $:
$1 – vsebina prve skupine$2 – vsebina druge skupine$3 – vsebina tretje skupineTipičen primer uporabe je sprememba formata datuma iz YYYY-MM-DD v DD. MM. YYYY.
<?php
$datum = "2021-03-12";
echo $datum . "<br>";
echo preg_replace("/(2021)-(03)-(12)/", "$3. $2. $1", $datum);
?>
Zgornji primer deluje, vendar je zelo specifičen (ujemajo se samo točno določene vrednosti).
Bolj splošen zapis uporabimo z razredi znakov in števniki:
<?php
echo preg_replace("/([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})/", "$3. $2. $1", $datum);
?>
() ustvarijo skupine.$1, $2, $3 dostopamo do ujemajočih delov.