regular - regex repetitions
Regex: ¿es perezoso peor? (6)
Siempre he escrito regexias como esta
<A HREF="([^"]*)" TARGET="_blank">([^<]*)</A>
pero acabo de enterarme de esta cosa floja y de que puedo escribirlo así
<A HREF="(.*?)" TARGET="_blank">(.*?)</A>
¿Hay alguna desventaja al usar este segundo enfoque? La expresión regular es definitivamente más compacta (incluso SO lo analiza mejor).
Editar : Aquí hay dos mejores respuestas, que señalan dos diferencias importantes entre las expresiones. La respuesta de ysth apunta a una debilidad en el no codicioso / flojo, en el que el hipervínculo podría incluir otros atributos de la etiqueta A (definitivamente no es bueno). Rob Kennedy señala una debilidad en el ejemplo codicioso, en que los textos de anclaje no pueden incluir otras etiquetas (definitivamente no está bien, porque tampoco captaría todo el texto de anclaje) ... así que la respuesta es que, las expresiones regulares son lo que son, las soluciones perezosas y no perezosas que parecen iguales probablemente no son semánticamente equivalentes.
Editar : La tercera mejor respuesta es por Alan M sobre la velocidad relativa de las expresiones. Por el momento, marcaré su mejor respuesta para que la gente le de más puntos :)
"Perezoso" es la palabra incorrecta aquí. Quieres decir no codicioso en lugar de codicioso. No hay desventaja en su uso, que yo sepa. Pero en su caso especial, tampoco debería ser más eficiente.
No codicioso es mejor, ¿no es así? Funciona hacia adelante, verificando una coincidencia cada vez y deteniéndose cuando encuentra una, mientras que el cierre de kleene normal (*) funciona al revés coincidiendo con el resto de la entrada y eliminando las cosas hasta que encuentra una coincidencia.
Al final, hacen cosas diferentes, pero creo que los no codiciosos superan a los codiciosos. Tenga en cuenta que no he probado esto, pero ahora tengo curiosidad.
No se trata de mejor o peor. El término que he visto más es codicioso vs. no codicioso, pero como quiera que sea, hacen dos cosas diferentes. Desea usar el correcto para la tarea. Es decir, desactive la opción codiciosa cuando no desee capturar múltiples coincidencias en una línea.
Tenga en cuenta que sus ejemplos no son equivalentes. Su primera expresión regular no seleccionará ningún enlace que contenga otras etiquetas, como img
o b
. La segunda expresión regular lo hará, y espero que eso sea probablemente lo que querías de todos modos.
Además de la diferencia de significado, la única desventaja que puedo pensar es que el apoyo para modificadores no codiciosos no es tan frecuente como lo es la negación de clase de carácter. Es más ampliamente compatible de lo que pensaba, antes de que lo revisara, pero notablemente ausente de la lista es GNU Grep. Si los evaluadores de expresiones regulares que está utilizando lo soportan, siga adelante y úselo.
La clase de personaje complementado define más rigurosamente lo que quiere hacer coincidir, así que cuando pueda, lo usaría.
La expresión regular no codiciosa coincidirá con cosas que probablemente no desee, como por ejemplo:
<A HREF="foo" NAME="foo" TARGET="_blank">foo</A>
donde tu primero. *? partidos
foo" NAME="foo
Otra cosa a considerar es cuánto tiempo es el texto de destino, y cuánto de él va a coincidir con la subexpresión cuantificada. Por ejemplo, si intentas hacer coincidir todo el elemento <BODY> en un documento HTML grande, es posible que tengas la tentación de utilizar esta expresión regular:
/<BODY>.*?<//BODY>/is
Pero eso va a hacer un montón de trabajo innecesario, haciendo coincidir un personaje a la vez y al mismo tiempo realizando un análisis negativo antes de cada uno. Usted sabe que la etiqueta </ BODY> va a estar muy cerca del final del documento, por lo que lo más inteligente es usar un cuantificador codicioso normal; deje que absorba todo el resto del documento y luego deshaga los pocos caracteres necesarios para que coincida con la etiqueta final.
En la mayoría de los casos, no notará ninguna diferencia de velocidad entre los cuantificadores codiciosos y reacios, pero es algo a tener en cuenta. La razón principal por la que debe ser juicioso en el uso de cuantificadores reacios es la señalada por los otros: pueden hacerlo de mala gana, pero coincidirán más de lo que usted desea si eso es lo que se necesita para lograr un total partido.