开发者

RegEx Match VB.NET Select Case with no Case Else

开发者 https://www.devze.com 2023-01-28 00:18 出处:网络
I\'m looking for a RegEx that will find Select Case Statements that have no Case Else in them. Here\'s what I came up with so far

I'm looking for a RegEx that will find Select Case Statements that have no Case Else in them.

Here's what I came up with so far

(?sm)^\s*Select Case.*(?<!^\s*Case Else.*)End Select

This one works perfectly except for cases that may have nested statements.

in my attempt to use balance groups, I came up with the following

Select Case(?>Select Case(?<DEPTH>)|End Select(?<-DEPTH>)|.?)*?(?(DEPTH)(?!))End Select

Which correctly finds balanced groups of Select Case/End Selects but I'm having a hard time getting it to work with the (?

Heres some sample data:

Select Case
 Case :
  Select Case
   Case : Something
  End Select
  Case Else : SomethingElse
End Select

In this case it should match just the inner Select Case because the Outter has it's Case Else

Select Case
 Case :
  Select Case
   Case : Something
   Case Else : SomethingElse
  End Select
End Select

Should match then entire block because the inner has the Else but the outter doesnt.

Select Case
 Case :
  Select Case
   Case : Something
   Case Else : SomethingElse
  End Select
  Case Else : SomethingElseOutter
End Select

Should not match because bo开发者_JS百科th inner and outter selects have a Case Else


Regex

^[ \t]*Select[ ]Case.*\n                    # Start of 'Select Case' statement
(?>                                         # REPEAT as few as possible
    (?>[ \t]*)                              #   whitespace at beginning of line
    (?>                                     #   And
        (?<nested>Select[ ]Case)            #       there's a nested Select (+1 balancing group)
    |                                       #     Or
        (?(nested)                          #       If inside a nested statement
            (?<-nested>End[ ]Select)?       #           match 'End Select' (-1 balancing group)
        |                                   #       Else
            (?!Case[ ]Else)                 #           it can't match a 'Case Else'
        )                                   #
    )                                       #
    .*\n                                    #   Consume the whole line (go to next line)
)*?                                         # END REPEAT
(?(nested)(?!)|                             # If inside a nested statement, it can't match
[ \t]*End[ ]Select)                         # if outer statement, match the 'End Select'

One-liner:

^[ \t]*Select Case.*\n(?>(?>[ \t]*)(?>(?<nested>Select Case)|(?(nested)(?<-nested>End Select)?|(?!Case Else))).*\n)*?(?(nested)(?!)|[ \t]*End Select)

Test on regexstorm.net


Description

The regex matches Select Case and then it tries to consume as few lines as it can until it finds an End Select. For each line:

  • If there's a nested Select Case, it creates a Capture in (?<nested>Select[ ]Case)
  • (?(nested)true|false) is an IF clause that:
    • If there's a capture for nested (i.e. inside a nested statement), it could substract a capture when (?<-nested>End[ ]Select)? matches (optional group).
    • Or if there isn't a capture (i.e. in the main statement), the line should not be an Else statement (?!Case[ ]Else).

This is the logic behind balancing groups. If it matches a nested Select Case, it creates a new capture, and if it matches an End Select it substracts the last capture. Therefore, only in the outer group there will be no captures stored.

We use that at the end of the pattern with (?(nested)(?!)|[ \t]*End[ ]Select). If there's a capture it goes to (?!) (which can never match), fails and backtracks to keep consuming more lines. But if there are no captures, it can match [ \t]*End[ ]Select (or backtrack and consume more lines as well).

That's it.

Notice though that if there are two Select staments without a Case Else, nested one in another, only the outer statement will be matched. if you're interested in matching both, use

(?=(previous pattern))

and use Match.Groups(1) to get the text matched.

0

精彩评论

暂无评论...
验证码 换一张
取 消