Php 拆分字符串,除非包含在其他字符串之间

Php 拆分字符串,除非包含在其他字符串之间,php,sql,Php,Sql,我知道这个问题被问了无数次,但我找不到一个有效的解决方案 我想在PHP(5.3)中使用分号作为分隔符拆分字符串,除非它们位于$BODY$字符串之间。目标是拆分SQL语句,其中语句可以是过程(本例中为postgresql) 例如: select; start $BODY$ begin; end; $BODY$ lang; update 选择;start$BODY$begin;结束$BODY$lang;更新 应导致: select start $BODY$ begin; end; $BODY$ la

我知道这个问题被问了无数次,但我找不到一个有效的解决方案

我想在PHP(5.3)中使用分号作为分隔符拆分字符串,除非它们位于
$BODY$
字符串之间。目标是拆分SQL语句,其中语句可以是过程(本例中为postgresql)

例如:

select; start $BODY$ begin; end; $BODY$ lang; update 选择;start$BODY$begin;结束$BODY$lang;更新 应导致:

select start $BODY$ begin; end; $BODY$ lang update 选择 start$BODY$begin;结束$BODY$lang 更新 我一直在玩弄
preg_split
有一段时间了,找不到有效的解决方案

非常感谢

编辑:它必须适用于多行输入(但我可以使用
str\u replace
手动删除换行符)


假设没有多个嵌套的$BODY$级别,这将起作用。我觉得必须有一个正则表达式才能完成,但我的大脑目前不合作。

这里有一个与您的示例相匹配的快速模式。希望它能为您指明更灵活的方向:

$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);

由于没有合适的正则表达式,下面是我为感兴趣的人所做的:

$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); $length=strlen($sql); $querys=array(); $offset=0; $last=0; 做{ if($colon=strpos(substr($sql,$offset),“;”)==false){ 打破 } $colon+=$offset; if($body=strpos(substr($sql,$offset),“$body$”)!==false){ $body+=$offset; if($body<$colon){ $offset=$body+strop(substr($sql,$body+6),“$body$”)+12; 继续; } } $querys[]=trim(substr($sql,$last,$colon-$last)); $last=$offset=$colon+1; }而($offset这里有一个更简单的方法

$test_string = 'select; start $BODY$ begin; end; $BODY$ lang; update';

$test_string = explode('$BODY$', $test_string);
$level_flag = 1;
for ($i = 0; $i < count($test_string); $i++) {
    if ($level_flag) {
        $test_string[$i] = str_replace(';', "\n", $test_string[$i]);
        $level_flag = 0;
    } else {
        $level_flag = 1;
    }
}
$test_string = implode('$BODY$', $test_string);
$test_string='select;start$BODY$begin;end;$BODY$lang;update';
$test_string=分解($BODY$,$test_string);
$level_标志=1;
对于($i=0;$i
您自己的解决方案与提供的示例不兼容。我得到的结果是:

select
start $BODY$ begin; end; $BODY$ lang
Nev Stokes的regexp中的一个小改动使其能够按要求工作:

$sql = 'select; start $BODY$ begin; end; $BODY$ lang; update';
preg_match(
    '/^(?:(.*?);\s?)([^;]+\$BODY\$.+?\$BODY\$[^;]+)(?:;\s?(.+?))$/',
    $sql,
    $queries
);
array_shift($queries);

给出一个更简单的例子,更多的文本输入和预期的输出结果。否则人们会建议编写解析器。完成,谢谢你的评论。我忘了提到$BODY$标记前面有一些文本破坏了regexp。我更新了这个例子。无论如何,谢谢!
$sql = 'select; start $BODY$ begin; end; $BODY$ lang; update';
preg_match(
    '/^(?:(.*?);\s?)([^;]+\$BODY\$.+?\$BODY\$[^;]+)(?:;\s?(.+?))$/',
    $sql,
    $queries
);
array_shift($queries);