添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
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;
                    Please, show how do you apply this technique to the test string: InitValue(Input1, Input2, Input3, Input4)
    – mrzasa
                    Jan 7, 2019 at 15:38
                    What do you mean? As I said, this is only ilustrative, not the full solution, but close enough. You can easily delete the InitValue(*) with a Substringand keep the arguments, if you mean that it is impossible when it's written InitValue, then yes, you are right, but that's far from being impossible =D
    – Nekeniehl
                    Jan 7, 2019 at 15:41
            

    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.