2008-10-23 19 views

Respuesta

9

Cuando necesite analizar una expresión que no esté definida por regular language.

+1

Bueno, hay extensiones Perl. Sacan expresiones regulares de la clase de idiomas regulares. – ADEpt

+0

Me gustaría ver un enfoque más pragmático, pero esta es la respuesta correcta hasta ahora. – Null303

+0

Siguiendo el enlace ... "se puede describir mediante una expresión regular formal". Tu definición es circular. : P – BoltBait

-1

Mi límite es un patrón de expresión que es aproximadamente 30-50 caracteres (varía dependiendo de la cantidad de texto es fija y cuánto es comandos de expresiones regulares)

0

un problema es demasiado complejo para expresiones regulares cuando restricciones del problema puede cambiar después de que se escribe la solución. Entonces, en su ejemplo, ¿cómo puede estar seguro de que una dirección de correo electrónico es válida cuando no tiene acceso al sistema de correo de destino para verificar que la dirección de correo electrónico esté conectada a un usuario válido? No puedes.

+0

Validar si un correo electrónico cumple o no con la norma RFC 2822 no es el mismo problema para determinar si esa dirección de correo electrónico está realmente en uso. – mmcdole

+0

Es cierto. Pero la pregunta original fue "¿Cuándo es un problema demasiado complejo para una expresión regular?" y di un ejemplo de un problema que es demasiado complejo para expresiones regulares. Entonces, a quien me votó negativamente, "¡eres un lamer!" : P – BoltBait

3

Resuelve el problema con una expresión regular, y entréguesela a otra persona con experiencia en expresiones regulares. Si no pueden decirte lo que hace (o al menos dicen con confianza que entienden) en unos 10 minutos, es demasiado complejo.

4

He aquí una buena cita de Raymond Chen:

No haga expresiones regulares hacen lo que no es bueno. Si desea hacer coincidir un patrón simple, haga coincidir un patrón simple. Si quieres hacer matemáticas, entonces haz matemáticas. Como comentarista Maurits puso, "El truco es no gastar tiempo el desarrollo de una combinación de martillo/destornillador, pero sólo tiene que utilizar un martillo y un destornillador

Source

3

señal segura de detener el uso de expresiones regulares se presente.: si tiene muchas llaves de agrupamiento '()' y muchas alternativas '|' entonces es una señal segura de que se intenta hacer un (complejo) parsing con expresiones regulares.

Añadir a la mezcla extensiones de Perl, referencias hacia atrás, etc y pronto usted tiene usted mismo un analizador que es difícil de leer, dura para modificar, y difícil de razonar acerca de sus propiedades (por ejemplo, hay una entrada en la que este analizador funcionará en un tiempo exponencial).

Este es un momento para detener la regexing y comenzar el análisis (con analizador sintáctico hecho a mano generadores o combinadores de analizador).

2

Junto con expresiones tremendas, existen limitaciones principales en las palabras, que pueden manejarse con la expresión regular Por ejemplo, no puede escribir la expresión regular para la palabra descrita por n caracteres a, luego n caracteres b, donde n puede ser cualquiera, más estrictamente alt text.

En diferentes idiomas, regexp es una extensión de Regular language, pero el tiempo de análisis puede ser extremadamente grande y este código no es portátil.

+0

Estoy muy interesado en las Matemáticas detrás del tema. Por favor, puedes decir dónde obtuviste tu expresión. Es difícil para mí entender cosas sin Matemáticas. –

+0

No puedo entender el significado real de las limitaciones aquí. No puede hacer condiciones como: 'si (n = k) imprime "a" siete veces; ¿No puedes escribir una oración if en expresiones regulares? –

+0

Si ha entendido bien, no puede hacer una implicción en Regex (o digamos que no es su propósito principal). Por lo tanto, no puede hacer cosas como la coincidencia de paréntesis o "escribir expresión regular para una palabra descrita por n caracteres a". Regex solo se trata de emparejar. –

14

Las expresiones regulares son una representación textual de finite-state automata. Es decir, están limitados a una coincidencia no recursiva. Esto significa que no puede tener ningún concepto de "alcance" o "subcorrespondencia" en su expresión regular. Considere el siguiente problema:

(())() 

¿Están todas las paridas abiertas combinadas con una paridad cercana?

Obviamente, cuando vemos esto como seres humanos, podemos ver fácilmente que la respuesta es "sí". Sin embargo, ninguna expresión regular podrá responder de manera confiable a esta pregunta. Para hacer este tipo de procesamiento, necesitará un pushdown automaton completo (como un DFA con una pila). Esto se encuentra más comúnmente bajo la apariencia de un analizador sintáctico, como los generados por ANTLR o Bison.

+0

.NET regex flavor se amplía para poder resolver el problema de coincidencia de paréntesis (http://msdn.microsoft.com/en-us/library/bs2twtah.aspx). Parece que hicieron trampa en Microsoft.:) –

1

Siempre que no se puede estar seguro de que realmente resuelve el problema, por ejemplo:

  • análisis de HTML
  • validación de correo electrónico
  • analizadores de lenguajes

Especialmente por lo que cuando ya existen herramientas que resuelven el problema de una manera totalmente comprensible.

Regex se puede utilizar en los dominios que mencioné, pero solo como un subconjunto de todo el problema y para casos específicos y simples.

Esto va más allá de las limitaciones técnicas de expresiones regulares (idiomas regulares + extensiones), el límite de facilidad de mantenimiento y legibilidad se supera mucho antes que el límite técnico en la mayoría de los casos.

-1

Esto puede sonar estúpido, pero a menudo me lamenta no poder hacer consultas de tipo de base de datos con la expresión regular. Ahora especialmente más que antes, porque estoy ingresando esos tipos de cadenas de búsqueda todo el tiempo en los motores de búsqueda. es muy difícil, si no imposible, buscar +complex AND +"regular expression"

Por ejemplo, ¿cómo busco en emacs los comandos que tienen tanto Buffer como Window en su nombre? Necesito buscar por separado .*Buffer.*Window and .*Window.*Buffer

7

Lo que se reduce a usar el sentido común. Si lo que intentas emparejar se convierte en una expresión regular de monstruo inmanejable, entonces debes dividirlo en expresiones pequeñas y lógicas o tienes que volver a pensar en tu solución.

Tome las direcciones de correo electrónico (según su ejemplo). Esta expresión regular sencilla (tomado de expresiones regulares de amigos) se corresponde con el 99% de todos los correos electrónicos por ahí:

\b[A-Z0-9._%+-][email protected][A-Z0-9.-]+\.[A-Z]{2,4}\b 

Es corto y al grano y que rara vez se tenga problemas con él. Sin embargo, como señala el autor de RegEx Buddy, si su dirección de correo electrónico está en el raro ".museum" de dominio de alto nivel, no será aceptada.

Para que coincida con todas las direcciones de correo electrónico, debe cumplir con el estándar conocido como RFC 2822. Describe la multitud de formas en que se pueden formatear las direcciones de correo electrónico y es extremadamente complejo.

Aquí es una expresión regular muestra trataban de dar cumplimiento a la RFC 2822:

(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|" 
(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x 
0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9] 
(?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.) 
{3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08 
\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\]) 

Obviamente, esto se convierte en un problema de los rendimientos decrecientes. Es mejor utilizar la implementación de fácil mantenimiento que coincide con el 99% de las direcciones de correo electrónico frente al monstruoso que acepta el 99,9% de ellas.

Las expresiones regulares son una gran herramienta para tener en su caja de herramientas de programadores, pero no son una solución para todos sus problemas de análisis. Si encuentra que su solución RegEx comienza a ser extremadamente compleja, debe intentar dividirla lógicamente en expresiones regulares más pequeñas para que coincidan con partes de su texto o debe comenzar a buscar otros métodos para resolver su problema. Del mismo modo, simplemente hay problemas que las expresiones regulares, debido a su naturaleza, no pueden resolver (como dijo un afiche, no se adhiere al Regular Language).

+0

¿Estás seguro de que no quieres decir esto en el primer ejemplo? \ b [A-Z0-9 ._% + -] + @ [A-Z0-9 -] + \. [AZ] {2,4} \ b – Keng

+0

¿Puedes resaltar la diferencia entre lo que acabas de publicar y ¿lo que tengo? No lo veo – mmcdole

+0

La diferencia es el punto en el segundo conjunto de corchetes (el de Simucal coincidiría con cualquier carácter [además de la nueva línea según los argumentos] antes del punto literal), y ninguno de los dos es realmente bueno (no permiten subdominios, por ejemplo) . – eyelidlessness

13

Un par de cosas a tener en cuenta:

  1. que comienza y termina la detección de etiquetas - emparejamiento emparejado
  2. recursividad
  3. necesidad de ir hacia atrás (aunque se puede invertir la secuencia, pero eso es un truco)

regexes, tanto como los amo, no son buenos en esas tres cosas. Y recuerde, ¡manténgalo simple! Si está intentando crear una expresión regular que hace "todo", entonces you're probably doing it wrong.

6

Las expresiones regulares son adecuadas para tokenizar, buscar o identificar fragmentos de texto individuales, p. Ej. encontrar palabras clave, cadenas, comentarios, etc. en el código fuente.

Las expresiones regulares no son adecuadas para determinar la relación entre varios bits de texto, p. encontrar un bloque de código fuente con llaves correctamente emparejadas. Necesitas un analizador para eso. El analizador puede usar expresiones regulares para tokenizar la entrada, mientras que el analizador en sí mismo determina cómo encajan las diferentes coincidencias de expresiones regulares.

Esencialmente, vas a llegar lejos con tus expresiones regulares si empiezas a pensar en "equilibrar grupos" (función de resta de grupo de .NET) o "recursión" (Perl 5.10 y PCRE).

Cuestiones relacionadas