如何处理正则表达式中的内部标签?

How to take care of inner tag in regex?

我尝试通过正则表达式 (PHP preg_match_all) 解析 CSS,例如

([^{]+)\s*\{\s*([^}]+)\s*}

但问题是存在内部 { 标签时。例如,

table {
    border-collapse: collapse;
    border-spacing: 0
}

@keyframes blinking {
    from {
        background: #f4a83d
    }
    to {
        background: rgba(244, 168, 61, 0)
    }
}

我需要把它解析成两个元素,但是结果是

Array
(
    [0] => Array
        (
            [0] => 
table {
    border-collapse: collapse;
    border-spacing: 0
}
            [1] => 

@keyframes blinking {
    from {
        background: #f4a83d
    }
            [2] => 
    to {
        background: rgba(244, 168, 61, 0)
    }
        )

    [1] => Array
        (
            [0] => 
table 
            [1] => 

@keyframes blinking 
            [2] => 
    to 
        )

    [2] => Array
        (
            [0] => border-collapse: collapse;
    border-spacing: 0

            [1] => from {
        background: #f4a83d
    
            [2] => background: rgba(244, 168, 61, 0)
    
        )

)

注意: 有几个 类 和用于解析 CSS 的程序,但它们对于我只需要捕获选择器和规则。他们解析了我需要重新加入的所有规则。因此,使用简单的正则表达式方法更方便。

使用

([^{]+)\s*({\s*((?:[^{}]++|(?2))*)\s*})

proof

说明

--------------------------------------------------------------------------------
  (                        group and capture to :
--------------------------------------------------------------------------------
    [^{]+                    any character except: '{' (1 or more
                             times (matching the most amount
                             possible))
--------------------------------------------------------------------------------
  )                        end of 
--------------------------------------------------------------------------------
  \s*                      whitespace (\n, \r, \t, \f, and " ") (0 or
                           more times (matching the most amount
                           possible))
--------------------------------------------------------------------------------
  (                        group and capture to :
--------------------------------------------------------------------------------
    {                        '{'
--------------------------------------------------------------------------------
    \s*                      whitespace (\n, \r, \t, \f, and " ") (0
                             or more times (matching the most amount
                             possible))
--------------------------------------------------------------------------------
    (                        group and capture to :
--------------------------------------------------------------------------------
      (?:                      group, but do not capture (0 or more
                               times (matching the most amount
                               possible)):
--------------------------------------------------------------------------------
        [^{}]++                   any character except: '{', '}' (1 or
                                 more times (matching the most amount
                                 possible possessively))
--------------------------------------------------------------------------------
       |                        OR
--------------------------------------------------------------------------------
        (                        group and capture to :
--------------------------------------------------------------------------------
          (?2)                   Capturing group 2 pattern recursed
--------------------------------------------------------------------------------
        )                        end of 
--------------------------------------------------------------------------------
      )*                       end of grouping
--------------------------------------------------------------------------------
    )                        end of 
--------------------------------------------------------------------------------
    \s*                      whitespace (\n, \r, \t, \f, and " ") (0
                             or more times (matching the most amount
                             possible))
--------------------------------------------------------------------------------
    }                        '}'
--------------------------------------------------------------------------------
  )                        end of