Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
Now I would like to capture any number of arguments to the InitValue-method. The number of arguments to InitValue are unknown.
Full match: InitValue(Input1, Input2, ..., Inputn)
Group1: Input1
Group2: Input2
Groupn: Inputn
Of course I can't repeat the following pattern in my regular expression since I don't know the number of arguments in advance:
\s*,\s*(\w*)
How do I write a regular expression which outputs n number of capture groups?
I use the regular expression in C#-code (Regex, Match)...
It is possible to do this in .NET - you use a single capture Group, and then you access the Group's Captures collection to see all the items it captured, not just the final Value.
You'll have to write a regex that can repeat the argument-matching group, something like
InitValue\((?:(\w+)\s*(?:,(?!\s*\))|(?=\s*\)))\s*)*\)
Have a play around with the Debuggex Demo to get it to match what you want.
WriteLine($"\tMethod: '{match.Groups[1].Value}'");
WriteLine("\tParameters:");
var captures = match.Groups[2].Captures;
if (captures.Count > 0)
x = 0;
foreach (Capture capture in captures)
WriteLine($"\t\tParam {++x}: '{capture.Value}'");
WriteLine("\t\tNo params found.");
WriteLine();
WriteLine("No matches found.");
Output:
String: 'InitValue()'
Method: 'InitValue'
Parameters:
No params found.
String: 'InitValue(Input1)'
Method: 'InitValue'
Parameters:
Param 1: 'Input1'
String: 'InitValue(Input1, Input2, Input3, Input4)'
Method: 'InitValue'
Parameters:
Param 1: 'Input1'
Param 2: 'Input2'
Param 3: 'Input3'
Param 4: 'Input4'
.NET supports infinite lookbehind (?<=. Instead of getting capturing groups, another option could be to get the matches instead:
(?<=\bInitValue\([^()]*)[^, ]+(?=[^()]*\))
Explanation
(?<= Positive lookbehind, check what is on the left matches:
\bInitValue\([^()]* Match wordboundary, InitValue( and then 0+ times not any of ( or )
) Close positive lookbehind
[^, \t]+ Negative character class, match 1+ times not a space or comma
(?= Positive lookahead to check what is on the right matches:
[^()]*\) Match 0+ times not any of ( or ), then match )
) Close positive lookahead
For example:
string pattern = @"(?<=\bInitValue\([^()]*)[^, ]+(?=[^()]*\))";
string str = "InitValue(Input1, Input2, Input3)";
foreach (Match m in Regex.Matches(str, pattern))
Console.WriteLine(m.Value);
Result
Input1
Input2
Input3
See the Regex demo | C# demo
You will have to touch it a little bit but I think it can guide you =D.
Edit, answering your question. b.Count will give you the number of matchings.
Edit 2, I post the picture to show the debug info. But here is the code for the sibarist.
string bar = "test, othertest";
Regex reg = new Regex(@"[\w]+");
MatchCollection b = reg.Matches(bar);
string b1 = b[0].Value;
string b2 = b[1].Value;
int numberGroups = b.Count;
Edit 3, as suggested in the comment this is the complete solution, you will need to clear the InitValue(*) part with another Regex or with a Substring
string input = "InitValue(test, othertest, bleh, blehTest, foo)";
Regex regArgs = new Regex(@"(?:InitValue\()(.*)(?:\))");
Match matchArgs = regArgs.Match(input);
string valueArgs = matchArgs.Groups[1].Value;
Regex reg = new Regex(@"[\w]+");
MatchCollection b = reg.Matches(valueArgs);
string b1 = b[0].Value;
string b2 = b[1].Value;
int numberGroups = b.Count;
–
–
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.