当前位置: 首页 > 知识库问答 >
问题:

如何使用正则表达式匹配嵌套括号?

芮歌者
2023-03-14

正如标题所说,以下是一个输入示例:

 (outer
   (center
     (inner)
     (inner)
   center)
 ouer)
 (outer
   (inner)
 ouer)
 (outer
 ouer)

当然,匹配的字符串将通过递归进行处理。

我希望第一个递归匹配:

 [
 (outer
   (center
     (inner)
     (inner)
   center)
 ouer),
 (outer
   (inner)
 ouer),
 (outer
 ouer)]

之后的过程不用说。。。

共有3个答案

谷梁英资
2023-03-14
匿名用户

我发现了一个简单的正则表达式,它使用递归提取所有嵌套的平衡组,尽管最终的解决方案并不像您预期的那样简单:

正则表达式模式(1(?:\1??[^1]*?2)

示例输入:1AB1CD1EF22221AB1CD1EF222

为了简单起见,我把1放在开放括号中,把2放在封闭括号中。字母字符代表一些内部数据。我将重写输入,以便易于解释。

1  ab  1 cd 1ef2 2  2     1  ab  1 cd 1ef2 2  2

            |_1|
       |______2__|
|_____________3_____|

在第一次迭代中,正则表达式将匹配第一个兄弟姐妹组中最内部的子组1ef21ab1cd1ef222。如果我们记住它和它的位置,并删除这个组,将保留1ab1cd22。如果我们继续使用正则表达式,它将返回1cd2,最后返回1ab2。然后,它将继续以相同的方式解析第二个兄弟姐妹组。

正如我们从这个例子中看到的,正则表达式将正确地提取出出现在括号定义的层次结构中的子串。在第二次迭代中,特定子串在层次结构中的位置将被确定,如果它在字符串中的位置在第二次迭代的子串之间,那么它是一个子节点,否则它是一个兄弟节点。

从我们的例子来看:

>

  • 1ab1cd1ef222 1ab1cd1ef222,迭代匹配1ef2,索引6

    1ab1cd22 1ab1cd1ef222,迭代匹配1cd2,索引3,以6结尾。因为3

    1ab2 1ab1cd1ef222,迭代匹配1ab2,索引0,以3结尾。因为0

    1ab1cd1ef222,迭代匹配1ef2,索引6,因为它不是3

    在移到父级之前,我们必须迭代并删除所有兄弟姐妹。因此,我们必须按照迭代中出现的顺序记住所有兄弟姐妹。

  • 南宫保臣
    2023-03-14

    不要使用正则表达式。

    相反,一个简单的递归函数就足够了。以下是总体结构:

    def recursive_bracket_parser(s, i):
        while i < len(s):
            if s[i] == '(':
                i = recursive_bracket_parser(s, i+1)
            elif s[i] == ')':
                return i+1
            else:
                # process whatever is at s[i]
                i += 1
        return i
    

    例如,下面是一个将输入解析为嵌套列表结构的函数:

    def parse_to_list(s, i=0):
        result = []
        while i < len(s):
            if s[i] == '(':
                i, r = parse_to_list(s, i+1)
                result.append(r)
            elif s[i] == ')':
                return i+1, result
            else:
                result.append(s[i])
                i += 1
        return i, result
    

    像这样调用parse_to_list('((a)((b))((c)(d))(efg')会产生[[['a'],'',[['b']],'',[[c'],['d']],'e','f','g']的结果。

    岳佐
    2023-03-14

    许多正则表达式实现不允许匹配任意数量的嵌套。然而,Perl、PHP和。NET支持递归模式。

    Perl中的演示:

    #!/usr/bin/perl -w
    
    my $text = '(outer
       (center
         (inner)
         (inner)
       center)
     ouer)
     (outer
       (inner)
     ouer)
     (outer
     ouer)';
    
    while($text =~ /(\(([^()]|(?R))*\))/g) {
      print("----------\n$1\n");
    }
    

    将打印:

    ----------
    (outer
       (center
         (inner)
         (inner)
       center)
     ouer)
    ----------
    (outer
       (inner)
     ouer)
    ----------
    (outer
     ouer)

    或者,PHP等价物:

    $text = '(outer
       (center
         (inner)
         (inner)
       center)
     ouer)
     (outer
       (inner)
     ouer)
     (outer
     ouer)';
    
    preg_match_all('/(\(([^()]|(?R))*\))/', $text, $matches);
    
    print_r($matches);
    

    它产生:

    Array
    (
        [0] => Array
            (
                [0] => (outer
       (center
         (inner)
         (inner)
       center)
     ouer)
                [1] => (outer
       (inner)
     ouer)
                [2] => (outer
     ouer)
            )
    
    ...

    一个解释:

    (          # start group 1
      \(       #   match a literal '('
      (        #   group 2
        [^()]  #     any char other than '(' and ')'
        |      #     OR
        (?R)   #     recursively match the entir pattern
      )*       #   end group 2 and repeat zero or more times
      \)       #   match a literal ')'
    )          # end group 1

    注意@Goozak的评论:

    更好的模式可能是\(?

     类似资料:
    • 问题内容: 我正在尝试匹配带有嵌套括号的类似数学表达式的字符串。 [‘((((1 + 0)+1)+1)’] 我希望它与所有包含的表达式匹配,例如(1 + 0),((1 + 0)+1)… 我什至不在乎它是否匹配不需要的表达式,例如(((1 + 0),我可以照顾的。 为什么它还没有这样做,我该怎么做? 问题答案: 正则表达式尝试匹配尽可能多的文本,从而消耗了所有字符串。它不会在字符串的一部分上寻找正则

    • 我有这样一个文本: 我试图在c#中使用正则表达式来提取嵌套的if/eles-段。 要查找“?”,我使用了: 模式1: 找到“:”我用了: 模式2:

    • 我正在寻找一个正则表达式(**),它将匹配未知数量的嵌套函数。所以 所有的比赛都会成功。但举例来说,如果我在末尾添加一个额外的结束括号,它将不会包含在比赛中。 (**)请不要回答通过解析(和计算括号)比使用正则表达式更容易做到这一点——在挠头一会儿后,我已经知道了!

    • 问题内容: 我正在尝试编写一个匹配嵌套括号的正则表达式,例如: 这样的字符串应该匹配,导致所有嵌套括号都被关闭,而是: 不应该或更好地至少匹配第一个“(((text)))(text)”部分。 实际上,我的正则表达式是: 但这并不能像我期望的那样正常工作。如何解决?我哪里错了?谢谢! 问题答案: 当我找到此答案时,我无法弄清楚如何修改模式以使用自己的定界符where 和。所以我的方法是使其更通用。

    • 问题内容: 匹配字符串中的’(’的正则表达式是什么? 以下是场景: 我有一串 我想使用正则表达式拆分字符串。为此,我正在使用 但是我收到以下异常。 转义似乎不起作用。 问题答案: 两种选择: 首先,你可以使用转义 回 斜线- 另外,由于它是单个字符,因此您可以将其放入不需要转义的字符类中-

    • 问题内容: 我一直试图在Java中编写一个正则表达式以删除下面括号中的所有内容,同时保留其他所有内容。 注意,括号可以嵌套,这就是为什么我的模式失败的原因 。有人能帮我吗?下面我试过了: 但这打印: d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 OO 6. Be2 e5 7. dxe5 dxe5 8. Qxd8 Rxd8 9. Bg5 Nbd7 10. OO