7

I have the expression already written, but whenever I run the code I get the entire string and a whole bunch of null values:

Regex regex = new Regex(@"y=\([0-9]\)\([0-9]\)(\s|)\+(\s+|)[0-9]");
Match match = regex.Match("y=(4)(5)+6");

for (int i = 0; i < match.Length; i++)
{
    MessageBox.Show(i+"---"+match.Groups[i].Value);
}

Expected output: 4, 5, 6 (in different MessageBoxes

Actual output: y=(4)(5)+6

It finds if the entered string is correct, but once it does I can't get the specific values (the 4, 5, and 6). What can I do to possibly get that code? This is probably something very simple, but I've tried looking at the MSDN match.NextMatch article and that doesn't seem to help either.

Thank you!

Scott
  • 5,338
  • 5
  • 45
  • 70
  • 1
    I don't quite understand the question - are you looking for the regular expression to match a string that is not in the correct format? – Oded Oct 04 '12 at 12:44
  • The regex matches the string fine - it returns true (or match.Success) when all the variables are filled. However, getting each individual value is what I'm after. – Scott Oct 04 '12 at 12:45
  • did you try tho check te .Captures ? http://msdn.microsoft.com/en-us/library/twcw2f1c.aspx – Caspar Kleijne Oct 04 '12 at 12:47

5 Answers5

5

As it currently is, you don't have any groups specified. (Except for around the spaces.)

You can specify groups using parenthesis. The parenthesis you are currently using have backslashes, so they are being used as part of the matching. Add an extra set of parenthesis inside of those.

Like so:

new Regex(@"y=\(([0-9]+)\)\(([0-9]+)\)\+([0-9]+)");

And with spaces:

new Regex(@"y\s*=\s*\(([0-9]+)\)\s*\(([0-9]+)\)\s*\+\s*([0-9]+)");

This will also allow for spaces between the parts to be optional, since * means 0 or more. This is better than (?:\s+|) that was given above, since you don't need a group for the spaces. It is also better since the pipe means 'or'. What you are saying with \s+| is "One or more spaces OR nothing". This is the same as \s*, which would be "Zero or more spaces".

Also, I used [0-9]+, because that means 1 or more digits. This allows numbers with multiple digits, like 10 or 100, to be matched. And another side note, using [0-9] is better than \d since \d refers to more than just the numbers we are used to.

LTAcosta
  • 500
  • 3
  • 9
  • 1
    Just updated my answer to be a little bit more clear. Hopefully you now understand what each part of your pattern was doing. – LTAcosta Oct 04 '12 at 13:14
4

You need to name your groups so that you can pull them out later. How do I access named capturing groups in a .NET Regex?

Regex regex = new Regex(@"y=\((?<left\>[0-9])\)\((?<right>[0-9])\)(\s|)\+(\s+|)(?<offset>[0-9])");

Then you can pull them out like this:

regex.Match("y=(4)(5)+6").Groups["left"];
Community
  • 1
  • 1
Rob
  • 517
  • 3
  • 10
3

Use (named) capturing groups. You will also need to use (?:) instead of () for the groups you don't want to capture. Otherwise, they will be in the result groups, too.

Regex regex = new Regex(@"y=(\([0-9]\))((\([0-9]\))(?:\s|)\+(?:\s+|)([0-9])");
Match match = regex.Match("y=(4)(5)+6");
Console.WriteLine("1: " + match.Groups[1] + ", 2: " + match.Groups[2] + ", 3: " + match.Groups[3]);

If the pattern found a match, the groups of that match are written into the property which can either be accessed via an index (index 0 contains the complete match).

You can also name those groups to have more readable code:

Regex regex = new Regex(@"y=(?<first>\([0-9]\))(?<second>(\([0-9]\))(?:\s|)\+(?:\s+|)(?<third>[0-9])");

Now, you can access the capturing groups by using match.Groups["first"] and so on.

F.P
  • 17,421
  • 34
  • 123
  • 189
2

C# is outside my area of expertise, but this may work:

@"y=\(([0-9])\)\(([0-9])\)(?:\s|)\+(?:\s+|)([0-9])"

It's basically your original regex, but with capturing groups around the numbers, and with the undesired capturing groups changed into non-capturing groups: (?: ... )

skunkfrukt
  • 1,550
  • 1
  • 13
  • 22
2

Group[0] will give always you the string that was matched, the null values are coming from (\s|).

This will work: y=\((\d)\)\((\d)\)\s*\+\s*(\d)

It's the groups starting from 1 that counts the brackets you use, but if you escape them they don't count (because you're telling it they're just text to match), so those digits need their own brackets. It's also not a good idea to use (x|) when something like ? or * would be more suitable, since you're not capturing that bit.

This will probably be even better y=\((\d+)\)\((\d+)\)\s*\+\s*(\d+) because it supports values larger than ten.

Patrick
  • 1,766
  • 1
  • 15
  • 27