Regex to capture all function arguments

I have the following regular expression:
(?<=def\s+\w+[\(])(?<arg>[^\),]+)

Open in new window

It does a fine job of capturing the first parameter in a Python function declaration like this:
def GetStatus(Param1, Param2, Param3)

Open in new window

How do I alter the expression so that it can capture each argument? Bear in mind that this needs to work for any Python function declaration so it may have any number of arguments.
LVL 21
Russ SuterAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Rgonzo1971Commented:
HI,

pls try to get all the parameters
(?<=def\s+\w+[\(])(?<args>[^)]+?)(?:\))

Open in new window

and then split with ", "

Regards
0
Russ SuterAuthor Commented:
No, I cannot use split for other technical reasons. I need each of the args captured separately.
0
aikimarkCommented:
What is the big picture problem you are trying to solve?
0
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

Russ SuterAuthor Commented:
I'm trying to get a regular expression that I can pass along to this control
https://github.com/PavelTorgashov/FastColoredTextBox
that will allow me to highlight the arguments.
0
aikimarkCommented:
Since you're passing the pattern into a .Net application, is it safe to assume that you will be working with the regular expression engine in the .Net framework?
0
Russ SuterAuthor Commented:
While I haven't looked in detail at the source code for that control I'd say it is almost certainly using the .Net Regex engine.
0
aikimarkCommented:
Try this:
def\s+(\w+)\((\w+(?:\W*))+\)

Open in new window

0
aikimarkCommented:
That pattern also works on this form:
def GetStatus(Param1, 
              Param2, 
              Param3)

Open in new window

0
Russ SuterAuthor Commented:
I ran this through Expresso and it did not return what I would expect.
Expresso ScreenshotIt also didn't work for the control in the above link.
0
aikimarkCommented:
Please test my pattern as posted.
0
Russ SuterAuthor Commented:
I already did. It didn't work which is why I altered it.
Expresso Screenshot
0
aikimarkCommented:
What is the relationship between Expresso and the FastColoredTextBox?
0
Russ SuterAuthor Commented:
It's useful to test the expression. I tested it also in C# using regex.Matches() and the function times out.
0
aikimarkCommented:
I tested it here:
http://regexstorm.net/tester

After first testing it at myregextester.com
0
Russ SuterAuthor Commented:
Thanks for that. It also doesn't produce the desired result. It's capturing the function name which I must not capture. I was able to handle that by adding ?: to the beginning of the group to make it a non-capture group. The 2nd capture is producing weird results. "Param3" appears in the capture list twice (once at the beginning, and again at the end) and the params have commas with them. This throws .Net into a tizzy when attempting to read .Matches()
0
aikimarkCommented:
capturing the function name which I must not capture
Then we remove the parentheses around the function name part of the pattern.
def\s+\w+\((\w+(?:\W*))+\)

Open in new window

0
Russ SuterAuthor Commented:
As I stated above, I already solved that part by making it a non-capturing group. The bigger issue is the 2nd part which I'm unable to get around.
0
aikimarkCommented:
I think the Param3 is the result of using a repeating capture group.  You get the last one.  We can name the group something else if that would help.  I'll test the pattern again.  I didn't notice the commas in the results of my test.
0
aikimarkCommented:
Ok.  Let's try this pattern:
def\s+\w+\((?:(\w+)(?:\W*))+\)

Open in new window

0
Russ SuterAuthor Commented:
That looked good until I tried unleashing it on an actual Python script. Try that pattern on http://regexstorm.net/tester against this code and take a look at what happens.
def getDataAdapter(sql, cmd):
    da = OleDb.OleDbDataAdapter(sql, cmd.Connection)
    # DataAdaptor apparently makes a clone of the passed in command object, but doesn't hold on to the transaction associated with it.
    da.SelectCommand.Transaction = cmd.Transaction
    return da

Open in new window

0
aikimarkCommented:
Ok.  Then this less ambitious pattern.
def\s+\w+\((?:(\w+)(?:\W*?))+\)

Open in new window

0
käµfm³d 👽Commented:
Is this what you're after?

(?<=def +GetStatus\((?:\w+, *)*)\w+

Open in new window


Screenshot
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Russ SuterAuthor Commented:
Yes, with one minor change. I needed the result to be part of a named capture group. This seems to have done the trick:

(?<parameter>(?<=def +GetStatus\((?:\w+, *)*)\w+)
0
käµfm³d 👽Commented:
You can stick the named group around just the bit you actually care about too:

(?<=def +GetStatus\((?:\w+, *)*)(?<parameter>\w+)

Open in new window

0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Regular Expressions

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.