本文共 2389 字,大约阅读时间需要 7 分钟。
从字符串中解析出 ${****},其中{}中间可能还有大括号。
/*算法1: * 1.寻找${,没找到,直接返回空列表
* 2.找到${,从${中的$所在索引位置向后找第一个}
* 3.在${和其后第一个}的字符串间进行探测,如果存在另外的{,有几个则往后推几个}
* 4.在第一个}和推后的}之间进行探测,如果存在{,有几个把最后的}向后推几个,重复此步,直到中间没有{
* 5.此时${和推后的}即为一个合法的公式区域段
*/
/*算法2:
* 1.按${将字符串分块
* 2.在每个块中执行如下逻辑:把${标记为2,单独的{标记为1,}标记为-1。依次标记
* 3.在每块中按照索引顺序从左向右加,如果标记值之和为1,说明${}是闭合合法的。处理下一个块
*/
/**
* 获取字符串中匹配的宏公式(不支持宏公式嵌套,如${ ${}}形式是不合法的,将忽略左侧的${)
* @param str待匹配字符串
* @return{@link ExressionRange}列表
*/
public static List match$Exprs(String str){
/*算法:
* 1.按${将字符串分块
* 2.在每个块中执行如下逻辑:把${标记为2,单独的{标记为1,}标记为-1。依次标记
* 3.在每块中按照索引顺序从左向右加,如果标记值之和为1,说明${}是闭合合法的。处理下一个块
*/
List ranges = new ArrayList();
if(StringUtils.isEmpty(str)) return ranges;
int offset = 0;
int start = str.indexOf("${",offset);
if(start == -1){
return ranges;
}
List indexMap = new ArrayList();
indexMap.add(new IndexObject(start, 2));
offset = start + 2;
while((start = str.indexOf("${", offset)) != -1){
indexMap.add(new IndexObject(start, 2));
offset = start + 2;
}
for(int i=0,size = indexMap.size();i
int left = indexMap.get(i).index;
int right = i == size-1 ? str.length() : indexMap.get(i+1).index;
int offset2 = left + 2,offset3 = left + 2;
int lk,rk;
while((lk = str.indexOf("{",offset2)) < right && lk != -1){
indexMap.add(new IndexObject(lk, 1));
offset2 = lk + 1;
}
while((rk = str.indexOf("}",offset3)) < right && rk != -1){
indexMap.add(new IndexObject(rk, -1));
offset3 = rk + 1;
}
}
return analysisExpressionRanges(ranges,indexMap,str);
}
/**
* 生成ExpressRange列表
* @param ranges待输出的ExpressRange列表
* @param indexMap索引标志小对象列表
* @param originalStr原始字符串
* @return 解析后的ExpressRange列表
*/
private static List analysisExpressionRanges(List ranges,List indexMap,String originalStr){
Collections.sort(indexMap);
int sum = 0,current$L = -1;
for(IndexObject idx:indexMap){
//每块的第一个标志必定是${
if(idx.ratio == 2){
current$L = idx.index;
}
sum += idx.ratio;
//累加和 = 1 并且本块尚未处理完成
if(sum == 1 && current$L !=-1){
ranges.add(new ExpressionRange(current$L, idx.index + 1, originalStr.substring(current$L, idx.index + 1)));
sum = 0;//清空累加只
current$L = -1;//标记本块处理完成,防止 出现 2+1-1-1 + 1-1 被误记的情况
}
}
return ranges;
}
/**
* 索引标志小对象
* @author wangtengfei
*/
private static class IndexObject implements Comparable{
int index;//当前标志在原字符串中的索引
int ratio;//系数
IndexObject(int index,int ratio){
this.index = index;
this.ratio = ratio;
}
public int compareTo(IndexObject o) {
return index - o.index;
}
}
转载地址:https://blog.csdn.net/weixin_32601635/article/details/114068987 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!