0

I am looking to find method names for python functions. I only want to find method names if they aren't after "def ". E.g.:

"def method_name(a, b):" # (should not match)
"y = method_name(1,2)"   # (should find `method_name`)

My current regex is /\W(.*?)\(/.

1
  • I understand the exclusion criterion, but I don't understand the inclusion criterion. For example, suppose the second line were y = str[1..-1].upcase. Would you want the method []= or upcase returned? I suspect that the second line must have a particular form, but you have not said what that is. Is it always a variable, an equals sign, the method name (without syntactic sugar), as in your example? Please clarify by editing. Commented Mar 19, 2016 at 2:28

2 Answers 2

2
str = "def no_match(a, b):\ny = match(1,2)"
str.scan(/(?<!def)\s+\w+(?=\()/).map(&:strip)
#⇒ ["match"]

The regex comments:

  • negative lookbehind for def,
  • followed by spaces (will be stripped later),
  • followed by one or more word symbols \w,
  • followed by positive lookahead for parenthesis.

Sidenote: one should never use regexps to parse long strings for any purpose.

Sign up to request clarification or add additional context in comments.

3 Comments

Have you tested this ? Because lookahead assertion won't be true for (1,2) as you are only looking forward for ().
@noob I don’t understand your complain. Probably because you failed to count parentheses. Go and test it yourself.
Ow ! My bad. I did failed to count it.
0

I have assumed that lines that do not contain "def" are of the form "[something]=[zero or more spaces][method name]".

R1 = /
     \bdef\b   # match 'def' surrounded by word breaks
     /x        # free-spacing regex definition mode 

R2 = /
     [^=]+      # match any characters other than '='
     =          # match '='
     \s*        # match >= 0 whitespace chars
     \K         # forget everything matched so far
     [a-z_]     # match a lowercase letter or underscore
     [a-z0-9_]* # match >= 0 lowercase letters, digits or underscores
     [!?]?      # possibly match '!' or '?'
     /x         

def match?(str)
  (str !~ R1) && str[R2]
end

match?("def method_name1(a, b):") #=> false 
match?("y = method_name2(1,2)")   #=> "method_name2" 
match?("y = method_name")         #=> "method_name" 
match?("y = method_name?")        #=> "method_name?" 
match?("y = def method_name")     #=> false 
match?("y << method_name")        #=> nil 

I chose to use two regexes to be able to deal with both my first and penultimate examples. Note that the method returns either a method name or a falsy value, but the latter may be either false or nil.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.