tags:

views:

63

answers:

3

I'm parsing a BB code image tag:

[img]http://imagesource.com[/img]

I'm using the following Replace() function:

Regex.Replace(msg, @"\[img\]([^\]]+)\[\/img\]", @"<img src=""$1"" border=""0"" />", RegexOptions.IgnoreCase);

And I need to get the URL while parsing. I need to know the value of "$1". Is it possible? The Regex class somehow replaces the "$1" string with the value that I need, so there must a way to get it.

A: 

To keep the captured string, just "capture" the return value.

 string s = Regex.Replace(msg, @"\[img\]([^\]]+)\[\/img\]", @"<img src=""$1"" border=""0"" />", RegexOptions.IgnoreCase); 
Michael Goldshteyn
But this returns the whole thing...
Alex
A: 

Capture groups are available in the Captures property for the Regex match, if you do a match instead of a replace, then you'll have access to the group.

Benjamin Anderson
I tried using "r.Match(text).Groups[0]" but it didn't work
Alex
Sorry, I listed the property. The Captures property has all capture groups, Groups are the named Capture groups. If there aren't any named ones, then Groups[0] is the last matched capture.
Benjamin Anderson
+2  A: 

It sounds like you're looking for the Replace method with an overload that accepts a MatchEvaluator. The MSDN page for that method can be found here.

Try this instead:

string input = "[img]http://imagesource.com[/img]";
string pattern = @"\[img]([^\]]+)\[\/img]";
string result = Regex.Replace(input, pattern, m =>
    {
        var url = m.Groups[1].Value;
        // do something with url here
        // return the replace value
        return @"<img src=""" + url + @""" border=""0"" />";
     },
    RegexOptions.IgnoreCase);

This uses a multi-statement lambda to simplify working with the group and performing more logic before returning the replacement value. You could, of course, get away with this instead:

string result = Regex.Replace(input, pattern,
    m => @"<img src=""" + m.Groups[1].Value + @""" border=""0"" />",
    RegexOptions.IgnoreCase);

In the above case there's no need for the return but it's just returning the original string without additional evaluation. You could stick some ternary operators and add that logic, but it'll look messy. A multi-statement lambda is much cleaner. You may consider breaking it out in its own method, as shown in the aforementioned MSDN link, if it is too large or will be reused in other Regex.Replace efforts.

BTW, I also simplified your pattern slightly by removing the escapes for ]. Only the opening [ needs to be escaped.

Ahmad Mageed
Amazing! That's exactly what I need. Thank you!
Alex