我有一个包含创建查询的字符串,我试图根据逗号分割它。不幸的是,有些行中有逗号括号括起来。
示例:
dbo.Display_Test1.Column,
CASE WHEN CHARINDEX(' To ', Test3) > 0 AND CHARINDEX('XVR', Test3) = 0 THEN LEFT(Test3, (CHARINDEX(' To ', Test3) - 12)) ELSE Test3 END AS Test3,
dbo.Display_Test2.Column,
ISNULL((CASE WHEN [2-Display-Test4].[Total Number] > 0 AND [1-Display-Test5].SumOfNumber = 0 THEN 0 ELSE (([2-Display-Test4].[Total Number] * 1000) / [1-Display-Test5].SumOfNumber) END), 0) AS Test6,
我想根据不在(可能是多个)括号内的逗号分割我的字符串。作为参考,我的例子应该分为换行符(尽管我的字符串中没有换行符)。
我尝试了许多不同的解决方案,但都没有做得很好:
/(?:\(*[^()]*\)|[^,])+/g
适用于第1,3和4行,但在第2行失败。它将该行分成多个匹配。
/((?:[^,(]+|(\((?:[^()]+)|$1\)))+)/g
适用于第1,2和3行,但在第4行失败。它还将该行分为多个匹配。
我似乎无法使其发挥作用。任何帮助表示赞赏。
答案 0 :(得分:2)
可能的一种解决方案:(注意:我们删除了分离彗星)
var str = "dbo.Display_Test1.Column, CASE WHEN CHARINDEX(' To ', Test3) > 0 AND CHARINDEX('XVR', Test3) = 0 THEN LEFT(Test3, (CHARINDEX(' To ', Test3) - 12)) ELSE Test3 END AS Test3, dbo.Display_Test2.Column, ISNULL((CASE WHEN [2-Display-Test4].[Total Number] > 0 AND [1-Display-Test5].SumOfNumber = 0 THEN 0 ELSE (([2-Display-Test4].[Total Number] * 1000) / [1-Display-Test5].SumOfNumber) END), 0) AS Test6,";
// if the string don't end by a coma , we add it.
var strArr = str.replace(/,*\s*$/ , ',').split('');
var res;
res = strArr.reduce(function( trans , charValue ){
if(charValue === '(') {
trans.deep++;
}
if(charValue === ')') {
trans.deep--;
}
if( trans.deep === 0){
if(charValue===',') {
trans.arr.push( trans.str);
trans.str = '';
}else{
trans.str += charValue;
}
}else{
trans.str += charValue;
}
return trans;
}, { arr : [] , str : '' ,deep : 0});
document.write('<pre>' + JSON.stringify(res.arr , null , ' ') + '</pre>');
&#13;
编辑:
答案 1 :(得分:0)
当然,如果我们想要无限制地嵌套括号,那么就不可能避免循环。对于某些有界嵌套,我们可以写一个捕获它的正则表达式。
最多1个括号级别可以是
/((?:[^(),]|\([^()]*\))+)/g
最多2个括号级别(可能是你的情况)
/((?:[^(),]|\((?:[^()]|\([^()]*\))*\))+)/g
依此类推,用[^()]*
(?:[^()]|\([^()]*\))*
答案 2 :(得分:0)
正则表达不会让你到达你想要的地方,仍然允许随意的复杂性。
一种方法是遍历字符串中的每个字符,跟踪打开和关闭括号的时间,并且只有当打开和关闭括号的数字相互抵消时才会在逗号上拆分(所以你知道你&#39 ;不在括号内。)
function splitQuery(input){
var arr = [];
var lastStart = 0;
var open = 0;
for(var i = 0, len = input.length; i < len; i++){
var curr = input[i];
if(curr === "("){open += 1;}
else if(curr === ")"){ open = open < 1 ? 0 :open -=1;}
else if(curr === ","){
if(open === 0){
arr.push(input.substring(lastStart,i));
lastStart = i+1;
}
}else if(i+1 === len){
arr.push(input.substring(lastStart,i+1));
}
}
return arr;
}
请注意,在处理特别大的字符串时,这种方法可能很昂贵(从性能角度来看)。
这是一个有效的例子:
var query = "dbo.Display_Test1.Column, CASE WHEN CHARINDEX(' To ', Test3) > 0 AND CHARINDEX('XVR', Test3) = 0 THEN LEFT(Test3, (CHARINDEX(' To ', Test3) - 12)) ELSE Test3 END AS Test3, dbo.Display_Test2.Column, ISNULL((CASE WHEN [2-Display-Test4].[Total Number] > 0 AND [1-Display-Test5].SumOfNumber = 0 THEN 0 ELSE (([2-Display-Test4].[Total Number] * 1000) / [1-Display-Test5].SumOfNumber) END), 0) AS Test6,";
var split = splitQuery(query);
var output = document.getElementById("output")
for(var el in split){
output.insertAdjacentHTML("beforeend",el + ": "+ split[el]+"<hr/>");
}
function splitQuery(input){
var arr = [];
var lastStart = 0;
var open = 0;
for(var i = 0, len = input.length; i < len; i++){
var curr = input[i];
if(curr === "("){open += 1;}
else if(curr === ")"){ open = open < 1 ? 0 :open -=1;}
else if(curr === ","){
if(open === 0){
arr.push(input.substring(lastStart,i));
lastStart = i+1;
}
}else if(i+1 === len){
arr.push(input.substring(lastStart,i+1));
}
}
return arr;
}
&#13;
<div id="output"></div>
&#13;