Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regex replace multiple groups

I would like to use regular expressions to replace multiple groups with corresponding replacement string.

Replacement table:

  • "&" -> "__amp"
  • "#" -> "__hsh"
  • "1" -> "5"
  • "5" -> "6"

For example, for the following input string

"a1asda&fj#ahdk5adfls"

the corresponding output string is

"a5asda__ampfj__hshahdk6adfls"

Is there any way to do that?

like image 483
bartosz.lipinski Avatar asked Sep 08 '11 15:09

bartosz.lipinski


People also ask

How do you replace multiple values in a string?

var str = "I have a cat, a dog, and a goat."; str = str. replace(/cat/gi, "dog"); str = str. replace(/dog/gi, "goat"); str = str. replace(/goat/gi, "cat"); //this produces "I have a cat, a cat, and a cat" //but I wanted to produce the string "I have a dog, a goat, and a cat".

Can I use RegEx in replace?

How to use RegEx with . replace in JavaScript. To use RegEx, the first argument of replace will be replaced with regex syntax, for example /regex/ . This syntax serves as a pattern where any parts of the string that match it will be replaced with the new substring.

How do I replace multiple characters in a string?

Use the replace() method to replace multiple characters in a string, e.g. str. replace(/[. _-]/g, ' ') . The first parameter the method takes is a regular expression that can match multiple characters.


3 Answers

Given a dictionary that defines your replacements:

IDictionary<string, string> map = new Dictionary<string, string>() {     {"&","__amp"},     {"#","__hsh"},     {"1","5"},     {"5","6"}, }; 

You can use this both for constructing a Regular Expression, and to form a replacement for each match:

var str = "a1asda&fj#ahdk5adfls"; var regex = new Regex(String.Join("|",map.Keys)); var newStr = regex.Replace(str, m => map[m.Value]); // newStr = a5asda__ampfj__hshahdk6adfls 

Live example: http://rextester.com/rundotnet?code=ADDN57626

This uses a Regex.Replace overload which allows you to specify a lambda expression for the replacement.


It has been pointed out in the comments that a find pattern which has regex syntax in it will not work as expected. This could be overcome by using Regex.Escape and a minor change to the code above:

var str = "a1asda&fj#ahdk5adfls"; var regex = new Regex(String.Join("|",map.Keys.Select(k => Regex.Escape(k)))); var newStr = regex.Replace(str, m => map[m.Value]); // newStr = a5asda__ampfj__hshahdk6adfls 
like image 71
Jamiec Avatar answered Oct 05 '22 05:10

Jamiec


How about using string.Replace()?

string foo = "a1asda&fj#ahdk5adfls"; 

string bar = foo.Replace("&","__amp")
                .Replace("#","__hsh")
                .Replace("5", "6")
                .Replace("1", "5");
like image 27
p.campbell Avatar answered Oct 05 '22 04:10

p.campbell


Given a dictionary like in the other answers, you can use an "aggregate" to map each pattern in the dictionary to a replacement. This will give you far more flexibility that the other answers, as you can have different regex options for each pattern.

For example, the following code will "romanize" greek text (https://en.wikipedia.org/w/index.php?title=Romanization_of_Greek&section=3#Modern_Greek, Standard/UN):

var map = new Dictionary<string,string>() {
    {"α[ύυ](?=[άαβγδέεζήηίΐϊιλμνόορύΰϋυώω])", "av"}, {"α[ύυ]", "af"}, {"α[ϊΐ]", "aï"}, {"α[ιί]", "ai"}, {"[άα]", "a"},
    {"β", "v"}, {"γ(?=[γξχ])", "n"}, {"γ", "g"}, {"δ", "d"},
    {"ε[υύ](?=[άαβγδέεζήηίΐϊιλμνόορύΰϋυώω])", "ev"}, {"ε[υύ]", "ef"}, {"ει", "ei"}, {"[εέ]", "e"}, {"ζ", "z"},
    {"η[υύ](?=[άαβγδέεζήηίΐϊιλμνόορύΰϋυώω])", "iv"}, {"η[υύ]", "if"}, {"[ηήιί]", "i"}, {"[ϊΐ]", "ï"},
    {"θ", "th"}, {"κ", "k"}, {"λ", "l"}, {"\\bμπ|μπ\\b", "b"}, {"μπ", "mb"}, {"μ", "m"}, {"ν", "n"},
    {"ο[ιί]", "oi"}, {"ο[υύ]", "ou"}, {"[οόωώ]", "o"}, {"ξ", "x"}, {"π", "p"}, {"ρ", "r"},
    {"[σς]", "s"}, {"τ", "t"}, {"[υύϋΰ]", "y"}, {"φ", "f"}, {"χ", "ch"}, {"ψ", "ps"}
};

var input = "Ο Καλύμνιος σφουγγαράς ψυθίρισε πως θα βουτήξει χωρίς να διστάζει."; 
map.Aggregate(input, (i, m) => Regex.Replace(i, m.Key, m.Value, RegexOptions.IgnoreCase));

returning (without modifying the "input" variable:

"o kalymnios sfoungaras psythirise pos tha voutixei choris na distazei."

You can of course use something like:

foreach (var m in map) input = Regex.Replace(input, m.Key, m.Value, RegexOptions.IgnoreCase);

which does modify the "input" variable.

Also you can add this to improve performance:

var remap = new Dictionary<Regex, string>();
foreach (var m in map) remap.Add(new Regex(m.Key, RegexOptions.IgnoreCase | RegexOptions.Compiled), m.Value);

cache or make static the remap dictionary and then use:

remap.Aggregate(input, (i, m) => m.Key.Replace(i, m.Value));
like image 38
Costas Avatar answered Oct 05 '22 03:10

Costas