首页 > 解决方案 > 正则表达式匹配包含特定字符的最里面的括号集

问题描述

什么是正则表达式来获取包含特定字符的最里面的括号集;'|' 在这种情况下?

一些示例和(c#)测试方法:

string[] tests = {
    "x () y", "",
    "x (a) y", "",
    "x (a.b()) y", "",
    "x ((a).b() | (b).c()) y", "(a).b() | (b).c()",
    "x (a|b) y", "a|b",
    "x ((a|b) | c)", "a|b",
    "x (a|b|c) y", "a|b|c",
    "x (a|a.b()|c) y", "a|a.b()|c",
    "x (a.b()|b.c()) y", "a.b()|b.c()",
    "x (a.b()|b.c()|c) y", "a.b()|b.c()|c",
    "x (a|b.c()|c.d()) y", "a|b.c()|c.d()",
    "x (a|(b.c()|d)) y", "b.c()|d",
    "x (a|a.b(a)|c) y", "a|a.b(a)|c"
};

for (int i = 0; i < tests.Length; i+=2)
{
    var match = re.Match(tests[i]);
    var result = match.Groups[1].Value;
    Assert.That(result, Is.EqualTo(tests[i + 1]));
}

标签: c#.netregex

解决方案


解决所有测试的“非常简单”的正则表达式:

var re = new Regex(@"
(?:\()
(
    (?>
        (?:  
            (?<p>\()  |  
            (?<-p>\))  |  
            [^()|]+  |  
            (?(p)(?!))(?<pipe>\|)  
        )*  
    )    
)
(?:\))
(?(p)(?!))
(?(pipe)|(?!))", RegexOptions.IgnorePatternWhitespace);

string result = match.Groups[1].Value;

注意使用RegexOptions.IgnorePatternWhitespace. 正则表达式基于平衡组。基于你不应该尝试使用你不完全理解的正则表达式这一事实,我将省略关于它如何工作的确切解释。我只会说检查(?(pipe)|(?!))检查是否至少 a|在捕获中被捕获,而(?(p)(?!))意味着“没有仍然被(?<p>\()表达式捕获的开括号”。

我对这个正则表达式的看法是,它在正则表达式中是一种徒劳且危险的练习!(如果不清楚我属于某些人,当遇到问题时,会想“我知道,我会使用正则表达式”现在他们有两个问题。学派)。你不应该使用它。这是不可调试的代码恐怖。

附加的事情:这个正则表达式大量回溯......添加(?>......)以禁用回溯。

回溯的附加测试(第一个带有不平衡括号):

"((((amusemen).emoadj().cap()(, (are we |arent we|I gather)|)?)", "are we |arent we|I gather",
"((amusemen).emoadj().cap()(, (are we |arent we|I gather)|)?)", "are we |arent we|I gather",

推荐阅读