tornadof3
tornadof3

Reputation: 234

Extract code from nested curly braces, including multiple internal curly braces in PHP

So, I got some ideas off here about how to do this and took on board some of the code suggestions; I have LaTeX files with components in the form {upper}{lower} where upper could be anything from plain text to LaTeX including its own nested {} and lower could be blank or substantial latex. Desired output is a pair of PHP strings $upper and $lower that contain only the content of the two parent braces.

$upperlowerQ='some string';  // in format {upper}{lower}
$qparts=nestor($upperlowerQ);
$upper=$qparts[0];
$lower=$qparts[1];


function nestor($subject) {
    $result = false;    
    preg_match_all('~[^{}]+|\{(?<nested>(?R)*)\}~', $subject, $matches);

    foreach($matches['nested'] as $match) {
        if ($match != "") {
            $result[] = $match;
            $nesty = nestor($match);
            if ($nesty) 
                $result = array_merge($result,$nesty); 
        }
    }
    return $result;
}

This function works for about 95% of my data (this upper/lower splitting is called in a loop for about 1,000 times) but it is failing on a few. An example of something it fails on looks like this:

{Draw an example of a reciprocal graph in the form $y=\frac{a}{x}$}{
\begin{tikzpicture}
    \begin{axis}[xmin=-8,xmax=8,ymin=-5,ymax=12,samples=50,grid=both,grid style={gray!30},xtick={-8,...,8},ytick={-5,...,12},axis x line = bottom,
        axis y line = left, axis lines=middle]
    \end{axis}
\end{tikzpicture}\par
%ans: smooth reciprocal function plotted.
}

which gives: $upper as Draw an example of a reciprocal graph in the form $y=\frac{a}{x}$ (which is correct) but $lower as a, which is the numerator of the fraction in the upper part... any ideas appreciated. It is always $lower that is wrong... $upper seems correct.

Upvotes: 2

Views: 444

Answers (1)

tornadof3
tornadof3

Reputation: 234

For any future readers, @Jonny5's response above worked perfectly. eval.in


Added from comments

Try using regex like this: {((?:[^}{]+|(?R))*)} for only extracting what's inside the outer { } and to check if exactly 2 items are matched by returned matchcount of preg_match_all.

$upper = ""; $lower = "";

if(preg_match_all('/{((?:[^}{]+|(?R))*)}/', $str, $out) == 2) {
  $upper=$out[1][0]; $lower=$out[1][1];
}

See test at eval.in

Upvotes: 2

Related Questions