最近工作需要,要截取一个sql中某个函数,刚好这个函数有括号,将此函数截掉,写了个匹配括号的程序,主要是基于字符串的索引写的
package com.cai.test; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author * * 2016年8月21日 */ public class Bracket { public static void main(String[] args) { Bracket bracket = new Bracket(); String sql = "SELECT Flt_Dpt_Dt" + " ,CASE WHEN Lane_Area IN ('港澳','台湾' ) THEN '港澳台' " + " ELSE Lane_Area " + " END AS Flt_Duty_Area " + " ,SUM (Total_Cap_Qty*Seg_Distance) AS ASK " + " FROM " + " (SELECT *" + " FROM PV_MART.ITM_FLIGHT_BASE T1" + " WHERE Lane_Type = '国际'" + " AND Leg_Ind <>'N'" + " AND (Flt_Dpt_Dt >=DATE '2014-01-01')" + " QUALIFY ROW_NUMBER() OVER(PARTITION BY Carrier_Cd,Flt_Dpt_Dt,Flt_Nbr,Lane_Area,Orig_Airport_Cd,Dest_Airport_Cd ORDER BY Dcp_Dt ) =1) T1 GROUP BY 1,2"; sql = bracket.formatStrBackspace(sql.replaceAll("QUALIFY ROW_NUMBER\\(\\)", "")); int index = sql.indexOf("OVER(") + 4; //System.out.println(index); String str = "(()()((()())))"; Map<Integer, Integer> bracketIndex = bracket.bracketIndex(sql); // System.out.println(bracketIndex); System.out.println(sql.substring(index-4, bracketIndex.get(index)+1)); } /** * 对字符串的括号进行配对 * 将字符的左括号和右括号索引进行存储,然后遇见右括号取出 * 步骤: * 将字符串先进行格式化,多个空格的用单个空格替换 * 根据括号规则分析可知:(()(()())) * 先取内部括号,后取外部括号 * @param str 字符创 * @param s 匹配的字符 */ public Map<Integer, Integer> bracketIndex(String str) { Map<Integer, Integer> indexMap = new HashMap<Integer, Integer>(); List<Integer> leftList = new ArrayList<Integer>(); List<Integer> rightList = new ArrayList<Integer>(); str = formatStrBackspace(str); char[] chs = str.toCharArray(); for (int i=0;i<chs.length;i++) { if(chs[i] == '(') { leftList.add(i); } else if(chs[i] == ')') { rightList.add(i); } } //42, 107, 150, 237, 288, 295 53, 134, 268, 289, 397, 401 一次后的结果为 150 if(leftList.size() == rightList.size()) { int size = leftList.size(); //取出内部括号匹配索引,一对括号的右括号必定在前后两个左括号中间 outter:for(int j=0;j<size;) { inner:for (int i=0;i<size;i++) { if(i+1<size) { if(rightList.get(j) > leftList.get(i) && rightList.get(j) < leftList.get(i+1)) { indexMap.put(leftList.get(i), rightList.get(j)); leftList.remove(i); rightList.remove(j); size--; break inner; } } else { break outter; } } } //最后剩余的括号则为外括号,里外对应即可 if(size > 0) { for(int i=0;i<size;i++) { indexMap.put(leftList.get(i), rightList.get(size-(i+1))); } } } return indexMap;//288=289, 237=268, 295=397, 42=53, 107=134, 150=401 } public String formatStrBackspace(String str) { return str.replaceAll(" +", " "); } }
如果有更好的方法,请提出好的意见。