You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

preg_match_all中重复子模式仅返回最后匹配结果的问题

问题解答:正则重复捕获组只返回最后一个匹配项的原因与解决方案

这真不是preg_match_all的bug哦,其实是正则表达式里重复捕获组的固有特性导致的——当你写(\s+\d+)+这种嵌套重复的捕获组时,正则引擎每完成一次内部组(\s+\d+)的匹配,就会覆盖掉这个组之前捕获到的内容,直到整个重复结构匹配完成,所以最后只会留下最后一次匹配的结果。

为什么会这样?

正则引擎处理捕获组的逻辑是:每次捕获到内容,就更新对应组的存储值。对于(\s+\d+)+来说,它会依次匹配 9、 334、 23423343、 3433434,但每匹配一次,组1的内容就被替换成当前的匹配结果,到最后自然只剩下最后一个 3433434了。这是所有正则引擎的通用行为,不是PHP的问题,所以完全不用给PHP开发者报bug~

解决方案

这里有两种靠谱的方法可以拿到所有数字:

方法1:先验证格式,再提取数字

先确认字符串符合mem: 数字 数字 ...的格式,再单独提取所有数字,逻辑清晰又简单:

<?php
$str = "mem: 9 334 23423343 3433434";
// 第一步:验证整体格式是否正确
if (!preg_match("/^mem:(\s+\d+)+$/", $str)) {
    throw new Exception("no match");
}
// 第二步:提取所有数字
preg_match_all("/\d+/", $str, $matches);
echo count($matches[0]) . " matches\n";
var_dump($matches[0]);
?>

输出会是:

4 matches
array(4) {
  [0] => string(1) "9"
  [1] => string(3) "334"
  [2] => string(8) "23423343"
  [3] => string(7) "3433434"
}

方法2:使用\G锚点一次性完成验证+捕获

如果你想在一次preg_match_all里搞定,可以用\G锚点——它会匹配上一次匹配结束的位置,这样既能确保整个字符串符合格式,又能捕获所有数字:

<?php
$str = "mem: 9 334 23423343 3433434";
$num_matches = preg_match_all("/(?:^mem:|\G)\s+(\d+)/", $str, $matches);
if (!$num_matches) {
    throw new Exception("no match");
}
echo "$num_matches matches\n";
var_dump($matches[1]);
?>

输出和方法1一致,还能避免匹配到字符串其他无关位置的数字。

内容的提问来源于stack exchange,提问作者S. Imp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:30:38