正如@nickb 已经评论的那样,重复捕获组仅保留其最后一场比赛。AFAIK,只有 .NET 提供了保留所有匹配项的实现。所以,我同意@m.buettner 的观点,即您必须至少使用两个匹配项。而@IngmardeLange 的解决方案似乎是一种替代实现,虽然我没有检查过,但仍然使用至少两个匹配项。
为了好玩,我设计了一种使用单个匹配的方法。最初的想法是对@{article
部件使用lookbehinds,但不支持可变长度lookbehinds。然后,(不幸的是,正如您将要见证的那样)我记得@TimPietzcker 曾经提到过实现可变长度后视的技巧:在反向字符串上进行可变长度前瞻。(请不要真正使用这种方法。)
<?php
function get_attr_val_matches($tag, $subject)
{
$regex = '/"(\w+)"=(\w+)\s+(?=(?:"\w+"=\w+\s+)*' . strrev($tag) . '\{@)/';
preg_match_all($regex, strrev($subject), $matches, PREG_SET_ORDER);
foreach ($matches as &$match)
{
$match = array_map(strrev, $match);
$match = array($match[0], array_reverse(array_slice($match, 1)));
}
return array_reverse($matches);
}
$tag = 'articles';
$subject = '@{articles mode="extrait" nb="3"}';
print_r(get_attr_val_matches($tag, $subject));
?>
输出:
Array
(
[0] => Array
(
[0] => mode="extrait"
[1] => Array
(
[0] => mode
[1] => extrait
)
)
[1] => Array
(
[0] => nb="3"
[1] => Array
(
[0] => nb
[1] => 3
)
)
)
这是一个正在运行的示例。
很明显,如果我还没有充分否认这一点,那么所有的逆转成本都不仅仅是做两场比赛。但是也许有一个应用程序可以将具有可变长度后视的表达式一般转换为如上所述的反向前瞻,然后返回。虽然可能不是。