2009-04-29 16 views
29

Si Regex usa con C#, VB.NET, Perl o cualquier otro idioma. Entonces, independientemente del idioma que use, comparta con nosotros una o dos de sus expresiones regulares desafiantes.¿Cuál es la expresión regular más difícil/desafiante que jamás haya escrito?

+9

Seguir adelante y hacer de esta comunidad wiki por favor. :) – Anthony

+1

Me atrevo a cualquier persona para verificar una dirección de correo electrónico con regex;) – Louis

+0

Lou, si está dispuesto a vivir sin los comentarios en la dirección de correo electrónico, este hace el trabajo: http://ex-parrot.com/~pdw /Mail-RFC822-Address.html No tengo idea de cuántas líneas de código tomaría para que sea legible, o incluso si puede hacerse legible. –

Respuesta

0

Mi empresa tiene un pequeño producto que hace envíos masivos, algo así como Constant Contact. Estaba basado en la web y el usuario ingresaba su correo electrónico html a través de un editor WYSIWYG. Queríamos que pudieran ingresar valores dinámicos, así que tuvimos que crear un sistema de tokening. Creé una biblioteca de análisis token completa usando expresiones regulares. Difícil y desafiante, pero muy divertido. Tuve el cuidado de declarar todas mis expresiones mágicas como constantes y utilizarlas en todo el código. Lo hizo extremadamente fácil de mantener y actualizar. Creo que el análisis a través de html tiene que ser el peor, especialmente cuando html puede estar dentro de las coincidencias que estás buscando.

28

Reescritura de este monstruo:

^(?:(?:(?:0?[13578]|1[02])(\/|-|\.)31)\1|(?:(?:0?[13-9]|1[0-2])(\/|-|\.)(?:29|30)\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:0?2(\/|-|\.)29\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:(?:0?[1-9])|(?:1[0-2]))(\/|-|\.)(?:0?[1-9]|1\d|2[0-8])\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$ 

para ser más legible/mantenible:

require 5.010; 
my $sep   = qr{ [/.-] }x;    #allowed separators  
my $any_century = qr/ 1[6-9] | [2-9][0-9] /x; #match the century 
my $any_decade = qr/ [0-9]{2} /x;   #match any decade or 2 digit year 
my $any_year = qr/ $any_century? $any_decade /x; #match a 2 or 4 digit year 

#match the 1st through 28th for any month of any year 
my $start_of_month = qr/ 
    (?:       #match 
     0?[1-9] |    #Jan - Sep or 
     1[0-2]     #Oct - Dec 
    ) 
    ($sep)      #the separator 
    (?: 
     0?[1-9] |    # 1st - 9th or 
     1[0-9] |    #10th - 19th or 
     2[0-8]     #20th - 28th 
    ) 
    \g{-1}      #and the separator again 
/x; 

#match 28th - 31st for any month but Feb for any year 
my $end_of_month = qr/ 
    (?: 
     (?: 0?[13578] | 1[02]) #match Jan, Mar, May, Jul, Aug, Oct, Dec 
     ($sep)     #the separator 
     31      #the 31st 
     \g{-1}     #and the separator again 
     |      #or 
     (?: 0?[13-9] | 1[0-2]) #match all months but Feb 
     ($sep)     #the separator 
     (?:29|30)    #the 29th or the 30th 
     \g{-1}     #and the separator again 
    ) 
/x; 

#match any non-leap year date and the first part of Feb in leap years 
my $non_leap_year = qr/ (?: $start_of_month | $end_of_month) $any_year/x; 

#match 29th of Feb in leap years 
#BUG: 00 is treated as a non leap year 
#even though 2000, 2400, etc are leap years 
my $feb_in_leap = qr/ 
    0?2       #match Feb 
    ($sep)      #the separtor 
    29       #the 29th 
    \g{-1}      #the separator again 
    (?: 
     $any_century?   #any century 
     (?:      #and decades divisible by 4 but not 100 
      0[48]  | 
      [2468][048] | 
      [13579][26] 
     ) 
     | 
     (?:      #or match centuries that are divisible by 4 
      16   | 
      [2468][048] | 
      [3579][26] 
     ) 
     00      
    ) 
/x; 

my $any_date = qr/$non_leap_year|$feb_in_leap/; 
my $only_date = qr/^$any_date$/; 
+1

Esto parece seguramente un monstruo clásico. : D – Rithet

+0

¿Qué es el lenguaje? No me gusta usar esta exp regular para validar la entrada. Debo usar if-else o switch-case para resolver esta validación. –

+0

Esto está en Perl 5.10, debe usar 5.10 para obtener \ g {-1}. La publicación donde hice esto es http://stackoverflow.com/questions/708254 Si miras esa respuesta, verás que se necesitan menos de veinte líneas de código para validar la fecha con el código normal (frente a las más de 70 líneas para la expresión regular mantenible). No los he comparado. Creo que debería. –

6

número validador romana para un proyecto de la tarea - no la mía, que ha sido un largo tiempo desde tengo tuvieron que hacer la tarea :-)

^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$ 

Cualquier más complejo que eso y tiendo a escribir código para él, ya que puedo documentarlo mejor y optimizarlo.

1
/=(?:[^\[\|]*?(?:\[\[[^\|\]]*(?:\|(?:[^\|\]]*))?\]\])?)+(?:\||\}\})/ 

Sí, ya sé que no es tan larga (al menos en comparación con Chas de!), Pero era difícil para mí para hacerlo bien. ¿Para qué sirve? Si usted tiene que pedir ...

Consejo:

/\|[^\|=]*=/ 

es el compañero mucho más simple.

Editar:

Gracias a Tomalak,

/=(?:[^\[|]*?(?:\[\[[^|\]]*(?:\|(?:[^|\]]*))?\]\])?)+(?:\||\}\})/ 

y

/\|[^|=]*=/ 

Es JavaScript expresiones regulares sabor de un plugin para Firefox que estamos esperando para liberar pronto.

+0

De hecho, "/ \ | [^ | =] * = /" sería el compañero más simple. No es necesario escapar del símbolo de la tubería en una clase de personaje. Esto ayudaría a la expresión regular más larga también. :-) – Tomalak

1

Bueno, este no es un problema difícil pero que tardó un tiempo en descifrarlo.

Para hacer:

SomeDocument1.docx 
SomeDocument2.docx 

Para:

<A HREF="SomeDocument1.docx" >SomeDocument1</A> 
<A HREF="SomeDocument2.docx" >SomeDocument2</A> 

Encontrar:

\(^[a-zA-Z0-9]+\)\.\([a-z]+\) 

Reemplazar con:

\<A HREF\=\"\1\.\2\" \>\1\<\/A\> 

Descubrir el problema \( y \) con Textpad para captura tomó tiempo.

+0

Grupos de captura con^(([^ \\\: \ * \? \ <\> \ | \ "] +) \. [^ \\\: \ * \? \ <\> \ | \"] +) $, y reemplace por \2

2

Mi amigo estaba tratando de escribir un RE que podría coincidir con {0,1} cadenas con un número impar de 1 y un número par de 0. No pude hacerlo yo mismo, pero escribí un programa que podría convertir un autómata finito en un RE equivalente. Aquí está la re que mi programa escupió:

>>> from dfa2re import * 
<module 'dfa2re' from 'dfa2re.py'> 
>>> a2 = GNFA('a', ['ab1', 'ba1', 'ac0', 'ca0', 'bd0', 'db0', 'cd1', 'dc1'], set('b')) 
>>> a2.re() 
'((1|0(00)*01)((11|10(00)*01))*|(0(00)*1|(1|0(00)*01)((11|10(00)*01))*(0|10(00)*1))((1(00)*1|(0|1(00)*01)((11|10(00)*01))*(0|10(00)*1)))*(0|1(00)*01)((11|10(00)*01))*)' 

es necesario agregar^$ y personajes para que funcione correctamente, pero funciona.

Como puede ver, hay mucho menos en la especificación de la GNFA. También fue mucho más fácil de diseñar, porque es muy visual y su corrección es más obvia.

+3

¿Cuán complicado es ese programa?¿Hay alguna posibilidad de que esté disponible para el resto del mundo? –

+0

Son 345 líneas. Podría ponerlo en algún lado, pero no estoy seguro de lo que valdría la pena, ya que no es mucho tiempo. – allyourcode

+0

Creo que obtuve el algoritmo de este libro, si quiere intentarlo usted mismo: http://tinyurl.com/sipser-computation-theory – allyourcode

24

No lo escribí pero este es el más loco que he visto.

(?:(?:\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*) 

http://ex-parrot.com/~pdw/Mail-RFC822-Address.html

+10

sí, y esta expresión regular no maneja el 100% de las direcciones de correo electrónico;) – romaintaz

+0

Por favor, elabore ... ¿ha cambiado el RFC? No veo ninguna referencia a TLD y la he usado para cientos de miles de direcciones de correo electrónico sin problema * todavía * pero estoy seguro de que no quiero invertir esto, así que si sabes algo ... dile ! –

+4

Creo que el comentario no del 100% fue solo una broma. –

Cuestiones relacionadas