2016-02-25 67 views
1

可以使用哪些图案分裂像这样的字符串逗号模式:以这样的方式拆分通过匹配

f.id AS id, CONCAT(a1.id, a2.id, a3.id) AS cnp, SUM(A3.nr) AS sum 

的结果是3个基团的一个这样的数组:

  1. f.id AS id
  2. CONCAT(a1.id, a2.id, a3.id) AS cnp
  3. SUM(A3.nr) AS sum

我可以匹配没有用圆括号括起来的逗号吗?

+0

yourString.split(“,”) –

+1

@ Jean-FrançoisSavard - 这也与所有逗号之间的逗号分开。 – DaoWen

+0

糟糕,读得太快。 –

回答

0

有可能是这个杀手正则表达式,但什么是更maintanable可能是:

  1. 临时设置占位符的括号
  2. 拆分所需的分离结果之间块
  3. 用原始值替换占位符

要使步骤1更一般化,您应该在分隔符的部分插入占位符d不起作用。只要你能够准确地确定这些部分是什么,你就可以应用这个配方。

0

使用@KevinEsche建议的实际SQL解析器,可能是最稳健的选择。

不过,如果你并不需要所有的SQL表达式解析,我只想用普通的老字符匹配:经过串字符的时间,计算嵌套在括号有多深你:

List<String> parts = new ArrayList<>(); 
int i = 0; 
int depth = 0; 
while (i < str.length()) { 
    int start = i; 
    while (i < str.length()) { 
    char ch = str.charAt(i); 
    if (ch == '(') { 
     depth++; 
    } else if (ch == ')') { 
     depth--; 
    } else if (ch == ',' && depth == 0) { 
     break; 
    } 
    i++; 
    } 
    // Maybe check that depth == 0 here. 
    parts.add(str.substring(start, i)); 
    i++; // To skip the comma. 
} 
2

模式似乎始终以格式... AS ...,你可以只使用正则表达式匹配:

Pattern p = Pattern.compile("(.*? as .*?)(,|$)", Pattern.CASE_INSENSITIVE); 
String query = "f.id AS id, CONCAT(a1.id, a2.id, a3.id) AS cnp, SUM(A3.nr) AS sum"; 
Matcher m = p.matcher(query); 
while (m.find()){ 
    System.out.println(m.group(1)); 
} 

IDEONE

只要您不希望任何相关的子查询嵌套在您的选择值(或其他边缘情况,如包含' as error,' AS id, ...的字符串)中,那么这应该适用于类似于您的格式的输入。

0

谢谢你的回答。我试图投票,但我还不能。 我提前用一下方式来解决这个问题:

String pattern = ",(?!([^(]*\\)))"; 
String str = "f.id AS id, CONCAT(a1.id, a2.id, a3.id) AS cnp, SUM(A3.nr) AS sum"; 
String strg [] = str.split(pattern); 
for(int i=0;i<strg.length;i++) { 
    System.err.println("Group "+i+" is "+strg[i]); 
} 

,其结果是:

组0 F.ID为ID

第1组CONCAT(a1.id,A2。 ID,a3.id)AS CNP

第2组是SUM(A3.nr)AS和

0

到底是太复杂了写SQL解析器,所以我决定用ANTLR4。

我用这里的例子,工作正常。 https://github.com/bkiers/sqlite-parser

但我不知道如何只提取查询的某些部分(select,joins,order ...),我在网上找不到任何示例。有人能说明这是怎么完成的吗?

谢谢。