首页 文章

使用RegEx balancer 匹配括号

提问于
浏览
30

我正在尝试创建一个.NET RegEx表达式,它将正确地 balancer 我的括号 . 我有以下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 回答

  • 47

    正则表达式绝对可以做 balancer 括号匹配 . 它可能很棘手,需要一些更高级的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);
    

    balancer 匹配组具有几个功能,但是对于此示例,我们仅使用捕获删除功能 . (?<-open> \) ) 行将匹配 ) 并删除之前的"open"捕获 .

    最棘手的一行是 (?(open)(?!)) ,所以让我解释一下 . (?(open) 是一个条件表达式,仅在存在"open"捕获时才匹配 . (?!) 是始终失败的否定表达式 . 因此, (?(open)(?!)) 说"if there is an open capture, then fail" .

    Microsoft's documentation也很有帮助 .

  • 0

    使用 balancer 组,它是:

    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> **** ) ) 也许,所以 \(\) 更多"evident" .

    如果你真的讨厌自己(以及世界/你的同事共同编程)足以使用这些东西,我建议到处使用 RegexOptions.IgnorePatternWhitespace 和"sprinkling"空格:-)

  • 19

    正则表达式仅适用于Regular Languages . 这意味着正则表达式可以找到"any combination of a's and b's" . ( abbabbabaaa 等)的东西但是它们找不到“n a,a b,n a” . ( a^n b a^n )正则表达式't guarantee that the first set of a' s匹配第二组如 .

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

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

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

    这部分你已经知道了:

    func[a-zA-Z0-9_]*\( --weird part-- \)
    
    • 奇怪的部分 - 部分只是意味着; ( 允许任何字符 .| 任何部分 (.*) 存在多次 )* . 唯一的问题是,你不能匹配任何字符 . ,你必须使用 [^()] 来排除括号 .
    (([^()])|(\([^()]*\)))*
    

相关问题