PHP: preg_match_all that matches inner brackets first?
Asked Answered
E

2

2

In PHP I have string with nested brackets:

bar[foo[test[abc][def]]bar]foo

I need a regex that matches the inner bracket-pairs first, so the order in which preg_match_all finds the matching bracket-pairs should be:

[abc]
[def]
[test[abc][def]]
[foo[test[abc][def]]bar]

All texts may vary.

Is this even possible with preg_match_all ?

Ecphonesis answered 14/2, 2013 at 15:45 Comment(4)
possible duplicate of Nested Parentheses to Array using regex in PHPInternist
Can there ever be more than one pair inside another pair? e.g. [foo[bar][baz][xyzzy]lol]?Receptor
yeah, ideally this could be the case. I changed the question to include this functionality...Ecphonesis
@MarcB The suggested duplicate wants to ignore the inner groups, which is the opposite of this question.Onieonion
S
2

This is not possible with regular expressions. No matter how complex your regex, it will always return the left-most match first.

At best, you'd have to use multiple regexes, but even then you're going to have trouble because regexes can't really count matching brackets. Your best bet is to parse this string some other way.

Salmonella answered 21/2, 2013 at 14:53 Comment(0)
F
0

Is not evident in your question what kind of "structure of matches" you whant... But you can use only simple arrays. Try

  preg_match_all('#\[([a-z\)\(]+?)\]#',$original,$m); 

that, for $original = 'bar[foo[test[abc][def]]bar]foo' returns an array with "abc" and "def", the inner ones.


For your output, you need a loop for the "parsing task". PCRE with preg_replace_callback is better for parsing.

Perhaps this loop is a good clue for your problem,

 $original = 'bar[foo[test[abc][def]]bar]foo';

 for( $aux=$oldAux=$original; 
      $oldAux!=($aux=printInnerBracket($aux)); 
      $oldAux=$aux
 );
 print "\n-- $aux";

 function printInnerBracket($s) {
    return preg_replace_callback(
            '#\[([a-z\)\(]+?)\]#',  // the only one regular expression
            function($m) {
               print "\n$m[0]"; 
               return "($m[1])";
            },
            $s
    );
 }

Result (the callback print):

[abc]
[def]
[test(abc)(def)]
[foo(test(abc)(def))bar]
-- bar(foo(test(abc)(def))bar)foo

See also this related question.

Feinleib answered 23/3, 2013 at 16:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.