【发布时间】:2019-08-31 22:04:36
【问题描述】:
我有一个字符串,我想用逗号分解,但前提是逗号没有嵌套在一些括号内。这是一个相当常见的用例,我一直在阅读此论坛中已回答的帖子,但并没有真正找到我想要的东西。
所以,详细地说:关键是,我有一个字符串(= SQL SELECT ... FROM 语句),我想从列表中提取元素,该列表用逗号分隔,在这个字符串中编码(=想要从中选择的列。但是,这些元素可以包含括号,并且实际上是函数调用。例如,在 SQL 中可以这样做
SELECT TO_CHAR(min(shippings.shippingdate), 'YYYY-MM-DD') as shippingdate, nameoftheguy FROM shippings WHERE ...
显然,我想要一个现在包含作为第一个元素的数组
TO_CHAR(min(shippings.shippingdate), 'YYYY-MM-DD') as shippingdate
作为第二个元素
nameoftheguy
到目前为止我遵循的方法是 PHP and RegEx: Split a string by commas that are not inside brackets (and also nested brackets), PHP: Split a string by comma(,) but ignoring anything inside square brackets?, Explode string except where surrounded by parentheses?,和 PHP: split string on comma, but NOT when between braces or quotes? (专注于其中的正则表达式,因为我想用一条正则表达式行来做),但是在我的小测试区域中,那些并没有给出正确的结果。事实上,他们都没有分裂或分裂太多:
$Input: SELECT first, second, to_char(my,big,house) as bigly, export(mastermind and others) as aloah FROM
$Output: Array ( [0] => first [1] => second [2] => to_char [3] => (my,big,house) [4] => as [5] => bigly [6] => export [7] => (mastermind and others) [8] => as [9] => aloah )
我的测试区的代码是
<?php
function test($sql){
$foo = preg_match("/SELECT(.*?)FROM/", $sql, $match);
$bar = preg_match_all("/(?:[^(|]|\([^)]*\))+/", $match[1], $list);
//$bar = preg_match_all("/\((?:[^()]|(?R))+\)|'[^']*'|[^(),\s]+/", $match[1], $list);
//$bar = preg_match_all("/[,]+(?![^\[]*\])/", $match[1], $list);
//$bar = preg_match_all("/(?:[^(|]|\([^)]*\))+/", $match[1], $list);
//$bar = preg_match_all("/[^(,\s]+|\([^)]+\)/", $match[1], $list);
//$bar = preg_match_all("/([(].*?[)])|(\w)+/", $match[1], $list);
print "<br/>";
return $list[0];
}
print_r(test("SELECT first, second, to_char(my,big,house) as bigly, export(mastermind and others) as aloah FROM"));
?>
您可以想象,我不是正则表达式专家,但如果可能的话,我想在一行中进行拆分。
【问题讨论】:
-
你真的应该看一个合适的解析器。如果您在选择列表中获得带有子查询的查询,例如,您会怎么做?
SELECT x, (SELECT y FROM z) AS p, z FROM ...?在这种情况下,您的$foo = preg_match("/SELECT(.*?)FROM/", $sql, $match);代码将无法正常工作... -
假设所有括号都是平衡的,您可以使用
,\s*(?![^(]*\))之类的东西进行拆分。 -
很公平。在第一行中,由于您刚刚解释的内容,我可能不应该像现在这样执行正则表达式。但是在这种情况下,第二行(有问题的行)应该(假设有我想象中的答案)仍然返回正确的列表,即 ["x", "(SELECT y FROM z) AS p", "z"]。
-
@PJProudhon 与此我收到错误“警告:preg_match_all(): 未找到结束分隔符 ','”