Matching with preg_match_all

2019-02-21 07:37发布

问题:

I got this regex:

$val = "(123)(4)(56)";
$regex = "^(\((.*?)\))+$";
preg_match_all("/{$regex}/", $val, $matches);

Can anyone please tell me why this matches only the last number (56) and not each set of numbers individually?

This is what $matches contains after the above regex runs:

array
  0 => 
    array
      0 => string '(123)(4)(56)' (length=12)
  1 => 
    array
      0 => string '(56)' (length=4)
  2 => 
    array
      0 => string '56' (length=2)

回答1:

As @develroot already has answered the way you want to use preg_match_all does not work, it will only return the last matching group, not all captures of that group. That's how regex works. At this point I don't know how to get all group catpures in PHP, I assume it's not possible. Might not be right, might change.

However you can work around that for your case by first check if the whole string matches your (repeated) pattern and then extract matches by that pattern. Put it all within one function and it's easily accessible (Demo):

$tests = explode(',', '(123)(4)(56),(56),56');   

$result = array_map('extract_numbers', $tests);

print_r(array_combine($tests, $result));

function extract_numbers($subject) {
    $number = '\((.*?)\)';
    $pattern = "~^({$number})+$~";
    if (!preg_match($pattern, $subject)) return array();
    $pattern = "~{$number}~";
    $r = preg_match_all($pattern, $subject, $matches);
    return $matches[1];
}