idlackage
idlackage

Reputation: 2863

Parentheses not capturing c# regex groups

Trying to extract the name and id from a string with the following code:

Regex.Matches
    "id: 123456, name: some dude",
    @"^id: (?<id>\d+), name: (?<name>[a-z]+(\s[a-z]+)?)"
);

However, the number of groups and captures is 1, and there are no named captures. What am I missing?

Edit: Found the answer (thanks everyone!) but for future reference, it turns out it's because I completely misunderstood the API and was accessing the matches wrong. I was doing stuff like this:

Console.WriteLine(matches.Count); // 1
foreach( Group g in matches ) {
    Console.WriteLine(g.Captures.Count); //1
    foreach( Capture c in g.Captures ) {
        Console.WriteLine(c.Value); // The whole string
    }
}

But now I know better!

Upvotes: 3

Views: 483

Answers (3)

TheGeneral
TheGeneral

Reputation: 81493

This works just fine

String sample = "id: 123456, name: some dude";
Regex regex = new Regex(@"^id: (?<id>\d+), name: (?<name>[a-z]+(\s[a-z]+)?)");

Match match = regex.Match(sample);

if (match.Success)
{
   Console.WriteLine(match.Groups["id"].Value);
   Console.WriteLine(match.Groups["name"].Value);
}

And when .Net Fiddle works again you can demo it here


For Completness

Regex.Match Method (String)

Searches the specified input string for the first occurrence of the regular expression specified in the Regex constructor.

Regex.Matches Method

Searches an input string for all occurrences of a regular expression and returns all the matches.

Match.Groups Property

Gets a collection of groups matched by the regular expression. Groups can then be retrieved from the GroupCollection object

GroupCollection.Item Property (String)

Enables access to a member of the collection by string index. GroupName can be either the name of a capturing group that is defined by the (?<name>) element in a regular expression, or the string representation of the number of a capturing group that is defined by a grouping construct

Upvotes: 2

Srdjan M.
Srdjan M.

Reputation: 3405

You should use Match instead of Matches, and use non-capturing groups (?:) in your regex.

Regex demo

String input = "id: 123456, name: some dude";

var output = Regex.Match(input, @"^id: (?<id>\d+), name: (?<name>.+)");

System.Console.WriteLine(output.Groups["id"]);
System.Console.WriteLine(output.Groups["name"]);

Output:

123456 
some dude

Upvotes: 2

Alexei Levenkov
Alexei Levenkov

Reputation: 100527

There is probably something wrong with the way you look for matches as your regex look ok:

Regex.Matches(
    "id: 123456, name: some dude",
    @"^id: (?<id>\d+), name: (?<name>[a-z]+(\s[a-z]+)?)"
)[0].Groups.Cast<Group>().Skip(2).Select(x => new {x.Name, x.Value})

Produces:

    Name  Value
    id    123456 
    name  some dude 

If you just need particular one - Regex.Matches(...)[0].Groups[2] or .Groups["id"].

Note that your code uses Matches that returns all matches, if you just expect single match - use Match as shown in Michael Randall answer

Upvotes: 2

Related Questions