2010-11-29 9 views
15

Cómo poner a prueba el uso de expresiones regulares en C# si:C# simple expresión regular - 32 caracteres, que contiene sólo 0-9 y AF (GUID)

  • longitud de la cadena es exactamente 32
  • cadena contiene sólo los números del 0 -9 cartas y pequeños de AF
+2

¿Qué has probado? ¿Cómo te ha funcionado eso? ¿Qué tipo de cosas no funcionaron? Estamos aquí para ayudar. No hacer el trabajo –

+0

Sé cómo verificar la longitud O verificar 0-9 O af, pero no puedo combinar todo :( –

+0

Todavía sería útil si publicara las cosas que ha intentado –

Respuesta

26

¿Qué tal:

Regex regex = new Regex("^[0-9a-f]{32}$"); 
if (regex.IsMatch(text)) 
... 
+0

Creo que te falta el guión. –

+0

@SimonOliverHurley: No de la descripción en la pregunta. "Cadena contiene solo números del 0-9 y letras minúsculas de af" - sin mención de un guión allí. –

4

Si no estás muerto-set en el uso de una expresión regular para este pu rpose, esto es bastante limpio:

Func<char, bool> charValid = c => (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'); 
bool isValid = text.Length == 32 && text.All(charValid); 
+1

Prefiero la expresión regular un millón de veces. Es más corta, más limpia, más fácil de entender y de cambiar, probablemente incluso más eficiente (no es que lo haya comprobado, o que importe). - ¿Por qué algunas personas están tan interesadas? para evitarlos? –

+1

@Konrad me personalmente porque generalmente son muy malos en la intención de comunicación y en general funcionan peor que las opciones más legibles. En este par No me importa la simple necesidad, aunque llamar a un método en Guid sería mi opción preferida si fuera posible –

+1

@Konrad, me gusta Regex, particularmente para tareas más sofisticadas que requieren una compleja coincidencia contextual. Sin embargo, si el problema es relativamente simple, a menudo prefiero un enfoque más explícito, aunque solo sea porque no todos mis colegas comprenden bien Regex. –

3

Ok, así que no hay una respuesta aquí que le muestra cómo averiguar si esta cadena es de 32 caracteres de longitud, y cada personaje es o bien un dígito o minúscula 'a' a minúsculas 'f' con una expresión regular , y otro que le muestra cómo hacerlo con un Func simple que escanea los caracteres en la cadena. Ambas son respuestas geniales y técnicamente correctas, pero en el título de su pregunta indica explícitamente "GUID" que abre una nueva lata de gusanos.

Los GUID pueden tomar una serie de representaciones de cadenas diferentes, y puede encontrar cualquiera de ellas. ¿Necesitas manejar todos estos? ¿Necesitarás acomodar cadenas que comiencen y terminen con llaves ('{' y '}') o paréntesis? ¿Qué pasa con los guiones ('-')? According to MSDN, creando un nuevo GUID con

string s = ...; 
Guid g = new Guid(s); 

Permite para cuerdas en las siguientes formas

32 dígitos contiguos: dddddddddddddddddddddddddddddddd

-o-

grupos de 8, 4, 4, 4 y 12 dígitos con guiones entre los grupos. La totalidad de GUID opcionalmente se puede encerrar en la adecuación de llaves o paréntesis: dddddddddddd-dddddddd-dddddddddddd

-o-

{dddddddddddd-dddddddd-dddddddddddd}

-o-

(dddddddddddd-dddddddd-dddddddddddd)

-o-

Grupos de 8, 4 y 4 dígitos, y un subconjunto de ocho grupos de 2 dígitos, con cada grupo con el prefijo "0x" o "0X", y separados por comas.La totalidad de GUID, así como el subconjunto, es encerrado en la adecuación de los apoyos: {0xDDDDDDDD, 0xdddd, 0xdddd, {0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd}}

Do necesita manejar todos estos casos? Además, considere si el uso de una expresión regular es realmente la mejor opción. Como algunas personas ya han comentado, regex puede ser confuso para algunos desarrolladores, y la intención no siempre es clara. Además de eso, regex puede ser lento en algunos casos.

me prepararon rápidamente una prueba de rendimiento rápido en tres formas diferentes de determinar si una cadena es de hecho una representación de cadena de un GUID:

  1. Regex
  2. Comprobación de todos los caracteres en la cadena
  3. Creación una nueva instancia de Guid con la cadena dada (si se puede crear el Guid, entonces la cadena es una representación de cadena válida)

Aquí está el código:

[Test]

public void Test_IsRegex_Performance() 
{ 
    Action withRegexMatch =() => 
    { 
     Regex regex = new Regex("^[0-9a-f]{32}$"); 
     Guid g = new Guid(); 
     string s = g.ToString(); 
     regex.IsMatch(s); 
    }; 

    Action withCharCheck =() => 
    { 
     Guid g = new Guid(); 
     string s = g.ToString(); 

     Func<char, bool> charValid = c => (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'); 
     bool isValid = s.Length == 32 && s.All(charValid); 
    }; 

    Action withNewGuid =() => 
    { 
     Guid g = new Guid(); 
     string s = g.ToString(); 
     try 
     { 
      Guid g2 = new Guid(s); 
      // if no exception is thrown, this is a valid string 
      // representation 
     } 
     catch 
     { 
      // if an exception was thrown, this is an invalid 
      // string representation 
     } 
    }; 

    const int times = 100000; 

    Console.WriteLine("Regex: {0}", TimedTask(withRegexMatch, times)); 
    Console.WriteLine("Checking chars: {0}", TimedTask(withCharCheck, times)); 
    Console.WriteLine("New Guid: {0}", TimedTask(withNewGuid, times)); 
    Assert.Fail(); 
} 

private static TimeSpan TimedTask(Action action, int times) 
{ 
    Stopwatch timer = new Stopwatch(); 
    timer.Start(); 
    for (int i = 0; i < times; i++) 
    { 
     action(); 
    } 
    timer.Stop(); 
    return timer.Elapsed; 
} 

Y los resultados de un millón de iteraciones en mi máquina:

Regex: 00:00:10.1786901 
Checking chars: 00:00:00.2504520 
New Guid: 00:00:01.3129005 

Por lo tanto, la solución de expresiones regulares es lento. Pregúntese si realmente necesita una expresión regular aquí. Tenga en cuenta que probablemente pueda obtener algún rendimiento adicional declarando la expresión regular una vez y reutilizándola, pero creo que el punto en este caso es que podría tener un mejor éxito si mira lo que está tratando de lograr, ya que opuesto a cómo.

Espero que ayude.

+0

El punto de referencia es totalmente injusto y no representativo. Por lo menos, compila la expresión una vez y vuelve a utilizarla. Además, pruebe también una solución de expresión regular * compilada *. Esto puede no importar mucho para esta expresión en particular, pero de nuevo, puede. Lo mismo aplica para 'nuevo Guid'. Elimina el bloque 'try' y utiliza' Guid.TryParse' en su lugar. –

+0

Algunos puntos: Lo que manejaba con mi publicación era que los Guids pueden tomar una cantidad de formas diferentes, por lo que tal vez el código de los carteles tenga que manejar eso. Me referí al hecho de que Regex puede declararse una vez y reutilizarse. Además, Guid.TryParse solo existe en .net 4.0, así que no lo intenté, apostaría a que el rendimiento sería similar a crear una nueva instancia de Guid (probablemente un poco más rápido). – matt

+0

Finalmente, el punto de que Regex es difícil para muchos desarrolladores sigue en pie, creo. La intención no siempre es clara, y a menos que exista una razón muy específica para usarlos (por ejemplo, verificar si el texto es totalmente numérico o si es un número de teléfono bien formado), rara vez los toco. Su experiencia puede ser diferente. – matt

Cuestiones relacionadas