仅使用正则表达式匹配最外面的块

时间:2016-06-13 14:09:58

标签: c# regex

我正在尝试在C#中编写一个正则表达式,它将匹配PL / SQL块,其中最外层 END;没有正斜杠,因为这些会导致脚本当使用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
);

我发现很多例子展示了如何找到不平衡的括号,但没有一个试图将模式限制为开始和结束标记 平衡的点。

我正在尝试用正则表达式做什么?

2 个答案:

答案 0 :(得分: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点击“表格”查看我的意思。

答案 1 :(得分:0)

这是我最终的结果,主要基于Camimir et Hippolyte的回答:

(?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块,这让我困惑了一段时间。