2

我正在寻找一个 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 但外部没有。

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

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

4

1 回答 1

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)

在 regexstorm.net 上测试


描述

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

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

这就是平衡组背后的逻辑。如果它匹配一个嵌套的Select Case,它创建一个新的捕获,如果它匹配一个End Select它减去最后一个捕获。因此,仅在外部组中不会存储捕获。

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

而已。

请注意,如果有两个没有 Case Else 的 Select 语句相互嵌套,则只会匹配外部语句。如果您有兴趣匹配两者,请使用

(?=(previous pattern))

并用于Match.Groups(1)获取匹配的文本。

于 2016-07-31T12:32:51.607 回答