2012-10-22 7 views
7

Sto analizzando un testo usando C# regex. Voglio sostituire solo un gruppo specifico per ogni partita. Ecco come lo sto facendo:Regex in C# - come sostituire un solo gruppo specifico in Match?

void Replace(){ 
    string newText = Regex.Replace(File.ReadAllText(sourceFile), myRegex, Matcher, RegexOptions.Singleline); 
    //....... 
} 

void string Matcher(Match m){ 
    // how do I replace m.Groups[2] with "replacedText"? 
    return ""; // I want to return m.Value with replaced m.Group[2] 
} 

risposta

10

Questo dovrebbe farlo:

string Matcher(Match m) 
{ 
    if (m.Groups.Count < 3) 
    { 
     return m.Value; 
    } 

    return string.Join("", m.Groups 
          .OfType<Group>() //for LINQ 
          .Select((g, i) => i == 2 ? "replacedText" : g.Value) 
          .Skip(1) //for Groups[0] 
          .ToArray()); 
} 

Esempio: http://rextester.com/DLGVPA38953

EDIT: lookarounds Anche se quanto sopra è la risposta alla tua domanda come scritto, si possono trovare zero larghezza più semplice per il vostro attuale scenario:

Regex.Replace(input, @"(?<=e)l+(?=o)", replacement) 

Esempio: http://rextester.com/SOWWS24307

012.
+0

@AlanDert - Questo è probabilmente un problema con la tua espressione regolare. [Ecco un esempio di questo codice in esecuzione online.] (Http://rextester.com/GFFO18933) Potresti voler provare a modificare il tuo modello regolare. –

+0

Un problema con questa soluzione è che è necessario che l'intera corrispondenza sia contenuta nei gruppi, mentre è logico avere solo parti specifiche di una corrispondenza in Gruppi per consentire un accesso più facile alle parti rilevanti. –

+0

@MrUniverse - Se ricordo bene, è quello che stavo ottenendo con il mio addendum sui lookaround a larghezza zero. –

4

È possibile utilizzare MatchEvaluator: Try This.

var replaced = Regex.Replace(text, pattern, m => m.Groups[1] + "AA" + m.Groups[3]); 

ho trovato un post in StackOverflow relative a questo: guardare This

+2

Ma OP ha già un MatchEvaluator 'vuoto stringa Matcher (Match m) {}' –

+1

In [che altra risposta] (http://stackoverflow.com/a/6005637/20938), la soluzione corretta era il primo: sostituirlo con la stringa '" $ 1AA $ 3 "'. Non c'era bisogno di un MatchValator lì, e probabilmente non c'è nemmeno bisogno di uno qui. –

4

ne dici di questo?

static string Matcher(Match m) 
    { 
     var group = m.Groups[2]; 
     var startIndex = group.Index - m.Index; 
     var length = group.Length; 
     var original = m.Value; 
     var prior = original.Substring(0, startIndex); 
     var trailing = original.Substring(startIndex + length); 
     return string.Concat(prior, "replacedText", trailing); 
    } 
2

Regex.Replace saranno sempre sostituire tutto che l'espressione regolare fornita ha abbinati.

Avete due possibilità:

  1. Partita solo ciò che si desidera sostituire

    o

  2. Inserire le parti della stringa originale, che è stato abbinato, ma dovrebbero essere tenuti, nella stringa di sostituzione, utilizzando i gruppi di cattura.

Fornite informazioni insufficienti per rispondere alla domanda in modo più specifico. Per esempio. hai davvero bisogno di un MatchEvaluator? Questo è necessario solo se si desidera fornire una singola stringa di sostituzione per ogni partita.

0
private string ReplaceText(string originalText) 
    { 
     string replacedText = null; 

     Regex regEx = new Regex("[your expression here]"); 

     Match match = regEx.Match(originalText); 

     if (match.Success) 
     { 
      Group matchGroup = match.Groups[2]; 

      //[first part of original string] + [replaced text] + [last part of original string] 
      replacedText = 
       $"{originalText.Substring(0, matchGroup.Index)}[Your replaced string here]{originalText.Substring(matchGroup.Index + matchGroup.Length)}"; 

     } 
     else 
      replacedText = originalText; 

     return replacedText; 
    } 
+0

si prega di chiarire la risposta –

+0

@AlexFilatov sicuro quale parte? Si potrebbe chiamarla in questo modo ReplaceText ("Ciao Country") normalmente questi sarebbero passati come parametro [tua espressione qui] è quello che stai cercando è "Paese" [ "La stringa qui sostituito "] è" Mondo " quello che torneresti restituito a" Hello World " se non viene trovato nulla si ripristina la stringa originale. – Raymond

0

Il codice seguente eseguirà una corrispondenza e costruirà una stringa di sostituzione in base alla raccolta groupValues. Questa raccolta specifica un indice di gruppo e il testo per sostituire il suo valore con.

A differenza di altre soluzioni, non richiede che l'intera partita sia contenuta in gruppi, ma solo le parti della corrispondenza che si desidera avere nei gruppi.

public static string ReplaceGroups(Match match, Dictionary<int, string> groupValues) 
{ 
    StringBuilder result = new StringBuilder(); 

    int currentIndex = 0; 
    int offset = 0; 

    foreach (KeyValuePair<int, string> replaceGroup in groupValues.OrderBy(x => x.Key)) 
    { 
     Group group = match.Groups[replaceGroup.Key]; 

     if (currentIndex < group.Index) 
     { 
      result.Append(match.Value.Substring(currentIndex, group.Index - match.Index - currentIndex)); 
     } 

     result.Append(replaceGroup.Value); 

     offset += replaceGroup.Value.Length - group.Length; 
     currentIndex = group.Index - match.Index + group.Length; 
    } 

    return result.ToString(); 
}