-2

That's my string:

myclass.test() and(myclass.mytest() and myclass.test("argument")) or (myclass.mytests(1))

I am trying to capture only the openings of parentheses "(" that is not part of a function,

So I tried to start capturing the functions (and then deny this rule):

\w*\.\w[^(]*\(

Perfect, i catch only the functions, when I tried to use the following expression I did not succeed (why?)

(?<=(\w*\.\w[^(]*\())\(

Notes: - myclass. never changes - don't forget the "and(" - (?<=t)( < works fine.

Thanks :)


Temporary Solution

I will continue studying and trying to apply the "lookbehind" for this case, it seems an interesting approach, but our friend @hwnd suggested a different approach that applies in my case:

\((?=myclass)

Thank u guys.

Jonny
  • 408
  • 4
  • 12
  • 2
    In which language do you do this? Java does not support variable length look-behind. And the `and(...)` is considered a function also, right? – justhalf Oct 18 '13 at 05:51
  • I think you can just remove the last parentheses in the look behind. It should not be there. So, try this one to capture the openings of parentheses that is not part of a function: `(?<!(\w*\.\w[^(]*))\(` – justhalf Oct 18 '13 at 05:55
  • @justhalf already tried but did not succeed – Jonny Oct 18 '13 at 15:08
  • Python also does not support variable length lookbehind. You must use other methods. And by "did not succeed", please tell us more. Is it an error? Does it run but doesn't accomplish what you want to do? – justhalf Oct 18 '13 at 15:48
  • @justhalf doesn't accomplish (checkout http://stackoverflow.com/questions/11640447/regexps-variable-length-lookbehind-assertion-alternatives) – Jonny Oct 19 '13 at 03:02

2 Answers2

1

I am a bit confused on what is part of a function or not here.

To match the following myclass.test( parts you could just do.

[a-zA-Z]+\.[a-zA-Z]+\(

Both of these will match the open parentheses that is not part of the myclass. function.

Positive Lookahead

\((?=[^)])

Regular expression:

\(          '('
(?=         look ahead to see if there is:
 [^)]       any character except: ')'
)           end of look-ahead

Negative Lookahead

\((?!\))

Regular expression:

\(          '('
 (?!        look ahead to see if there is not:
  \)        ')'
 )          end of look-ahead

See live demo

You could possibly even use a Negative Lookbehind here.

(?<!\.)\((?!\))
hwnd
  • 69,796
  • 4
  • 95
  • 132
  • I am not a regex expert, but wouldn't `\((?!\))` be sufficient? Why do you need the look-behind for a closing parenthesis? The string does not contain any closing parentheses followed by an opening one, does it?! At least, the result in your live demo stays the same after I removed the look-behind. – gehho Oct 18 '13 at 08:56
  • @hwnd when i use arguments like test("xxx"), should not work :( I just want the parenthesis that do not come from methods, so in this case enters the previous example. – Jonny Oct 18 '13 at 15:18
  • @gehho test("xxx") :( – Jonny Oct 18 '13 at 15:18
  • From your string `myclass.test() and(myclass.mytest() and myclass.test("argument")) or (myclass.mytests(1))` what parentheses should be matched? – hwnd Oct 18 '13 at 15:28
  • @hwnd only 2, from "and(" and "or (", only those which divide the blocks – Jonny Oct 18 '13 at 15:38
  • Try this. `\((?=myclass)` – hwnd Oct 18 '13 at 15:44
  • @hwnd, basically, as he said in the question, he wants every parenthesis which is not matched by `\w*\.\w[^(]*\(` – justhalf Oct 18 '13 at 16:30
  • @hwnd I never thought of it this way, thank you for opening my mind – Jonny Oct 19 '13 at 03:07
0

Since you can't use variable-length lookbehind in Python, you will need to do some of the job outside regex. One possible way is to capture two groups, the first one will capture the class.function part if it exists, the second one will capture the open parenthesis. So you can just take those parenthesis for which the first group has no match.

In this case, we check whether the match length is one character (i.e., only the opening parenthesis), then we print the matching index. You can print the matching string also, which would always be an open parenthesis =D

import re
text = 'myclass.test() and(myclass.mytest() and myclass.test("argument")) or (myclass.mytests(1))'
for result in re.finditer(r'(\w+\.\w[^(]*\()?\(',text):
    if result.end()-result.start()==1:
        print result.span(), result.string

Result:

(18,19)
(69,70)
justhalf
  • 8,960
  • 3
  • 47
  • 74