2008-12-10 6 views
14

Parece que la opción de usar el análisis sintáctico de cadenas frente a las expresiones regulares aparece de forma regular en cualquier momento que surge una situación en la que necesito parte de una cadena, información sobre dicha cadena, etc.¿Cuándo es mejor usar expresiones regulares sobre la división de cadenas básica/subcadena?

La razón por la que se trata de que estamos evaluando la acción de un encabezado de soap, después de que se ha analizado en algo manejable a través del objeto OperationContext para WCF y luego tomando decisiones al respecto. En este momento, la solución simple parece ser una subcadena básica para mantener la implementación simple, pero una parte de mí se pregunta si RegEx sería mejor o más robusto. La otra parte de mí se pregunta si sería como usar una escopeta para matar una mosca en nuestro escenario particular.

Así que tengo que preguntar, ¿cuál es el umbral típico que la gente usa cuando se trata de decidir utilizar RegEx sobre el análisis de cadenas típicas. Tenga en cuenta que no soy muy fuerte en expresiones regulares, y debido a esto, trato de alejarme a menos que sea absolutamente vital evitar introducir más complicaciones de las que necesito.

Si no puede decirlo por mi elección de abreviaturas, esto está en .NET land (C#), pero creo que no tiene mucha relación con la pregunta.


EDITAR: Parece como por mi encanto típico Raybell, he sido demasiado prolijos o engañosa en mi pregunta. Quiero pedir disculpas. Estaba dando algunos antecedentes para ayudar a dar pistas sobre lo que estaba haciendo, no engañar a la gente.

Básicamente estoy buscando una guía sobre cuándo usar la subcadena, y sus variaciones, sobre las expresiones regulares y viceversa. Y aunque algunas de las respuestas pueden haber pasado por alto esto (y nuevamente, mi culpa), realmente las aprecié y voté como correspondía.

Espero que esto ayude a algunos.

+0

A menos que diga lo contrario, creo que esta pregunta responde a la misma pregunta que está formulando: http://stackoverflow.com/questions/56342/whats-the-best-way-of-parsing-strings – EBGreen

+0

Está cerca de lo que estaba buscando Busqué, pero nunca encontré nada que pensé que fuera adecuado, aunque parece tan cercano como cualquier cosa. –

+0

Supongo que lo que estoy preguntando es si esa pregunta te da la información que estabas buscando. – EBGreen

Respuesta

21

Mi directriz principal es usar expresiones regulares para el código desechable, y para la validación de entrada de usuario. O cuando estoy tratando de encontrar un patrón específico dentro de un gran globo de texto. Para la mayoría de los demás propósitos, escribiré una gramática e implementaré un analizador simple.

Una directriz importante (que es realmente difícil de eludir, aunque veo que la gente intenta todo el tiempo) es usar siempre un analizador en los casos en que la gramática del idioma de destino sea recursiva.

Por ejemplo, considere un pequeño "lenguaje de expresiones" para evaluar expresiones aritméticas entre paréntesis. Los ejemplos de "programas" en este lenguaje se vería así:

1 + 2 
5 * (10 - 6) 
((1 + 1)/(2 + 2))/3 

Una gramática es fácil de escribir, y se ve algo como esto:

DIGIT := ["0"-"9"] 
NUMBER := (DIGIT)+ 
OPERATOR := ("+" | "-" | "*" | "/") 
EXPRESSION := (NUMBER | GROUP) (OPERATOR EXPRESSION)? 
GROUP := "(" EXPRESSION ")" 

Con que la gramática, se puede construir un descenso recursivo analizador en un santiamén.

Una expresión regular equivalente es REALMENTE difícil de escribir, porque las expresiones regulares no suelen tener un soporte muy bueno para la recursividad.

Otro buen ejemplo es la ingestión de JSON. He visto a gente tratar de consumir JSON con expresiones regulares, y es INSANE.Los objetos JSON son recursivos, por lo que solo piden gramáticas regulares y analizadores sintácticos de descenso recursivo.


Hmmmmmmm ... Al ver las respuestas de otras personas, creo que puedo haber respondido la pregunta incorrecta.

Lo interpreté como "¿cuándo debería usar una expresión regular simple, en lugar de un analizador en toda regla?" mientras que la mayoría de la gente parece haber interpretado la pregunta como "¿cuándo deberías lanzar tu propio esquema de validación ad hoc de carácter por personaje, en vez de usar una expresión regular?"

Dada esa interpretación, mi respuesta es: nunca.


Okay .... one more edit.

Voy a ser un poco más indulgente con el esquema de rollo propio. Simplemente ... no lo llame "análisis sintáctico": o)

Creo que una buena regla general es que solo debe usar primitivas de coincidencia de cadenas si puede implementar TODA su lógica con un solo predicado. De esta manera:

if (str.equals("DooWahDiddy")) // No problemo. 

if (str.contains("destroy the earth")) // Okay. 

if (str.indexOf(";") < str.length/2) // Not bad. 

Una vez que sus condiciones contienen múltiples predicados, entonces usted ha comenzado inventar su propio idioma validación cadena ad hoc y se debe probablemente al hombre y estudiar algunas expresiones regulares.

if (str.startsWith("I") && str.endsWith("Widget") && 
    (!str.contains("Monkey") || !str.contains("Pox"))) // Madness. 

Las expresiones regulares realmente no son tan difíciles de aprender. En comparación con un lenguaje de funciones completas como C# con docenas de palabras clave, tipos primitivos y operadores, y una biblioteca estándar con miles de clases, las expresiones regulares son absolutamente simples. La mayoría de las implementaciones de expresiones regulares admiten alrededor de una docena de operaciones (dar o recibir).

Aquí es una gran referencia:

http://www.regular-expressions.info/

PD: Como beneficio adicional, si alguna vez qué desea aprender acerca de cómo escribir sus propios programas de análisis (con lex/yacc, antlr, JavaCC, u otro herramientas similares), aprender expresiones regulares es una gran preparación, porque las herramientas generadoras de analizadores usan muchos de los mismos principios.

+0

Tenía la impresión de que el "análisis básico de cadenas" implicaba cosas como llamadas .indexOf() y 2 .subString() o algo similar. Para cosas tan complejas como esta, definitivamente iría con la ruta del analizador. –

+0

No estoy necesariamente haciendo una validación de carácter por carácter. Simplemente estoy queriendo agarrar una subcadena, y luego actuar sobre eso. En general, estoy buscando cuál es la guía general para elegir substring'ing sobre regex. Creo que no he sido muy claro en mi pregunta ... –

+0

Por lo tanto, de todos ellos, seguido con su edición reciente, esto es básicamente lo que estaba buscando. ¡Gracias! –

6

La expresión regular puede ser

  • más fácil de entender
  • expresar más claramente la intención
  • mucho más corto
  • más fácil cambiar/adaptar

En algunas situaciones todos aquellos se obtendrían ventajas mediante el uso de expresiones regulares, en otros solo se lograron algunos (la expresión regular no es realmente fácil de entender para e xample) y en otras situaciones, la expresión regular es más difícil de entender, ofusca la intención, más larga y difícil de cambiar.

Cuantas más (y posiblemente otras) ventajas obtengo de la expresión regular, más posibilidades tengo de usarlas.

Regla de oro: si la comprensión de la expresión regular llevaría minutos para alguien que esté familiarizado con las expresiones regulares, entonces no desea usarla (a menos que el código "normal" sea aún más enrevesado ;-).

Hm ... aún no hay una regla general, lo siento.

1

Cuando la transformación requerida no es básica, pero todavía es conceptualmente simple.

ninguna razón para sacar expresión regular, si está haciendo un reemplazo de cadena recta, por ejemplo ... es más fácil de usar sólo el String.Replace

por el contrario, una regla compleja con muchas o condicionales casos especiales que se necesitarían más de 50 caracteres de expresiones regulares puede ser una pesadilla para mantener más adelante si no explícitamente escribirlo

0

yo siempre utilizar una expresión regular a menos que sea algo muy simples, tales como dividir una coma -cadena separada. Si creo que existe la posibilidad de que algún día las cadenas se vuelvan más complicadas, probablemente comenzaré con una expresión regular.

No me suscribo a la opinión de que las expresiones regulares son difíciles o complicadas. Es una herramienta que todo desarrollador debe aprender y aprender bien. Tienen una gran variedad de usos, y una vez aprendido, este es exactamente el tipo de cosas de las que nunca más tendrás que preocuparte.

Regexes rara vez son exagerados: si la coincidencia es simple, también lo es la expresión regular.

+0

Incluso algo que un analizador de CSV es engañosamente complejo de escribir, dadas las reglas de cotización. (Los caracteres y comas de Newline pueden aparecer dentro de un solo campo, siempre que el campo esté entre comillas). ¡No subestime el humilde CSV! Incluso con una expresión regular, es realmente difícil de analizar correctamente: o) – benjismith

+0

Dije una cadena separada por comas, no un archivo CSV. Nunca recomendaría nada más que una biblioteca o analizador dedicado para un archivo CSV. De hecho, he escrito un analizador C++ CSV que hizo frente a todo lo anterior, pero mi padre era un DFA – Draemon

2

[W] stamos evaluar la acción de un encabezado de jabón y tomar decisiones en ese

Nunca utilice expresiones regulares o cadena básica de análisis para procesar XML. Todos los lenguajes de uso común en este momento tienen soporte XML perfectamente bueno. XML es un estándar engañosamente complejo y es poco probable que su código sea correcto en el sentido de que analizará correctamente todas las entradas XML bien formadas, e incluso si lo hace, está perdiendo el tiempo porque (como se acaba de mencionar) cada idioma en el uso común tiene soporte XML. No es profesional usar expresiones regulares para analizar XML.

Para responder a su pregunta, en general, el uso de expresiones regulares debe minimizarse ya que no son muy legibles. A menudo puede combinar el análisis sintáctico de cadenas y las expresiones regulares (quizás en un ciclo) para crear una solución mucho más simple que las expresiones regulares solamente.

+0

Estaba un poco confundido aquí, y me disculpo. La realidad es que, para cuando nos estamos enterando de esto, lo hemos analizado a través de OperationContext. ¡Te agradezco por señalar esto! –

+0

He actualizado la pregunta un poco para mejorar la claridad, pero me parece que todavía es confuso. Lo volveré a programar un poco más cuando tenga más tiempo. Me disculpo. –

+0

Lo siento. Probablemente podría haber sido más educado, pero esto es algo que me vuelve loco cada vez que lo veo. – Tmdean

1

Estoy de acuerdo con lo que dijo el benjismith, pero quiero elaborarlo un poco. Para sintaxis muy simples, el análisis básico de cadenas puede funcionar bien, pero también lo pueden hacer los regexes. Yo no los llamaría excesivos. Si funciona, funciona: ve con lo que encuentres más simple. Y para el análisis de cadenas de moderado a intermedio, una expresión regular suele ser el camino a seguir.

Tan pronto como empiece a encontrar la necesidad de definir una gramática, es decir, un complejo análisis de cadenas, vuelva a utilizar algún tipo de máquina de estados finitos o los "me gusta" tan rápido como pueda. Regexes simplemente no escala bien, para usar el término libremente. Se vuelven complejos, difíciles de interpretar e incluso incapaces.

He visto al menos un proyecto donde el uso de expresiones regulares siguió creciendo y creciendo y pronto tuvieron problemas para insertar nuevas funcionalidades. Cuando finalmente llegó el momento de hacer una nueva versión principal, descartaron todas las expresiones regulares y siguieron la ruta de un analizador gramatical.

+0

En un caso aquí, he visto una expresión regular en realidad de forma recursiva con solo la entrada correcta. CPUs del servidor enriquecidas y DOS permitidos. No hace falta decir que soy bastante cauteloso cuando los veo aparecer como una solución por esta misma razón. –

0

Creo que la forma más fácil de saber cuándo usar expresiones regulares y cuándo no, es cuando su búsqueda requiere una instrucción IF/THEN o cualquier cosa que se parezca a esta o aquella lógica, entonces necesita algo mejor que una simple cadena comparación que es donde regex brilla.

Cuestiones relacionadas