RegEx Match VB.NET Выбрать чехол без дела - PullRequest
2 голосов
/ 03 декабря 2010

Я ищу RegEx, который найдет утверждения Select Case, в которых нет Case Else.

Вот что я придумала до сих пор

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

1 Ответ

0 голосов
/ 31 июля 2016

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-вкладыш:

^[ \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 (или возвращаться назад и потреблять больше строк).

Вот и все.

Обратите внимание, что если есть две позиции Select без Case Else, вложенные одна в другую, будет сопоставляться только внешнее утверждение. если вы заинтересованы в совпадении обоих, используйте

(?=(previous pattern))

и используйте Match.Groups(1) для согласования текста.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...