views:

260

answers:

1

This is not as simple as it seems. Most of you are likely thinking of the regex /([A-Z])/_$1/ like I have found all over the Internet, but my particular situation is slightly more complicated. My source string contains more content that I don't want to have converted before a portion that I do.

Consider a regular setter:

public function setUserId()

Of course, this method is missing a parameter. Perhaps I have many of these methods. I'd like to convert that line into

public function setUserId($user_id)

which is a rather simple thing to consider, but not so simple as I ponder it deeper. It's similar to what Andreas_D in this thread, but with the added challenge of trying to iteratively modify the variable name...

It's probably going to be something obvious using regular expressions, but I'm still pretty new with them. Either way, I can't find a decent solution to this problem anywhere in my searches.

Edit: of course, I realize that there are no capitals in "public function" which leave it safe. But, this search & substitution will be running against blocks of code, and I want to ensure that the string I'm modified begins with "public function".

+1  A: 

First search for function definitions, and then on each match, insert a parameter based on the function name.

/\b(function\s+set([A-Z]\w*))\b\s*\(\)/g

This pattern will give you matches with the function-keyword and the function name in group 1, and the camel-cased part of the function name in group 2.

/([a-z](?=[A-Z])|[A-Z](?=[A-Z][a-z]))/g

This pattern will find the last letter before an upper-case/lower-case sequence that make up camel-case.

You didn't specify what language you will be using, so here is a demonstration using Python:

import re

pattern1 = re.compile(r'\b(function\s+set([A-Z]\w*))\b\s*\(\s*\)')
pattern2 = re.compile(r'([a-z](?=[A-Z])|[A-Z](?=[A-Z][a-z]))')

def fix_setters(code):
    def replacer(match):
        var_name = pattern2.sub(r'\1_', match.group(2)).lower()
        return "%s($%s)" % (match.group(1), var_name)
    return pattern1.sub(replacer, code)

The last line ("return pattern1.sub(replacer, code)"), uses a callback to generate the text to be substituted. There should be similar functionality in most languages.

Python (before version 3.0) uses the modulus operator ("%") for formatting, similar to sprintf in e.g. the language C.

Example:

>>> s = """\
... public function setUserName() {
...   blaha
... }
... """
>>> print s
public function setUserName() {
  blaha
}

>>> print fix_setters(s)
public function setUserName($user_name) {
  blaha
}

>>>

More information: .NET - How can you split a “caps” delimited string into an array?

MizardX
AWESOME MizardX.This is exactly what I needed and it works GREAT. I don't know Python yet (still intend to learn...) but it's a very intuitive language, easy to read. Very good choice for a test case.
JMTyler