2

"supplant() 对字符串进行变量替换。它扫描字符串以查找括在 { } 大括号中的表达式。如果找到表达式,则将其用作对象上的键,并且该键是否具有字符串值或数字值,它被替换为括号表达式并重复。”

更具体地说,我正在尝试做一些类似的事情:

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

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

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

4

2 回答 2

2

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

看:

于 2010-12-02T20:03:29.133 回答
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)Matcher 来访问它。
  2. 用于appendReplacement(sb, "")附加上一个匹配项(如果有)和当前匹配项之间出现的任何文本。
  3. 查找替换并使用 StringBuffer 的append()方法附加它。(您可以通过将替换字符串作为第二个参数传递给 来组合步骤 2 和 3 appendReplacement(),但是您必须注意字符串中的美元符号和反斜杠,它们会受到特殊处理。这种方式要简单得多。)
  4. 用于appendTail(sb)附加最后一场比赛后剩下的任何内容。

有几个人发布了帮助类,让您无需编写所有样板代码即可完成此类任务。我最喜欢的是 Elliott Hughes 的Rewriter

于 2010-12-02T21:42:29.010 回答