Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用分号(但不在引号内)拆分php中的sql语句_Php_Regex_Split_Quotes - Fatal编程技术网

用分号(但不在引号内)拆分php中的sql语句

用分号(但不在引号内)拆分php中的sql语句,php,regex,split,quotes,Php,Regex,Split,Quotes,我有一个系统,当用户在自由格式字段中使用分号时会导致错误。我将其追溯到一个简单的爆炸声明: $array = explode( ";", $sql ); 因为这一行是在一个从整个系统调用的子程序中,所以我想用一个可以正确分割事物的东西来替换这一行,而不会破坏系统的其余部分。我以为我会用str_getcsv成为赢家,但这也不够复杂。看看下面的例子 $sql = "BEGIN;INSERT INTO TABLE_A (a, b, c) VALUES('42', '12', '\'ab\'c; DE

我有一个系统,当用户在自由格式字段中使用分号时会导致错误。我将其追溯到一个简单的爆炸声明:

$array = explode( ";", $sql );
因为这一行是在一个从整个系统调用的子程序中,所以我想用一个可以正确分割事物的东西来替换这一行,而不会破坏系统的其余部分。我以为我会用str_getcsv成为赢家,但这也不够复杂。看看下面的例子

$sql = "BEGIN;INSERT INTO TABLE_A (a, b, c) VALUES('42', '12', '\'ab\'c; DEF');INSERT INTO TABLE_B (d, e, f) VALUES('42', '43', 'XY\'s Z ;uvw') ON DUPLICATE KEY UPDATE f='XY\'s Z ;uvw';COMMIT;";

$array = str_getcsv($sql, ";", "'");
foreach( $array as $value ) {
    echo $value . "<br><br>";
}
$sql=“BEGIN;在表A(A,b,c)中插入值('42','12','ab'c;DEF');在重复键更新时插入表b(d,e,f)中的值('42','43','XY's Z;uvw');提交;”;
$array=str_getcsv($sql,“;”,“”);
foreach($array作为$value){
回显$value。“

”; }
当我运行时,输出如下:

开始

在表A(A,b,c)中插入值('42','12','\'ab'c

定义')

在表_B(d,e,f)中插入值('42','43','XY's Z

重复关键点更新f='XY's Z时的uvw')

uvw'

承诺

所以它没有注意到分号在引号中。(据我所知,系统中不同位置的带引号的字符串总是单引号,但有时它们可能是双引号,对此我不确定。)

谁能告诉我怎么做?我想我可以用一个非常复杂的正则表达式来实现这一点,但这是我无法理解的。

(*SKIP)(*FAIL)Magic

这将显示下面两个选项的输出(带或不带分号)

这就是您需要的:

$splits = preg_split('~\([^)]*\)(*SKIP)(*F)|;~', $sql);
看到我们在右边分号上分开

输出:

[0] => BEGIN
[1] => INSERT INTO TABLE_A (a, b, c) VALUES('42', '12', '\'ab\'c; DEF')
[2] => INSERT INTO TABLE_B (d, e, f) VALUES('42', '43', 'XY\'s Z ;uvw')
[3] => COMMIT
[4] =>
[0] => BEGIN;
[1] => INSERT INTO TABLE_A (a, b, c) VALUES('42', '12', '\'ab\'c; DEF');
[2] => INSERT INTO TABLE_B (d, e, f) VALUES('42', '43', 'XY\'s Z ;uvw');
[3] => COMMIT;
空项#4是最终
另一侧的匹配项。另一种选择是保留分号(见下文)

选项2:保留分号

如果要保留分号,请执行以下操作:

$splits = preg_split('~\([^)]*\)(*SKIP)(*F)|(?<=;)(?![ ]*$)~', $sql);
解释

这个问题是本问题中解释的技术的一个经典案例

在交替的左侧,regex
\([^)]*\)
匹配complete
(括号)
,然后故意失败,之后引擎跳转到字符串中的下一个位置。右侧与
匹配您想要的单词,我们知道它们是正确的,因为它们与左边的表达式不匹配。现在可以在上面拆分了


在选项2中,我们保留分号,右边的匹配匹配位置,但不匹配字符。这个位置是由lookback
(?嘿,这里,跟进一下。其中一个答案是否为您解决了问题,或者问题是否仍然存在?请给我们一些反馈。:)这正是我要寻找的。这是一种享受。谢谢。我们需要在不久的将来观看您的实时php演示。刚刚遇到另一种情况,这种情况不起作用,即SQL语句确实有一个“ON replicate”部分,在这种情况下,参数不在括号中。我已经更新了问题以反映这一点。好的,我已经解决了,你提供的链接证明非常有用。如果我将正则表达式更改为“~([^)]*)(*跳过)(*F)\\”(?:\\\'\\'\\\\\'.[^\'])*”(*跳过)(*F)\~”它起作用了。也许你可以在你的答案中更新它,让其他人看到这个答案。如果其他人不熟悉
(*SKIP)(*FAIL)
黑魔法,你可以在中阅读。@EdCottrell谢谢你,Ed!更直接的是,请参见perl文档中的。添加到参考资料中,好主意,谢谢。:)