Pregunta

Estoy intentando analizar una cadena como la siguiente usando una expresión regular .NET:

H3Y5NC8E-TGA5B6SB-2NVAQ4E0

y devuelve lo siguiente usando Split:     H3Y5NC8E     TGA5B6SB     2NVAQ4E0

Valido cada carácter contra un conjunto de caracteres específico (tenga en cuenta que las letras 'I', 'O', 'U' & amp; 'W' están ausentes), por lo que usar string.Split no es una opción. El número de caracteres en cada grupo puede variar y el número de grupos también puede variar. Estoy usando la siguiente expresión:

([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8}-?){3}

Esto hará coincidir exactamente 3 grupos de 8 caracteres cada uno. Más o menos fallará el partido. Esto funciona en la medida en que coincida correctamente con la entrada. Sin embargo, cuando uso el método de división para extraer cada grupo de caracteres, solo obtengo el grupo final. RegexBuddy se queja de que he repetido el grupo de captura y de que debo colocar un grupo de captura alrededor del grupo repetido. Sin embargo, ninguno de mis intentos de hacer esto logra el resultado deseado. He estado intentando expresiones como esta:

(([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8})-?){4}

Pero esto no funciona.

Ya que genero la expresión regular en código, solo podía expandirla por el número de grupos, pero esperaba una solución más elegante.


Tenga en cuenta que el conjunto de caracteres no incluye todo el alfabeto. Es parte de un sistema de activación de producto. Como tal, se eliminan los caracteres que puedan interpretarse accidentalmente como números u otros caracteres. p.ej. Las letras 'I', 'O', 'U' & amp; 'W' no está en el conjunto de caracteres.

Los guiones son opcionales ya que un usuario no necesita la parte superior para escribirlos, pero pueden estar allí si el usuario realiza una copia & amp; pegar.

¿Fue útil?

Solución 2

He descubierto la respuesta que estaba buscando. Aquí está mi código de trabajo:

    static void Main(string[] args)
    {
        string pattern = @"^\s*((?<group>[ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8})-?){3}\s*<*>quot;;
        string input = "H3Y5NC8E-TGA5B6SB-2NVAQ4E0";
        Regex re = new Regex(pattern);
        Match m = re.Match(input);

        if (m.Success)
            foreach (Capture c in m.Groups["group"].Captures)
                Console.WriteLine(c.Value);
    }

Otros consejos

Por cierto, puede reemplazar [ABCDEFGHJKLMNPQRSTVXYZ0123456789] clase de caracteres con una clase de caracteres restada más legible.

[[A-Z\d]-[IOUW]]

Si solo quieres hacer coincidir 3 grupos así, ¿por qué no usas este patrón 3 veces en tu expresión regular y solo usas 1, 2, 3 subgrupos capturados para formar la nueva cadena?

([[A-Z\d]-[IOUW]]){8}-([[A-Z\d]-[IOUW]]){8}-([[A-Z\d]-[IOUW]]){8}

En PHP volvería (no sé .NET)

return "$1 $2 $3";

Después de revisar su pregunta y las respuestas dadas, se me ocurrió esto:

RegexOptions options = RegexOptions.None;
Regex regex = new Regex(@"([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8})", options);
string input = @"H3Y5NC8E-TGA5B6SB-2NVAQ4E0";

MatchCollection matches = regex.Matches(input);
for (int i = 0; i != matches.Count; ++i)
{
    string match = matches[i].Value;
}

Desde el " - " Es opcional, no necesitas incluirlo. ¿No estoy seguro de para qué usaba el {4} al final? Encontrará las coincidencias en función de lo que desee y luego, utilizando MatchCollection, podrá acceder a cada coincidencia para reconstruir la cadena.

¿Por qué usar Regex? Si los grupos siempre están divididos por un -, ¿no puede usar Split ()?

Lo siento si esto no es lo que pretendía, pero su cadena siempre tiene el guión que separa los grupos. En lugar de usar expresiones regulares, ¿no podría usar el método String.Split ()?

Dim stringArray As Array = someString.Split("-")

¿Cuáles son las características definitorias de un bloque válido? Necesitaríamos saber eso para ser realmente útiles.

Mi sugerencia genérica, validar el conjunto de caracteres en un primer paso, luego dividir y analizar en un método separado basado en lo que esperas. Si esto está en un sitio web / aplicación, puede usar la validación ASP Regex en el extremo delantero y luego dividirlo en el extremo posterior.

Si solo está verificando el valor del grupo, con group (i) .value, solo obtendrá el último. Sin embargo, si desea enumerar todas las veces que se capturó ese grupo, use group (2) .captures (i) .value, como se muestra a continuación.

system.text.RegularExpressions.Regex.Match("H3Y5NC8E-TGA5B6SB-2NVAQ4E0","(([ABCDEFGHJKLMNPQRSTVXYZ0123456789]+)-?)*").Groups(2).Captures(i).Value

Mike,

Puedes usar el conjunto de caracteres de tu elección dentro del grupo de caracteres. Todo lo que necesitas es agregar " + " Modificador para capturar todos los grupos. Vea mi respuesta anterior, simplemente cambie [A-Z0-9] a lo que necesite (es decir, [ABCDEFGHJKLMNPQRSTVXYZ0123456789])

Puedes usar este patrón:

Regex.Split("H3Y5NC8E-TGA5B6SB-2NVAQ4E0", "([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8}+)-?")

Pero deberá filtrar las cadenas vacías de la matriz resultante. Cita de MSDN :

  

Si hay varias coincidencias adyacentes entre sí, se inserta una cadena vacía en la matriz.

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