2016-06-13 2 views
1

Я пытаюсь написать регулярное выражение в C#, которое будет соответствовать блокам PL/SQL, где есть outermostEND; без обратной косой черты, поскольку это приводит к выходу сценариев тихо в этот момент при запуске с SQLPlus.Согласование только внешних блоков с регулярным выражением

Так, например, это должно вызвать регулярное выражение:

BEGIN 
END; 

и это должно не триггер это:

BEGIN 
END; 
/

Но вложенная BEGIN ... END блоки не нужна косая черта, поэтому следующее должно быть не быть совпадением:

BEGIN 
    BEGIN 
    END; 
    -- no trailing slash here, and that's fine 
END; 
/

Чувствуется, что балансирующие группы должны быть в состоянии справиться с этим. Я хочу соответствовать «END»; если за ним не следуют дополнительные пробелы и косая черта, а только для самого внешнего блока.

Я пробовал некоторые вариации на следующем, но это не совсем там:

var trigger = new Regex(   
    @"(?<keyword>BEGIN).*?(?<-keyword>END;)(?(keyword)(\s*/))", 
    RegexOptions.Singleline | RegexOptions.IgnoreCase 
); 

Я нашел много примеров, показывающих, как найти несбалансированные скобки, но ни что не пытаются ограничить шаблоны только точки, где начальный и конечный теги являются сбалансированным.

Является ли то, что я пытаюсь сделать с помощью регулярного выражения?

+0

Чтобы быть ясным, в вашем последнем примере вы хотите соответствовать самому внутреннему BEGIN/END или нет? –

+0

@CasimiretHippolyte No. С тремя примерами я хочу, чтобы IsMatch() был истинным для первого, а false для остальных. –

+0

Также стоит отметить, что в последовательности может быть несколько внешних блоков. Я хочу, чтобы регулярное выражение соответствовало, если кому-либо из них не хватает косой черты. –

ответ

0

Вот что я закончил с, в значительной степени на основе ответа Camimir ЕТ Ипполита:

(?xi) 
^([^B]|B(?!EGIN))*    # chomp everything before the first BEGIN 
(?>        # possible content in a block 
    (?<c> \bBEGIN\b) [^BE]* | 
    (?<-c> \bEND; ) [^BE]* | 
    \b[BE]+   [^BE]* | 
    B(?!EGIN\b)  [^BE]* | 
    E(?!ND;)   [^BE]* 
)*? 
(?<-c>\bEND;)      # pop closing END; off the stack 
(?(c)(?!))      # only match outer blocks 
\s*        # ignore whitespace between END; and/
([^/ \t\n\r]|$)     # it's a match if there is no trailing/

Это позволяет избежать необходимости делать какие-либо постобработки групп: либо IsMatch верно, и есть недостающий / или это ложь и нет. Это лучше подходит для рамки, в которой я пытаюсь сложить это (по общему признанию, в моем вопросе не очень хорошо).

Также важно привязать поиск к первому BEGIN. Если он свободно плавает, то он может вернуться к соответствию вложенным блокам BEGIN ... END, которые немного смутили меня.

2

Идея заключается в том, чтобы соответствовать все крайние блоки без исключения, то определить, какой из них не следует косая черта, вам нужно только проверить для каждого результата, который один имеет пустой захвата группы 1.

модель с игнорировать пробельные вариант:

(?xi) 
\bBEGIN\b [^BE]* 
(?> # possible content in a block 
    (?<c> \bBEGIN\b) [^BE]* | 
    (?<-c> \bEND; ) [^BE]* | 
    \B[BE]+  [^BE]* | 
    B(?!EGIN\b) [^BE]* | 
    E(?!ND;) [^BE]* 
)*? 
(?(c)(?!)) # <-- perhaps better if you exchange these 
\bEND;  # <-- two lines in real world 
\s* 
(/?) # optional 

Demo нажмите на «столе», чтобы увидеть, что я имею в виду.

Смежные вопросы