El otro día comentaba lo poderosas que son las expresiones regulares y adelantaba el concepto de ‘codicioso’

Por defecto, las expresiones regulares son ‘codiciosas’ o greedy, esto es, intentan encontrar el resultado con mayor número de caracteres, cosa que no siempre es bueno.

Por ejemplo, si tenemos la cadena:

$text = "<b>Esto esta en negrita</b> Pero esto no <b> y esto sí</b>";

y usamos el patrón:

$pattern = "/<b>(.*)</b>/i";

preg_replace capturará «Esto esta en negrita</b> Pero esto no <b> y esto sí«.
Si eso es lo que querías, estupendo, pero me da a mí, que si estás leyendo esta página, lo que realmente querías capturar es «Esto esta en negrita»
Para hacer que la captura no sea codiciosa y que el motor se conforme con el primer par «<b>» y «</b>» debemos usar (.*?) o indicar el modificador U:

$pattern = "/<b>(.*)</b>/iU";

que es lo mismo que:

$pattern = "/<b>(.*?)</b>/i";

Aquí os dejo el link a un tutorial muy completo:

Tutorial php y expresiones regulares

Suerte!