preg_match_all如何获得*所有*组合?即使是重叠的

时间:2014-03-17 12:16:01

标签: php regex

PHP正则表达式函数中是否有一种方法可以获得正则表达式的所有匹配项,即使这些匹配项重叠

e.g。获取所有3位数的子字符串'/ [\ d] {3} /'...

你可能会得到:

“123456”=> ['123','234','345','456']

但是 preg_match_all()只返回

['123','456']

这是因为它在匹配的子字符串之后再次开始搜索(如文档中所述):

  

“找到第一场比赛后,后续搜索会在最后一场比赛结束时继续进行。”。

如果没有编写自定义解析器,有没有办法解决这个问题?

3 个答案:

答案 0 :(得分:7)

对救援的前瞻性断言!

preg_match_all('/(?=(\d{3}))/', $str, $matches);
print_r($matches[1]);

它基本上捕获了前瞻断言匹配的内容。由于断言为零宽度,$matches[0]将只包含空字符串,但$matches[1]将包含预期的捕获模式。

答案 1 :(得分:2)

这可能不太理想,但至少它是什么。

看起来您可以使用正向前瞻和PREG_OFFSET_CAPTURE来获取存在3位数字的所有字符串索引

$str = "123456";

preg_match_all("/\d(?=\d{2})/", $str, $matches, PREG_OFFSET_CAPTURE);

$numbers = array_map(function($m) use($str){
  return substr($str, $m[1], 3);
}, $matches[0]);

print_r($numbers);

输出

Array
(
    [0] => 123
    [1] => 234
    [2] => 345
    [3] => 456
)

答案 2 :(得分:1)

在后视中使用 \K

preg_match_all('~(?<=\K..).~', '123456', $m);
print_r($m[0]);

demo

只消耗一个字符(第三个),前两个不是,因为它们位于零宽度断言的后视内。但是 \K 给出了匹配结果的开始,并且返回了前两个(第三个)。

注意:你不能把所有三个字符都放在lookbehind中并写成(?<=\K...),因为在这种情况下,正则表达式引擎将永远停留在字符串中的相同位置。