2010-08-09 6 views
13

Estoy tratando de crear una función de Python que pueda tomar una descripción simple en inglés de una expresión regular y devolver la expresión regular a la persona que llama.¿hay necesidad de una forma más declarativa de expresar expresiones regulares? :)

Actualmente estoy pensando en la descripción en formato YAML. Por lo tanto, podemos almacenar la descripción como una variable de cadena sin procesar, que se pasa a esta otra función y la salida de esa función se pasa luego al módulo 're'. Lo que sigue es un ejemplo bastante simple:

# a(b|c)d+e* 
re1 = """ 
- literal: 'a' 
- one_of: 'b,c' 
- one_or_more_of: 'd' 
- zero_or_more_of: 'e' 
""" 
myre = re.compile(getRegex(re1)) 
myre.search(...) 

etc.

¿Alguien piensa que algo de este tipo sería de uso más amplio? ¿Conoces paquetes existentes que pueden hacerlo? ¿Cuáles son las limitaciones que ve a este enfoque? ¿Alguien piensa que tener la cadena declarativa en el código lo haría más fácil de mantener?

+0

¿JSON o XML quizás? DTD o XSD también pueden describir bien una estructura de datos. – codymanix

+7

Así que, en lugar de una expresión completa compleja que toma una línea completa, ocupará toda una página :) –

+4

Las personas que conocen expresiones regulares se sienten cómodas con ella, pero a todos los demás les parece que el alfabeto se vomitó. Esto podría ser un problema, pero no estoy seguro. Después de todo, puede decir lo mismo de los lenguajes de programación para las personas que programan frente a las personas que no lo hacen. Podría ser bueno hacerlo con objetos y funciones instaladas de cadenas, pero no estoy seguro de cuál sería la mejor manera de implementarlo. +1 a la innovación de todos modos. – psicopoo

Respuesta

2

Para los desarrolladores que intentan escribir expresiones regulares que son fáciles para asimilar y mantener, me pregunto si este tipo de enfoque ofrecería algo que re.VERBOSE no proporciona ya.

Para los principiantes, su idea puede ser atractiva. Sin embargo, antes de seguir este camino, puede intentar simular cómo se vería su sintaxis declarativa para las expresiones regulares más complicadas mediante la captura de grupos, anclas, aserciones de anticipación, etc. Un desafío es que puede terminar con una sintaxis declarativa que es tan difícil de recordar como el lenguaje regex.

También puede pensar en formas alternativas de expresar cosas. Por ejemplo, el primer pensamiento que se me ocurrió fue expresar una expresión regular usando funciones con nombres cortos y fáciles de recordar. Por ejemplo:

from refunc import * 

pattern = Compile(
    'a', 
    Capture(
     Choices('b', 'c'), 
     N_of('d', 1, Infin()), 
     N_of('e', 0, Infin()), 
    ), 
    Look_ahead('foo'), 
) 

Pero cuando veo eso en acción, me parece un dolor. Hay muchos aspectos de la expresión regular que son bastante intuitivos, por ejemplo, + para significar "uno o más". Una opción sería un enfoque híbrido, que le permita a su usuario mezclar aquellas partes de expresiones regulares que ya son simples con funciones para los bits más esotéricos.

pattern = Compile(
    'a', 
    Capture(
     '[bc]', 
     'd+', 
     'e*', 
    ), 
    Look_ahead('foo'), 
) 

Debo añadir que, en mi experiencia, las expresiones regulares son sobre aprender un proceso de pensamiento. Sentirse cómodo con la sintaxis es la parte fácil.

6

Esto es en realidad bastante similar (¿idéntico?) A cómo funciona un analizador/analizador. Si tuvieras una gramática definida, entonces probablemente podrías escribir un analizador sintáctico sin demasiados problemas. Por ejemplo, podría escribir algo como esto:

<expression> :: == <rule> | <rule> <expression> | <rule> " followed by " <expression> 
<rule>  :: == <val> | <qty> <val> 
<qty>  :: == "literal" | "one" | "one of" | "one or more of" | "zero or more of" 
<val>  :: == "a" | "b" | "c" | "d" | ... | "Z" | 

Eso no está cerca de una descripción perfecta. Para obtener más información, echa un vistazo al this BNF of the regex language. Luego puede mirar lexing y parsing la expresión.

Si lo hizo de esta manera, probablemente podría acercarse un poco más a Natural Language/versiones en inglés de expresiones regulares.


Veo que una herramienta como esta es útil, pero como se dijo anteriormente, principalmente para principiantes. La principal limitación de este enfoque sería la cantidad de código que tiene que escribir para traducir el idioma a expresiones regulares (y/o viceversa). Por otro lado, creo que una herramienta de traducción bidireccional sería más ideal y vería más uso. Ser capaz de tomar una expresión regular y convertirlo al inglés podría ser mucho más útil para detectar errores.

Por supuesto, no toma demasiado tiempo recoger expresiones regex ya que la sintaxis es generalmente concisa y la mayoría de los significados son bastante explicativos, al menos si usa | o || como OR en su idioma, y ​​piensa en * como multiplicar por 0-N, + como agregar 0-N.

Aunque a veces no me importaría escribir "encontrar uno o más 'a' seguida de tres dígitos o 'b' y luego 'c'"

+0

En respuesta a su 'Ser capaz de tomar una expresión regular y convertirla al inglés podría ser mucho más útil para detectar errores. parámetro 're.DEBUG' con python en modo repl. – Daenyth

+0

@Daenyth - Conozco ese modo, aunque no he tenido motivo para usarlo, y no puedo decir que sea mucho mejor que el regex original, a menos que sea una expresión regular extremadamente complicada. –

6

favor, eche un vistazo a pyparsing. Muchos de los problemas que describes con RE son los mismos que me inspiraron a escribir ese paquete.

Aquí hay algunas características específicas de pyparsing del O'Reilly e-book capítulo "What's so special about pyparsing?".

+1

¡Me ganaste por un segundo! Por cierto, gracias por escribir pyparsing :) –

2

tal vez no es exactamente lo que está pidiendo, pero hay una manera de cómo escribir expresiones regulares manera más legible (VERBOSE, poco X bandera):

rex_name = re.compile(""" 
    [A-Za-z] # first letter 
    [a-z]+  # the rest 
""", re.X) 

rex_name.match('Joe') 
Cuestiones relacionadas