Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get Expression in Named Capture

Tags:

c#

regex

I am providing a textbox for one to enter a Regular Expression to match filenames. I plan to detect any named capture groups that they provide with the Regex method GetGroupNames().

I want to get the expression that they entered inside each named capture group.

As an example, they might enter a regular expression like this:

December (?<FileYear>\d{4}) Records\.xlsx

Is there a method or means to get the sub-expression \d{4} apart from manually parsing the regular expression string?

like image 572
John Kurtz Avatar asked Nov 08 '22 23:11

John Kurtz


1 Answers

Here is an ugly brute force extension for parsing without using another Regex to detect the subexpression (or subpattern):

    public static string GetSubExpression(this Regex pRegex, string pCaptureName)
    {
        string sRegex = pRegex.ToString();
        string sGroupText = @"(?<" + pCaptureName + ">";
        int iStartSearchAt = sRegex.IndexOf(sGroupText) + sGroupText.Length;
        string sRemainder = sRegex.Substring(iStartSearchAt);
        string sThis;
        string sPrev = "";
        int iOpenParenCount = 0;
        int iEnd = 0;
        for (int i = 0; i < sRemainder.Length; i++)
        {
            sThis = sRemainder.Substring(i, 1);
            if (sThis == ")" && sPrev != @"\" && iOpenParenCount == 0)
            {
                iEnd = i;
                break;
            }
            else if (sThis == ")" && sPrev != @"\")
            {
                iOpenParenCount--;
            }
            else if (sThis == "(" && sPrev != @"\")
            {
                iOpenParenCount++;
            }
            sPrev = sThis;
        }
        return sRemainder.Substring(0, iEnd);
    }

The usage looks like this:

    Regex reFromUser = new Regex(txtFromUser.Text);
    string[] asGroupNames = reFromUser.GetGroupNames();
    int iItsInt;
    foreach (string sGroupName in asGroupNames)
    {
        if (!Int32.TryParse(sGroupName, out iItsInt)) //don't want numbered groups
        {
            string sSubExpression = reParts.GetSubExpression(sGroupName);
            //Do what I need to do with the sub-expression
        }
    }

Now, if you would like to generate test or sample data, you can use the NuGet package called "Fare" in the following way after you get a sub-expression:

            //Generate test data for it
            Fare.Xeger X = new Fare.Xeger(sSubExpression);
            string sSample = X.Generate();
like image 122
John Kurtz Avatar answered Nov 15 '22 05:11

John Kurtz