Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regular expression to match function name and all arguments in Python

Tags:

python

regex

Suppose I have a string such as the following:

"func(arg1, arg2, arg3, arg4, ..., argn)"

EDIT: This function is not in some particular language. It just has this format. If it makes it easier, don't think of it as a function call, just a string.

I want to write a regular expression to match the function and each of the arguments. I am writing this in Python. The desired output of this is:

{"function" : "func", "arg" : ["arg1", "arg2", ... , "argn"]}

EDIT: While the arguments could be function calls, I can easily recursively try to match them with the same regular expression once I create one that works. By this I mean I can recurse on the function with each of the arguments. But this is not really relevant. I am not trying to create an interpreter, just something to recognize the arguments.

Here is my attempt at this:

import re
s = "func(arg1, arg2, arg3, arg4, argn)"
m = re.match(r"(?P<function>\w+)\s?\((?P<args>(?P<arg>\w+(,\s?)?)+)\)", s)
print m.groupdict()

And here is the output:

{'function': 'func', 'args': 'arg1, arg2, arg3, arg4, argn', 'arg': 'argn'}

The function matches just fine, and so does the argument set. However, I can't seem to match the individual arguments. Is this a problem with my regex, or a limitation of Python regular expression matching?

EDIT2: I am aware that I can now split the arguments using the following code:

d["arg"] = d["args"].split(", ")

But I was wondering if I could do the whole job with regular expressions. In particular, I am wondering why "arg" is matched to only the last argument.

EDIT3: I guess I am (1) hoping to figure out why Python only matches the last argument every time, and (2) whether I can do Scheme-style pattern-matching in Python. Or if there is something just as intuitive in Python as Scheme-style pattern matching. I looked at the ast module, and its syntax is prohibitively complex.

like image 926
Daniel Kats Avatar asked Apr 15 '12 17:04

Daniel Kats


People also ask

What is difference [] and () in regex?

[] denotes a character class. () denotes a capturing group. [a-z0-9] -- One character that is in the range of a-z OR 0-9. (a-z0-9) -- Explicit capture of a-z0-9 .

Does * match everything in regex?

Throw in an * (asterisk), and it will match everything. Read more. \s (whitespace metacharacter) will match any whitespace character (space; tab; line break; ...), and \S (opposite of \s ) will match anything that is not a whitespace character.

What will the regular expression match in Python?

A regular expression (or RE) specifies a set of strings that matches it; the functions in this module let you check if a particular string matches a given regular expression (or if a given regular expression matches a particular string, which comes down to the same thing).

What will the '$' regular expression match?

By default, regular expressions will match any part of a string. It's often useful to anchor the regular expression so that it matches from the start or end of the string: ^ matches the start of string. $ matches the end of the string.


2 Answers

Regular expressions cannot parse complex programming languages.

If you're just trying to parse Python, I suggest taking a look at the ast module, which will parse it for you.

like image 100
mpnk121 Avatar answered Oct 25 '22 15:10

mpnk121


Looks like you're 90% there, why not just swap the arg and args groupings and do:

import re

fn_match = re.match(r"(?P<function>\w+)\s?\((?P<arg>(?P<args>\w+(,\s?)?)+)\)", s)
fn_dict = fn_match.groupdict()
del fn_dict['args']
fn_dict['arg'] = [arg.strip() for arg in fn_dict['arg'].split(',')]
like image 39
mVChr Avatar answered Oct 25 '22 16:10

mVChr