1

While using Regex to replace keywords with value in a template, I tested the following code.

string input = "Welcome {{friend}} Get my new {{id}} with {{anonymous}} People";
            Dictionary<string, string> mydict = new Dictionary<string, string> ();
            mydict.Add("friend", "<<My Friend>>");
            mydict.Add("id", "<<Your ID>>");
            string pattern = @"(?<=\{{2})[^}}]*(?=\}{2})";// @"\{{2}^(.*?)$\}{2}";//"^[{{\\w}}]$";
            //var m = Regex.Match(input, @"\{{(.*)\}}");
            string regex = Regex.Replace(input, pattern, delegate(Match match) {
                string v = match.ToString();
                return mydict.ContainsKey(v) ? mydict[v] : v;

            });

            Console.WriteLine(regex);

The curley braces still remain in the output which is not desired

I need <<My Friend>> instead of {{ <<My Friend>> }}. I would appreciate your suggestion.

3
  • For some alternatives: What's a good way of doing string templating in .NET? Commented Mar 29, 2018 at 13:02
  • @Fildor That's one of these "best practices" questions from 2009 that would have been closed as too broad had it been asked today. Commented Mar 29, 2018 at 13:06
  • @dasblinkenlight Yes, but nevertheless, there are some alternatives in the answers that may be worth consideration. Commented Mar 29, 2018 at 13:10

2 Answers 2

3

You may use a simple {{(.*?)}} regex and use the Group 1 vlaue to check for the dictionary match:

string pattern = @"{{(.*?)}}";
string regex = Regex.Replace(input, pattern, delegate(Match match) {
     string v = match.Groups[1].Value;
     return mydict.ContainsKey(v) ? mydict[v] : v;
});
// => Welcome <<My Friend>> Get my new <<Your ID>> with anonymous People

The same code with a lambda expression:

string regex = Regex.Replace(input, pattern, x =>
     mydict.ContainsKey(match.Groups[1].Value) ?
                mydict[match.Groups[1].Value] : match.Groups[1].Value;
});

See the C# demo.

Note that [^}}] does not mean match any text other than }}, it just matches any char other than }, same as [^}], so .*? is preferable in this case. Or even \w+ if you only have letters, digits and underscores in between {{ and }}.

Sign up to request clarification or add additional context in comments.

Comments

2

Braces remain in the original text because you are using zero-width lookahead and lookbehind constructs. This leaves the content matched by (?<=...) and (?=...) outside regex's captured value, so it does not get replaced.

To fix this problem remove lookahead and lookbehind from your regex, put a capturing group around the text of the tag, and use it to search replacement dictionary:

string pattern = @"\{{2}([^}}]*)\}{2}";
...
var v = match.Group[1].Value;
return mydict.ContainsKey(v) ? mydict[v] : v;

2 Comments

A downvote of the question and a correct solution without as much as a comment is quite obnoxious. You should at least say what you think is wrong.
Hm, From Wiktor's answer: "Note that [^}}] does not mean match any text other than }}, it just matches any char other than }, same as [^}]" - but that doesn't deserve a dv, does it? It still works.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.