Ver Mensaje Individual
  #2 (permalink)  
Antiguo 24/06/2005, 03:36
leonardop
 
Fecha de Ingreso: julio-2003
Mensajes: 165
Antigüedad: 20 años, 8 meses
Puntos: 1
Tu primer intento es bastante bueno. La razón por la que está haciendo la transformación de ese modo es que, en las expresiones regulares, caracteres como '*' y '+' son "codiciosos" por omisión. Es decir, tratan de coincidir con tantos caracteres como les sea posible.

Como ves, en tu ejemplo la expresión regular coincide con la etiqueta de apertura [codigo], luego empieza a buscar uno o más caracteres antes de encontrarse con el cierre [/codigo]. La expresión pasa por el primer cierre, pero al ser "codicioso" el segmento (.|\s)+ continúa su trabajo en caso de que encuentre otro cierre más, y así poder coincidir con tantos caracteres como pueda. Efectivamente, encuentra la cadena '[/codigo]' otra vez, así que coincide con toda la cadena completa, y la transformación culmina del modo que observas.

Una solución es usar el caracter '?', el cual usado después de '+' o '*' le quita su naturaleza codiciosa al operador, de modo que la expresión trata de coincidir con la menor cantidad de caracteres posible.

Considera por ejemplo:

Código PHP:
function elCode ($codigo) {
    
$hay preg_match_all ('/\\[(codigo)\\]((.|\s)+?)\\[\\/\\1\\]/i'$codigo$resultado);

    if (! 
$hay)
        return 
$codigo;

    for(
$i 0$i count ($resultado[1]); $i++) {  // por cada code
        
$HTML '<div class="code">' nl2br($resultado[2][$i]) . '</div>';
        
$codigo str_replace ($resultado[0][$i], $HTML ,$codigo);
    }
    return 
$codigo;

Disculpa que hice algunos cambios de estilo :), en realidad el detalle importante es que la expresión (.|\s)+ tiene un signo '?' al final para que no coincida "codiciosamente".