【问题标题】:How to get the history of the captures如何获取捕获的历史
【发布时间】:2016-08-05 17:16:26
【问题描述】:

据我所知,这不仅是 PHP 问题,而且我在这里询问的是 PHP(实际上是 PHP7)。

考虑这样简单的正则表达式(如果不清楚——这是一个示例):

/((\w+): (\d+))+/

及其文字:

foo: 2008bar: 2009

匹配是在整个文本上,问题是一旦正则表达式引擎在文本上前进,就会使用和忘记子捕获。结果,您将只获得最后一次捕获。

我想获取所有有效(正确)的捕获,因此是整个历史记录,而不仅仅是最后的捕获。

这是测试它的代码:

<?php

$str = 'foo: 2008bar: 2009';

preg_match_all('/((\w+): (\d+))+/', $str, $matches);

print_r($matches);

?>

这是输出

Array
(
    [0] => Array
        (
            [0] => foo: 2008bar: 2009
        )

    [1] => Array
        (
            [0] => bar: 2009
        )

    [2] => Array
        (
            [0] => bar
        )

    [3] => Array
        (
            [0] => 2009
        )

)

正如您所见,整个文本都已匹配,但对于捕获,仅存储了最后一个。那些都不见了:

foo: 2008
foo
2008

因此我的问题是:如何获取捕获的整个“历史”?

【问题讨论】:

  • regex101 给出相同的结果...
  • 这是 PCRE 的预期行为。它不支持重复组。 .NET/PyPi 正则表达式 Python 模块和 Boost(使用特定设置编译)支持它们。
  • 是这样工作的吗/((\w+):\s(\d+))/g
  • @WiktorStribiżew,所以我在 PHP 中的唯一选择是绑定到其中一些引擎?您能否将此作为常规答案发布?
  • 只需删除最后一个 + 并使用全局标志 /((\w+): (\d+))/g。 PHP 没有全局标志,但 preg_match_all 可以完成这项工作。 (在 regex101 上测试)

标签: php regex


【解决方案1】:

对于这项任务,\G(继续逃生序列)穿着一件与身体一样长的斗篷,并具有 X 射线视力。 ;)

它允许您从字符串的开头或模式最后完成的位置开始匹配。

代码:(Demo)

$str = 'foo: 2008bar: 2009';
var_export(
    preg_match_all(
        '~\G(\w+): (\d+)~',
        $str,
        $out
    )
    ? $out
    : 'no matches'
);

输出:

array (
  0 => 
  array (
    0 => 'foo: 2008',
    1 => 'bar: 2009',
  ),
  1 => 
  array (
    0 => 'foo',
    1 => 'bar',
  ),
  2 => 
  array (
    0 => '2008',
    1 => '2009',
  ),
)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-26
    • 1970-01-01
    • 2011-01-16
    • 1970-01-01
    • 2021-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多