Expresiones regulares lentas.

other
06 de Noviembre del 2003
Hola. Tengo una web sobre programación en cuyos foros normalmente se postea gran cantidad de código ya sea c++, html o cualquier cosa. El problema es que debo permitir que se incluyan algunas etiquetas HTML mientras que otras debo borrarlas. Además debo utilizar la función nl2br para que el texto se muestre correctamente.
He definido una etiqueta llamada code (<code>) dentro de la cual las etiquetas HTML no se eliminan pero tampoco se interpretan, sino que se muestran tal cual. Para ello utilizo expresiones regulares. El problema es que cuando los textos son relativamente largos, la página tarda 15 o 20 segundos en mostrarse. Os paso el código problemático:

function prepara_texto($datos)
{

//Primero buscamos la etiqueta especial <code> y </code> y entre ellas cambiamos los < y > por &lt; y &gt;
while ( eregi ( "(.*)(<code>)(.*)(</code>)(.*)" ,$datos,$datos_1))
{
$datos_1[3] = strtr(
$datos_1[3],
array(
"<" => "&lt;" ,
">" => "&gt;"
)
);
$datos=$datos_1[1]."<&coded%>".$datos_1[3]."</&coded%>".$datos_1[5];
}
//Ya tenemos salvados los code y la nueva etiqueta <&coded%> y </&coded%>
//Ahora reemplazamos << y >> por &lt; y &gt;
$datos = strtr($datos,
array("<<" => "&lt;" ,
">>" => "&gt;" )
);
//Ahora eliminamos las cadenas que no nos interesan y salvamos las demás. Además cambiamos los intros por <BR>
$datos =nl2br(strip_tags($datos, '><i><u><b><a><&coded%><LI><UL><OL><DL><DH><DD><DT><H1><H2><H3><H4><H5><H6><')) ;
//Ahora hacemos que los hipervinculos salten fuera
$datos =strtr($datos,array("HREF=" => "target=_blank HREF=" ,
"Href=" => "target=_blank HREF=" ,
"href=" => "target=_blank HREF=" ,
"HRef=" => "target=_blank HREF=") );
//Ahora cambiamos la etiqueta coded por un font y salvamos los espacions
$datos =strtr($datos,
array("<&coded%>" => "<font class=CodedFont>" ,
"</&coded%>" => "</font>" ,
" " => "&nbsp;"
)
);

return $datos;
}

¿¿Alguna sugerencia??

other
06 de Noviembre del 2003
He olvidado decir que lo que causa el problema es el primer while.
¿Alquien sabe de algún sitio donde tengan hecho algo similar?
¿Saben si sepodría hacer un programa compilado con algún otro lenguaje que fuese más rápido, y leugo ejecutarlo desde PHP y obtener la salida? ¿Seria globalmente más rápido, aunque hubiese que trabajar incluso con ficheros de por medio para enviar la entrada al programa?
Gracias

other
06 de Noviembre del 2003
Ya lo he conseguido.
Lo he hecho con el mismo algoritmo, pero cambiando la función eregi por una de perl:

function prepara_texto($datos)
{

//Primero buscamos la etiqueta especial <code> y </code> y entre ellas cambiamos los < y > por &lt; y &gt;
while(preg_match_all ("|(.*)(<CODE>)(.*)(</CODE>)(.*)|is", $datos, $matches))
{
$matches[3][0]=strtr(
$matches[3][0],
array(
"<" => "&lt;" ,
">" => "&gt;"
)
);
$datos=$matches[1][0]."<&coded%>".$matches[3][0]."</&coded%>".$matches[5][0];
}

//Ya tenemos salvados los code y la nueva etiqueta <&coded%> y </&coded%>
//Ahora reemplazamos << y >> por &lt; y &gt;
$datos = strtr($datos,
array("<<" => "&lt;" ,
">>" => "&gt;" )
);
//Ahora eliminamos las cadenas que no nos interesan y salvamos las demás. Además cambiamos los intros por <BR>
$datos =nl2br(strip_tags($datos, '><i><u><b><a><&coded%><LI><UL><OL><DL><DH><DD><DT><H1><H2><H3><H4><H5><H6><')) ;
//Ahora hacemos que los hipervinculos salten fuera
$datos =strtr($datos,array("HREF=" => "target=_blank HREF=" ,
"Href=" => "target=_blank HREF=" ,
"href=" => "target=_blank HREF=" ,
"HRef=" => "target=_blank HREF=") );
//Ahora cambiamos la etiqueta coded por un font y salvamos los espacions
$datos =strtr($datos,
array("<&coded%>" => "<font class=CodedFont>" ,
"</&coded%>" => "</font>" ,
" " => "&nbsp;"
)
);

return $datos;
}

balvo
06 de Noviembre del 2003
la funcion eregi_replace(,,) te puede servir, no me acuerdo exactamente, pero toma dos argumentos: un patron y una cadena (ambos strings), en que orden no me acuerdo, pero es bastante facil de usar, de rapidez..... hummm... no se
busca en el manual de php