2009-02-01 74 views
11

He tenido la necesidad de usar expresiones regulares solo unas pocas veces en el trabajo que he hecho. Sin embargo, en esas pocas ocasiones descubrí una forma de expresión muy poderosa que me permitiría hacer algunas cosas extremadamente útiles.Compilador de expresiones regulares

El problema es que el lenguaje utilizado para las expresiones regulares es incorrecto - punto.

Es un error desde un punto de vista psicológico: el uso de símbolos desencarnados proporciona una referencia útil solo para aquellos con memoria eidética. Si bien las reglas sintácticas están claramente establecidas, según mi experiencia y lo que he aprendido de otros, desarrollar una expresión regular que funcione con éxito puede resultar una tarea difícil en todas las situaciones excepto en las más triviales. Esto es comprensible ya que es un análogo simbólico para la teoría de conjuntos, lo cual es algo bastante complicado.

Una de las cosas que puede resultar difícil es disolver la expresión en la que está trabajando en sus partes discretas. Debido a la naturaleza del lenguaje, es posible leer una expresión regular de múltiples maneras si no comprende su objetivo principal, por lo que es complicado interpretar las expresiones regulares de otras personas. En el estudio del lenguaje natural, creo que esto se llama pragmática.

La pregunta que me gustaría hacer es: ¿existe algo así como un compilador de expresiones regulares? ¿O se puede incluso construir?

Podría ser posible considerar las expresiones regulares, desde un punto de vista metafórico, como lenguaje ensamblador: existen algunas similitudes. ¿Se podría diseñar un compilador que pudiera convertir un lenguaje más natural, un lenguaje superior, en expresiones regulares? Luego, en mi código, podría definir mis expresiones regulares utilizando el lenguaje de nivel superior en un archivo de encabezado y hacer referencia a ellos cuando sea necesario utilizando una referencia simbólica. Yo y otros podríamos referirnos desde mi código al archivo de encabezado y apreciar más fácilmente lo que estoy tratando de lograr con mis expresiones regulares.

Sé que se puede hacer desde un punto de vista lógico; de lo contrario, las computadoras no serían posibles, pero si ha leído hasta aquí, ¿consideraría invertir el tiempo en realizarlo?

+4

Encuentro expresiones regulares bastante fáciles de leer. –

+1

Creo que la ambigüedad de un lenguaje natural podría aumentar las complicaciones en lugar de aliviarlas. Regex parece desalentador desde el principio, especialmente cosas como el retroceso y los operadores no codiciosos. Sin embargo, después de haber vuelto a aprender regex recientemente, me parece una noche de intenso estudio para obtener la mayor parte de ella. Sin embargo, estoy seguro de que alguien con más experiencia podría fácilmente regex me. Como todo lo que vale la pena saber, se reduce a la práctica y la persistencia. –

+0

La respuesta de Andrea Ambu es de gran ayuda para cualquiera que tenga problemas con la expresión regular. Es lo que quise decir, pero realmente esperaba que pudiera haber una biblioteca de macros o similar para varios lenguajes de programación que pudieran definir la búsqueda textual con una sintaxis combinatoria, etc. Las personas tienen diferentes modelos mentales, y algunos programadores, yo mismo incluido, es virtualmente imposible trabajar con expresiones regulares, aunque hay terceros disponibles a un bajo costo para escribirlos. Si trabaja regularmente, es más fácil, pero cuando es solo un proyecto ocasional, es difícil. –

Respuesta

5

Nunca me encontré con algo así. Y no creo que algo así sea útil.

Ese lenguaje de alto nivel sería muy detallado y supongo que necesitaría unas declaraciones bastante largas para llegar a una expresión regular de complejidad promedio.

Tal vez simplemente no has estado usando expresiones regulares con la suficiente frecuencia. Créame, mi memoria está lejos de ser eidética (o incluso buena), pero rara vez tengo problemas para crear expresiones regulares o entender las de mis compañeros de trabajo.

2

Una forma de evitar este problema es mediante el uso de programas como QuickREx, que muestra cómo funciona la expresión regular en múltiples datos de prueba (con iluminaciones). Podrías guardar datos de texto en un archivo cerca de tu expresión regular y luego cuando quieras cambiarlo, entenderlo o arreglarlo, lo que sería mucho más fácil.

0

¿Ha considerado utilizar un generador de analizador (también conocido como compilador de compilador) como ANTLR?

ANTLR también tiene algún tipo de IDE (ANTLR Works) donde puede visualizar/depurar analizadores.

Por otro lado, un generador de analizador no es algo que arrojar a su aplicación en unos pocos segundos, como una expresión regular, y también sería una exageración total para algo como verificar el formato de la dirección de correo electrónico.

También para situaciones simples esto sería una exageración total y tal vez una mejor manera es solo escribir comentarios para su expresión regular explicando lo que hace.

5

¿Qué hay de escribirlos con Regex Buddy y pegar la descripción que genera como comentario en su código?

+0

+1: regex es extremadamente difícil de leer, pero este es un problema de herramientas, no un problema de idioma –

10

1) Perl permite que el /x cambie las expresiones regulares para permitir que los comentarios y los espacios en blanco se incluyan dentro de la misma regex. Esto hace posible extender una expresión regular compleja en varias líneas, usando sangrías para indicar la estructura del bloque.

2) Si no le gustan los símbolos que se asemejan al ruido de línea, no es demasiado difícil escribir sus propias funciones que crean expresiones regulares. P.ej. en Perl:

sub at_start { '^'; } 
sub at_end { '$'; } 
sub any { "."; } 
sub zero_or_more { "(?:$_[0])*"; } 
sub one_or_more { "(?:$_[0])+"; } 
sub optional { "(?:$_[0])?"; } 
sub remember { "($_[0])"; } 
sub one_of { "(?:" . join("|", @_) . ")"; } 
sub in_charset { "[$_[0]]"; }  # I know it's broken for ']'... 
sub not_in_charset { "[^$_[0]]"; } # I know it's broken for ']'... 

Entonces, p. una expresión regular para que coincida con una cadena entre comillas (/^"(?:[^\\"]|\\.)*"/) se convierte en:

at_start . 
'"' . 
zero_or_more(
    one_of(
     not_in_charset('\\\\"'), # Yuck, 2 levels of escaping required 
     '\\\\' . any 
    ) 
) . 
'"' 

Utilizando esta estrategia de "funciones de fomento de la cadena" se presta para expresar materiales de construcción útiles como funciones (por ejemplo, la expresión regular anterior podría ser almacenado en una función llamada quoted_string() , es posible que tenga otras funciones para hacer coincidir de manera confiable cualquier valor numérico, una dirección de correo electrónico, etc.).

3

Hay formas de hacer que los RE en su forma habitual sean más legibles (como la sintaxis de perl /x) y varios lenguajes mucho más prolijos para expresarlos. Veo:

Tomo nota, sin embargo, que no parece una gran cantidad de veteranos como a ellos.

No existe una razón fundamental por la que no se pueda escribir un compilador para un lenguaje de RE de gran tamaño que se oriente a uno compacto, pero no veo ninguna gran ventaja en él. Si te gusta la forma prolija, solo úsala.

5

Expresiones regulares (bueno, expresiones regulares "reales", ninguna de esas cosas modernas;) son máquinas de estado finito. Por lo tanto, crea una sintaxis que describe expresiones regulares en términos de estados, bordes, entrada y posiblemente etiquetas de salida. El fsmtools de AT & T es compatible con algo así, pero están lejos de ser una herramienta lista para el uso diario.

El lenguaje en XFST, el kit de herramientas de estado finito Xerox, también es más detallado.

Aparte de eso, diría que si su expresión regular se vuelve demasiado compleja, debería pasar a algo con más poder expresivo.

3

El "modelo de contenido" de XML Schema es un ejemplo de lo que desea.

c(a|d)+r 

se puede expresar como un modelo de contenido en el esquema XML como:

<sequence> 
<element name="c" type="xs:string"/> 
<choice minOccurs="1" maxOccurs="unbounded"> 
    <element name="a" type="xs:string"/> 
    <element name="d" type="xs:string"/>  
</choice> 
<element name="r" type="xs:string"/> 
<sequence> 

Relax NG tiene otra manera de expresar la misma idea.No tiene que ser un formato XML en sí mismo (Relax NG también tiene una sintaxis equivalente no XML).

La legibilidad de la expresión regular se reduce por todos los escapes necesarios, y un formato como el anterior reduce la necesidad de eso. La legibilidad de expresiones regulares también se reduce cuando la expresión regular se vuelve compleja, porque no hay una forma sistemática de componer expresiones regulares más grandes de las más pequeñas (aunque puede concatenar cadenas). La modularidad generalmente ayuda. Pero para mí, la sintaxis más corta es tremendamente más fácil de leer (a menudo convierto modelos de contenido XML Schema en expresiones regulares para ayudarme a trabajar con ellos).

0

Estoy de acuerdo en que la sintaxis del ruido de línea de las expresiones regulares es un gran problema, y ​​francamente no entiendo por qué tanta gente lo acepta o defiende, no es legible para el ser humano.

Algo que no menciona en su publicación, pero que es casi tan malo, es que casi todos los idiomas, editor o herramienta tienen su propia variación en la sintaxis de la expresión regular. Algunos de ellos soportan la sintaxis POSIX como se definió hace muchos años, algunos soportan la sintaxis de Perl como lo es hoy. Pero muchos tienen sus propias formas independientes de expresar cosas, o qué caracteres son "especiales" (los caracteres especiales son otro tema) y cuáles no. Lo que se escapó y lo que no. Etc. No solo es difícil leer una expresión regular escrita para un idioma o herramienta, sino que incluso si memorizas totalmente las reglas de sintaxis de tu variación favorita, pueden hacerte tropezar en un idioma diferente, donde ya no {2,3} significa lo que esperas Es realmente un desastre.

Además, creo que hay muchos no programadores que (si supieran que existía) apreciarían tener un lenguaje de patrones que pudieran usar en herramientas cotidianas como Google o Microsoft Word. Pero debería haber una sintaxis más fácil para eso.

Por lo tanto, para responder a su pregunta, a menudo he pensado en crear algún tipo de biblioteca multiplataforma, cross-language, cross-everything que le permita "traducir" desde cualquier sintaxis de expresiones regulares (ya sea Perl, o POSIX, o Emacs, etc.) en cualquier otra sintaxis de expresiones regulares. Para que no tenga que preocuparse si las expresiones regulares de Python pueden hacer un look-back negativo, o si se deben escapar los corchetes de la clase de caracteres en una expresión regular de Emacs. Podrías simplemente memorizar una sintaxis, luego hacer una llamada a función para obtener la sintaxis equivalente para lo que sea que estuvieras usando.

A partir de ahí, podría ampliarse con un nuevo lenguaje de coincidencia de patrones, que sería un poco más detallado o al menos más mnemónico. Algo para las personas que no quieren pasar media hora estudiando una expresión regular para descubrir qué es lo que hace. (Y las personas que piensan que las expresiones regulares están bien tal como son, obviamente nunca tuvieron que mantener algo que no escribieron, o comprenderían la necesidad de que otras personas puedan analizar lo que escribieron).

¿Alguna vez intentaré semejante bestia? No sé, ha estado en mi lista de cosas por hacer durante mucho tiempo, y también hay muchos proyectos más fáciles y entretenidos allí. Pero si estás contemplando algo similar, házmelo saber.

1

veo adjudicar de respuestas que tratan de resolver el problema, pero creo que tengo una respuesta para usted.

Creo que toda la sintaxis de expresiones regulares llegó desde finales de los 70. (Desearía poder encontrar algún tipo de historia sobre el tema) Recogí un libro de 1979 sobre autómatas de letras y todo el libro está lleno de pruebas matemáticas sobre cómo encontrar patrones en el texto. Conseguiré el título cuando llegue a casa y lo actualizaré aquí.

Lo que pasa es que este libro tenía algunos símbolos muy complicadas en relación con el cálculo de que si no hubiera pasado a través de una clase tal que no sería capaz de entenderlo. Apuesto, sin embargo, un matemático que regularmente usa esta sintaxis podría leerlo como una novela.

Me tomó un buen mes para tener una idea de cómo leer las expresiones regulares hasta el punto de que sólo hay que echar un vistazo a él. Para el profano, parece un asm complicado con todos estos símbolos extraños. No considero expresiones regulares como ensamblaje, es una fórmula matemática para encontrar patrones en el texto. Considerando la sintaxis y que viene originalmente del matemático, no creo que esté lejos.

Así como para un compilador dudo que pueda haber alguien así. Como dmckee mencionó "Noté, sin embargo, que a muchas manos viejas no parece gustarles". Tienes dibujos animados y comedias de situación que representan complicadas ecuaciones matemáticas en pizarras. Es una broma para mostrar lo difícil que es un tema determinado, pero en realidad cualquier persona con experiencia podría entenderlo si se les da el subtexto y un poco de entrenamiento. Regex no es difícil. Una vez que obtienes lo básico, todo se reduce al analizador en particular que usas. Es como algunos niños me dicen que no quieren aprender C/C++, ya que su más duro que Javascript incluso si no tiene la misma sintaxis. Su percepción más que dificultad.

vez que haya aprendido expresiones regulares, sus motores de los que le dan problemas. Visual Studio usa corchetes en lugar de paréntesis para agrupar. El simple biblioteca de expresiones regulares SLRE utilizo tiene un simple subconjunto vs PCRE sintaxis más completa. En este punto, comenzamos a hablar de un lenguaje más nuevo en lugar de una herramienta para el ajuste de texto.

Además, la mayoría de los programadores utilizar una única línea bajos para su expresión coincide en lugar de construir un partido lleno de expresiones regulares, porque lo que quieren es analizar algunos datos aleatorios. La coincidencia de Regex es una herramienta como Bison, yacc o ANTLR. Un analizador construido a mano siempre será mejor así que, en esencia, puede compilar su propia expresión regular, entonces, ¿por qué pasar el tiempo con 2 páginas de código para una coincidencia de expresiones regulares cuando un ciclo simple de ansi c while es más rápido?

Si desea expresiones regulares para ser más dinámico y sea legible, es mejor construir su programa de análisis en el idioma nativo de su uso para su programa. Regex está destinado a ser una herramienta y no un lenguaje completo.

Como nota al margen vistazo a una parte del código fuente de Lua entre Lua 3.0 y 3.2.2. Cambian de un analizador de Bison a uno creado a mano. Se da cuenta de cuánto más libertad tienen con eso que utilizando una herramienta para hacer su análisis de texto, especialmente con las últimas versiones de características. Por supuesto, también hace que sea más complicado un código para mantenerse actualizado. Era una elección entre la claridad de los archivos * .y la solidez de ser construido a mano.

1

Tal vez algunas herramientas de JavaScript puede ayudar:

Tristemente Yo no encuentre cualquier herramienta JS "apuntar y hacer clic" lista para usar para construir y manipular fácilmente RegEx aún.El poder de expresiones regulares (PCRE, POSIX, Python) es, que

  • son extremadamente compacto (se puede argumentar bastante demasiado compacta)
  • can be used nearly everywhere
  • siempre tienen el mismo aspecto (un tamaño incómodo única) y por lo tanto son fáciles de detectar en el código

Reinventar la rueda tal vez no es la mejor opción, y Regular Expressions are internally compiled ya para acelerar mucho las cosas. Si busca algo más elaborado, hay LEX y YACC (y sus sucesores), pero la mayoría de las veces exageran las cosas en comparación con la forma sencilla en que se puede aplicar RegEx.

siguiente podría ser útil a los demás, pero no es Linux, así que no fue capaz de probarlo:

Si encuentras otros enlaces buenos, tal vez añadir un comentario. Sé que esto es un poco de abuso para solicitar esto, pero es increíblemente útil. Gracias.

0

Si lee Dragon Book para compiladores, le indica que use regex para analizar y analizar su lenguaje de nivel superior. Entonces, las expresiones regulares parecen ser algo más bajo. Los uso muy a menudo en mis tareas de trabajo diarias para el desarrollo de frontend/backend y sí, encontré que algunos de ellos son algo crípticos. Sin embargo, eso no hace mal la expresión regular, siempre puedes escribir un nuevo idioma si no te gustan, dado que 1) tienes el tiempo 2) estás dispuesto a poner el esfuerzo adecuado 3) la fuerza es fuerte dentro de ti usted :)