tags:

views:

60

answers:

3

Hi all,

I know this question have been asked endless times but I can't find a working solution for my case.

I want to split a string in PHP (5.3) using semicolons as delimiters unless they are between $BODY$ strings. The goal is to split SQL statements where statements can be procedures (postgresql in this case).

Example:

select; start $BODY$ begin; end; $BODY$ lang; update

Should result in:

select
start $BODY$ begin; end; $BODY$ lang
update

I have been toying with preg_split for a while and cannot find a working solution.

Many thanks

Edit: it must works with multiline inputs (but I can remove line breaks using str_replace before hand)

A: 
$a = explode(';', 'select; $BODY$ begin; end; $BODY$ lang; update');
$b = array();
$index = 0;
$waiting = false;
foreach($a as $str) {
    if(strpos($str,'$BODY$') !== false) {
        $waiting = !$waiting;
    }
    $b[$index] .= $str.';';
    if(!$waiting) {
        $index++;
    }
}
print_r($b);

This would work assuming there were wasn't multiple levels of nested $BODY$. I feel like there has to be a regular expression that could accomplish but my brain is not cooperating at the moment.

methodin
A: 

Here's a quick pattern that will match your example. Hopefully it'll point you in the right direction for something more flexible:

$string = 'select; $BODY$ begin; end; $BODY$ lang; update';

preg_match('/^(?:(.*?);\s?)?(\$BODY\$.+?\$BODY\$[^;]+)(?:;\s?(.+?))?$/', $string, $array);
$array = array_filter($array);
$array = array_slice($array, 1, 3);

var_dump($array);
Nev Stokes
I forgot to mention that there is some text before the $BODY$ tag which breaks the regexp. I updated the example. Thanks anyway!
maximebf
A: 

As no regexps seemed to fit, here is how I did it for the one who are interested:

$length = strlen($sql);
$queries = array();
$offset = 0;
$last = 0;
do {
    if (($colon = strpos(substr($sql, $offset), ';')) === false) {
        break;
    }
    $colon += $offset;

    if (($body = strpos(substr($sql, $offset), '$BODY$')) !== false) {
        $body += $offset;
        if ($body < $colon) {
            $offset = $body + strpos(substr($sql, $body + 6), '$BODY$') + 12;
            continue;
        }
    }

    $queries[] = trim(substr($sql, $last, $colon - $last));
    $last = $offset = $colon + 1;

} while($offset <= $length);
maximebf