与preg_match_all()重复匹配

时间:2011-07-05 08:36:25

标签: php regex preg-match preg-match-all

我试图让所有子串与乘数匹配:

$list = '1,2,3,4';
preg_match_all('|\d+(,\d+)*|', $list, $matches);
print_r($matches);

此示例按预期返回[1]中的最后一个匹配项:

Array
(
    [0] => Array
        (
            [0] => 1,2,3,4
        )

    [1] => Array
        (
            [0] => ,4
        )

)

但是,我想让(,\d+)匹配所有字符串,以获得类似的内容:

Array
(
    [0] => ,2
    [1] => ,3
    [2] => ,4
)

有没有办法使用preg_match_all()等单一功能执行此操作?

6 个答案:

答案 0 :(得分:8)

根据Kobi(见上述评论):

  

PHP不支持同一组的捕获

因此这个问题没有解决方案。

答案 1 :(得分:2)

使用lookbehind是一种完成工作的方法:

$list = '1,2,3,4';
preg_match_all('|(?<=\d),\d+|', $list, $matches);
print_r($matches);

所有,\d+都在0组。

<强>输出:

Array
(
    [0] => Array
        (
            [0] => ,2
            [1] => ,3
            [2] => ,4
        )
)

答案 2 :(得分:1)

PHP(或更确切地说说PCRE)确实不存储重复捕获组的值以供以后访问(请参见PCRE docs):

  

如果捕获子模式重复匹配,则返回的是它匹配的字符串的最后一部分。

但是在大​​多数情况下,已知令牌\G可以完成任务。 \G 1)匹配输入字符串的开头(如未设置\A的情况下为^m)或2)从上一个匹配结束处开始匹配。这样说,您必须像下面这样使用它:

preg_match_all('/^\d+|\G(?!^)(,?\d+)\K/', $list, $matches);

请参见live demo here

或者捕获组无关紧要:

preg_match_all('/\G,?\d+/', $list, $matches);

$matches将通过其保存(请参见live demo):

Array
(
    [0] => Array
        (
            [0] => 1
            [1] => ,2
            [2] => ,3
            [3] => ,4
        )

)

注意:与其他答案(例如\G或后向解决方案或仅explode())相比,使用preg_match_all('/,?\d+/', ...)的好处是您可以验证导出匹配项时,输入字符串只能同时处于所需格式^\d+(,\d+)*$

preg_match_all('/(?:^(?=\d+(?:,\d+)*$)|\G(?!^),)\d+/', $list, $matches);

答案 3 :(得分:0)

为什么不呢:

$ar = explode(',', $list);
print_r($ar);

答案 4 :(得分:0)

只有在模式中不使用要拆分的字符才能匹配时,拆分才是一个选项。 我的情况是,格式错误的逗号分隔行必须被解析为许多已知选项中的任何一个。

即。选项'1,2','2','2,3' 主题'1,2,3'。

分裂','将导致'1','2'和'3';只有一个('2')是有效匹配,这是因为分隔符也是选项的一部分。

天真的正则表达式会像'〜^(1,2 | 2 | 2,3)(?:,(1,2 | 2 | 2,3))* $〜我',但这会遇到同组捕获的问题。

我的“解决方案”是扩展正则表达式以匹配可能的最大匹配数: “〜^(1,2 | 2 | 2,3)(:,(1,2 | 2 | 2,3)?)?(?:,(1,2 | 2 | 2,3))?$〜一世' (如果有更多选项,只需重复'(?:,(1,2 | 2 | 2,3))?'位。 这会导致“未使用”匹配的空字符串结果。

这不是最干净的解决方案,但是当您必须处理格式错误的输入数据时,它才有效。

答案 5 :(得分:0)

来自http://www.php.net/manual/en/regexp.reference.repetition.php

  

当重复捕获子模式时,捕获的值是与最终迭代匹配的子字符串。

也是类似的主题:

How to get all captures of subgroup matches with preg_match_all()?