2010-09-30 4 views
0

Je n'arrive pas à comprendre les captures + groupes dans Regex (.net).Regex: captures, groupes, confusion

Disons que j'ai la chaîne d'entrée suivante, où chaque lettre est en fait un espace réservé pour l'expression regex plus complexe (si simple exclusion de caractère ne fonctionnera pas):

CBDAEDBCEFBCD 

Ou, de manière plus générale, voici un modèle de chaîne écrite dans « regex »:

(C|B|D)*A(E*)(D|B|C)*(E*)F(B|C|D)* 

Il ne sera qu'un a et un F. je dois capturer en tant qu'individu « capture » (ou des allumettes ou des groupes) tous les cas de B, C, D (qui dans mon application sont des groupes plus complexes) qui se produisent af ter A et avant F. Je dois aussi A et F. Je ne ai pas besoin E. Et je ne ai pas besoin du C, B, D avant la A ou B, C, D après le F.

J'attends le résultat correct d'être:

Groups["start"] (1 capture) = A 
Groups["content"] (3 captures) 
    Captures[0] = D 
    Captures[1] = B 
    Captures[2] = C 
Groups["end"] (1 capture) = F 

J'ai essayé quelques tentatives faibles, mais aucun d'entre eux travaillaient.

seulement "de manière incorrecte" capture le dernier C avant EF dans la chaîne de l'échantillon ci-dessus (ainsi que correctement start = A, fin = F)

(?<=(?<start>A)).+(?<content>B|C|D).+(?=(?<end>F)) 

Mêmes résultats que ci-dessus (juste ajouté un + après (? B | C | D))

(?<=(?<start>A)).+(?<content>B|C|D)+.+(?=(?<end>F)) 

est débarrassé de regarder autour de choses ... même résultat que ci-dessus

(?<start>A).+(?<content>B|C|D)+.+(?<end>F) 

Et puis mon g Le cerveau du «rien pour rien» s'est mis en grève.

Alors, quelle est la bonne façon d'aborder ce sujet? Les look-arounds sont-ils vraiment nécessaires pour cela ou pas?

Merci!

Répondre

2

Ouais, oublier les lookarounds, ils compliquent inutilement les choses simplement.Mais je soupçonne que votre regex finale ne fonctionnera que si vous faites cette première .+ réticente:

(?<start>A).+?(?<content>B|C|D)+.+(?<end>F) 

EDIT: yep:

string s = "CBDAEDBCEFBCD"; 
Regex r = new Regex(@"(?<start>A).+?(?<content>B|C|D)+.+(?<end>F)"); 

foreach (Match m in r.Matches(s)) 
{ 
    Console.WriteLine(@"Groups[""start""] = {0}", m.Groups["start"]); 
    foreach (Capture c in m.Groups["content"].Captures) 
    { 
    Console.WriteLine(@"Capture[""content""] = {0}", c.Value); 
    } 
    Console.WriteLine(@"Groups[""end""] = {0}", m.Groups["end"]); 
} 

sortie:

Groups["start"] = A 
Capture["content"] = D 
Capture["content"] = B 
Capture["content"] = C 
Groups["end"] = F 
+0

Vraiment! Donc, les lookarounds ne sont pas nécessaires hein ... incroyable. – Jimmy

+0

@Jimmy: Dans ce cas, oui, les correctifs ne sont pas nécessaires. Mais ils ont leurs utilisations. : P –

0

Puisque vous avez dit tout instance de C,B,D, je pense que vous voudriez utiliser un groupement pour cette [CBD]* Aussi, si vous êtes à la recherche de quelque chose à être après la lettre A mais avant F, alors vous devriez être capable d'utiliser ces littéraux avec quelques exclusions.

Voici un modèle que j'ai imaginé. Groupe $4 doit contenir la lettre DBC

([^A]*)(A)([^CBDF]*)([CBD]*)([^F]*)(F)(.*) 

Voici un exemple de this pattern in action.

La question est, que voulez-vous si la chaîne d'origine est CBDAEDEBECEFBCD?

+0

Désolé, toutes les lettres sont les détenteurs de place pour les groupes plus complexes (je mettrai à jour la question) - donc je ne peux pas simplement utiliser des exclusions littérales. La chaîne CBDAEDEBECEFBCD que vous suggérez ne devrait pas correspondre du tout - il y a juste un tas de E entre A et le premier (B | C | D), et un tas de E juste avant le F. Encore une fois, dans mon application, ils ' ne sont pas seulement des E, ils sont juste des textes dont je n'ai pas besoin. – Jimmy

+0

Si c'est le cas, alors les look-arounds sont probablement votre seule option. – Snekse

+0

Pouvez-vous suggérer un look qui fonctionne? Même avec les regards, je n'arrive toujours pas à le faire fonctionner. – Jimmy