使用RegEx平衡匹配括号

时间:2011-10-26 03:06:25

标签: c# .net regex

我正在尝试创建一个.NET RegEx表达式,它将正确地平衡我的括号。我有以下RegEx表达式:

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

我想要匹配的字符串是:

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

应该发生什么是正则表达式应匹配从funcPow到第二个右括号的所有内容。它应该在第二个右括号后停止。相反,它一直匹配到最后一个右括号。 RegEx将此返回:

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

它应该返回:

"funcPow((3),2)"

对此有任何帮助将不胜感激。

4 个答案:

答案 0 :(得分:49)

正则表达式绝对可以做平衡括号匹配。它可能很棘手,需要一些更高级的Regex功能,但它并不太难。

示例:

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);

平衡匹配组有几个功能,但对于此示例,我们仅使用捕获删除功能。行(?<-open> \) )将匹配)并删除之前的“打开”捕获。

最棘手的一句话是(?(open)(?!)),所以让我解释一下。 (?(open)是一个条件表达式,仅在存在“打开”捕获时才匹配。 (?!)是一个总是失败的否定表达式。因此,(?(open)(?!))表示“如果有开放捕获,则失败”。

Microsoft's documentation也很有帮助。

答案 1 :(得分:19)

使用平衡组,它是:

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>\))Balancing GroupBR我用的名称是Brackets)。以这种方式更清楚 (?<BR> \( )|(?<-BR> <强大> \) ) 也许,以便\(和{ {1}}更“明显”。

如果你真的讨厌自己(以及这个世界/你的同伴共同编程)足以使用这些东西,我建议到处使用\)和“洒”白色空间: - )

答案 2 :(得分:0)

正则表达式仅适用于Regular Languages。这意味着正则表达式可以找到“a和b的任意组合”的类型。(abbabbabaaa等)但是他们找不到“ n a,一个b, n a的“。(a^n b a^n)正则表达式不能保证第一组a匹配第二组a。

因此,它们无法匹配相同数量的开括号和右括号。编写一个一次遍历字符串一个字符的函数就很容易了。有两个柜台,一个用于打开paren,一个用于关闭。如果opening_paren_count != closing_parent_count返回false,则在遍历字符串时递增指针。

答案 3 :(得分:-1)

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

您可以使用它,但如果您正在使用.NET,则可能有更好的替代方案。

这部分你已经知道了:

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

- 奇怪的部分 - 部分只是意味着; (允许任何字符.|任何部分(.*)按其所需的次数)*存在。唯一的问题是,您无法匹配任何字符.,您必须使用[^()]来排除括号。

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