如何在替换之前对replaceAll中的正则表达式部分进行计算?

时间:2012-11-27 13:03:22

标签: java regex format

我有一个字符串:"2E6 3.34e-5 3 4.6"我希望使用replaceAll替换令牌,如:

"((\\-)?[0-9]+(\\.([0-9])+)?)(E|e)((\\-)?[0-9]+(\\.([0-9])+)?)"

(即它们之间带有e或E的两个数字)为等效的正常数字格式(即用"2E6"替换"2000000",用"3.34e-5"替换"0.0000334"

我写道:

value.replaceAll("((\\-)?[0-9]+(\\.([0-9])+)?)(E|e)((\\-)?[0-9]+(\\.([0-9])+)?)", "($1)*10^($6)");

但我想将第一个参数乘以10乘以第二个参数的力量,而不仅仅是这样写。任何想法?

更新

我根据您的建议做了以下事项:

Pattern p = Pattern.compile("((\\-)?[0-9]+(\\.([0-9])+)?)(E|e)((\\-)?[0-9]+(\\.([0-9])+)?)");
Matcher m = p.matcher("2E6 3.34e-5 3 4.6");
StringBuffer sb = new StringBuffer();
while (m.find()) {
    m.appendReplacement(sb, "WHAT HERE??"); // What HERE ??
}
m.appendTail(sb);
System.out.println(sb.toString());

更新

最后,这就是我所达到的目标:

// 32 #'s because this is the highest precision I need in my application
private static NumberFormat formatter = new DecimalFormat("#.################################");

private static String fix(String values) {
    String[] values_array = values.split(" ");
    StringBuilder result = new StringBuilder();
    for(String value:values_array){
        try{
            result.append(formatter.format(new Double(value))).append(" ");
        }catch(NumberFormatException e){ //If not a valid double, copy it as is
            result.append(value).append(" ");
        }
    }
    return result.toString().substring(0, result.toString().length()-1);
}

4 个答案:

答案 0 :(得分:2)

    StringBuffer buffer = new StringBuffer();

    Pattern regex = Pattern.compile("((\\-)?[0-9]+(\\.([0-9])+)?)(E|e)((\\-)?[0-9]+(\\.([0-9])+)?)");
    Matcher matcher = regex.matcher( "2E6 3.34e-5 3 4.6");
    while (matcher.find()) {

      String a = matcher.group(1); //The $1
      String b = matcher.group(6); //The $6
      String repl = null;
      if( a != null && b != null ) { //Check if both exist for this match
                      //Parse, do calculations and convert to string again
          repl = BigDecimal.valueOf( Double.parseDouble( a ) * Math.pow( 10, Double.parseDouble( b ) )).toString();
      }
      else {
          repl = matcher.group(0); //Else return unaffected
      }
      matcher.appendReplacement(buffer, repl);
    }
    matcher.appendTail(buffer);

    System.out.println( buffer.toString());
     //"2000000.0 0.0000334 3 4.6"

答案 1 :(得分:1)

如果您需要将科学数字符号转换为正常形式,则可以使用DecimalFormat

public static void main(String[] args) {
    NumberFormat formatter = new DecimalFormat();

    double num1 = 2E6;
    formatter = new DecimalFormat("##########");
    System.out.println(formatter.format(num1)); 

    double num2 = 3.3e-5;
    formatter = new DecimalFormat("#.##########");
    System.out.println(formatter.format(num2));
}

只需添加逻辑以将初始字符串拆分为spaces并应用上述逻辑。

您可以在DecimalFormat的javadoc上查看有关#(在本例中)的符号的更多信息。

Symbol Location     Localized?  Meaning   
------------------------------------------------------------
#      Number       Yes         Digit, zero shows as absent 

答案 2 :(得分:0)

我认为你无法用replaceAll方法做到这一点。你似乎知道正则表达式,所以我只会指出你正确的方向。试试PatternMatcher课程。通过这种方式,您可以编译正则表达式模式并查找组,例如,在e之后将第一组乘以10乘以组的幂。

答案 3 :(得分:0)

如果你想做的事情比从匹配到替换的逐字复制组更复杂,那么你必须使用find()的{​​{1}}和appendReplacement/appendTail方法做到这一点。 。 javadoc for appendReplacement中有一个很好的例子。

在循环内部,您可以使用Matcher访问匹配的字符串,使用m.group()访问第n个括号组,这样您就可以为输出格式创建合适的m.group(n)你需要然后做一些像

这样的事情
NumberFormat

或使用double val = Double.parseDouble(m.group()); m.appendReplacement(nf.format(val));

String.format

(如果您无法确定您的值是否都可以表示为m.appendReplacement(String.format("%f", val)); ),请使用BigDecimal