- Home /
Regex capturing groups find whole match instead
I'm trying to find pairs of numbers in parentheses, then parse them. For that reason I constructed a regular expression with capturing groups inside this snippet of code:
Regex rgx = new Regex(@"\(([0-9]*)\, ?([0-9]*)\)");
MatchCollection matches = rgx.Matches(current["EmptyFields"].InnerText);
if (matches.Count > 0) {
foreach (Match match in matches) {
CaptureCollection captures = match.Captures;
emptyFields.Add(new GameBoardCoords(Int32.Parse (captures[0].Value), Int32.Parse (captures[1].Value)));
}
}
The intended result are two capturing groups, each with one member of a pair. For example, for "(0,0)", there should be two capturing groups with "0" and "0". This is how it works when I test the expression in the regex explorer.
For some reason instead, this code generates one capturing group with the entire match - "(0,0)" in our example. Is there something I missed here?
Answer by asafsitner · Mar 16, 2015 at 08:36 AM
Your regex works perfectly - try it out in Regexr
So why does it not work?
Because you're accessing the wrong groups.
In a regex match, group 0 is always the whole match!
You can see it in Regexr by hovering over the matches and see which group is which part of the match.
Instead you need to access groups 1 and 2 in your code like so:
emptyFields.Add(new GameBoardCoords(Int32.Parse (captures[1].Value), Int32.Parse (captures[2].Value)));
You may want to change your regex to force number input however, or you might run into an empty string. Basically just replace the *
with +
in the pattern like so:
Regex rgx = new Regex(@"\(([0-9]+)\, ?([0-9]+)\)");
Alternatively, either check for string.IsNullOrRmpty
or use int.TryParse
like so:
if (matches.Count > 0)
{
foreach (Match match in matches)
{
CaptureCollection captures = match.Captures;
// either check for empty strings and fill with default value
int coord1 = string.IsNullOrEmpty(captures[1].Value) ? 0 : Int32.Parse(captures[1].Value);
int coord2 = string.IsNullOrEmpty(captures[2].Value) ? 0 : Int32.Parse(captures[2].Value);
// or use try parse
if (!Int32.TryParse(captures[1].Value, out coord1)) coord1 = 0;
if (!Int32.TryParse(captures[2].Value, out coord2)) coord2 = 0;
emptyFields.Add(new GameBoardCoords(coord1, coord2));
}
}
Answer by dethtoll · Mar 16, 2015 at 08:24 AM
In C#, the backslash () character is a special 'escape' character used for representing special characters such as newlines (\n). In order to represent a backslash, you must use a double backslash (\) instead.
This can be slightly confusing, since the backslash is being used as an escape character in the regex itself - eg. to represent a left paren instead of the beginning of a capture. But the regex won't even see the backslash in this case because c# is 'eating' it beforehand.
That is not entirely true - notice the @
symbol indicating a verbatim string, so the regex will pick it up exactly as it is.
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Illuminating a 3D object's edges OnMouseOver (script in c#)? 1 Answer
Flip over an object (smooth transition) 3 Answers
Replace with a value from hashtable 1 Answer