C# - Case Insensitive Regex.Replace function with dictionaries

72 views Asked by At

I have a sentence like this My name is [name] and I'm [age] years old

I would like to replace the text inside of square brackets with something belonging to a dictionary. I googled a bit and I've found out about the Regex.Replace function so I've ended up with this code:

string sentence =  "My name is [name] and I'm [age] years old"
string someVariable1 = "John";
string someVariable2 = "34";

var replacements = new Dictionary<string, string>()
        {
            {"[name]", someVariable1},
            {"[age]", someVariable2},
        };

var replaced = Regex.Replace(sentence, string.Join("|", replacements.Keys.Select(k => Regex.Escape(k.ToString()))), m => replacements[m.Value]);

The problem is that the sentence is supposed to be an user input where I ask to type stuff inside square brackets in order to retrieve some variables. That's where my concernes start, is there a way to let the text inside square brackets to be case insensitive? I mean, is there a way that even if someone types "[NAME]" or "[Name]" instead of "[name]" it does the job? I've tried with regex syntax such as @"[[Nn]ame]" and with Regex.Options.IgnoreCase but I can't make it work. I suppose that's something I'm not understanding correctly.

Thank you.

3

There are 3 answers

0
Charlieface On BEST ANSWER

Seems you just need to add a case-insensitive comparer to the dictionary. You also obviously need to apply RegexOptions.IgnoreCase in order for the Regex finder to search while ignoring case.

var replacements = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
    {"[name]", someVariable1},
    {"[age]", someVariable2},
};

dotnetfiddle

1
Yong Shun On

For your scenario, applying the RegexOptions.IgnoreCase will ignore the case-sensitive for the placeholders from the user input.

If your placeholders which are the keys in the replacements dictionary are initialized as lower-case, you can set the m.Value to lower-case.

replaced = Regex.Replace(sentence, string.Join("|", replacements.Keys.Select(k => Regex.Escape(k.ToString()))), m => replacements[m.Value.ToLower()], RegexOptions.IgnoreCase);

You may also work with iterate each key-value pair in replacements dictionary and replace if the regex is matched.

string replaced = sentence;

foreach (var kvp in replacements)
{
    var regex = new Regex(Regex.Escape(kvp.Key), RegexOptions.IgnoreCase);
    if (regex.IsMatch(replaced))
    {
        replaced = regex.Replace(replaced, replacements[kvp.Key]);
    }
}
0
Dmitry Bychenko On

If you want to ignore case, just let .Net know it:

string sentence =  "My name is [name] and I'm [age] years old";

string someVariable1 = "John";
string someVariable2 = "34";

// When looking for a key, ignore case
var replacements = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
    {"[name]", someVariable1},
    {"[age]", someVariable2},
};

// Pattern doesn't have letters, so no case policy required
var resplace = Regex.Replace(
    sentence, 
  @"\[[^\]\[]+\]", 
    m => replacements.TryGetValue(m.Value, out string s) ? s : m.Value);

Fiddle

I've changed the logic here: instead of building a long pattern I'm looking for any [key] match where key can be any string which doesn't contain [ and ] characters and look up in the dictionary for substitution.

Pattern \[[^\]\[]+\] explained:

\[       - [ character
[^\]\[]+ - one or more characters except ']' or '['
\]       - ] character