C# 如果括号可能为';逃脱';

C# 如果括号可能为';逃脱';,c#,.net,regex,C#,.net,Regex,假设我有一个具有以下字符串的玩具语言: fun( fun3\(\) ) + fun4() 这里,“fun”接受“fun3()”作为其参数。fun4()将留待以后评估 现在假设我有一个不同的字符串: fun( fun3()\\) ) 在这里,“fun”应该是“fun3()\”,我们有一个)剩余的 通过做“\”来转义一个“\”意味着我们从字面上理解了它,因此,/这对“\”不再从括号中转义。第三个\将再次脱离括号,等等 现在,假设我想使用C#)更强大的正则表达式库来匹配这个字符串,使用它匹配方括号

假设我有一个具有以下字符串的玩具语言:

fun( fun3\(\) ) + fun4()
这里,“fun”接受“fun3()”作为其参数。fun4()将留待以后评估

现在假设我有一个不同的字符串:

fun( fun3()\\) )
在这里,“fun”应该是“fun3()\”,我们有一个)剩余的

通过做“\”来转义一个“\”意味着我们从字面上理解了它,因此,/这对“\”不再从括号中转义。第三个\将再次脱离括号,等等

现在,假设我想使用C#)更强大的正则表达式库来匹配这个字符串,使用它匹配方括号的方式,特别是这样的方式;我知道通常我会使用正确的解析方法,而不是(扩展的)正则表达式。这不是关于我应该使用什么工具,而是关于这个工具可以做什么

我将使用以下三个字符串作为测试

fun(abc) fun3()
这意味着fun()接受“abc”作为其参数。fun3()是剩余的

fun(\\\)\)) fun3()
fun(fun2(\)\\\() ) fun3()
这意味着fun()接受“\)”作为其参数。fun3()是剩余的

fun(\\\)\)) fun3()
fun(fun2(\)\\\() ) fun3()
这意味着fun()接受'fun2()\()'作为其参数。fun3()是剩余的

fun(\\\)\)) fun3()
fun(fun2(\)\\\() ) fun3()
正如艾伦·摩尔(Alan Moore)在书中所设想的那样,我想用的第一件事就是向后看。 下面的正则表达式处理第一种情况,但显然不是第二种情况。它看到第一个“)太快了

Regex catchRegex = new Regex(@"^fun\((.*?(?<!\\)(?:\\\\)*)(?<ClosingChar>[\)])(.*$)");
string testcase0 = @"fun(abc) fun3()";
string testcase1 = @"fun(\\\)\)) fun3()";
string testcase2 = @"fun(fun2(\)\\\() ) fun3()";
Console.WriteLine(catchRegex.Match(testcase0).Groups[1]); // 'abc'
Console.WriteLine(catchRegex.Match(testcase0).Groups[2]); // ' fun3()'
Console.WriteLine(catchRegex.Match(testcase0).Groups[3]); // ')'

Console.WriteLine(catchRegex.Match(testcase1).Groups[1]); // '\\\)\)'
Console.WriteLine(catchRegex.Match(testcase1).Groups[2]); // ' fun3()'
Console.WriteLine(catchRegex.Match(testcase1).Groups[3]); // ')'

Console.WriteLine(catchRegex.Match(testcase2).Groups[1]); // 'fun2(\)\\\(' <--!
Console.WriteLine(catchRegex.Match(testcase2).Groups[2]); // ' ) fun3()' <--!
Console.WriteLine(catchRegex.Match(testcase2).Groups[3]); // ')'
Regex-catchRegex=newregex(@“^fun”(.*?(?[\]))(.*$)”;
字符串testcase0=@“fun(abc)fun3()”;
字符串testcase1=@“fun(\\\)\)fun3()”;
字符串testcase2=@“fun(fun2(\)\ \ \ \())fun3()”;
Console.WriteLine(catchRegex.Match(testcase0.Groups[1]);/'abc'
Console.WriteLine(catchRegex.Match(testcase0.Groups[2]);/'fun3()
Console.WriteLine(catchRegex.Match(testcase0.Groups[3]);/“)
Console.WriteLine(catchRegex.Match(testcase1.Groups[1]);/“\\)\”
Console.WriteLine(catchRegex.Match(testcase1.Groups[2]);/'fun3()
Console.WriteLine(catchRegex.Match(testcase1.Groups[3]);/“)
Console.WriteLine(catchRegex.Match(testcase2.Groups[1]);/'fun2(\)\\('我建议使用以下正则表达式:

@"^fun\(((?:[^()\\]|\\.|(?<o>\()|(?<-o>\)))+(?(o)(?!)))\)(.*$)"

我有另一种处理转义字符的方法,它使用的是类似于:

(?:[^()\\]|\\.)
当与平衡组结合时,其结束于上面的一个

^fun\(匹配“fun”(“fun”)开头的字面意思
(                
(?:            
[^()\\]匹配任何不是“(”、“)”或“\”的内容
|              
\\.匹配任何转义字符
|              
(?\()匹配一个“(”并将其命名为“o”
|            
(?\)匹配a'),并删除命名的“o”捕获
)+           
(?(o)(?!)如果“o”不存在,则使正则表达式失败
)                
\)(.*$)匹配剩余的任何内容

@leppie对我来说,听起来更像是你没有读过这个问题。非常感谢你,杰瑞。我不敢相信我没有“看到”转义字符的方法。