2

CaseElseが含まれていないSelectCaseステートメントを見つける正規表現を探しています。

これが私がこれまでに思いついたものです

(?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

この場合、OutterにはCase Elseがあるため、内側のSelectCaseと一致する必要があります。

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

内側と外側の両方の選択にCaseElseがあるため、一致しないはずです

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 のない 2 つの Select ステートメントがあり、互いに入れ子になっている場合は、外側のステートメントのみが一致することに注意してください。両方を一致させたい場合は、

(?=(previous pattern))

Match.Groups(1)テキストを一致させるために使用します。

于 2016-07-31T12:32:51.607 に答える