如何在java中实现“取代”

时间:2010-12-02 19:57:31

标签: java regex substitution

“supplant()对字符串执行变量替换。它扫描字符串,查找{}括号中包含的表达式。如果找到表达式,则将其用作对象上的键,如果键有字符串值或数值,它代替括号表达式并重复。“

更具体地说,我想尝试做一些事情:

public static String supplant(CharSequence message, Map<String,Object> params)

我正在尝试使用像\ {([\ w] *)\}这样的正则表达式捕获变量,然后查找地图并替换,但我无法编写匹配的正则表达式...

你将如何在java中实现supplant()?

2 个答案:

答案 0 :(得分:2)

是否需要使用这种确切的格式? Java已经有了将变量替换为字符串的内置方法。

请参阅:

答案 1 :(得分:1)

您所描述的内容通常称为模板。有许多模板应用程序和库,但如果你只想要一个快速而肮脏的解决方案,它可以很容易地用正则表达式实现。

在许多正则表达式中,您将使用内置的回调标注机制,如PHP的preg_replace_callback函数或Perl的/e/ee修饰符。 Java没有这样的东西,但是它提供了API来让你自己实现它。这是一个例子:

import java.util.*;
import java.util.regex.*;

public class Test
{
  public static void main(String[] args) throws Exception
  {
    String s = "Lorem ipsum {foo} impedit civibus ei pri, legimus\n" +
        "antiopam no {marco}, quo id everti forensibus maiestatis.";
    Map<String,Object> p = new HashMap<String,Object>()
    {{
      put("foo", "BAR");
      put("marco", "POLO!");
    }};
    System.out.printf("%s%n%n%s%n", s, supplant(s, p));
  }

  public static CharSequence supplant(CharSequence message, Map<String,Object> params)
  {
    Matcher m = Pattern.compile("\\{(\\w+)\\}").matcher(message);
    StringBuffer sb = new StringBuffer();
    while (m.find())
    {
      m.appendReplacement(sb, "");
      String key = m.group(1);
      sb.append(params.get(key).toString());
    }
    m.appendTail(sb);
    return sb.toString();
  }
}

显然,这段代码省略了一些基本组件(主要是异常处理),但它展示了这种技术的要点:

  1. 使用括号捕获大括号内的内容,然后通过调用匹配器上的group(1)来访问它。
  2. 使用appendReplacement(sb, "")附加上一场比赛(如果有的话)和当前比赛之间出现的任何文字。
  3. 查找替换并使用StringBuffer的append()方法附加它。 (你可以通过将替换字符串作为第二个参数传递给appendReplacement()来组合步骤2和3,但是你必须注意字符串中的美元符号和反斜杠,特殊待遇。这种方式更简单。)
  4. 使用appendTail(sb)附加最后一场比赛后剩余的内容。
  5. 有些人已经发布了帮助程序类,可以让您完成这类任务,而无需编写所有样板代码。我最喜欢的是Elliott Hughes的Rewriter