【问题标题】:RegEx Match VB.NET Select Case with no Case Else正则表达式匹配 VB.NET 选择大小写,没有其他大小写
【发布时间】:2011-05-19 18:23:31
【问题描述】:

我正在寻找一个 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
 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

【问题讨论】:

  • 是否必须在单个 RegEx 中完成?
  • 我希望有一个。但是,是的,如果情况变得更糟,我将使用代码中的循环深入研究它们。

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


【解决方案1】:

正则表达式

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

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

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

就是这样。

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

(?=(previous pattern))

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

【讨论】:

    猜你喜欢
    • 2018-04-07
    • 1970-01-01
    • 2014-10-12
    • 2011-02-01
    • 2012-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多