0

我想对两个花括号内第一次出现的字符进行匹配,但忽略其中的字符。

{{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 实现这一点?

4

1 回答 1

3

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

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

Where(?R)将整个模式再次嵌套在自身内部。

我不确定 PCRE 的优化效果如何,但是您可以通过使所有重复都具有所有格来提供一些帮助。这抑制了回溯,这在此处不是必需的,因为所有连续的重复都是互斥的:

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

如果你确实允许单括号,你可以用前瞻做类似的事情,但这已经说明了为什么正则表达式不是真正为嵌套结构制作的(即使引擎支持它):

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

现在代替非{}字符,我们允许重复任何字符,除非它标志着 a{{或的开始}}。同样,使其具有所有格可能是一个好主意:

'/\{\{(?:(?!\{\{|\}\}).)*+(?:(?R)(?:(?!\{\{|\}\}).)*+)*+\}\}/'
于 2012-12-02T23:12:56.033 回答