Pregunta

Acabo de ver un enorme regex para Java que me hizo pensar un poco acerca de la capacidad de mantenimiento de expresiones regulares en general.Creo que la mayoría de las personas - excepto algunos badass perl traficantes - estaría de acuerdo en que las expresiones regulares son difícil de mantener.

Yo estaba pensando acerca de cómo esta situación podría ser fijo.Hasta ahora, la idea más prometedora que tengo es el uso de un interfaz fluida.Para dar un ejemplo, en lugar de:

Pattern pattern = Pattern.compile("a*|b{2,5}");

uno podría escribir algo como esto

import static util.PatternBuilder.*

Pattern pattern = string("a").anyTimes().or().string("b").times(2,5).compile();

Pattern alternative = 
  or(
    string("a").anyTimes(),
    string("b").times(2,5)
  )
  .compile();

En este ejemplo, la forma más común de la creación de la expresión regular es todavía muy legible a cualquier mediocre talento desarrollador.Sin embargo, pensar en aquellos espeluznantes expresiones que llenar dos o más líneas de 80 caracteres cada una.Seguro, el (detallado) fluidez de la interfaz requeriría varias líneas en lugar de sólo dos, pero estoy seguro de que sería mucho más legible (por lo tanto, fácil de mantener).

Ahora mis preguntas:

  1. ¿Sabe usted de cualquier enfoque similar a las expresiones regulares?

  2. ¿Está usted de acuerdo en que este enfoque podría ser mejor que el uso de cadenas sencillas?

  3. ¿Cómo calificaría el diseño de la API?

  4. Usarías una clara utilidad en sus proyectos?

  5. ¿Crees que esto iba a ser divertido de ejecución?;)

EDITAR: Imaginar que podría haber métodos que están en un nivel superior que el de simples construcciones que no todo es de regex, por ejemplo,

// matches aaaab@example.com - think of it as reusable expressions
Pattern p = string{"a").anyTimes().string("b@").domain().compile();

EDITAR - resumen de los comentarios:

Es interesante leer que la mayoría de la gente piensa que las expresiones regulares están aquí para quedarse - a pesar de que lleva herramientas para leer y smart chicos a pensar en maneras de hacerlos fáciles de mantener.Aunque no estoy seguro de que una interfaz fluida es la mejor manera de ir, estoy seguro de que algunos de los ingenieros inteligente - nos?;) - debe pasar algún tiempo para hacer expresiones regulares en una cosa del pasado - es suficiente que ellos han estado con nosotros durante 50 años saben, no crees?

ABRA RECOMPENSA

La recompensa será otorgado a la mejor idea (no hay código necesario) para un nuevo enfoque de las expresiones regulares.

EDITAR - UN BUEN EJEMPLO:

aquí es el tipo de patrón que estoy hablando - extra felicitaciones a la primera persona que es capaz de traducir - RegexBuddies permitido (es de un proyecto Apache btw) extra felicitaciones otorgado a chii y mez:es compatible con RFC dirección de correo electrónico de validación del patrón - a pesar de su RFC822 (ver ex-parrot.com), no 5322 - no estoy seguro si hay una diferencia, aunque - si sí, voy a siguiente premio extra felicitaciones por un parche para que se ajuste 5322 ;)

private static final String pattern = "(?:(?:\\r\\n)?[ \\t])*(?:(?:(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t]"
    + ")+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:"
    + "\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:("
    + "?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ "
    + "\\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\0"
    + "31]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\"
    + "](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+"
    + "(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:"
    + "(?:\\r\\n)?[ \\t])*))*|(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z"
    + "|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)"
    + "?[ \\t])*)*\\<(?:(?:\\r\\n)?[ \\t])*(?:@(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\"
    + "r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?["
    + " \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)"
    + "?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t]"
    + ")*))*(?:,@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?["
    + " \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*"
    + ")(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t]"
    + ")+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*)"
    + "*:(?:(?:\\r\\n)?[ \\t])*)?(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+"
    + "|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r"
    + "\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:"
    + "\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t"
    + "]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031"
    + "]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\]("
    + "?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?"
    + ":(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?"
    + ":\\r\\n)?[ \\t])*))*\\>(?:(?:\\r\\n)?[ \\t])*)|(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?"
    + ":(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?"
    + "[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)*:(?:(?:\\r\\n)?[ \\t])*(?:(?:(?:[^()<>@,;:\\\".\\[\\] "
    + "\\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|"
    + "\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>"
    + "@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\""
    + "(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t]"
    + ")*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\"
    + "\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?"
    + ":[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\["
    + "\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*|(?:[^()<>@,;:\\\".\\[\\] \\000-"
    + "\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|("
    + "?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)*\\<(?:(?:\\r\\n)?[ \\t])*(?:@(?:[^()<>@,;"
    + ":\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[(["
    + "^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\""
    + ".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\"
    + "]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*(?:,@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\"
    + "[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\"
    + "r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] "
    + "\\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]"
    + "|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*)*:(?:(?:\\r\\n)?[ \\t])*)?(?:[^()<>@,;:\\\".\\[\\] \\0"
    + "00-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\"
    + ".|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,"
    + ";:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?"
    + ":[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*"
    + "(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\"."
    + "\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:["
    + "^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]"
    + "]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*\\>(?:(?:\\r\\n)?[ \\t])*)(?:,\\s*("
    + "?:(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\"
    + "\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:("
    + "?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=["
    + "\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t"
    + "])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t"
    + "])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?"
    + ":\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|"
    + "\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*|(?:"
    + "[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\"
    + "]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)*\\<(?:(?:\\r\\n)"
    + "?[ \\t])*(?:@(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\""
    + "()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)"
    + "?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>"
    + "@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*(?:,@(?:(?:\\r\\n)?["
    + " \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,"
    + ";:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t]"
    + ")*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\"
    + "\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*)*:(?:(?:\\r\\n)?[ \\t])*)?"
    + "(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\"."
    + "\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:"
    + "\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\["
    + "\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])"
    + "*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])"
    + "+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\"
    + ".(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z"
    + "|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*\\>(?:("
    + "?:\\r\\n)?[ \\t])*))*)?;\\s*)";
¿Fue útil?

Solución

¿Cómo diseñaría la API?

Me tomaría prestado una página de la API de Hibernate criterios. En lugar de utilizar:

string("a").anyTimes().or().string("b").times(2,5).compile()

Usar un patrón como:

Pattern.or(Pattern.anyTimes("a"), Pattern.times("b", 2, 5)).compile()

Esta notación es un poco más concisa, y siento que es más fácil de entender la jerarquía / estructura del patrón. Cada método podría aceptar, ya sea una cadena, o un fragmento del modelo, como el primer argumento.

¿Sabe usted de cualquier enfoque similar a las expresiones regulares?

No improviso, no.

¿Está de acuerdo que este enfoque podría ser mejor que el uso de cadenas simples?

Sí, absolutetely ... si está utilizando expresiones regulares es para nada remotamente complicado. En casos muy cortas y simples, una cadena es más conveniente.

¿Quieres que utiliza una utilidad de tales ordenada en sus proyectos?

Posiblemente, ya que se convirtió probada / estable ... de rodadura en un proyecto de utilidad más grande como Apache Commons podría ser una ventaja.

¿Cree que esto sería divertido implementar? ;)

1

Otros consejos

otra estrategia . Es decir, tomando partes significativas de la expresión regular y sustituirlas por variables. Él usa siguiente ejemplo:

 "^score\s+(\d+)\s+for\s+(\d+)\s+nights?\s+at\s+(.*)" 

se convierte

   String scoreKeyword = "^score\s+";
   String numberOfPoints = "(\d+)";
   String forKeyword = "\s+for\s+";
   String numberOfNights = "(\d+)";
   String nightsAtKeyword = "\s+nights?\s+at\s+";
   String hotelName = "(.*)";

   String pattern = scoreKeyword + numberOfPoints +
      forKeyword + numberOfNights + nightsAtKeyword + hotelName;

Lo que es mucho más fácil de leer y fácil de mantener.

El objetivo del ejemplo anterior era para analizar numberOfPoints, numberOfNights y hotelName fuera de una lista de cadenas como:

score 400 for 2 nights at Minas Tirith Airport

Puede ser que sea un poco más fácil para alguien sin ninguna experiencia de expresiones regulares, pero después de que alguien se entera de su sistema, que todavía no será capaz de leer una expresión regular normales en otros lugares.

Además, creo que su versión es más difícil de leer para un experto en expresiones regulares.

Yo recomendaría anotar la expresión regular como esto:

Pattern pattern = Pattern.compile(
  "a*     # Find 0 or more a        \n" +
  "|      # ... or ...              \n" +
  "b{2,5} # Find between 2 and 5 b  \n",
Pattern.COMMENTS);

Esto es fácil de leer para cualquier nivel de experiencia, y para los inexpertos, que enseña expresiones regulares al mismo tiempo. Además, los comentarios se pueden adaptar a la situación de explicar las reglas de negocio detrás de la expresión regular en lugar de sólo la estructura.

Además, una herramienta como RegexBuddy puede tomar su expresión regular y traducirla en:

Match either the regular expression below (attempting the next alternative only if this one fails) «a*»
   Match the character "a" literally «a*»
      Between zero and unlimited times, as many times as possible, giving back as needed (greedy) «*»
Or match regular expression number 2 below (the entire match attempt fails if this one fails to match) «b{2,5}»
   Match the character "b" literally «b{2,5}»
      Between 2 and 5 times, as many times as possible, giving back as needed (greedy) «{2,5}»

Este es un concepto interesante, pero tal como se presenta hay algunos defectos.

Pero las primeras respuestas a las preguntas clave que se hacen:

Ahora mis preguntas:

1. ¿Sabe usted de cualquier enfoque similar a las expresiones regulares?

Nada que no se han mencionado ya. Y aquellos que me enteré de la lectura de las preguntas y respuestas.

2. ¿Está de acuerdo que este enfoque podría ser mejor que el uso de cadenas simples?

Si funciona como se anuncia, que sin duda hace las cosas mucho más fáciles de depurar.

3. ¿Cómo diseñaría la API?

Ver mis notas en la siguiente sección. Tomo sus ejemplos y la biblioteca .NET ligado como punto de partida.

4. Usarías una utilidad tal ordenada en sus proyectos?

indeciso. No tengo ningún problema de trabajo con la versión actual de expresiones crípticas con regularidad. Y que iba a necesitar una herramienta para convertir expresiones regulares existentes a la versión del idioma con fluidez.

5. Cree usted que esto sería divertido implementar? ;)

Yo disfrutaría la elaboración de la mayor nivel cómo, que escribir el código real. Lo que explica la pared del texto que es esta respuesta.


Aquí hay un par de problemas que me di cuenta, y la forma en que se ocuparía de ello.

estructura poco clara.

Su ejemplo parece crear una expresión regular mediante la concatenación de cadenas. Esto no es muy robusta. Creo que estos métodos deben ser añadidos a los objetos String y Patern / expresiones regulares, ya que hará que la aplicación y el código más limpio. Además de que es similar a la forma en que las expresiones regulares se definen clásicamente.

El hecho de que no puede ver su funcionamiento de ninguna otra manera, el resto de mis anotaciones al esquema propuesto asumirá que todos los métodos y actúan sobre los objetos del patrón de retorno.

Editar Me parece que han utilizado las siguientes convenciones en todo. Así que les he clarificado y moverlos hacia arriba aquí.

  • Los métodos de instancia: aumento de patrón. por ejemplo:. captura, la repetición, la mirada alrededor afirmaciones

  • Operadores: orden de las operaciones. alternancia, la concatenación

  • Las constantes: clases de personajes, fronteras (in-situ de \ w, $, \ b, etc)

¿Cómo se captura / agrupamiento ser manejado?

La captura es una gran parte de las expresiones regulares.

I ver cada modelo objeto se almacena internamente como un clúster. (?: Patrón) en términos de Perl. Permitir que para el patrón de fichas para ser fácilmente mezclado y mezclado sin interferir con otras piezas.

Me esperan capturar a ser hecho como un método de instancia en un patrón. Tomando una variable para almacenar la cadena coincidente [s] en.

pattern.capture(variable) almacenaría patrón en variable. En el caso de que la captura es parte de una expresión a ser comparada varias veces, variable debe contener una matriz de cadenas de todos los partidos para el patrón.

idiomas con fluidez puede ser muy ambigua.

idiomas con fluidez no están bien adaptados a la naturaleza recursiva de las expresiones regulares. Por lo que las necesidades que se prevea que el orden de las operaciones. Sólo el encadenamiento de métodos juntos no permite expresiones regulares muy complejos. Exactamente la situación en la que una herramienta de este tipo sería útil.

¿Tiene

Pattern pattern = string("a").anyTimes().or().string("b").times(2,5).compile();

/a*|b{2,5}/ producto o /(a*|b){2,5}/?

alternancia ¿Cómo sería un mango tal esquema de agrupar? Por ejemplo: /a*|b(c|d)|e/

Veo tres maneras de manejar la alternancia en las expresiones regulares

  1. Como operador: pattern1 or pattern2 => pattern # /pattern1|pattern2/
  2. Como un método de clase: Pattern.or( pattern1, pattern2[, pattern3]*) => pattern # /pattern1|patern2|patern3|...|/
  3. Como método de instancia: pattern1.or(pattern2) => pattern # /pattern1|patern2/

I se ocuparía de la concatenación de la misma manera.

  1. Como operador: pattern1 + pattern2 => pattern # /pattern1pattern2/
  2. Como un método de clase: Pattern.concatenate( pattern1, pattern2[, pattern3]*) => pattern # /pattern1patern2patern3.../
  3. Como método de instancia: pattern1.then(pattern2) => pattern # /pattern1patern2/

Cómo extender para comúnmente usada patterns

El esquema utilizado .domain() propuesta que parece ser una expresión regular común. Para los patrones definidos por el usuario para considerar como un métodos no significa que sea fácil de añadir nuevos patrones. En un lenguaje como Java usuarios de la biblioteca tendría que sustituir la clase de añadir métodos para patrones de uso común.

Este es tratada por mi sugerencia para tratar cada pieza como un objeto. Un modelo objeto puede ser creado para cada expresión regular comúnmente usado como búsqueda de un dominio, por ejemplo. Teniendo en cuenta mis anteriores pensamientos acerca de la captura que no sería demasiado difícil para asegurarse de que la captura de obras para múltiples copias del mismo patrón común que contiene una sección capturado.

También debería ser constantes para distintos patrones determinados tipos de personajes.

Cero ancho vistazo alrededor afirmaciones

La expansión en mis pensamientos que todas las piezas debe ser implícitamente agrupado. Mirar alrededor afirmaciones no deben ser demasiado duro también hacer con un método de instancia.

pattern.zeroWidthLookBehind() produciría (?<patten).


Cosas que aún necesitan ser considerados.

  • backreferences: Esperemos que no sea demasiado duro con la captura llamado discutido anteriormente
  • ¿Cómo realmente en práctica. No he dado las partes internas demasiada importancia. Es el lugar donde la verdadera magia va a pasar.
  • Traducción: No debería ser una herramienta de traducir desde y hacia regexs clásicos (Perl decir dialecto) y el nuevo programa. Traduciendo del nuevo esquema podría ser una parte del paquete

Poniendo todo junto, mi versión propuesta de un patrón que coincide con una dirección de correo electrónico:

Pattern domain_label = LETTER_CHARACTER + (LETTER_CHARACTER or "-" or DIGIT_CHARACTER).anyTimes()
Pattern domain = domain_label + ("." + domain_label).anyTimes()
Pattern pattern = (LETTER_CHARACTER + ALPHANUMERIC_CHARACTER + "@" + domain).compile

En retrospectiva, mi esquema inspira en gran medida del enfoque de Martin Fowler en uso. A pesar de que no tenía la intención de que las cosas van de esta manera, que sin duda hace que el uso del sistema tal más fácil de mantener. También se ocupa de un problema o dos con el enfoque de Fowler (orden de captura).

Mi humilde intento se puede encontrar en GitHub . Aunque no creo que vale la pena el uso de las expresiones simples, proporciona un par de ventajas aparte de la mejora de la legibilidad:

  • Se ocupa de coincidencia de soporte
  • Maneja escapar de todos los caracteres 'especiales' que puede conducir rápidamente al infierno barra invertida

Algunos ejemplos simples:

 // Matches a single digit
    RegExBuilder.build(anyDigit()); // "[0-9]"

 // Matches exactly 2 digits
    RegExBuilder.build(exactly(2).of(anyDigit())); // "[0-9]{2}"

 // Matches between 2 and 4 letters
    RegExBuilder.build(between(2,4).of(anyLetter())); // "[a-zA-Z]{2,4}"

Y una más complicada (que más o menos valida las direcciones de correo electrónico):

final Token ALPHA_NUM = anyOneOf(range('A','Z'), range('a','z'), range('0','9'));
final Token ALPHA_NUM_HYPEN_UNDERSCORE = anyOneOf(characters('_','-'), range('A','Z'), range('a','z'), range('0','9'));

String regexText = RegExBuilder.build(
 // Before the '@' symbol we can have letters, numbers, underscores and hyphens anywhere
    oneOrMore().of(
        ALPHA_NUM_HYPEN_UNDERSCORE
    ),
    zeroOrMore().of(
        text("."), // Periods are also allowed in the name, but not as the initial character
        oneOrMore().of(
            ALPHA_NUM_HYPEN_UNDERSCORE
        )
    ),
    text("@"),
 // Everything else is the domain name - only letters, numbers and periods here
    oneOrMore().of( 
        ALPHA_NUM
    ),
    zeroOrMore().of(
        text("."), // Periods must not be the first character in the domain
        oneOrMore().of(
            ALPHA_NUM
        )
    ),
    text("."), // At least one period is required
    atLeast(2).of( // Period must be followed by at least 2 letters (this is the TLD)
        anyLetter()
    )
);

Respuesta corta:. Lo he visto abordado desde una formación de pelusas y el ángulo de la compilación, que creo que es algo a considerar para este

Respuesta larga: El trabajo que la empresa de motores de expresiones regulares basadas en hardware hace que para el filtrado de contenido empresarial aplicaciones. Piense correr antivirus o aplicaciones de cortafuegos a 20 GB / seg velocidades justo en los routers de la red en lugar de tomar los ciclos de procesador de servidor o valiosos. Más anti-virus, anti-spam o aplicaciones de cortafuegos son un montón de expresiones de expresiones regulares en el núcleo.

De todos modos, la forma de las expresiones regulares se escriben tiene un gran impacto en el rendimiento de la exploración. Puede escribir regexs de varias maneras diferentes de hacer la misma cosa, y algunos tendrán un rendimiento drásticamente más rápido. Hemos escrito compiladores y borra de nuestros clientes para ayudarles a mantener y ajustar sus expresiones.

Volver a la pregunta del PO, en lugar de definir una sintaxis completamente nuevo, me gustaría escribir una desfibradora (lo siento, la nuestra es propietaria) cortar y pegar de expresiones regulares en que se descompone el legado de expresiones regulares y la salida de "fluidez Inglés" para alguien de entender mejor. También me gustaría añadir controles de rendimiento relativo y sugerencias para las modificaciones comunes.

La respuesta corta, para mí, es que, una vez que llegue a las expresiones regulares (u otra coincidencia de patrones que hace lo mismo) que son lo suficiente como para causar un problema ... probablemente debería estar considerando si están la herramienta adecuada para el trabajo en el primer lugar.

En serio, cualquier interfaz fluida parece que sería más difícil de leer que una expresión regular estándar. Para expresiones muy breves, la versión fluidez es prolijo, pero no demasiado largo; que es legible. Pero también lo es la expresión regular para algo tanto tiempo.

Para un medio de tamaño expresión regular, una interfaz fluida se convierte en difícil de manejar; el tiempo suficiente que es difícil, si no imposible, para leer.

Para una expresión a largo regular (es decir, la dirección de correo electrónico uno), en donde la expresión regular es realmente difícil (si no imposible) para leer, la versión de fluidez se hizo imposible de leer hace 10 páginas.

¿Sabe usted de cualquier enfoque similar a las expresiones regulares?

No, a excepción de la respuesta anterior

¿Está de acuerdo que este enfoque podría ser mejor que el uso de cadenas simples?

Una especie de - creo que en lugar de un solo carácter para representar construcciones, podríamos utilizar el marcado más descriptivo, pero dudo que haría una lógica compleja más claro.

¿Cómo diseñaría la API?

Traducir cada constructo en un nombre de método, y permitir que las llamadas a funciones anidadas de manera que es muy fácil de tomar una cadena y método sustituto nombres en ella.

Creo que la mayor parte del valor estará en la definición de una sólida biblioteca de funciones de utilidad, al igual que con el tema "e-mails", "números de teléfono", "líneas que no contienen X", etc., que se pueden personalizar.

¿Quieres que utiliza una utilidad de tales ordenada en sus proyectos?

Tal vez -., Pero probablemente sólo para los más largos, en los que sería más fácil de llamadas a funciones de depuración de edición de cadena de depuración, o cuando existe una función de utilidad agradable listo para su uso

¿Cree que esto sería divertido implementar? ;)

Por supuesto!

En respuesta a la última parte de la pregunta (por Kudos)

private static final String pattern = "(?:(?:\\r\\n)?[ \\t])*(?:(?:(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t]"
    + ")+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:"
    + "\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:("
    + "?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ "
    + "\\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\0"
    + "31]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\"
    + "](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+"
    + "(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:"
    + "(?:\\r\\n)?[ \\t])*))*|(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z"
    + "|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)"
    + "?[ \\t])*)*\\<(?:(?:\\r\\n)?[ \\t])*(?:@(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\"
    + "r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?["
    + " \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)"
    + "?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t]"
    + ")*))*(?:,@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?["
    + " \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*"
    + ")(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t]"
    + ")+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*)"
    + "*:(?:(?:\\r\\n)?[ \\t])*)?(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+"
    + "|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r"
    + "\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:"
    + "\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t"
    + "]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031"
    + "]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\]("
    + "?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?"
    + ":(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?"
    + ":\\r\\n)?[ \\t])*))*\\>(?:(?:\\r\\n)?[ \\t])*)|(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?"
    + ":(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?"
    + "[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)*:(?:(?:\\r\\n)?[ \\t])*(?:(?:(?:[^()<>@,;:\\\".\\[\\] "
    + "\\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|"
    + "\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>"
    + "@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\""
    + "(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t]"
    + ")*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\"
    + "\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?"
    + ":[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\["
    + "\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*|(?:[^()<>@,;:\\\".\\[\\] \\000-"
    + "\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|("
    + "?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)*\\<(?:(?:\\r\\n)?[ \\t])*(?:@(?:[^()<>@,;"
    + ":\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[(["
    + "^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\""
    + ".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\"
    + "]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*(?:,@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\"
    + "[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\"
    + "r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] "
    + "\\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]"
    + "|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*)*:(?:(?:\\r\\n)?[ \\t])*)?(?:[^()<>@,;:\\\".\\[\\] \\0"
    + "00-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\"
    + ".|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,"
    + ";:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\"(?"
    + ":[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*"
    + "(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\"."
    + "\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:["
    + "^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]"
    + "]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*\\>(?:(?:\\r\\n)?[ \\t])*)(?:,\\s*("
    + "?:(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\"
    + "\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:("
    + "?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=["
    + "\\[\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t"
    + "])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t"
    + "])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?"
    + ":\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|"
    + "\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*|(?:"
    + "[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\"
    + "]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)*\\<(?:(?:\\r\\n)"
    + "?[ \\t])*(?:@(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\""
    + "()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)"
    + "?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>"
    + "@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*(?:,@(?:(?:\\r\\n)?["
    + " \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,"
    + ";:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t]"
    + ")*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\"
    + "\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*)*:(?:(?:\\r\\n)?[ \\t])*)?"
    + "(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\"."
    + "\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:"
    + "\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\["
    + "\"()<>@,;:\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])"
    + "*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])"
    + "+|\\Z|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\"
    + ".(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z"
    + "|(?=[\\[\"()<>@,;:\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*\\>(?:("
    + "?:\\r\\n)?[ \\t])*))*)?;\\s*)";

coincide con direcciones de correo electrónico compatible con RFC: D

Una expresión regular es una descripción de una máquina de estado finito. La representación textual clásica no es necesariamente malo. Es compacto, es relativamente unambigous y está bastante bien adoptada.

Puede ser que una mejor representación sería un diagrama de transición de estado, pero que probablemente sería difícil de utilizar en el código fuente.

Una posibilidad sería la de construirlo a partir de una variedad de contenedores y objetos combinador.

Algo a lo largo de la línea de la siguiente (girando esto desde pseudo-código de idioma de su elección se deja como ejercicio para el ansioso):

domainlabel = oneormore(characterclass("a-zA-Z0-9-"))
separator = literal(".")
domain = sequence(oneormore(sequence(domainlabel, separator)), domainlabel)
localpart = oneormore(characterclassnot("@"))
emailaddress = sequence(localpart, literal("@"), domain)

Tenga en cuenta que lo anterior se clasifican de manera incorrecta arbritarily muchas direcciones de correo electrónico como válidos que no se ajustan a la gramática que están obligados a seguir, ya que la gramática requiere más que una simple para EFM completa de análisis. No creo que sería misclassify una dirección válida como no válido, sin embargo.

Debe corresponden a [^ @] + @ ([a-zA-Z0-9 -] +.) + ([A-zA-Z0-9 -] +).

4. Usarías una utilidad tal ordenada en sus proyectos?

Lo más probable es que no. Creo que este es un caso de uso de la herramienta adecuada para el trabajo. Hay algunos grandes respuestas aquí, tales como: 1579202 de Jeremy Stein. Recientemente he "conseguido" expresiones regulares en un proyecto reciente y nos parecieron ser muy útil tal y como son, y cuando comentan adecuadamente, son comprensibles si conoce la sintaxis.

Creo que el "conocer la sintaxis" parte es lo que convierte a las personas fuera de las expresiones regulares, a los que no entienden que se ven arcano y críptico, pero son una poderosa herramienta y en Ciencias de la Computación (por ejemplo, software de escritura solicitado la vida) me siento como profesionales inteligentes debería y debe ser capaz de aprender a utilizar ellos y nosotros de manera apropiada.

Como se suele decir "Un gran poder conlleva una gran responsabilidad". He visto personas utilizan expresiones regulares en todas partes para todo, sino que se utiliza juiciosamente por alguien que ha tomado el tiempo para aprender la sintaxis de fondo, son increíblemente útiles; para mí, añadiendo otra capa sería en una derrota manera su propósito, o por lo menos quitarle su poder.

Esto sólo mi propia opinión y puedo entender de dónde viene la gente que desearía un marco como éste, o que evitaría las expresiones regulares, pero tengo dificultades para oír "expresiones regulares son malos" de los que no tienen tomar el tiempo para aprender de ellos y tomar una decisión informada.

Para hacer felices a todos (maestros de expresiones regulares y defensores de interfaz de líquidos), asegúrese de que la salida de la interfaz lata de líquido de un patrón de expresión prima adecuada, y también tener una expresión regular regular usando un método de fábrica y generar código de fluido para ello.

Lo que usted está buscando se puede encontrar aquí: . Es un buillder expresión regular que sigue el patrón Asistente de Diseño

esta misma idea .

El pensamiento de aplicarla a mí mismo, pero luego encontró VerbalExpressions .

Vamos a comparar: He trabajado a menudo con (N) consultas de Hibernate ICriteria, que se pueden considerar una Fluido mapeo a SQL. Yo era (y todavía lo soy) entusiasta acerca de ellos, pero lo que hacen las consultas SQL más legible? No, más bien lo contrario, pero otro beneficio subió:. Se hizo mucho más fácil construir mediante programación declaraciones, a subclasificarlos y crear sus propias abstracciones, etc.

Lo que quiero llegar es que el uso de una nueva interfaz para una lengua dada, si el derecho de hacer, puede resultar útil, pero no pensar demasiado alto de la misma. En muchos casos no será más fácil de leer (clases de personajes resta anidados, captura en el look-detrás, en caso de ramificación para nombrar unos pocos conceptos avanzados que serán difíciles de combinar con fluidez). Pero al igual que en muchos casos, los beneficios de una mayor flexibilidad son mayores que los gastos indirectos añaden complejidad de la sintaxis.

Para añadir a su lista de posibles enfoques alternativos y aprovechar esta fuera del contexto de la única Java, considere la sintaxis de LINQ. Esto es lo que podría ser similar (un poco artificial) (from, where y select son palabras clave en LINQ):

// for ^str(aa|bb){3}
from part in mystring
where part startswith "str"
and part hasgroups "aa" or "bb" as first    /* "aa" or "bb" in group 'first' */
and part repeats first 3                    /* repeat group 'first' 3 times */
select part + "extra"                       /* can contain complete statement block */

sólo una idea aproximada, lo sé. Lo bueno de LINQ es que se comprueba por el compilador, una especie de lengua en un idioma. Por defecto, LINQ también se puede expresar como la sintaxis encadenado con fluidez, lo que hace que, si están bien diseñados, compatible con otros lenguajes orientados a objetos.

Yo digo ir por ella, estoy seguro de que es divertido para poner en práctica.

Sugiero utilizando un modelo de consulta (similar a jQuery, django ORM), donde cada función devuelve un objeto de consulta, por lo que puede encadenar juntos.

any("a").some("b").one("@").some(chars).one(".").some(chars) //a*b+@\w+\.\w+

donde está predefinido chars para adaptarse a cualquier carácter.

or se puede lograr mediante el uso de opciones:

any("a").choice("x", "z") // a(x|z)

El argumento para cada función puede ser una cadena o de otra consulta. Por ejemplo, la variable chars mencionado anteriormente se puede definir como una consulta:

//this one is ascii only
chars = raw("a-zA-Z0-9")

Y así, usted puede tener una función de "prima" que acepta una cadena de expresiones regulares como entrada si se siente incómodo para utilizar el sistema de consulta con fluidez.

En realidad, estas funciones se acaba de regresar de expresiones regulares en bruto, y el encadenamiento de ellas es simplemente concatenando las cadenas de expresiones regulares en bruto.

any("a") ---> "a*"
raw("b+") ----> "b+"
one(".") ---> "\."
choice("a", "b") ----> (a|b)

No estoy seguro de que la sustitución de regexp con una API fluida traería mucho.

Tenga en cuenta que no soy un regexp asistente (tengo que volver a leer el doc casi cada vez que tengo que crear un regexp).

Una API fluida haría cualquier medio de complejidad regexp (digamos ~50 caracteres) aún más complejas de lo necesario y no más fáciles de leer en la final, aunque se puede mejorar la la creación de de un regexp en un IDE, gracias a la finalización de código.Pero el mantenimiento del código en general representa un mayor costo de desarrollo de código.

De hecho, ni siquiera estoy seguro de que sería posible tener una API lo suficientemente inteligente como para proporcionar realmente suficiente guía para el desarrollador a la hora de crear un nuevo regexp, no hablar sobre ambigua de los casos, como se mencionó en una respuesta anterior.

Usted ha mencionado un regexp ejemplo para un RFC.Estoy 99% seguro de que (todavía hay un 1% de esperanza;-)) que cualquier API de no hacer que el ejemplo más simple, pero a la vez, que solamente lo haría más complejo de leer!Eso es un ejemplo típico donde usted no desea utilizar regexp de todos modos!

Incluso en relación con la regexp creación, debido al problema de la ambigua patrones, es probable que con un fluent API, usted nunca llegaría con la expresión de la derecha en el primer tiempo, pero tendría que cambiar varias veces hasta que usted consigue lo que usted realmente desea.

No se equivoquen, me encanta interfaces fluidas;He desarrollado algunas bibliotecas que hacen uso de ellos, y yo uso varias bibliotecas 3rd-party basados en ellos (por ejemplo,FEST para Java pruebas).Pero no creo que puede ser el oro de martillo para cualquier problema.

Si consideramos Java exclusivamente, creo que el principal problema con regex es el es necesario escapar de barras en Java las constantes de cadena.Ese es un punto que hace que sea increíblemente difícil de crear y entender regexp en Java.Por lo tanto, el primer paso para mejorar Java regexp sería, para mí, ser un cambio de idioma, a la Groovy, donde las constantes de cadena no necesita para escapar de barras diagonales inversas.

Tan lejos que iba a ser mi única propuesta para mejorar la regexp en Java.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top