preg_match_all模式中的重复模式不会导致多个$ matches

时间:2019-02-08 20:53:05

标签: php regex preg-match-all

我的脚本很简单:

<?php
$str = "mem: 9 334 23423343 3433434";

$num_matches = preg_match_all("/^mem:(\s+\d+)+$/", $str, $matches);
if (!$num_matches) {
        throw new Exception("no match");
}

echo "$num_matches matches\n";
var_dump($matches);

我期望模式(\s+\d+)+应该与$str中的所有数字匹配,但是由于某些原因,输出仅显示最后一个匹配项:

1 matches
array(2) {
  [0] =>
  array(1) {
    [0] =>
    string(27) "mem: 9 334 23423343 3433434"
  }
  [1] =>
  array(1) {
    [0] =>
    string(8) " 3433434"
  }
}

如您所见,$matches[1]仅包含\s+\d+中最近出现的$str。我期望它包含所有匹配项:9, 334, 23423343, 343434

是否有某种方法可以更改我的模式,以便它为可能包含任意数量的字符串的字符串返回所有这些数字?我是否认为preg_match_all是不正确的行为?我应该将其报告给PHP开发人员吗?

编辑:根据docs,默认标志为 PREG_PATTERN_ORDER

  

对结果进行排序,以使$ matches [0]是完整模式匹配的数组,$ matches [1]是由第一个带括号的子模式匹配的字符串的数组,依此类推。

1 个答案:

答案 0 :(得分:1)

PCRE将最后一次出现的事件存储在重复的捕获组中,因此可以预期该行为。在这种情况下,要返回单个匹配项,您需要使用\G令牌,如下所示:

(?:^mem:|\G(?!^))\s+\K\d+

See live demo

正则表达式细目:

  • (?:非捕获组的开始
    • ^mem:在输入字符串的开头匹配mem:
    • |
    • \G(?!^)从上一场比赛结束的地方开始比赛
  • )非捕获组的结尾
  • \s+\K匹配任何空白序列,然后清除输出
  • \d+匹配数字

PHP代码:

preg_match_all("~(?:^mem:|\G(?!^))\s+\K\d+~", $str, $matches);
相关问题