RegEx匹配VB.NET Select Case没有Case Else

时间:2010-12-03 13:41:28

标签: .net regex regex-group balancing-groups

我正在寻找一个RegEx,它会找到其中没有Case Else的Select Case语句。

这是我到目前为止所提出的

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

除了可能有嵌套语句的情况外,这个工作正常。

在我尝试使用余额组时,我想出了以下内容

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

哪个正确找到了Select Case / End Selects的平衡组,但是我很难让它与(?

以下是一些样本数据:

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

在这种情况下,它应该只匹配内部的Select Case,因为Outter有它的Case Else

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

应该匹配整个区块,因为内部有Else但是outter不存在。

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

不应该匹配,因为内部和外部选择都有一个Case Else

1 个答案:

答案 0 :(得分:0)

<强>正则表达式

^[ \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'

一衬垫:

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

Test on regexstorm.net

<强>描述

正则表达式与Select Case匹配,然后尝试使用尽可能少的行,直到找到End Select。对于每一行:

  • 如果有嵌套Select Case,则会在(?<nested>Select[ ]Case)
  • 中创建一个捕获
  • (?(nested) true | false )是一个IF子句:
    • 如果有nested的捕获(即在嵌套语句中),它可以在(?<-nested>End[ ]Select)?匹配时(可选组)减去捕获。
    • 或者如果没有捕获(即在主要声明中),该行不应该是Else语句(?!Case[ ]Else)

这是balancing groups背后的逻辑。如果它与嵌套的Select Case匹配,则会创建一个新的捕获,如果它与End Select匹配,则会减去最后一次捕获。因此,只有在外部组中才会存储捕获。

我们在(?(nested)(?!)|[ \t]*End[ ]Select)模式的末尾使用它。如果有捕获它会转到(?!)(它永远不会匹配),失败并回溯以继续消耗更多行。但如果没有捕获,它可以匹配[ \t]*End[ ]Select(或回溯并消耗更多行)。

那就是它。

请注意,如果有两个没有Case Else的Select staments,则嵌套在另一个中,只会匹配外部语句。如果您对匹配两者感兴趣,请使用

(?=(previous pattern))

并使用Match.Groups(1)来匹配文字。