PHP 嵌套正则表达式

PHP nested regex

这个字符串:

$subject = '\displaystyle{\ce{Cu^{2+}{(aq)}}+\ce{Zn{(s)}}\ce{->}\ce{Cu_{(s)}}+\ce{Zn^{2+}_{(aq)}}}'

我要捕捉:

我的正则表达式灵感来自 PHP - help with my REGEX-based recursive function

$pattern = '#\\ce\{(?:[^{}]|(?R))*}#';

我试过

preg_match_all($pattern, $subject, $matches);
print_r($matches);
Array
(
    [0] => Array
        (
            [0] => \ce{->}
        )
 )

但如您所见,它不起作用...

您可以使用这个递归正则表达式:

(\ce(\{(?:[^{}]|(?-1))*\}))

RegEx Demo

这里 (?-1) 递归\ce 之后开始的第二个 子模式

代码:

$re = "/(
  \\ce
  (
    \{
    (?:[^{}]|(?-1))*
    \}
  )
)/x"; 

$str = 
 "\displaystyle{\ce{Cu^{2+}{(aq)}}+\ce{Zn{(s)}}\ce{->}\ce{Cu_{(s)}}+\ce{Zn^{2+}_{(aq)}}}"; 

if ( preg_match_all($re, $str, $m) )
   print_r($m[1]);

输出:

Array
(
    [0] => \ce{Cu^{2+}{(aq)}}
    [1] => \ce{Zn{(s)}}
    [2] => \ce{->}
    [3] => \ce{Cu_{(s)}}
    [4] => \ce{Zn^{2+}_{(aq)}}
)

这在我的测试中有效。
请注意 \ce 不能是没有平衡括号的子模式。
所以,这将失败 \ce{Zn\cepp{(s)}}
并且,这将通过 \ce{Zn^{2+}\ce{Zn^{2+}_{(aq)}}_{(aq)}}
否则,为什么要首先寻找 \ce{}

 #  '/\\ce(\{(?:(?>(?!\\ce)[^{}])+|(?R)|(?1))*\})/'

 \ce
 (                  # (1 start)
      \{
      (?:
           (?>
                (?! \ce )         # Not '\ce' ahead
                [^{}]              # A char, but not { or }
           )+
        |                   # or,
           (?R)               # Recurse whole expression
        |                   # or,
           (?1)               # Recurse group 1
      )*
      \}                
 )                  # (1 end)