Dan
Dan

Reputation: 3103

php preg_match multiple groups at the end of the string

I have a preg_match problem. Here's the string

field[0][price][8]

And the regex

"/([\[]([a-zA-Z0-9\_]+)?[\]])+$/"

I want to check if the string ends with one ore more [ ] and extract all the values inside. When i put the $ flag, preg_match_all only gets the big and the last found groups. Something similar happens with preg_match.

Output:

array (size=3)
  0 => 
    array (size=1)
      0 => string '[0][price][8]' (length=13)
  1 => 
    array (size=1)
      0 => string '[8]' (length=3)
  2 => 
    array (size=1)
      0 => string '8' (length=1)

This is the desired result, that i get only if i omit the $ flag, which is not ok because i need to check if the string ends with the matched pattern:

array (size=3)
  0 => 
    array (size=3)
      0 => string '[0]' (length=3)
      1 => string '[price]' (length=7)
      2 => string '[8]' (length=3)
  1 => 
    array (size=3)
      0 => string '[0]' (length=3)
      1 => string '[price]' (length=7)
      2 => string '[8]' (length=3)
  2 => 
    array (size=3)
      0 => string '0' (length=1)
      1 => string 'price' (length=5)
      2 => string '8' (length=1)

Any ideas? Thanks a lot!

Upvotes: 0

Views: 1302

Answers (3)

Danon
Danon

Reputation: 2973

If you don't like writing $match[0][$something[0], you can use T-Regx library:

pattern("([\[]([a-zA-Z0-9\_]+)?[\]])+$")
    ->match('field[0][price][8]')
    ->first(function (Match $match) {

       $match->text();   // the matched occurrence

       $match->group(1); // group #1 of the match
    });

Upvotes: 0

Casimir et Hippolyte
Casimir et Hippolyte

Reputation: 89547

An other way using strrev:

$str = 'field[0][price][8]';

if (preg_match_all('~\G]([^[]*)\[~', strrev($str), $m))
    $result = array_map('strrev', $m[1]);

print_r($result);

Upvotes: 0

Amal Murali
Amal Murali

Reputation: 76646

You can use a positive lookahead to check if the string ends with the required format:

preg_match_all("/(?=.*(?:\[.*?])+$)\[(.*?)]/", $str, $matches);
$result = $matches[1];

(?:\[.*?])+ matches one or more [xyz] sections. The actual matching is performed only if the lookahead succeeds.

For the string in question, $result would contain:

array(3) {
  [0]=>
  string(1) "0"
  [1]=>
  string(5) "price"
  [2]=>
  string(1) "8"
}

Upvotes: 2

Related Questions