Timothy Fisher
Timothy Fisher

Reputation: 1129

How can I match this array-like notation using regex in PHP?

I'm trying to match the following array-like pattern with regex:

foo[bar][baz][bim]

I almost have it with the following regex:

~([^[]+)(?:\[(.+?)\])*~gm

However, the capturing groups only include:

Full match: foo[bar][baz][bim]
Group 1: foo
Group 2: bim

I can't figure out why it's only capturing the last occurrence of the [] structure. I'd like it capture foo, bar, baz, and bim in this case.

Any ideas on what I'm missing?

Upvotes: 2

Views: 199

Answers (2)

Andreas
Andreas

Reputation: 23958

This can also be parsed without regex.
Remove the closing ] and then explode on the opening [.

$str = "foo[bar][baz][bim]";

$str = str_replace("]","",$str);
$arr = explode("[", $str);
var_dump($arr);

Returns:

array(4) {
  [0]=>
  string(3) "foo"
  [1]=>
  string(3) "bar"
  [2]=>
  string(3) "baz"
  [3]=>
  string(3) "bim"
}

Where the first item is the "array" name and the following is the children/path.

Upvotes: 1

revo
revo

Reputation: 48741

Repeated capturing groups in PCRE don't remember the values of each previous pattern. For this you need to invoke \G token:

(?|(\w+)|\G(?!\A)\[([^][]*)\])

See live demo here

Regex breakdown:

  • (?| Start of a branch reset group
    • (\w+) Capture word characters
    • | Or
    • \G(?!\A) Conitnue from where previous match ends
    • \[ Match an opening bracket
    • ([^][]*) Capture any thing except [ and ]
    • \] Match a closing bracket
  • ) End of cluster

PHP code:

preg_match_all('~(?|(\w+)|\G(?!\A)\[([^][]*)\])~', 'foo[bar][baz][bim]', $matches);
print_r($matches[1]);

Upvotes: 2

Related Questions