5

I usually end up with a lot of conditions and/or loops to parse a regex and interpolate values back into its capture groups, and am looking for experienced answers to solve this problem in hopefully a simple manner.

For example, given a regex pattern like X(?<xid>\d+)-(?<xsub>\w+)\.xml having the named capture groups "xid" and "xsub", intended to match filenames like: X1-foo.xml, X555-bar.xml, etc, when provided with the arguments: int xid=999, string xsub="baz", I want to interpolate those values into the pattern groups to construct the proper filename: X999-baz.xml

To keep it simple, explicit captures are not nested.


Without String.Format:

This concept is easily accomplished with .NET String format items like String.Format("X{0}-{1}.xml", xid, xsub) however I already have a Regex pattern to parse out those values from any filename string, and want to use the same pattern to go in the opposite direction by reconstructing a filename with it, for accuracy. If I require a regex pattern to parse values from a string, but a string with format items to reconstruct the filename, it requires two kinds of distinct syntaxes to be used, creating a greater chance of manual error when writing them - it's too easy to mistakenly create a bad format item string that does not properly reconstruct the result of a regex pattern match, or vice versa.

2 Answers 2

2

You can use regex (yay, meta-regexes!):

public static string RegexInterp(Regex pattern, Dictionary<string, string> pairs) {
    string regex = pattern.ToString();
    string search;

    foreach(KeyValuePair<string, string> entry in pairs) 
    {
        // using negative lookbehind so it doesn't match escaped parens
        search = @"\(\?<" + entry.Key + @">.*?(?<!\\)\)"; 
        regex  = Regex.Replace(regex, search, entry.Value);
    }

    return Regex.Unescape(unescaped);
}

And then:

Regex rx = new Regex(@"X(?<xid>\d\d+)-(?<xsub>\w+)\.xml");

var values = new Dictionary <string, string>() {{"xid", "999"},
                                                {"xsub", "baz"}} ;

Console.WriteLine(RegexInterp(rx, values));     

Prints

X999-baz.xml

Demo: http://ideone.com/QwI2W

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

Comments

0

I may have read this wrong but it sounds like you need the Regex.Replace method in the System.Text.RegularExpressions namespace.

string pattern = "Your pattern";
string replacement = "Your text to replace";
Regex rgx = new Regex(pattern);
string result = rgx.Replace(input, replacement);

There are other methods in the regex library that might better accomodate multiple replacements in a single string.

1 Comment

In this situation, the regex is in fact the input.

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.