tags:

views:

543

answers:

5

I have a regex call that I need help with.

I haven't posted my regex, because it is not relevant here. What I want to be able to do is, during the Replace, I also want to modify the ${test} portion by doing a Html.Encode on the entire text that is effecting the regex.

Basically, wrap the entire text that is within the range of the regex with the bold tag, but also Html.Encode the text inbetween the bold tag.

RegexOptions regexOptions = RegexOptions.Compiled | RegexOptions.IgnoreCase;
text = Regex.Replace(text, regexBold, @"<b>${text}</b>", regexOptions);
+3  A: 

Don't use Regex.Replace in this case... use..

foreach(Match in Regex.Matches(...))
{
    //do your stuff here
}
Ben Scheirman
A: 

If you do a Regex.Match, the resulting match objects group at the 0th index, is the subset of the intput that matched the regex.

you can use this to stitch in the bold tags and encode it there.

DevelopingChris
A: 

Can you fill in the code inside {} to add the bold tag, and encode the text? I'm confused as to how to apply the changes to the entire text block AND replace the section in the text variable at the end.

public static
+2  A: 

Heres an implementation of this I've used to pick out special replace strings from content and localize them.

        protected string FindAndTranslateIn(string content)
        {
            return Regex.Replace(content, @"\{\^(.+?);(.+?)?}", new MatchEvaluator(TranslateHandler), RegexOptions.IgnoreCase);
        }

public string TranslateHandler(Match m)
{
    if (m.Success)
    {
        string key = m.Groups[1].Value;
        key = FindAndTranslateIn(key);
        string def = string.Empty;
        if (m.Groups.Count > 2)
        {
            def = m.Groups[2].Value;
            if(def.Length > 1)
            {
                def = FindAndTranslateIn(def);
            }
        }

        if (group == null)
        {
            return Translate(key, def);
        }
        else
        {
            return Translate(key, group, def);
        }
    }
    return string.Empty;
}

From the match evaluator delegate you return everything you want replaced, so where I have returns you would have bold tags and an encode call, mine also supports recursion, so a little over complicated for your needs, but you can just pare down the example for your needs.

This is equivalent to doing an iteration over the collection of matches and doing parts of the replace methods job. It just saves you some code, and you get to use a fancy shmancy delegate.

DevelopingChris
+2  A: 

There is an incredibly easy way of doing this (in .net). Its called a MatchEvaluator and it lets you do all sorts of cool find and replace. Essentially you just feed the Regex.Replace method the method name of a method that returns a string and takes in a Match object as its only parameter. Do whatever makes sense for your particular match (html encode) and the string you return will replace the entire text of the match in the input string.

Example: Lets say you wanted to find all the places where there are two numbers being added (in text) and you want to replace the expression with the actual number. You can't do that with a strict regex approach, but you can when you throw in a MatchEvaluator it becomes easy.

public void Stuff()
{
    string pattern = @"(?<firstNumber>\d+)\s*(?<operator>[*+-/])\s*(?<secondNumber>\d+)";
    string input = "something something 123 + 456 blah blah 100 - 55";
    string output = Regex.Replace(input, pattern, MatchMath);
    //output will be "something something 579 blah blah 45"
}

private static string MatchMath(Match match)
{
    try
    {
        double first = double.Parse(match.Groups["firstNumber"].Value);
        double second = double.Parse(match.Groups["secondNumber"].Value);
        switch (match.Groups["operator"].Value)
        {
            case "*":
                return (first * second).ToString();
            case "+":
                return (first + second).ToString();
            case "-":
                return (first - second).ToString();
            case "/":
                return (first / second).ToString();
        }
    }
    catch { }
    return "NaN"; 
}

Find out more at http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.matchevaluator.aspx

viggity