views:

211

answers:

1

First, a little background. I have strings that resemble the following:

((Foo.Bar.StartsWith("A")) && (Foo.Bar.EndsWith("B")))

And I'm trying to reformat these to look like this:

((Foo.Any(Bar.StartsWith("A"))) && (Foo.Any(Bar.EndsWith("B"))))

Side Note: The parts following the .Bar may sometimes not include (), like .Bar == "AB" .

I'm trying to capture two groups: the Foo. and the Bar.StartsWith("<A or B>") . I worked out the following pattern but it drops the trailing parenthesis.

\((Foo\.)(.*?)\)

So instead of getting what I'm looking for, I'm getting:

((Foo.Any(Bar.StartsWith("A")) && (Foo.Any(Bar.EndsWith("B")))

Which is two parentheses short.

The problem is I need to include closing parentheses in the .*? match IF there's also an opening parenthesis in there. I haven't figured out how to do this, anyone know?

PS - The code is C#.NET but that shouldn't matter unless the solution involves some obscure language-specific RegEx stuff.

+2  A: 

Is there a reason you have to do this with regular expressions? Trying to find "matching" pairs is one of the things that regex does not do well.

I would just do it through normal code. Do a search to find "(Foo.", then make a loop that iterates over the subsequent characters, keeping a counter for how many open/close parentheses you have passed. Increment it when you hit a ( and decrement when you hit a ). If you hit a closing parenthesis and the counter is at 0, that's the end of the string you need to capture. Stop capturing at that point, take that string and put it inside your Any() that you're adding. Then find the next "(Foo.".

Does that make sense? I could probably pseudocode it if you're not really following what I mean. Of course, this is only a valid option if you're able to abandon regular expressions anyway.

Chad Birch
I was using regex because at first glance it seemed like a quick, simple solution..until I hit this obstacle. I'm doing it the way you recommend since it makes things much easier. Thanks!
Nick Gotch