views:

469

answers:

6

Assuming I have this string: "abc{def{ghi{jkl}mno{pqr}st}uvw}xyz"

and I want to match this: "{def{ghi{jkl}mno{pqr}st}uvw}"

what should my regular expression look like..?

In other words, the match should start with "{" and end with "}", but it must have as many {'s as }'s in between.

+4  A: 

That grammar is irregular, therefore you cannot use a regular expression to parse it.

Ignacio Vazquez-Abrams
Yes. The pattern is irregular. But Perl so-called "regular expressions" (including PCRE library, which PHP uses) can handle irregular patterns. Because they can actually handle context-free grammars.
codeholic
+1  A: 

While you can technically use PCRE to do this, it's a bad idea (PCRE is actually capable of parsing certain non-regular expressions via the recursion operator, but that can quickly become overly complex).

You're much better off writing something that just iterates through the string and keeps track of how many currently open braces there are.

Amber
+1 Good answer, sometimes you have to accept ugly code over elegant code when the result is faster and/or more correct.
Renesis
A: 

I would develop a script that starts from either end making note of the character position of each open and closing brackets then assigning the two together to get the 'matching pair'. It is of course slightly more complex than that, but I hope you understand what I am getting at.

+3  A: 

I think I found the answer in another thread..

"#\{((?>[^\{\}]+)|(?R))*\}#x"

I tested it with different strings and it seems to do the job..

Any comments on how it works..? Pros and cons..?

Thanks for the answers btw.. :)

KarmicMind
`(?R)` is effectively a placeholder for the enclosing regex. It recursively applies the whole regex when that part of the regex is reached. You don't hear about it much because it's hard to understand and even harder to read--even by regex standards! Also, it's not as useful as you might expect.
Alan Moore
@alan Recursive regular expressions are alright. It's just a more advanced practice.
codeholic
A: 
#!/usr/bin/perl
use strict;
use warnings;

my $str = "abc{def{ghi{jkl}mno{pqr}st}uvw}xyz" ;
$str =~ /[^{]*({.*})/ ;
print $1 ;

and the result is :

{def{ghi{jkl}mno{pqr}st}uvw}

meet your needs? I'm not familiar with php , but I guess you can still use the same regex .

Haiyuan Zhang
Quoth the OP, *"...but it must have as many {'s as }'s in between."*
Alan Moore
A: 

Your expression could be:

\{.*\}

'*' is greedy, so it'll get everything from the first bracket until it finds the last bracket

Gray
Since your downvoter didn't leave a comment... That will work *given the test string* but the condition (from the OP) "but it must have as many {'s as }'s in between" will not be true if the total number of {s and }s is different.
Renesis