0

Given the following PHP code:

<?php
$str = '/foo/bar/baz';
preg_match('#^(/[^/]+?)*$#', $str, $matches);
var_dump($matches);

...I'm getting the following output:

array (size=2)
  0 => string '/foo/bar/baz' (length=12)
  1 => string '/baz' (length=4)

...but I don't understand why. I would expect each match of (/[^/]+?) to be captured into its own group and stuck into $matches, such that it looked like this instead:

array (size=4)
  0 => string '/foo/bar/baz' (length=12)
  1 => string '/foo' (length=4)
  2 => string '/bar' (length=4)
  3 => string '/baz' (length=4)

What am I missing?

Edit:

This is the output if I use preg_match_all() instead, which still isn't what I'm looking for:

array (size=2)
  0 => 
    array (size=1)
      0 => string '/foo/bar/baz' (length=12)
  1 => 
    array (size=1)
      0 => string '/baz' (length=4)
FtDRbwLXw6
  • 27,774
  • 13
  • 70
  • 107

4 Answers4

1

This is the standard behavior of repeated capture groups -- they match all the repetitions, but only capture the last one. See Can Regex groups and * wildcards work together? for a similar question using Python. I tried it in Perl and got the same result.

Community
  • 1
  • 1
Barmar
  • 741,623
  • 53
  • 500
  • 612
0

preg_match only grabs the first. If you want all of them, use preg_match_all.

However: If this is really the exact usecase, use explode() instead.

Evert
  • 93,428
  • 18
  • 118
  • 189
0

Maybe like this:

preg_match_all('(/[^/]+)', $str, $matches);
cdtits
  • 1,118
  • 6
  • 7
  • I need to match the whole string, which I can't do using `preg_match_all()`. For example, `$str = "test/foo/bar/baz"` is invalid, but would still match if I used this. – FtDRbwLXw6 Aug 11 '12 at 04:48
0

What you're trying to do with dynamic capture groups is possible in some regex flavours (like C# - Regular expression with variable number of groups? ) , but unfortunately not in PHP.

Community
  • 1
  • 1
Michael Low
  • 24,276
  • 16
  • 82
  • 119