我正在尝试在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
);
我发现很多例子展示了如何找到不平衡的括号,但没有一个试图将模式限制为开始和结束标记 平衡的点。
我正在尝试用正则表达式做什么?
答案 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块,这让我困惑了一段时间。