Ahneuden rajoittaminen PHP:n säännöllisissä lausekkeissa
Säännölliset lausekkeet ovat oletusarvoisesti ahneita. Tämä tarkoittaa, että ne sieppaavat mahdollisimman paljon merkkejä.
Käydään tämä läpi esimerkin avulla. Oletetaan, että meillä on seuraava merkkijono:
<?php
$str = 'aeeex zzz x kkk';
?>
Oletetaan, että haluamme löytää tästä merkkijonosta osajonon
'aeeex' seuraavan mallin mukaisesti: kirjain
'a', sitten mikä tahansa merkki yksi tai useampi
kerta, sitten kirjain 'x'.
<?php
$res = preg_replace('#a.+x#', '!', $str);
?>
Odotamme, että muuttujaan tuloksena
kirjoitetaan merkkijono '! zzz x kkk'. Kuitenkin,
nin ei käy - muuttujaan päätyy merkkijono
'! kkk'.
Syynä on se, että säännöllisemme etsii kaikki
merkit kirjaimesta 'a' kirjaimeen 'x'.
Mutta merkkijonossamme on kaksi kirjainta 'x'. Ahneuden
takia käy niin, että säännöllinen lauseke etsii
viimeiseen x-kirjaimeen asti, siepaten näin
muuta kuin mitä odotimme.
Tietenkin tällainen käyttäytyminen on usein juuri sitä mitä tarvitsemme. Mutta tässä tapauksessa haluaisimme peruuttaa ahneuden ja käskeä säännöllisen lausekkeen etsimään ensimmäiseen x-kirjaimeen asti.
Ahneuden rajoittamiseksi tulee toistooperaattorin jälkeen laittaa kysymysmerkki:
<?php
$res = preg_replace('#a.+?x#', '!', $str);
?>
Ahneutta voidaan rajoittaa kaikille toistooperaattoreille,
näin: *?, ??
ja {}?.
Annettu merkkijono:
<?php
$str = 'aba accca azzza wwwwa';
?>
Kirjoita säännöllinen lauseke, joka löytää kaikki merkkijonot,
joiden reunoilla on kirjaimet 'a',
ja korvaa jokainen niistä merkillä '!'. Kirjainten
a välissä voi olla mikä tahansa merkki (paitsi
'a').