9
votes

I'm parsing a text using C# regex. I want to replace only one specific group in for each match. Here how I'm doing it:

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]
}
6

6 Answers

12
votes

This should do it:

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());
}

Example: http://rextester.com/DLGVPA38953

EDIT: Although the above is the answer to your question as written, you may find zero-width lookarounds simpler for your actual scenario:

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

Example: http://rextester.com/SOWWS24307

5
votes

You can use MatchEvaluator: Try This.

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

I found one post in stackoverflow related to this: watch This

5
votes

How about this?

    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
votes

Regex.Replace will always replace everything that the provided regex has matched.

You have two possibilities:

  1. Match only what you want to replace

    or

  2. Insert the parts of the original string which has been matched, but should be kept, into the replacement string, using capturing groups.

You provided not enough information to answer your question more specific. E.g. do you really need a MatchEvaluator? This is only needed, if you want to provide an individual replacement string for each match.

0
votes
    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
votes

The below code will take a match and construct a replacement string based on the groupValues collection. This collection specifies a Group index and the text to replace it's value with.

Unlike other solutions, it does not require the entire match to be contained in groups, only the parts of the match that you want to have in groups.

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();
}