我们在很多地方都能看到代表参数意义的符号${},可能我们在写一些框架的时候,有时候也需要用到这个符号,但他们是如何精确解析的?或者说需要我们自已写的时候,如何写?我们先来看以下的几个场景:
1.字符串"a${a}a"
2.字符串"a\${a}a"
3.字符串"a${a\}a"
4.字符串"a${a\}a}a"
5.字符串"a${a}a${"
6.字符串"a${a}a${a}"
以上几个字符串中,只有1,4,6的是有意义的,所以我们在解析的时候,要把各种情况都考虑清楚,尽量的做到全面,这样我们的框架才有意义。
很显然,我们都会采用正则来解析,于是我们来新建一个JAVA正则的类:
public class RegExp {
public boolean match(String reg, String str) {
return Pattern.matches(reg, str);
}
public List find(String reg, String str) {
Matcher matcher = Pattern.compile(reg).matcher(str);
List list = new ArrayList();
while (matcher.find()) {
list.add(matcher.group());
}
return list;
}
public List find(String reg, String str, int index) {
Matcher matcher = Pattern.compile(reg).matcher(str);
List list = new ArrayList();
while (matcher.find()) {
list.add(matcher.group(index));
}
return list;
}
public String findString(String reg, String str, int index) {
String returnStr = null;
List list = this.find(reg, str, index);
if (list.size() != 0)
returnStr = list.get(0);
return returnStr;
}
public String findString(String reg, String str) {
String returnStr = null;
List list = this.find(reg, str);
if (list.size() != 0)
returnStr = list.get(0);
return returnStr;
}
public static void main(String[] args) {
RegExp re = new RegExp();
System.out.println(re.find("(a)b", "ababab", 1));
}
}
对于一个字符串,我们得先判断一下是否存在参数化的符号:
private boolean hadSubParameter(String p){
return p.matches(".*(?
}
注:这个正则".*(?
如果存在,则我们还要判断一下字符串中的参数化符号是否合法,也就是说是否完整:
private boolean isValidSubParameter(String p){
return p.matches(".*((?
}
注:这个正则".*((?
合法后,最后就是替换了:
private String getRealValue(String key){
if(ConstantUtil.INT_PARAMS.containsKey(key)){
return ConstantUtil.INT_PARAMS.get(key);
}
if(ConstantUtil.EXT_PARAMS.containsKey(key)){
return ConstantUtil.EXT_PARAMS.get(key);
}
throw new RuntimeException("The parameter: "+key+" had not been defined.");
}
private String getSubParameter(String p){
String reg = "(?
while(this.hadSubParameter(p)){
p = p.replaceFirst(reg, this.getRealValue(re.findString(reg, p, 1)));
}
return p;
}
注:其中ConstantUtil.INT_PARAMS与ConstantUtil.EXT_PARAMS就是两个hashmap。
这样就能返回出其参数符号中的变量对应的具体的值了。
还有一种场景:
字符串"a${a,b}a\,${a},${a}"
希望以,分割,如上面这个字符串,就是两个参数"a${a,b}a\,${a}","${a}",但如果单纯的以,分割的话,会分割出四个子字符串出来,还好的是split支持正则,但也会分割出三个子字符串来"a${a","b}a\,${a}","${a}",
解决办法是,先分割出三个来,然后再循环的判断一下当前这个子字符串是不是合法的,就是上面的isValidSubParameter方法,如果不合法,则相邻的两个相加,一直到合法为止,这样就能解决这个问题了,代码如下:
public List getParameter(){
List list = new ArrayList();
if(param.trim().equals("")){
return list;
}
String[] ps = param.split("(?
StringBuffer sb = new StringBuffer();
for (int i = 0; i <= ps.length; i++) {
if(sb.length()!=0){
if(this.hadSubParameter(sb.toString()) && this.isValidSubParameter(sb.toString())){
list.add(this.getSubParameter(sb.toString()));
sb = new StringBuffer();
}else if(!this.hadSubParameter(sb.toString())){
list.add(sb.toString());
sb = new StringBuffer();
}
}
if(i!=ps.length){
sb.append(ps[i]);
}
}
return list;
}
总结一下:解析这个参数符号,要掌握的主要是正则,其中尤其以预查模式(欢迎访问我的一篇关于预查模式的博客),然后其它的就是一些字符串的操作方法了。
希望能对大家有用。