Mixnuts Everyone
Mixnuts Everyone

Reputation: 3

Getting rid anything outside curly braces

I need a regex in php that allows the following:

here is the given example
1. aaa aaa{bb b {c cc}{d dd}e ee}xxx
2. 123{asd{asd{asd{asd}asd}}asd}qwe

the output will be:
1. {bb b {c cc}{d dd}e ee}
2. {asd{asd{asd{asd}asd}}asd}

I tried this but does not work

preg_match_all('/{(.*?)}/', $resonse, $matches);

its basically getting rid of anything outside the main curly braces eventhought there are curly braces inside of it. I really need you help. thanks so much.

Upvotes: 0

Views: 172

Answers (5)

Qsario
Qsario

Reputation: 1026

Is this really a job for a regex? It would appear easier to just grab the substring you want by looking for the first { and the last }. For example, this:

$str = "abc {kjlj { jkljlkj } ljkj } kljlj";

$start = strpos($str, '{');  # First {
$end = strrpos($str, '}');   # Last }

$section = substr($str, $start, $end - $start + 1);
echo $section;  # => "{kjlj { jkljlkj } ljkj }"

Upvotes: 0

Tim S.
Tim S.

Reputation: 13843

You don't need regex at all:

$str = 'aaa aaa{bb b {c cc}{d dd}e ee}xxx';

$replace = substr(substr($str, 0, strrpos($str, '}') + 1), strpos($str, '{'));

echo $replace; // displays "{bb b {c cc}{d dd}e ee}"

If you'd benchmark this code it'd probably turn out much faster than regex. You shouldn't use something complex for something so simple.

I figured you might want to match multiple results per-string. In that case, I still probably have a faster solution that doesn't rely on any modules:

$str = 'aaa aaa{bb b {c cc}{d dd}e ee}xxxaaa qaaa{bb b {cqwe cc}{d cdd}e qweee}xxx';
$array = str_split($str);
$opens = 0;
$result = '';

$results = array();

for($i = 0; $i < count($array); $i++) {
    if($array[$i] === '{') {
        $opens++;
    } else if($array[$i] === '}' && $opens > 0) {
        $opens--;
    }

    if($opens > 0) $result .= $array[$i];

    if($opens === 0 && strlen($result) > 0) {
        $results[] = $result . '}';
        $result = '';
    }
}

print_r($results);

/*
results:
Array
(
    [0] => {bb b {c cc}{d dd}e ee}
    [1] => {bb b {cqwe cc}{d cdd}e qweee}
)

*/

Upvotes: 2

VolkerK
VolkerK

Reputation: 96159

You will need PCRE's recursion capabilities to do this.

<?php
$pattern = '!
  { # patterns start with curly brace
      (?:           # ?: means that this is only for grouping, not for capturing
                    # the { } contain 
        [^{}]*      # not-curly-braces-characters
      |             # or
        (?R)        # this pattern again, i.e. {^[{}] | (?R) } again
      )*
  } # patterns ends with curly brace
!x';

foreach( array('aaa aaa{bb b {c cc}{d dd}e ee}xxx', '123{asd{asd{asd{asd}asd}}asd}qwe') as $subject ) {
    echo "\n$subject: ";
    if ( preg_match($pattern, $subject, $m) ) {
        echo $m[0];
    }
    else {
        echo '--no match--';
    }
}

prints

aaa aaa{bb b {c cc}{d dd}e ee}xxx: {bb b {c cc}{d dd}e ee}
123{asd{asd{asd{asd}asd}}asd}qwe: {asd{asd{asd{asd}asd}}asd}

Upvotes: 3

davidrac
davidrac

Reputation: 10738

Maybe this will do it: preg_replace('/(^[^{]*)|([^}]*$)/', '', 'aaa aaa{bb b {c cc}{d dd}e ee}xxx');

Upvotes: 0

S.Visser
S.Visser

Reputation: 4725

<?php
$str = "abc{def{ghi{jkl}mno{pqr}st}uvw}xyz" ;

$str = preg_match("#\{((?>[^\{\}]+)|(?R))*\}#x", $str, $matches, PREG_OFFSET_CAPTURE, 3);

print_r($matches);
?>

Upvotes: 0

Related Questions