我一直试图在字符串中提取一些东西。我收到了以下字符串:
*, bob, DATE('gdfgfd', 'Fdsfds', ('fdsfdfsd')), george
我想在()之外用逗号提取,并且假设给出:
我一直在尝试使用爆炸,但它通过函数均值来削减内部(和)...逻辑。
所以我已经这样做了:[^(,\s]+|\([^)]+\)
但是即使在括号内找到了逗号也会给出剪切。
任何人都知道如何做我的意思吗?
由于
编辑:
好的非常明确和直接。
我得到了这个:SELECT MyField, Field2, Blabla, Function(param), etc FROM table Blabla
我已经获得了字符串MyField, Field2, Blabla, Function(param), etc
,因为查询是由多个函数类完成的,例如$DB->Select('MyField, Field2, Blabla, Function(param), etc');
,但现在我想解析逗号之间的所有内容,以便MyField, Field2, Blabla, Function(param), etc
成为:{/ p>
答案 0 :(得分:4)
将此作为答案发布,因为它可能比其他任何东西都好:
http://code.google.com/p/php-sql-parser/
使用该项目来解析SQL语句。结果以数组的形式返回,包括SELECT
和FROM
之间的位作为单个元素,就像您想要的那样。这比你使用的任何正则表达式解决方案都要好得多。
答案 1 :(得分:2)
这是我做的,不支持多字节字符:
编辑:添加了字符串感知
<?php
$stack = array();
$stuff = array();
$escaping = false;
$input = "*, bob, [], DATE('g()d\\'f,gfd', ('Fd()sf)ds'), ('fdsfd\"\"()fsd')), ',(),() (,,'";
$len = strlen( $input );
$i = 0;
$curstr = "";
$char;
while( $i < $len ) {
$char = $input[$i++];
if( $escaping ) {
$curstr .= $char;
$escaping = false;
continue;
}
switch( $char ) {
case "\\":
$escaping = true;
break;
case '"':
$top = end( $stack );
if( $top === '"' ) {
array_pop( $stack );
}
else if( $top !== "'" ){
$stack[] = '"';
}
$curstr .= $char;
break;
case "'":
$top = end( $stack );
if( $top === "'" ) {
array_pop( $stack );
}
else if( $top !== '"' ) {
$stack[] = "'";
}
$curstr .= $char;
break;
case ",":
if( count( $stack ) ) {
$curstr .= $char;
}
else {
$stuff[] = trim($curstr);
$curstr = "";
}
break;
case "(":
$top = end( $stack );
if( $top !== "'" && $top !== '"' ) {
$stack[] = "(";
}
$curstr .= $char;
break;
case ")":
$top = end( $stack );
if( $top !== "'" && $top !== '"' ) {
if( end($stack) !== "(" ) {
die( "Unbalanced parentheses" );
}
array_pop( $stack );
}
$curstr .= $char;
break;
default:
$curstr .= $char;
break;
}
}
if( count( $stack ) ) {
die( "Unbalanced ".end($stack) );
}
$stuff[] = trim( $curstr );
print_r( $stuff );
/*
Array
(
[0] => *
[1] => bob
[2] => []
[3] => DATE('g()d'f,gfd', ('Fd()sf)ds'), ('fdsfd""()fsd'))
[4] => ',(),() (,,'
)
*/
答案 2 :(得分:0)
您在评论中说明您准备使用递归,因为您有嵌套列表。但是,正则表达式无法进行递归。这是因为正则表达式无法无限期地“计算”任何东西。由于无法计算开/关括号,因此无法知道其中有多少级别,或者它必须达到多少级别。
你可以编写非常复杂的正则表达式来处理N级深度(参见anubhava's answer),但是一旦你遇到N + 1级深度的表达式,你的正则表达式就会失败。这就是我们使用编程语言来解析不规则语言的原因,因为它们可以计算递归(参见diolemo's answer)。 在这个递归中,我们可以使用一小部分正则表达式。
答案 3 :(得分:0)
这将起作用(大部分)。如果括号内有括号(部分数据),则会失败。你可以扩展代码来处理引用的括号(但是你必须考虑转义引号和类似的东西。正则表达式永远不会正常工作。
编辑:最好使用SpikeX回答的PHP SQL Parser。
function unreliable_comma_explode($str)
{
$last_split = 0;
$len = strlen($str);
$brackets = 0;
$parts = array();
for ($i = 0; $i < $len; $i++)
{
if ($str[$i] == '(')
{
$brackets++;
continue;
}
if ($str[$i] == ')')
{
if (--$brackets == -1) $brackets = 0;
continue;
}
if ($str[$i] == ',' && $brackets == 0)
{
$parts[] = substr($str, $last_split, ($i-$last_split));
$last_split = $i + 1;
}
}
if (($len-$last_split) > 0)
$parts[] = substr($str, $last_split, ($len-$last_split));
return $parts;
}
答案 4 :(得分:0)
您可以使用此基于正则表达式的代码以您希望的方式获取拆分结果:
$str = "*, bob, DATE('gdfgfd', 'Fdsfds', ('fdsfdfsd')), george";
$arr = preg_split('/([^,]*(?:\([^)]*\))[^,]*)+|,/', $str, -1,
PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
虽然我的原始答案适用于OP发布的示例,但由于某些成员提出的问题,我发布的解决方案将使用嵌套括号以及只要括号平衡: < / p>
$str = "*, bob, DATE('gdfgfd', ('Fdsfds'), ('fdsfdfsd', ('foo'))) 'foo'=[bar]," .
"john, MY('gdfgfd', ((('Fdsfds'))), ('fdsfdfsd')), george";
$arr = preg_split('/\s*( [^,()]* \( ( [^()]* | (?R) )* \) [^,()]* ) ,?\s* | \s*,\s*/x',
$str, -1 , PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
print_r($arr);
<强>输出:强>
Array
(
[0] => *
[1] => bob
[2] => DATE('gdfgfd', ('Fdsfds'), ('fdsfdfsd', ('foo'))) 'foo'=[bar]
[3] => john
[4] => MY('gdfgfd', ((('Fdsfds'))), ('fdsfdfsd'))
[5] => george
)
警告:尽管这种基于递归的正则表达式模式适用于深嵌套括号,但这并不意味着在某些边缘情况下(例如不平衡括号)不会破坏它。
答案 5 :(得分:-1)
我不确定你想在这里做什么..但是如果你只想提取字符串。你可以使用implode。
$array = array("*", "bob", "DATE('gdfgfd', 'Fdsfds', '(\"fdsfdfsd\"))", "george");
echo $test = implode($array, ",");