2016-08-09 462 views
2

Ich habe eine Regexrule.cs Klasse, es besteht aus den folgenden Eigenschaften:Ersetzen Regex String in C#

public string Expression { get; set; } 
    public string FirstOpen { get; set; } 
    public string FirstClose { get; set; } 
    public string SecondOpen { get; set; } 
    public string SecondClose { get; set; } 

Expression hält einen Regular Expression Wert, und es wird immer zurück 2 Gruppen erwartet.

Die vier Felder (ohne Expression) sind Präfixe und Suffixe für die beiden Gruppen, die gefunden werden, wird erwartet, dass ... so, dass dies geschieht:

FirstOpen + Group[1] + FirstClose und SecondOpen + Group[2] + SecondClose

Wie dem auch sei, ich habe eine List<RegexRule> Rules; das enthält eine Liste von RegexRules Objekten.

Die Predicament

Ihr Ziel ist, durch jeden man jene (RegexRules r) zur Schleife, führen ihre jeweiligen Ausdruck (r.Expression) auf eine besonders lange Zeichenfolge, und als die beiden erwarteten Gruppen sind gefunden, möchte ich das Skript jede Gruppe mit ihren Präfixe und Suffixe in der Art und Weise ... wieder gezeigt,

r.FirstOpen + Group[1] + r.FirstClose und r.SecondOpen + Group[2] + r.SecondClose

einzukapseln

Ich habe viele verschiedene Möglichkeiten ausprobiert, aber eine Sache, die ich weiß ist, dass str.Replace nicht funktioniert, in einer Schleife. Weil es die Präfixe und Suffixe für jedes Auftreten der Ergebnisse des Ausdrucks immer wieder anwendet.

Also, wie sonst kann das erreicht werden?

Vielen Dank.

bearbeiten

Dies ist, was ich zur Zeit habe:

foreach (RegexRule r in RegexRules.ToList()) 
{ 
    Regex rx = new Regex(r.Expression); 
    MatchCollection mc = rx.Matches(str); 
    foreach (Match m in mc) 
    { 
     MessageBox.Show("replacing"); 
     str = str.Replace(m.Groups[1].Value, r.OpenBBOne + m.Groups[1].Value + r.CloseBBOne); 
    } 
} 

Edit 2 - Besonderheiten

Benutzer ihre eigenen Regex Konfigurationen in ein schaffen .config Datei, und es wird in diesem Format sein:

reg {(\w+).(\w+)\(\);} = [("prefix1","suffix1"),("prefix2","suffix2")];


reg - Standard-Wort für ein neues RegexRule definieren
{ {(\w+).(\w+)\(\); } - Ihr Regulärer Ausdruck (Bedingung: Ausdruck muss immer wieder zurückkehrt 2 Gruppen in seinen Ursachen)
[("prefix1","suffix1"),("prefix2","suffix2")] - Zwei Parameter in `[(“ “, ""), ("", "")] -, die den Präfixen und Suffixen für die beiden Gruppen repräsentieren

** ** Beispiel

Wenn wir die obige Konfiguration auf diese Zeichenfolge angewandt:

Lorem ipsum foo.bar(); dolor sit bar.foo(); amit consecteteur...

Die Regex würde foo.bar() als Übereinstimmung erfassen, in diesen foo ist Spiel [1] Gruppe [1], und bar ist Spiel [1] Gruppe [2], entsprechend dem regulären Ausdruck.

Das Gleiche gilt für bar.foo(), weil bar Spiel ist [2] Gruppe [1], und foo Spiel [2] Gruppe [2]

Ich hoffe, dass dieses Gefühl ... unser macht

+2

Das fühlt sich wirklich so an, als wollten Sie ein Designmuster erzwingen, das nicht dem tatsächlichen Bedarf entspricht. Vielleicht möchten Sie einen Schritt sichern und versuchen, aus einem anderen Blickwinkel zu sehen, was Sie tun. Mein $ .02 –

+0

@ JeremyHolovacs Ich weiß nicht ... wie sonst könnte es getan werden? –

+0

@BarryD, Angenommen, Sie haben '([0-9]). ([A-z])' als Regex und '1aa1' als Eingabezeichenfolge. Möchten Sie * beide * '1 ersetzen oder nur die erste (d. H. Eine, die der Regex entspricht)? –

Antwort

1

Per Diskussion, ich denke, das könnte eine Lösung für Sie sein. Es hat mit dem ersten Kommentar zu tun, den ich gemacht habe. Es gibt Ihnen einzigartige Werte für Ihre MatchCollection mit .Distinct(), so dass Sie nicht am Ende die Präfixe und Suffixe zu ergänzen.

foreach(RegexRule r in RegexRules.ToList()) 
{ 
    Regex rx = new Regex(r.Expression); 
    MatchCollection mc = rx.Matches(str); 
    foreach(Match m in mc.OfType<Match>().Distinct()) 
    { 
     MessageBox.Show("replacing"); 
     str = str.Replace(m.Groups[1].Value, 
          r.OpenBBOne + m.Groups[1].Value + r.CloseBBOne); 
    } 
} 

Wenn Sie LINQ aus irgendeinem Grunde nicht verwenden, können Sie immer tun, im Grunde nur die gleiche Sache selbst durch eine neues List<Match> zu schaffen und nur in denjenigen hinzufügen, die noch nicht in der Liste enthalten sind.

foreach(RegexRule r in RegexRules.ToList()) 
{ 
    Regex rx = new Regex(r.Expression); 
    MatchCollection mc = rx.Matches(str); 

    List<Match> matches = new List<Match>(); 
    List<string> strings = new List<string>(); 
    foreach(Match m in mc) 
     if(!strings.Contains(m.Value)) 
     { 
      matches.Add(m); 
      strings.Add(m.Value); 
     } 

    foreach(Match m in matches) 
    { 
     MessageBox.Show("replacing"); 
     str = str.Replace(m.Groups[1].Value, 
          r.OpenBBOne + m.Groups[1].Value + r.CloseBBOne); 
    } 
} 
+0

Das war nicht nur schwierig zu erklären, aber ich konnte wirklich nicht darüber hinweg kommen, und Sie präsentierten die einzige Lösung, die ich ohne Ausnahme habe. Und es hat funktioniert. Vielen Dank, mein Herr!! Aber: 'mc.Distinct();' wird nicht funktionieren, weil es eine 'MatchCollection' ist, danke für die Alternative :) –

+0

Ah, yeah, du hast Recht. Ich habe vergessen, dass Sie den Typ definieren müssen, damit Sie den Enumerator erhalten können. Ich habe meine Antwort bearbeitet, damit sie mit LINQ funktioniert. – Meloviz