简体   繁体   中英

Trying to get multiple RegEx matches with named groups in C#

I have a string like this one:

A Residential Usage Credit of $80 will be applied for each billing cycle in which YOUR USAGE falls between 1,000 kWh and 1,500 kWh. A Residential Usage Credit of $40 will be applied for each billing cycle in which YOUR USAGE falls between 1,501 kWh and 2,000 kWh.

You can see there is a repeated format for the two sentences. I have created a Regex using named groups like so:

A Residential Usage (?<costType>[\w\s]+) of \p{Sc}*(?<cost>\s?\d+[., ]?\d*) will be applied for each billing cycle in which YOUR USAGE falls between (?<firstUsage>[0-9, ]+) kWh and (?<secondUsage>[0-9, ]+) kWh

I have a lot of these combos of strings to regex capture with named groups, and I use this function to capture them:

  public static string[] ValidatePattern(string pattern, string input, List<string> groupNames)
    {
        Regex regex = new Regex(pattern);
        var match = regex.Match(input);

        List<string> results = new List<string>();
        if (match.Success)
        {
            //results.Add(input);
            foreach (var name in groupNames)
            {
                if (match.Groups[name].Captures.Count > 0) results.Add(match.Groups[name].Value);
                else results.Add(String.Empty);
            }
            return results.ToArray();
        }
        return null;
    }

This works well for my current situation, as for most of my scenarios I don't have it repeated like the example above. However, when I do have a breakpoint and look to see if it caught both matches, it only gets the first one on the object (ie the 1,000 to 1500 in this example) on the "match" object.

My question is, how do I get the second match on the Regex object? I can refactor from there, but I don't know how to grab the data.

You need to iterate through all the matches of the string. Regex.Match will only return the first match.

public static string[] ValidatePattern(string pattern, string input, List<string> groupNames)
{
    Regex regex = new Regex(pattern);
    var matches = regex.Matches(input);

    List<string> results = new List<string>();
    foreach (Match match in matches) {
        foreach (var name in groupNames)
        {
            var group = match.Groups[name];
            results.Add(group.Success ? group.Value : string.Empty);
        }
    }
    return results.ToArray();
}

Check out the example at Regex.Match Method (String) to see how to match on multiple occurrences in a string. I think what you want is the following:

    while (match.Success)
    {
        //results.Add(input);
        foreach (var name in groupNames)
        {
            if (match.Groups[name].Captures.Count > 0) results.Add(match.Groups[name].Value);
            else results.Add(String.Empty);
        }
        match = match.NextMatch();
    }
    return results.Count > 0 ? results.ToArray() : null;

This replaces your if statement with a while statement.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM