2008-10-20 18 views
36

Permito a los usuarios ingresar una expresión regular para que coincida con las direcciones IP, para hacer una filtración IP en un sistema relacionado. Me gustaría validar si las expresiones regulares ingresadas son válidas ya que muchos usuarios se meterán en problemas, aunque con buenas intenciones.¿Puedo probar si una expresión regular es válida en C# sin arrojar la excepción?

Por supuesto, puedo hacer un Regex.IsMatch() dentro de un try/catch y ver si explota de esa manera, pero ¿hay alguna forma más inteligente de hacerlo? La velocidad no es un problema, simplemente prefiero evitar excepciones sin ningún motivo.

+0

¿quiere decir explotar en crear el Regex real? nueva expresión regular (str)? –

+0

Permitir que los usuarios ingresen un valor inicial y final para cada octeto (o una solución similar) podría valer la pena considerar en lugar de regex. – Greg

+0

También podría considerar el uso de CIDR (192.168.0.0/24) si su dirección de IP regex es para rangos. http: //en.wikipedia.org/wiki/CIDR –

Respuesta

34

Siempre y cuando capture excepciones muy específicas, simplemente haga la prueba/captura.

Las excepciones no son malas si se usan correctamente.

+19

Desafortunadamente, por desgracia, las consecuencias sobre el rendimiento (específicas del escenario, lo sé) y la interrupción de la depuración cuando el tipo de excepción es muy general (ArgumentException es terrible para esto). Me encantaría ver 'Regex.TryParse()' introducido en .NET algún día :) –

0

Tengo un método para probar si un RegEx es válido, pero simplemente ajusta la expresión regular en un Try/Catch. No estoy seguro de si hay una mejor manera de hacerlo, pero no pude encontrar uno.

1

Una expresión regular mal formada no es la peor de las razones para una excepción.

A menos que renuncie a un subconjunto muy limitado de la sintaxis de expresiones regulares - y luego escribir una expresión regular (o un analizador) para que - creo que no tienen otra manera de probar si es válido, pero para tratar de construir una establecer la máquina y hacer que coincida con algo.

4

No sin mucho trabajo. El análisis Regex puede ser bastante complicado, y no hay nada público en el Marco para validar una expresión.

System.Text.RegularExpressions.RegexNode.ScanRegex() parece ser la función principal responsable de analizar una expresión, pero es interna (y arroja excepciones para cualquier sintaxis no válida de todos modos). Por lo tanto, se le solicitará que vuelva a implementar la funcionalidad de análisis, que sin dudas fallará en casos límite o actualizaciones de Framework.

Creo que simplemente capturar la ArgumentException es una buena idea, como es probable que tenga en esta situación.

+1

Tenemos TryParse para tratar con números potencialmente malformados. Deberíamos tener un TryRegex para hacer lo mismo: devolver un error en lugar de una excepción. ¡La depuración de las expresiones regulares introducidas por el usuario es molesta! –

0

En .NET, a menos que escriba su propio analizador de expresiones regulares (que desaconsejaría encarecidamente), casi con seguridad tendrá que ajustar la creación del nuevo objeto Regex con un try/catch.

1

Dependiendo de quién sea el objetivo para esto, sería muy cuidadoso. No es difícil construir expresiones regulares que puedan retroceder sobre sí mismas y consumir mucha CPU y memoria: pueden ser un vector eficaz de denegación de servicio.

+0

¿No hay protección de "desbordamiento de pila" en la biblioteca de análisis regex de .NET? ¿Puedes darme un ejemplo que me pueda dar problemas? –

+2

Regex.IsMatch ("bbbbbbbbbb", "(. *) {50} a"); – Hound

+2

Con .NET 4.5, puede agregar un valor de tiempo de espera a su objeto Regex – Sparky

39

Creo que las excepciones son correctas en este caso.

Esto es lo que arme:

private static bool IsValidRegex(string pattern) 
{ 
    if (string.IsNullOrEmpty(pattern)) return false; 

    try 
    { 
     Regex.Match("", pattern); 
    } 
    catch (ArgumentException) 
    { 
     return false; 
    } 

    return true; 
} 
+1

Me pregunto si el compilador JIT será lo suficientemente inteligente o tonto para optimizar todo el bloque try catch porque no se usa el valor de retorno de una función pura. – deerchao

+0

¿'IsMatch()' sería más rápido/mejor que 'Match()', ya que no queremos realizar una coincidencia? Al igual que la prueba de primalidad es infinitamente (bueno, casi) más rápido que encontrar los factores. – dotNET

+0

'IsMatch()' [llamadas] (https://github.com/dotnet/corefx/blob/master/src/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.cs) 'ejecución de coincidencia interna (bool quick, int prevlen, string input, int beginning, int length, int startat) 'con' quick' establecido en 'true' mientras' Match() 'lo llama con' quick' establecido en 'false'. De hecho, es un poco más rápido, aproximadamente ** 1-5% ** de acuerdo con mis pruebas simples. –

0

Al utilizar el método siguiente puede comprobado si su expresión reguler es válida o no. aquí testPattern es el patrón que debes verificar.

public static bool VerifyRegEx(string testPattern) 
{ 
    bool isValid = true; 
    if ((testPattern != null) && (testPattern.Trim().Length > 0)) 
    { 
     try 
     { 
      Regex.Match("", testPattern); 
     } 
     catch (ArgumentException) 
     { 
      // BAD PATTERN: Syntax error 
      isValid = false; 
     } 
    } 
    else 
    { 
     //BAD PATTERN: Pattern is null or blank 
     isValid = false; 
    } 
    return (isValid); 
} 
Cuestiones relacionadas