使用RegEx来平衡匹配括号

我正在尝试创build一个.NET正则expression式,将正确地平衡我的括号。 我有以下正则expression式:

func([a-zA-Z_][a-zA-Z0-9_]*)\(.*\) 

我想匹配的string是这样的:

 "test -> funcPow((3),2) * (9+1)" 

正则expression式应该匹配从funcPow到第二个funcPow括号的所有内容。 它应该在第二个右括号之后停止。 相反,它一直匹配到最后一个右括号。 RegEx正在返回这个:

 "funcPow((3),2) * (9+1)" 

它应该返回这个:

 "funcPow((3),2)" 

任何帮助,将不胜感激。

正则expression式绝对可以做平衡的括号匹配。 这可能会非常棘手,需要一些更高级的正则expression式function,但这并不难。

例:

 var r = new Regex(@" func([a-zA-Z_][a-zA-Z0-9_]*) # The func name \( # First '(' (?: [^()] # Match all non-braces | (?<open> \( ) # Match '(', and capture into 'open' | (?<-open> \) ) # Match ')', and delete the 'open' capture )+ (?(open)(?!)) # Fails if 'open' stack isn't empty! \) # Last ')' ", RegexOptions.IgnorePatternWhitespace); 

平衡的匹配组有两个function,但在这个例子中,我们只使用了捕获删除function。 行(?<-open> \) )将匹配a )并删除先前的“打开”捕获。

最棘手的一行是(?(open)(?!)) ,所以让我解释一下。 (?(open)是一个条件expression式,只有在“open”捕获的情况下才匹配。 (?(open)(?!))是一个总是失败的负expression式。因此(?(open)(?!))表示“一个公开的捕捉,然后失败“。

微软的文档也很有帮助。

使用平衡组,它是:

 Regex rx = new Regex(@"func([a-zA-Z_][a-zA-Z0-9_]*)\(((?<BR>\()|(?<-BR>\))|[^()]*)+\)"); var match = rx.Match("funcPow((3),2) * (9+1)"); var str = match.Value; // funcPow((3),2) 

(?<BR>\()|(?<-BR>\))是一个平衡组 (我使用的BR的名字是Brackets )。 这样可以更清楚地说明(?<BR> \( )|(?<-BR> \) ) ,这样\(\)更“明显”。

如果你真的恨自己(和世界/你的同事共同程序员)足够使用这些东西,我build议使用RegexOptions.IgnorePatternWhitespace和“洒”空白无处不在:-)

正则expression式仅适用于正规语言 。 这意味着一个正则expression式可以find“a和b的任意组合”types的东西( abbabbabaaa等),但是他们找不到“ n a's,one b, n a's”( a^nba^n )正则expression式不能保证第一组a与第二组a相匹配。

因此,它们不能匹配相等数量的开合括号。 编写一次遍历string一个字符的函数将是很容易的。 有两个柜台,一个开放paren,一个closures。 在遍历string时增加指针,如果opening_paren_count != closing_parent_count返回false。

 func[a-zA-Z0-9_]*\((([^()])|(\([^()]*\)))*\) 

你可以使用它,但是如果你使用.NET,可能会有更好的select。

这部分你已经知道:

  func[a-zA-Z0-9_]*\( --weird part-- \) 

– 简单的部分 – 部分只是意味着; (允许任何字符,或任何部分(.*)存在尽可能多的次数)* 。 唯一的问题是,你不能匹配任何字符. ,你必须使用[^()]来排除括号。

 (([^()])|(\([^()]*\)))*