Omezení chamtivosti v regulárních výrazech v PHP
Regulární výrazy jsou ve výchozím nastavení chamtivé. To znamená, že zachytí maximální možný počet znaků.
Pojďme si to vysvětlit na příkladu. Předpokládejme, že máme takovýto řetězec:
<?php
$str = 'aeeex zzz x kkk';
?>
Předpokládejme, že v tomto řetězci chceme najít podřetězec
'aeeex' podle následujícího vzoru: písmeno
'a', poté jakýkoli znak jeden nebo více
krát, poté písmeno 'x'.
<?php
$res = preg_replace('#a.+x#', '!', $str);
?>
Očekávali bychom, že do proměnné se jako výsledek
zapíše řetězec '! zzz x kkk'. Avšak
tak to není - do proměnné se dostane řetězec
'! kkk'.
Všechno je to tím, že náš regulární výraz hledá všechny
znaky od písmene 'a' až po písmeno 'x'.
Ale v našem řetězci jsou dvě písmena 'x'. Kvůli
chamtivosti se stane, že regulární výraz hledá až
do posledního 'x', čímž zachytí
něco jiného, než jsme očekávali.
Samozřejmě, často je toto chování přesně to, co potřebujeme. Ale konkrétně v tomto případě bychom chtěli zrušit chamtivost a říct regulárnímu výrazu, aby hledal pouze k prvnímu 'x'.
Chcete-li omezit chamtivost, musíte za operátor opakování umístit otazník:
<?php
$res = preg_replace('#a.+?x#', '!', $str);
?>
Chamtivost lze omezit u všech operátorů
opakování, takto: *?, ??
a {}?.
Je dán řetězec:
<?php
$str = 'aba accca azzza wwwwa';
?>
Napište regulární výraz, který najde všechny řetězce
na jejichž okrajích stojí písmena 'a',
a nahradí každý z nich na '!'. Mezi
písmeny a může být jakýkoli znak (kromě
'a').