RegEx Match VB.NET Выбрать чехол без дела
Я ищу RegEx, который найдет Select Case Statement, в которых нет 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
Должен совпадать с целым блоком, потому что у внутреннего есть иное, а у внешнего нет.
Select Case
Case :
Select Case
Case : Something
Case Else : SomethingElse
End Select
Case Else : SomethingElseOutter
End Select
Не должно совпадать, потому что как у внутреннего, так и у внешнего выбора есть другой случай
1 ответ
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'
Один лайнер:
^[ \t]*Select Case.*\n(?>(?>[ \t]*)(?>(?<nested>Select Case)|(?(nested)(?<-nested>End Select)?|(?!Case Else))).*\n)*?(?(nested)(?!)|[ \t]*End Select)
Описание
Регулярные совпадения Select Case
и затем он пытается использовать как можно меньше строк, пока не найдет End Select
, Для каждой строки:
- Если есть вложенный
Select Case
Создает Захват в(?<nested>Select[ ]Case)
(?(nested)
правда|
ложный)
является условием 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)
чтобы текст соответствовал.