0

I want to add an additional argument to my function using regular expressions and Python.

My function looks like this:

mail(arg1, arg2, arg3, arg4);

Can anyone help with regular expression to get this result:

mail(arg1, arg2, arg3, arg4, arg5);

I have an overall idea:

import os, fnmatch

for path, dirs, files in os.walk(os.path.abspath('directory')):
        for filename in fnmatch.filter(files, '*.php'):
                filepath = os.path.join(path, filename)

                with open(filepath) as php:
                        i = php.read()
                i = i.sub(re, re, line)
                with open(filepath,"w") as f:
                        f.write(i)
Laurel
  • 5,965
  • 14
  • 31
  • 57
  • 3
    What is the problem you're actually trying to solve? It's unlikely that rewriting the file is the best way of doing this. – jonrsharpe Jun 09 '16 at 21:58
  • I don't believe that python is a regular language. I don't think that tag means what you think it means (however, welcome to SO and well formatted question for your first one!) – en_Knight Jun 09 '16 at 22:02
  • Furthermore, regular expressions can't capture function declarations (at least in python, I don't know about php but I strongly suspect similarly). You need context free grammars for that. very vaguely related answer of mine on the topic: http://stackoverflow.com/questions/36802298/simple-tokenizer-for-c-in-python/36802496#36802496, I'm sure there are much better fits on SO – en_Knight Jun 09 '16 at 22:07

2 Answers2

0

Assuming you're not doing complex multiline parsing, and that your arguments aren't expressions with whitespace or commas, and that your spaces between arguments are consistent, here is a naive regex:

re.sub(r'(mail\(\S+, \S+, \S+)\);', '\\1, arg4);', src)

You may wish to surround the \S+ with \s*\S+\s* to allow flexibility in whitespace around each argument.

It also will catch functions that might be named foomail, so you may wish to add a mandatory whitespace (r' (mail...')to the beginning of the expression. That won't catch beginnings of lines, so then you'd also need (r'^(mail...')

Parsing and regex matching are two very different disciplines. I understand sometimes one needs something quick and dirty to just change a bunch of lines of code, so I hope this helps.

Be sure to make a copy first.

rrauenza
  • 6,285
  • 4
  • 32
  • 57
  • Im appreciated for your quick reply. I am kind of new to Regex, but I have a big file and the mail function is called over and over again (same format: passing 4 arguments, separated by comma but each argument has different content). I want to add a fixed fifth argument. If that make sense to you? Please help. Thanks! – Hoang Pham Jun 10 '16 at 14:47
  • If you're going to use a regex, your process is going to be iterative. Start with what I've given you, see where it fails, modify, tweak, and repeat. – rrauenza Jun 10 '16 at 16:42
0

I'd like to propose a different answer than the one you are asking for.

Consider a couple of other alternatives. Assuming the 5th argument is always the same, there are a couple of other approaches.

(1) Write a new function call. Let's call it newmail.

function newmail($arg1, $arg2, $arg3, $arg4) {
    return mail($arg1, $arg2, $arg3, $arg4, "My constant 5th argument");
}

Now change all mail() calls to newmail()

(2) Make your fifth argument a default argument in the existing mail():

(This could also be done in solution (1) above)

function mail($arg1, $arg2, $arg3, $arg4, $arg5 = "My constant 5th argument") {
    [...]
}
rrauenza
  • 6,285
  • 4
  • 32
  • 57