2010-12-29 21 views
5
myRegex.GetGroupNames() 

Parece que también devuelve los grupos numerados ... ¿cómo obtengo solo los nombres?C# Regex: ¿Obtener nombres de grupos?

Una solución que use el objeto Match real también estaría bien.

+0

¿Por qué tiene grupos nombrados y numerados? ¿Por qué no te limitas a una u otra? ¿Puedes publicar tu expresión regular? –

+0

@Mark: Yo no. Se agregan automáticamente (el grupo puede referirse por nombre o número). Mi expresión regular es '^ (?:/Image :(? \ d +)) $'. Los paréntesis externos no deberían capturar si no me equivoco. – mpen

+0

** Editar: ** En realidad, el 0 es probablemente el que coincide con la expresión regular completa ... – mpen

Respuesta

2
public string[] GetGroupNames(Regex re) 
{ 
    var groupNames = re.GetGroupNames(); 
    var groupNumbers = re.GetGroupNumbers(); 

    Contract.Assert(groupNames.Length == groupNumbers.Length); 

    return Enumerable.Range(0, groupNames.Length) 
     .Where(i => groupNames[i] != groupNumbers[i].ToString()) 
     .Select(i => groupNames[i]) 
     .ToArray(); 
} 

En realidad, esto todavía se producirá un error cuando el nombre del grupo y el número de pasar a ser la misma: \ Pero tendrá éxito incluso cuando el nombre del grupo es un número, siempre y cuando el número no es lo mismo como su índice.

+0

Sí ... lea el último párrafo. Todavía falla bajo esa única condición. Si sabes una forma de evitar esto, por favor, ilumíname :) ** Editar: ** Doh ... borraste tu comentario. Ahora esto parece fuera de lugar. – mpen

+0

¡Excelente! Ahorro mucho tiempo Gracias. – Cylian

2

Vea los otros comentarios/respuestas sobre el uso de (?:) y/o quedarse con "un estilo". Aquí es mi mejor enfoque que trata de resolver directamente la cuestión:

var named = regex.GetGroupNames().Where(x => !Regex.IsMatch(x, "^\\d+$")); 

Sin embargo, esto va a fallar por expresiones regulares como (?<42>...).

Happy coding.

+0

Sí ... Creo que podemos hacer una mejor sin embargo. Codificándolo ahora – mpen

+0

@Ralph Considere este caso: '(? <1> ..)' - GetGroupNumbers/Los nombres todavía deben "alinearse" :-) –

+0

Sí :(Pero todavía es un poco más robusto que esta solución: P – mpen

7

¿Al usar la opción RegexOptions.ExplicitCapture al crear la expresión regular, haga lo que quiera? p.ej.

Regex theRegex = new Regex(@"\b(?<word>\w+)\b", RegexOptions.ExplicitCapture); 

De MSDN:

Especifica que los únicos válidos capturas se nombran o numeradas grupos de forma explícita (?<name>...). Este permite que los paréntesis sin nombre actúen como grupos no capturados sin la torpeza sintáctica de la expresión (?:...).

Así que no tendrá que preocuparse si los usuarios de su API pueden o no pueden usar grupos no capturados si esta opción está configurada.

+0

¡Oh! Sneaky. I Tengo que pensar en esto. Quería manejar capturas nombradas y numeradas por separado, por eso es importante para mí diferenciar entre las dos ... pero estoy debatiendo qué tan útil es la compatibilidad de las capturas numeradas. ** Editar: * * Incluso con captura explícita, todavía devuelve la captura número 0, pero se puede recortar fácilmente. – mpen

+2

Los grupos nombrados y los grupos numerados no se deben usar en la misma expresión regular de todos modos, es demasiado confuso. Si no controla la fuente de las expresiones regulares, puede ahorrarse muchas molestias forzando el modo ExplicitCapture. Además, es posible que desee prohibir el uso de nombres de grupos que * parecen * números, por ejemplo '(? <2> ...) ' –

+0

@ Alan: Tal vez no deberían mezclarse, pero creo que aún deberían tener la opción de cualquiera. Esto va a un enrutador url para un marco web.Las coincidencias nombradas se convertirán en argumentos para una función con parámetros con el mismo nombre. Alternativamente, pueden usar coincidencias numeradas para completar los argumentos de izquierda a derecha. – mpen

Cuestiones relacionadas