如何用字分割字符串但不用撇号分隔字符串

时间:2016-08-18 11:20:00

标签: java regex

我有一种SQL查询,我想通过' AND'和'或者'。问题是这些关键字可能以撇号或引号出现在查询中。

E.g。以下查询:

attribute1 IS 'test AND attribute2 IS NOT 'test' AND attribute2 IN ('me and you', 'me or you')

应拆分如下:

attribute1 IS 'test
attribute2 IS NOT 'test'
attribute2 IN ('me and you', "me or you")

所以基本上不应该处理撇号或引号中的任何字符串('我和你',"我或你")。 我怎么能用一个正则表达式做到这一点?实际上是两个,一个用" OR"和另一个用" AND"分开。

提前感谢您的帮助! 马里乌什

1 个答案:

答案 0 :(得分:2)

正如Wiktor所说,编写自己的解析器。尝试使用单个正则表达式执行此操作可能会导致难以阅读和维护代码。

然而,正则表达式可能有助于大幅减少您自己的解析器编码。尝试这里描述的方法:http://www.rexegg.com/regex-best-trick.html(文章很长,您可能希望直接跳到匹配泰山而不是#34;泰山" 部分。)

简而言之:使用这个表达式:

'.*?'|".*?"|(AND|OR)

演示(寻找绿色高光):https://regex101.com/r/jC2jC9/1。注意:演示中的表达式比'.*?'|".*?"|(AND|OR)略微复杂,因为后者我只是想更清楚地概述这个想法。

然后在Java代码中找到定义了group(1)的所有匹配项。引号中的AND和OR将由前两个备选方案涵盖,并且不会被该组捕获。您现在需要的是使用匹配的start()end()索引来分割输入字符串,并定义group(1)

Pattern pattern = Pattern.compile("'.*?'|\".*?\"|\\s*\\b(AND|OR)\\b\\s*", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(input);
int nextPartPos = 0;
while (matcher.find()) {
    if (matcher.group(1) != null) {
        System.out.println(input.substring(nextPartPos, matcher.start()));
        nextPartPos = matcher.end();
        System.out.println("--> " + matcher.group(1) + " <--");
    }
}
if (nextPartPos < input.length()) {
    System.out.print(input.substring(nextPartPos));
}

完整的演示代码:https://ideone.com/3cmGhY

最后注意事项:此代码实际上构建了一个子表达式的平面列表,而您需要一个层次结构来实现AND / OR优先级。我确定,在代码中添加树构建功能并不是什么大不了的事。我这里没有这样做只是为了专注于主要想法。