我可以用什么模式来分割这样的字符串:
f.id AS id, CONCAT(a1.id, a2.id, a3.id) AS cnp, SUM(A3.nr) AS sum
以这样的方式,结果是这样的3个组的数组:
f.id AS id
CONCAT(a1.id, a2.id, a3.id) AS cnp
SUM(A3.nr) AS sum
我可以匹配括号中没有括起的逗号吗?
答案 0 :(得分: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) );
}
只要您不希望任何相关的子查询嵌套在您的选择值(或其他边缘情况,例如包含' as error,' AS id, ...
的字符串)中,那么这应该适用于与您的格式类似的输入。< / p>
答案 1 :(得分:0)
可能有一个杀手正则表达式,但更可能的是:
为了使第1步更加通用,您应该在分隔符不起作用的部分插入占位符。只要您能够准确地确定这些部分是什么,您就可以应用此配方。
答案 2 :(得分: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.
}
答案 3 :(得分: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 AS id
第1组是CONCAT(a1.id,a2.id,a3.id)AS cnp
第2组是SUM(A3.nr)AS总和
答案 4 :(得分:0)
最后写一个SQL Parser太复杂了所以我决定使用ANTLR4。
我从这里使用了这个例子并且运行正常。 https://github.com/bkiers/sqlite-parser
但我不知道如何只提取查询的某些部分(选择,连接,顺序......),我在网上找不到任何例子。 someoane可以说明这是怎么做的吗?
谢谢。