Edit: To work with nested tags, multiple matches per input string.
Restrictions: text inside a tag pair cannot contain "{" or "}".
private string FormatInput(string input)
{
const string patternNonGreedy = @"\{(?<tag>.+?):(\s*)(?<content>.*?)(\s*)}";
const string patternGreedy = @"\{(?<tag>.+?):(\s*)(?<content>.*)(\s*)}";
Match mtc = Regex.Match(input, patternGreedy);
if (!mtc.Success)
return input;
string content = mtc.Groups["content"].Value;
int braces = 0;
foreach (char c in content)
{
if (c == '{')
braces++;
else if (c == '}')
{
if (braces > 0)
braces--;
}
}
if (braces == 0)
return input.Substring(0, mtc.Index)
+ string.Format("<{0}>{1}</{0}>", mtc.Groups["tag"].Value, FormatInput(content))
+ input.Substring(mtc.Index + mtc.Length);
mtc = Regex.Match(input, patternNonGreedy);
Debug.Assert(mtc.Success);
content = mtc.Groups["content"].Value;
return input.Substring(0, mtc.Index)
+ string.Format("<{0}>{1}</{0}>", mtc.Groups["tag"].Value, content)
+ FormatInput(input.Substring(mtc.Index + mtc.Length));
}
Test examples:
string output1 = FormatInput("{strong:Lorum ipsum dolar}");
// output1: <strong>Lorum ipsum dolar</strong>
string output2 = FormatInput("{strong:{italic:Lorum ipsum dolar}}");
// output2: <strong><italic>Lorum ipsum dolar</italic></strong>
string output3 = FormatInput("{strong:Lor{i:e}m ipsum dol{i:o}r}");
// output3: <strong>Lor<i>e</i>m ipsum dol<i>o</i>r</strong>
$str = q({strong:Lorum ipsum dolar}); $str =~ m/\{(\w+):(.+?)\}/; $str = "<$1>$2</$1>";awful solution, but works (perl){strong:Lor{i:e}m ipsum dol{i:o}r}. With Perl's extensions to regex, that would even be possible to do – in “pure” regex, you can only do it up to some predetermined nesting depth.