I’m having a classic if, else, endif implementation in a proprietary language.
Given I have the string below, I want to locate the [!--@Else--] statement, but only the one that is NOT inside the [!--@If--]...[!--@EndIf--] block. So I want an even number of openings and closing of ifs before matching the else…
Lorem ipsum
[!--@If(1=1)--]
One it is
[!--@If(2=1)--]
2 is not 1
[!--@Else--]
so do this
[!--@EndIf--]
[!--@Else--]
1 is not 1
[!--@EndIf--]
and something else
In this example, I want to locate the second else – and not the first since it is inside the if/endif block.
I’ve now spend countless hours with negative and positive lookbehinds and cannot get it to work!?
As Abbondanza mentioned, you will need balancing groups if you want to do this with regex. I should warn you, this is not going to be a nice solution. While .NET’s regex engine is one of the few, that can handle cases like this, it is still not really the recommended approach. You are probably better off parsing your language manually, which allows you to count nesting levels much more easily.
Anyway, just to show you, why regular expressions are inappropriate for this task in productive software, here is a regex (use
RegexOptions.IgnorePatternWhitespaceandRegexOptions.Singleline) that still makes some simplifying assumptions (which I will get to later):Now this is already quite a beast, which almost no one would understand without this novel of comments.
But I mentioned simplifying assumptions. Here you go.
Ifconditions. If you want to do that, you will have to check their correct nesting, too. It is slightly simpler than what I did here, but it will still require building up and down a stack of parentheses.[\[]]*. Since I disallow any kind of opening parentheses, you cannot have conditional statements inside theElseblock. Now if you want to allow this, you have to copy almost the whole thing again into the actual match, so that you know whichIfs andEndIfs are inside theElseand which ones come afterwards.You see, to get a regex solution that covers 100% of all cases, you would need to make that code completely unmaintainable. That’s why you should really consider, analyzing the string manually and building some kind of syntax tree. This way you get an OOP representation of your nesting structures which can easily be traversed for the specific
Elses you want to find.