忽略preg_match_all中的嵌套结果

时间:2012-12-02 23:07:07

标签: php regex preg-match-all

我想在两个冰壶括号内首次出现的角色匹配,但忽略其中的角色。

{{some text here {{nested text here}} another text {{another nested text here}} final text}}

所以结果必须是

some text here {{nested text here}} another text {{another nested text here}} final text

但是这次搜索

preg_match_all("^\{{(.*?)\}}^", $string, $results);

给了我第一对括号内的那些:

$results[0][0] = nested text here
$results[0][1] = another nested text here

有没有办法用preg_match_all来实现这个目标?

1 个答案:

答案 0 :(得分:3)

嵌套结构经常会导致正则表达式出现问题(因为它们使语言匹配比常规更复杂)。 PCRE是其中一个引擎,它允许匹配它们,因为它支持递归。如果您的双括号内没有单个花括号,则可以使用此模式:

'/\{\{[^{}]*(?:(?R)[^{}]*)*\}\}/'

(?R)将整个模式再次嵌入其中。

我不确定PCRE的优化程度,但你可以通过重复possessive来帮助我。这抑制了回溯,这在这里是不必要的,因为所有连续的重复是相互排斥的:

'/\{\{[^{}]*+(?:(?R)[^{}]*+)*+ \}\}/'

如果你允许使用单个括号,你可以做一些类似于前瞻的东西,但这已经说明为什么正则表达式不是真正用于嵌套结构(即使引擎支持它):

'/\{\{(?:(?!\{\{|\}\}).)*(?:(?R)(?:(?!\{\{|\}\}).)*)*\}\}/'

现在我们允许重复任何字符,而不是非{}个字符,除非它标记{{}}的开头。再次,使它占有欲可能是一个好主意:

'/\{\{(?:(?!\{\{|\}\}).)*+(?:(?R)(?:(?!\{\{|\}\}).)*+)*+\}\}/'