2010-02-12 8 views
6

Je fais une petite application en utilisant les types .NET Regex. Et les types "Capture, Groupe et Match" m'ont totalement confondu. Je n'ai jamais vu une solution aussi laide. Quelqu'un pourrait-il expliquer leur utilisation pour moi? Merci beaucoup.Différences entre .NET Capture, Groupe, Correspondance

+0

Avez-vous un exemple d'expression régulière que vous voulez que nous l'expliquions? – Gumbo

Répondre

12

Voici un exemple plus simple que celui dans le document cité @Dav:

string s0 = @"foo%123%456%789"; 
Regex r0 = new Regex(@"^([a-z]+)(?:%([0-9]+))+$"); 
Match m0 = r0.Match(s0); 
if (m0.Success) 
{ 
    Console.WriteLine(@"full match: {0}", m0.Value); 
    Console.WriteLine(@"group #1: {0}", m0.Groups[1].Value); 
    Console.WriteLine(@"group #2: {0}", m0.Groups[2].Value); 
    Console.WriteLine(@"group #2 captures: {0}, {1}, {2}", 
        m0.Groups[2].Captures[0].Value, 
        m0.Groups[2].Captures[1].Value, 
        m0.Groups[2].Captures[2].Value); 
} 

Résultat:

full match: foo%123%456%789
group #1: foo
group #2: 789
Les résultats full match et group #1 sont simples, mais les autres nécessitent quelques explications. Les résultats full match et group #1 sont simples. Le groupe 2, comme vous pouvez le voir, fait partie d'un groupe non-capturant contrôlé par un quantificateur +. Il correspond trois fois, mais si vous demandez son Value, vous obtenez seulement ce qu'il correspondait la troisième fois - la capture finale. De même, si vous utilisez l'espace réservé $2 dans une chaîne de remplacement, la capture finale est ce qui est inséré à sa place.

Dans la plupart des saveurs de regex, c'est tout ce que vous pouvez obtenir; chaque capture intermédiaire est écrasée par la suivante et perdue; .NET est presque unique en préservant toutes les captures et en les rendant disponibles après le match. Vous pouvez y accéder directement comme je l'ai fait ici, ou parcourir le CaptureCollection comme vous le feriez pour un MatchCollection. Cependant, il n'y a pas d'équivalent pour les espaces réservés pour la chaîne de remplacement $1. La raison pour laquelle la conception de l'API est si moche (comme vous l'avez dit) est double: tout d'abord, elle a été adaptée du support de regex intégral de Perl à la structure orientée objet de .NET; puis la structure CaptureCollection a été greffée dessus. Perl 6 offre une solution beaucoup plus propre, mais les auteurs l'ont fait en réécrivant pratiquement Perl à partir de rien et en rejetant la compatibilité descendante par la fenêtre.

+1

Bonjour, merci Alan. Juste 2 questions de plus, il y a une propriété nommée "Captures" pour Match et Groupe, quelle est la différence entre Match.Captures et Group.Captures? Et pourquoi les Match.Groups [0] sont-ils toujours les mêmes que Match.Value? Merci encore. – smwikipedia

+0

Une correspondance ISA Group ISA Capture, donc Match hérite 'Captures' de Groupe et' Value' de Capture. Le Match est le groupe zéro, donc 'Match.Captures' est simplement une liste d'un élément contenant toute la correspondance - comme si nous avions besoin d'un autre moyen de s'y référer! La valeur est évidemment la méthode préférée, étant beaucoup plus courte et plus intuitive. Mais même cela est facultatif si vous utilisez la référence Match/Group/Capture qui attend une chaîne, car 'ToString()' délègue simplement 'Value'. –

+0

Pour ce qui est de * pourquoi * le Match est le zéro-ème Groupe, voir cette réponse: http://stackoverflow.com/questions/2248213/in-c-regular-expression-why-does-the-initial-match-show -up-in-the-groups/2248767 # 2248767 –

2

Une correspondance est le résultat de n'importe quelle correspondance du entier d'une regex. Les groupes et les captures ont tous deux quelque chose à voir avec les groupes de capture (chacun (expression) à partir de la regex), mais varient dans la façon dont ils se comportent. Voici une citation de l'article MSDN sur la classe de capture qui explique la différence:

Si vous ne faites pas un quantificateur à un groupe de capture , les Group.Captures propriété retourne un CaptureCollection avec un seul objet de capture que fournit des informations sur la même capture que l'objet Groupe. Si vous ne appliquer un quantificateur à un groupe la capture, le Group.Index, Group.Length, et propriétés Group.Value fournir d'informations que sur le dernier groupe capturé , alors que les objets capture dans le CaptureCollection fournir des informations à propos de toutes les captures de sous-expression . L'exemple fournit une illustration.

(Source)