Get repeated matches with preg_match_all()

According to Kobi (see comments above):

PHP has no support for captures of the same group

Therefore this question has no solution.


Using lookbehind is a way to do the job:

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

All the ,\d+ are in group 0.

output:

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

It's true that PHP (or better to say PCRE) doesn't store values of repeated capturing groups for later access (see PCRE docs):

If a capturing subpattern is matched repeatedly, it is the last portion of the string that it matched that is returned.

But in most cases the known token \G does the job. \G 1) matches the beginning of input string (as \A or ^ when m modifier is not set) or 2) starts match from where the previous match ends. Saying that, you have to use it like the following:

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

See live demo here

or if capturing group doesn't matter:

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

by which $matches will hold this (see live demo):

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

)

Note: the benefit of using \G over the other answers (like explode() or lookbehind solution or just preg_match_all('/,?\d+/', ...)) is that you are able to validate the input string to be only in the desired format ^\d+(,\d+)*$ at the same time while exporting the matches:

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