SqlParser 一个利用正则表达式解析单句SQL的类_正则表达式

先看要解析的样例SQL语句:

复制代码 代码如下:

select * from dual
SELECT * frOm dual
Select C1,c2 From tb
select c1,c2 from tb
select count(*) from t1
select c1,c2,c3 from t1 where condi1=1
Select c1,c2,c3 From t1 Where condi1=1
select c1,c2,c3 from t1,t2 where condi3=3 or condi4=5 order by o1,o2
Select c1,c2,c3 from t1,t2 Where condi3=3 or condi4=5 Order by o1,o2
select c1,c2,c3 from t1,t2,t3 where condi1=5 and condi6=6 or condi7=7 group by g1,g2
Select c1,c2,c3 From t1,t2,t3 Where condi1=5 and condi6=6 or condi7=7 Group by g1,g2
Select c1,c2,c3 From t1,t2,t3 Where condi1=5 and condi6=6 or condi7=7 Group by g1,g2,g3 order by g2,g3

解析效果之一(isSingleLine=false):

复制代码 代码如下:

原SQL为select * from dual
解析后的SQL为
select
*
from
dual
原SQL为SELECT * frOm dual
解析后的SQL为
select
*
from
dual
原SQL为Select C1,c2 From tb
解析后的SQL为
select
C1,c2
from
tb
原SQL为select c1,c2 from tb
解析后的SQL为
select
c1,c2
from
tb
原SQL为select count(*) from t1
解析后的SQL为
select
count(*)
from
t1
原SQL为select c1,c2,c3 from t1 where condi1=1
解析后的SQL为
select
c1,c2,c3
from
t1
where
condi1=1
原SQL为Select c1,c2,c3 From t1 Where condi1=1
解析后的SQL为
select
c1,c2,c3
from
t1
where
condi1=1
原SQL为select c1,c2,c3 from t1,t2 where condi3=3 or condi4=5 order by o1,o2
解析后的SQL为
select
c1,c2,c3
from
t1,t2
where
condi3=3 or condi4=5
order by
o1,o2
原SQL为Select c1,c2,c3 from t1,t2 Where condi3=3 or condi4=5 Order by o1,o2
解析后的SQL为
select
c1,c2,c3
from
t1,t2
where
condi3=3 or condi4=5
order by
o1,o2
原SQL为select c1,c2,c3 from t1,t2,t3 where condi1=5 and condi6=6 or condi7=7 group by g1,g2
解析后的SQL为
select
c1,c2,c3
from
t1,t2,t3
where
condi1=5 and condi6=6 or condi7=7
group by
g1,g2
原SQL为Select c1,c2,c3 From t1,t2,t3 Where condi1=5 and condi6=6 or condi7=7 Group by g1,g2
解析后的SQL为
select
c1,c2,c3
from
t1,t2,t3
where
condi1=5 and condi6=6 or condi7=7
group by
g1,g2
原SQL为Select c1,c2,c3 From t1,t2,t3 Where condi1=5 and condi6=6 or condi7=7 Group by g1,g2,g3 order by g2,g3
解析后的SQL为
select
c1,c2,c3
from
t1,t2,t3
where
condi1=5 and condi6=6 or condi7=7
group by
g1,g2,g3
order by
g2,g3

解析效果之二(isSingleLine=true):

复制代码 代码如下:

原SQL为select * from dual
解析后的SQL为
select
*
from
dual
原SQL为SELECT * frOm dual
解析后的SQL为
select
*
from
dual
原SQL为Select C1,c2 From tb
解析后的SQL为
select
C1,
c2
from
tb
原SQL为select c1,c2 from tb
解析后的SQL为
select
c1,
c2
from
tb
原SQL为select count(*) from t1
解析后的SQL为
select
count(*)
from
t1
原SQL为select c1,c2,c3 from t1 where condi1=1
解析后的SQL为
select
c1,
c2,
c3
from
t1
where
condi1=1
原SQL为Select c1,c2,c3 From t1 Where condi1=1
解析后的SQL为
select
c1,
c2,
c3
from
t1
where
condi1=1
原SQL为select c1,c2,c3 from t1,t2 where condi3=3 or condi4=5 order by o1,o2
解析后的SQL为
select
c1,
c2,
c3
from
t1,
t2
where
condi3=3 or
condi4=5
order by
o1,
o2
原SQL为Select c1,c2,c3 from t1,t2 Where condi3=3 or condi4=5 Order by o1,o2
解析后的SQL为
select
c1,
c2,
c3
from
t1,
t2
where
condi3=3 or
condi4=5
order by
o1,
o2
原SQL为select c1,c2,c3 from t1,t2,t3 where condi1=5 and condi6=6 or condi7=7 group by g1,g2
解析后的SQL为
select
c1,
c2,
c3
from
t1,
t2,
t3
where
condi1=5 and
condi6=6 or
condi7=7
group by
g1,
g2
原SQL为Select c1,c2,c3 From t1,t2,t3 Where condi1=5 and condi6=6 or condi7=7 Group by g1,g2
解析后的SQL为
select
c1,
c2,
c3
from
t1,
t2,
t3
where
condi1=5 and
condi6=6 or
condi7=7
group by
g1,
g2
原SQL为Select c1,c2,c3 From t1,t2,t3 Where condi1=5 and condi6=6 or condi7=7 Group by g1,g2,g3 order by g2,g3
解析后的SQL为
select
c1,
c2,
c3
from
t1,
t2,
t3
where
condi1=5 and
condi6=6 or
condi7=7
group by
g1,
g2,
g3
order by
g2,
g3

使用的类SqlParser,你可以拷贝下来使用之:

复制代码 代码如下:

package com.sitinspring.common.sqlFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* SQL语句解析器类
* @author: sitinspring(junglesong@gmail.com)
* @date: 2008-3-12
*/
public class SqlParser{
/**
* 逗号
*/
private static final String Comma = ",";
/**
* 四个空格
*/
private static final String FourSpace = " ";
/**
* 是否单行显示字段,表,条件的标识量
*/
private static boolean isSingleLine=true;
/**
* 待解析的SQL语句
*/
private String sql;
/**
* SQL中选择的列
*/
private String cols;
/**
* SQL中查找的表
*/
private String tables;
/**
* 查找条件
*/
private String conditions;
/**
* Group By的字段
*/
private String groupCols;
/**
* Order by的字段
*/
private String orderCols;
/**
* 构造函数
* 功能:传入构造函数,解析成字段,表,条件等
* @param sql:传入的SQL语句
*/
public SqlParser(String sql){
this.sql=sql.trim();
parseCols();
parseTables();
parseConditions();
parseGroupCols();
parseOrderCols();
}
/**
* 解析选择的列
*
*/
private void parseCols(){
String regex="(select)(.+)(from)";
cols=getMatchedString(regex,sql);
}
/**
* 解析选择的表
*
*/
private void parseTables(){
String regex="";
if(isContains(sql,"\\s+where\\s+")){
regex="(from)(.+)(where)";
}
else{
regex="(from)(.+)($)";
}
tables=getMatchedString(regex,sql);
}
/**
* 解析查找条件
*
*/
private void parseConditions(){
String regex="";
if(isContains(sql,"\\s+where\\s+")){
// 包括Where,有条件
if(isContains(sql,"group\\s+by")){
// 条件在where和group by之间
regex="(where)(.+)(group\\s+by)";
}
else if(isContains(sql,"order\\s+by")){
// 条件在where和order by之间
regex="(where)(.+)(order\\s+by)";
}
else{
// 条件在where到字符串末尾
regex="(where)(.+)($)";
}
}
else{
// 不包括where则条件无从谈起,返回即可
return;
}
conditions=getMatchedString(regex,sql);
}
/**
* 解析GroupBy的字段
*
*/
private void parseGroupCols(){
String regex="";
if(isContains(sql,"group\\s+by")){
// 包括GroupBy,有分组字段
if(isContains(sql,"order\\s+by")){
// group by 后有order by
regex="(group\\s+by)(.+)(order\\s+by)";
}
else{
// group by 后无order by
regex="(group\\s+by)(.+)($)";
}
}
else{
// 不包括GroupBy则分组字段无从谈起,返回即可
return;
}
groupCols=getMatchedString(regex,sql);
}
/**
* 解析OrderBy的字段
*
*/
private void parseOrderCols(){
String regex="";
if(isContains(sql,"order\\s+by")){
// 包括GroupBy,有分组字段
regex="(order\\s+by)(.+)($)";
}
else{
// 不包括GroupBy则分组字段无从谈起,返回即可
return;
}
orderCols=getMatchedString(regex,sql);
}
/**
* 从文本text中找到regex首次匹配的字符串,不区分大小写
* @param regex: 正则表达式
* @param text:欲查找的字符串
* @return regex首次匹配的字符串,如未匹配返回空
*/
private static String getMatchedString(String regex,String text){
Pattern pattern=Pattern.compile(regex,Pattern.CASE_INSENSITIVE);
Matcher matcher=pattern.matcher(text);
while(matcher.find()){
return matcher.group(2);
}
return null;
}
/**
* 看word是否在lineText中存在,支持正则表达式
* @param lineText
* @param word
* @return
*/
private static boolean isContains(String lineText,String word){
Pattern pattern=Pattern.compile(word,Pattern.CASE_INSENSITIVE);
Matcher matcher=pattern.matcher(lineText);
return matcher.find();
}
public String toString(){
// 无法解析则原样返回
if(cols==null && tables==null && conditions==null && groupCols==null && orderCols==null ){
return sql;
}
StringBuffer sb=new StringBuffer();
sb.append("原SQL为"+sql+"\n");
sb.append("解析后的SQL为\n");
for(String str:getParsedSqlList()){
sb.append(str);
}
sb.append("\n");
return sb.toString();
}
/**
* 在分隔符后加上回车
* @param str
* @param splitStr
* @return
*/
private static String getAddEnterStr(String str,String splitStr){
Pattern p = Pattern.compile(splitStr,Pattern.CASE_INSENSITIVE);
// 用Pattern类的matcher()方法生成一个Matcher对象
Matcher m = p.matcher(str);
StringBuffer sb = new StringBuffer();
// 使用find()方法查找第一个匹配的对象
boolean result = m.find();
// 使用循环找出模式匹配的内容替换之,再将内容加到sb里
while (result) {
m.appendReplacement(sb, m.group(0) + "\n ");
result = m.find();
}
// 最后调用appendTail()方法将最后一次匹配后的剩余字符串加到sb里;
m.appendTail(sb);
return FourSpace+sb.toString();
}
/**
* 取得解析的SQL字符串列表
* @return
*/
public List<String> getParsedSqlList(){
List<String> sqlList=new ArrayList<String>();
// 无法解析则原样返回
if(cols==null && tables==null && conditions==null && groupCols==null && orderCols==null ){
sqlList.add(sql);
return sqlList;
}
if(cols!=null){
sqlList.add("select\n");
if(isSingleLine){
sqlList.add(getAddEnterStr(cols,Comma));
}
else{
sqlList.add(FourSpace+cols);
}
}
if(tables!=null){
sqlList.add(" \nfrom\n");
if(isSingleLine){
sqlList.add(getAddEnterStr(tables,Comma));
}
else{
sqlList.add(FourSpace+tables);
}
}
if(conditions!=null){
sqlList.add(" \nwhere\n");
if(isSingleLine){
sqlList.add(getAddEnterStr(conditions,"(and|or)"));
}
else{
sqlList.add(FourSpace+conditions);
}
}
if(groupCols!=null){
sqlList.add(" \ngroup by\n");
if(isSingleLine){
sqlList.add(getAddEnterStr(groupCols,Comma));
}
else{
sqlList.add(FourSpace+groupCols);
}
}
if(orderCols!=null){
sqlList.add(" \norder by\n");
if(isSingleLine){
sqlList.add(getAddEnterStr(orderCols,Comma));
}
else{
sqlList.add(FourSpace+orderCols);
}
}
return sqlList;
}
/**
* 设置是否单行显示表,字段,条件等
* @param isSingleLine
*/
public static void setSingleLine(boolean isSingleLine) {
SqlParser.isSingleLine = isSingleLine;
}
/**
* 测试
* @param args
*/
public static void main(String[] args){
List<String> ls=new ArrayList<String>();
ls.add("select * from dual");
ls.add("SELECT * frOm dual");
ls.add("Select C1,c2 From tb");
ls.add("select c1,c2 from tb");
ls.add("select count(*) from t1");
ls.add("select c1,c2,c3 from t1 where condi1=1 ");
ls.add("Select c1,c2,c3 From t1 Where condi1=1 ");
ls.add("select c1,c2,c3 from t1,t2 where condi3=3 or condi4=5 order by o1,o2");
ls.add("Select c1,c2,c3 from t1,t2 Where condi3=3 or condi4=5 Order by o1,o2");
ls.add("select c1,c2,c3 from t1,t2,t3 where condi1=5 and condi6=6 or condi7=7 group by g1,g2");
ls.add("Select c1,c2,c3 From t1,t2,t3 Where condi1=5 and condi6=6 or condi7=7 Group by g1,g2");
ls.add("Select c1,c2,c3 From t1,t2,t3 Where condi1=5 and condi6=6 or condi7=7 Group by g1,g2,g3 order by g2,g3");
for(String sql:ls){
System.out.println(new SqlParser(sql));
//System.out.println(sql);
}
}
}

时间: 2024-08-01 18:28:48

SqlParser 一个利用正则表达式解析单句SQL的类_正则表达式的相关文章

SqlParser 一个利用正则表达式解析单句SQL的类

先看要解析的样例SQL语句: 复制代码 代码如下: select * from dual SELECT * frOm dual Select C1,c2 From tb select c1,c2 from tb select count(*) from t1 select c1,c2,c3 from t1 where condi1=1 Select c1,c2,c3 From t1 Where condi1=1 select c1,c2,c3 from t1,t2 where condi3=3

正则表达式中\w不能识别中文_正则表达式

正则表达式用于字符串处理,表单验证等场合,实用高效,但用到时总是不太把握,以致往往要上网查一番.我将一些常用的表达式收藏在这里,作备忘之用.本贴随时会更新. 匹配中文字符的正则表达式: [\u4e00-\u9fa5] 匹配双字节字符(包括汉字在内):[^\x00-\xff] 应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1) String.prototype.len=function(){return this.replace([^\x00-\xff]/g,"aa")

正则表达式零宽断言详解_正则表达式

正则表达式零宽断言: 零宽断言是正则表达式中的难点,所以本章节重点从匹配原理方面进行一下分析.零宽断言还有其他的名称,例如"环视"或者"预搜索"等等,不过这些都不是我们关注的重点. 一.基本概念: 零宽断言正如它的名字一样,是一种零宽度的匹配,它匹配到的内容不会保存到匹配结果中去,最终匹配结果只是一个位置而已. 作用是给指定位置添加一个限定条件,用来规定此位置之前或者之后的字符必须满足限定条件才能使正则中的字表达式匹配成功. 注意:这里所说的子表达式并非只有用小括号

正则表达式详细介绍(下)_正则表达式

本文是前一片文章<正则表达式详细介绍(上)>的续篇,在本文中讲述了正则表达式中的组与向后引用,先前向后查看,条件测试,单词边界,选择符等表达式及例子,并分析了正则引擎在执行匹配时的内部机理. 9. 单词边界 元字符<<\b>>也是一种对位置进行匹配的"锚".这种匹配是0长度匹配. 有4种位置被认为是"单词边界": 1) 在字符串的第一个字符前的位置(如果字符串的第一个字符是一个"单词字符") 2) 在字符串的最

[php]正则表达式的五个成功习惯_正则表达式

正则表达式难于书写.难于阅读.难于维护,经常错误匹配意料不到的文本或者错过了有效的文本,这些问题都是由正则表达式的表现和能力引起的.每个元字符(metacharacter)的能力和细微差别组合在一起,使得代码不借助于智力技巧就无法解释.       许多包含一定特性的工具使阅读和编写正则表达式变得容易了,但是它们又很不符合习惯.对于很多程序员来说,书写正则表达式就是一种魔法艺术.他们坚持自己所知道的特征并持有绝对乐观的态度.如果你愿意采用本文所探讨的五个习惯,你将可以让你设计的正则表达式经受的住

正则表达式查找相似单词的方法_正则表达式

本文通过展示各种不同的正则表达式结构,以及在实际应用中会用到的技巧,熟悉掌握正则表达式的应用. 问题描述: 在这个实例中你要解决如下几个问题. 1.想要在一个字符串中找到所有的color和colour. 2.想要找到这3个以"at"结尾的单词中的任意一个:bat.cat或rat. 3.想要找到以phobia结尾的单词. 4.想要找的名字"Steven"的常见变形:Steve.Steven和Stephen. 5.想要匹配术语"regular expressi

PHP正则表达式完全教程之基础篇_正则表达式

目前,正则表达式已经在很多软件中得到广泛的应用,包括*nix(Linux, Unix等),HP等操作系统,PHP,C#,Java等开发环境,以及很多的应用软件中,都可以看到正则表达式的影子. 正则表达式的使用,可以通过简单的办法来实现强大的功能. 为了简单有效而又不失强大,造成了正则表达式代码的难度较大,学习起来也不是很容易. 例子: ^.+@.+..+$ 这样的代码曾经多次把我自己给吓退过.可能很多人也是被这样的代码给吓跑的吧. 学习完本教程将让你也可以自由应用这样的代码. 正则表达式的历史

JavaScript正则表达式上之基本语法(推荐)_正则表达式

相关阅读: js正则表达式基本语法(精粹) 正则表达式语法 一个正则表达式就是由普通字符(例如字符 a 到 z)以及特殊字符(称为元字符)组成的文字模式.该模式描述在查找文字主体时待匹配的一个或多个字符串.正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配. 定义 JavaScript种正则表达式有两种定义方式,定义一个匹配类似 <%XXX%> 的字符串 1. 构造函数 复制代码 代码如下: var reg=new RegExp('<%[^%>]+%>','g')

正则表达式详细介绍(上)_正则表达式

本文是Jan Goyvaerts为RegexBuddy写的教程的译文,下面来看吧! 1. 什么是正则表达式 基本说来,正则表达式是一种用来描述一定数量文本的模式.Regex代表Regular Express.本文将用<<regex>>来表示一段具体的正则表达式. 一段文本就是最基本的模式,简单的匹配相同的文本. 2. 不同的正则表达式引擎 正则表达式引擎是一种可以处理正则表达式的软件.通常,引擎是更大的应用程序的一部分.在软件世界,不同的正则表达式并不互相兼容.本教程会集中讨论Pe