Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace multiple Regex Matches each with a different replacement

Tags:

c#

regex

I have a string that may or may not have multiple matches for a designated pattern.

Each needs to be replaced.

I have this code:

var pattern = @"\$\$\@[a-zA-Z0-9_]*\b";
var stringVariableMatches = Regex.Matches(strValue, pattern);
var sb = new StringBuilder(strValue);

foreach (Match stringVarMatch in stringVariableMatches)
{
    var stringReplacment = variablesDictionary[stringVarMatch.Value];
    sb.Remove(stringVarMatch.Index, stringVarMatch.Length)
            .Insert(stringVarMatch.Index, stringReplacment);
}

return sb.ToString();

The problem is that when I have several matches the first is replaced and the starting index of the other is changed so that in some cases after the replacement when the string is shorten I get an index out of bounds..

I know I could just use Regex.Replace for each match but this sound performance heavy and wanted to see if someone could point a different solution to substitute multiple matches each with a different string.

like image 336
Mortalus Avatar asked May 11 '16 09:05

Mortalus


People also ask

How do you substitute in regex?

To perform a substitution, you use the Replace method of the Regex class, instead of the Match method that we've seen in earlier articles. This method is similar to Match, except that it includes an extra string parameter to receive the replacement value.

What is $1 in regex replace?

For example, the replacement pattern $1 indicates that the matched substring is to be replaced by the first captured group.

Is regex faster than string replace?

String operations will always be faster than regular expression operations. Unless, of course, you write the string operations in an inefficient way. Regular expressions have to be parsed, and code generated to perform the operation using string operations.

Does Python replace take regex?

Regex can be used to perform various tasks in Python. It is used to do a search and replace operations, replace patterns in text, check if a string contains the specific pattern.


1 Answers

Use a Match evaluator inside the Regex.Replace:

var pattern = @"\$\$\@[a-zA-Z0-9_]*\b";
var stringVariableMatches = Regex.Replace(strValue, pattern, 
        m => variablesDictionary[m.Value]);

The Regex.Replace method will perform global replacements, i.e. will search for all non-overlapping substrings that match the indicated pattern, and will replace each found match value with the variablesDictionary[m.Value].

Note that it might be a good idea to check if the key exists in the dictionary.

See a C# demo:

using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Linq;
public class Test
{
    public static void Main()
    {
        var variablesDictionary = new Dictionary<string, string>();
        variablesDictionary.Add("$$@Key", "Value");
        var pattern = @"\$\$@[a-zA-Z0-9_]+\b";
        var stringVariableMatches = Regex.Replace("$$@Unknown and $$@Key", pattern, 
                m => variablesDictionary.ContainsKey(m.Value) ? variablesDictionary[m.Value] : m.Value);
        Console.WriteLine(stringVariableMatches);
    }
}

Output: $$@Unknown and Value.

like image 191
Wiktor Stribiżew Avatar answered Oct 01 '22 13:10

Wiktor Stribiżew