在较长的文本中查找与php / regex匹配的括号

I've tried to wrap my head around this for quite a while, but still haven't found a solution.

I'm working on some simple way of formatting, where I want some tags containing strings inside brackets, with the tag defined right before the bracket. The tags should be able to be inside other brackets too.

String:

This is some random text, tag1{while this is inside a tag2{tag}}. This is some
other text tag2{also with a tag  tag3{inside} of it}.

What I want to do now, is the content of each

tag1{}
tag2{}
tag3{}

I've found others with similar problems (Find matching brackets using regular expression) but their problem was more oriented on how to find matching brackets inside of other brackets, while my problem is both that, and finding multiply brackets in a longer text.

the regex it's this:

tag[0-9]+\{[^\}]+

and you should replace the inside tags first

I don't know, if there is a regexp, that gets you all the inner and outer tags in one call, but you can use this regexp /\{(([^\{\}]+)|(?R))*\}/ from the question you linked and iterate recursively into the results.

I added your tag name and some named sub patterns to the regexp for more clarity:

function search_tags($string, $recursion = 0) {
    $Results = array();
    if (preg_match_all("/(?<tagname>[\w]+)\{(?<content>(([^\{\}]+)|(?R))*)\}/", $string, $matches, PREG_SET_ORDER)) {
        foreach ($matches as $match) {
            $Results[] = array('match' => $match[0], 'tagname' => $match['tagname'], 'content' => $match['content'], 'deepness' => $recursion);
            if ($InnerResults = search_tags($match['content'], $recursion+1)) {
                $Results = array_merge($Results, $InnerResults);
            }
        }
        return $Results;
    }
    return false;
}

This returns an array with all matches containing the whole match, the tag name, the content of the brackets and an iteration counter, showing you how often the match was nested inside other tags. I have added another level of nesting to your string for demonstration:

$text = "This is some random text, tag1{while this is inside a tag2{tag}}. This is some other text tag3{also with a tag tag4{and another nested tag5{inside}} of it}.";
echo '<pre>'.print_r(search_tags($text), true).'</pre>';

The output will be:

Array
(
    [0] => Array
        (
            [match] => tag1{while this is inside a tag2{tag}}
            [tagname] => tag1
            [content] => while this is inside a tag2{tag}
            [deepness] => 0
        )

    [1] => Array
        (
            [match] => tag2{tag}
            [tagname] => tag2
            [content] => tag
            [deepness] => 1
        )

    [2] => Array
        (
            [match] => tag3{also with a tag tag4{and another nested tag5{inside}} of it}
            [tagname] => tag3
            [content] => also with a tag tag4{and another nested tag5{inside}} of it
            [deepness] => 0
        )

    [3] => Array
        (
            [match] => tag4{and another nested tag5{inside}}
            [tagname] => tag4
            [content] => and another nested tag5{inside}
            [deepness] => 1
        )

    [4] => Array
        (
            [match] => tag5{inside}
            [tagname] => tag5
            [content] => inside
            [deepness] => 2
        )

)

If the tags are always balanced, you could use an expression like this to get content and name of all tags, including nested tags.

\b(\w+)(?={((?:[^{}]+|{(?2)})*)})

Example:

$str = "This is some random text, tag1{while this is inside a tag2{tag}}. This is some other text tag2{also with a tag  tag3{inside} of it}.";

$re = "/\\b(\\w+)(?={((?:[^{}]+|{(?2)})*)})/";
preg_match_all($re, $str, $m);

echo "* Tag names:
";
print_r($m[1]);
echo "* Tag content:
";
print_r($m[2]);

Output:

* Tag names:
Array
(
    [0] => tag1
    [1] => tag2
    [2] => tag2
    [3] => tag3
)
* Tag content:
Array
(
    [0] => while this is inside a tag2{tag}
    [1] => tag
    [2] => also with a tag  tag3{inside} of it
    [3] => inside
)

I think there is no other way. You need to loop over each bracket.

     $output=array();
     $pos=0;     
while(preg_match('/tag\d+\{/S',$input,$match,PREG_OFFSET_CAPTURE,$pos)){
   $start=$match[0][1];
   $pos=$offset=$start+strlen($match[0][0]);
   $bracket=1;
   while($bracket!==0 and preg_match('/\{|\}/S',$input,$found,PREG_OFFSET_CAPTURE,$offset)){
      ($found[0][0]==='}')?$bracket--:$bracket++;
      $offset=$found[0][1]+1;
   }
   $output[]=substr($input,$start,$offset-$start);
}