1、问题描述
把(1+3*m+s*b+c*v)^3的表达式化简为形如(1+3*m+s*b+c*v)*(1+3*m+s*b+c*v)*(1+3*m+s*b+c*v)的格式。
ps:这个问题是我在别人的博客看到的,最近刚好在自学正则表达式,顺便练练手。
2、思路
2.1、分析
从上面的表达式的形式中可以看出,表达式的展开是根据右上角的数字的个数来实现的。那么这就好办了,我们可以利用正则表达式里面的捕获分组和字符串替换来解决这个问题。这个表达式主要是两部分(1+3*m+s*b+c*v)和3,也就是主角是底数和指数,因此我们可以用两个分组来捕获指数和底数。
2.1.1、正则表达式编写过程
①底数
底数是由数字和运算符组成的,但我们为了简单,我们可以直接用点.来匹配就可以了。
正则表达式中的 . 可以匹配任何一个字符,于是1+3*m+s*b+c*v可以写成.+,表示底数至少需要一个字符。接下来需要匹配小括号,但小括号在正则表达式中是特殊字符,表示分组的意思,所以这边我们需要把小括号转义一下,写成\(\),于是完整的底数部分就可以写成\(.+\)
②指数
指数部分是由正整数组成的,于是我们可以用[0-9]来表示,[0-9]表示匹配一个数字,我们知道指数至少是一个,默认是1。所以我们这个这样写[0-9]+,可以简写为\d+
③指数符号^
^在正则表达式中也是一个特殊字符,表示脱字符。因此我们也需要对它进行转义一下,写成\^
于是完整的正则表达式就变成了\(.+\)\^\d+,但我们需要利用分组来获取我们需要的底数和指数,于是写成(\(.+\))\^(\d+)
2.1.2、代码的实现
第一种方法:利用Matcher的replaceAll()
/** * 解析数学表达式 * @param input * @return */ public static String analyticalExpression1(String input){ Matcher m=Pattern.compile("(\\(.+\\))\\^(\\d+)").matcher(input); int count=0; StringBuilder sb=null; while(m.find()){ sb=new StringBuilder(); count=Integer.parseInt(m.group(2)); for(int i=0;i<count;i++){ sb.append("$1"); sb.append(i<count-1?"*":""); } } return m.replaceAll(sb.toString()); }
第二种方法:利用Matcher的appendReplacement()
/** * 解析正则表达式 * @param input * @return */ public static String analyticalExpression2(String input){ Matcher m=Pattern.compile("(\\(.+\\))\\^(\\d+)").matcher(input); int count=0; StringBuffer result=new StringBuffer(); StringBuilder replacement=null; while(m.find()){ count=Integer.parseInt(m.group(2)); replacement=new StringBuilder(); for(int i=0;i<count;i++){ replacement.append("$1"); replacement.append(i<count-1?"*":""); } m.appendReplacement(result,replacement.toString()); } m.appendTail(result); return result.toString(); }
结果: