【问题标题】:How to replace multiple occurrence of same regex pattern in a String with different values in Java如何用Java中的不同值替换字符串中多次出现的相同正则表达式模式
【发布时间】:2021-08-24 07:46:42
【问题描述】:

考虑如下示例:

String string = "Hi$?Hello$?"。 在字符串对象中的“$?”是正则表达式模式。 第一次出现 $?必须替换为“那里”和第二次出现的 $?必须替换为“世界”。

如何使用 Java 实现相同的功能?或者 Apache commons StringUtils 中是否有任何方法可以实现相同的功能?

【问题讨论】:

  • 问题是$? 不是一个正则表达式模式。实际上是什么模式,两种模式都一样吗?
  • 我们也可以将模式更改为其他有效的正则表达式模式。但是,如何在多个地方用不同的值替换该模式?
  • 好吧,您没有回答它们是否是相同的值。在我看来,它们可能是占位符而不是模式

标签: java string replace apache-stringutils


【解决方案1】:

这是使用正式 Java 模式匹配器的一般方法。我们可以将替换字符串项存储在一个列表中,然后在\$ 上迭代匹配的输入字符串。对于每场比赛,我们可以用一个替换项目替换。

String string = "Hi$?Hello$?";
StringBuffer sb = new StringBuffer();
List<String> replacements = Arrays.asList(new String[] {"there", "world"});
Pattern r = Pattern.compile("\\$");
Matcher m = r.matcher(string);
int counter = 0;

while (m.find()) {
    m.appendReplacement(sb, replacements.get(counter++));
}
m.appendTail(sb);
System.out.println(sb.toString());  // Hithere?Helloworld?

【讨论】:

    【解决方案2】:

    如果您只需要顺序替换搜索字符串中的某些占位符字符串,您可以使用Apache StringUtils

    String string = "Hi$?Hello$?";
    String placeHolder = "$?";
    String[] replacements = {"there", "world"};
    for (String replacement : replacements) {
        string = StringUtils.replaceOnce(string, placeHolder, replacement);
    }
    System.out.println(string);
    

    前提是事先知道序列并且保证存在占位符。

    【讨论】:

    • 是否可以作为值数组传递并在一行中替换相同的值?
    • 你可以在数组的循环中调用replaceOnce
    • @Vishal:查看编辑后的答案,找到了一种方法来做到这一点
    • 由于两个地方的占位符相同 ($?),因此将替换相同的值。结果是“HithereHellothere”而不是“HithereHelloworld”
    • @Vishal,你是对的。所以循环替换数组并调用 replaceOnce() 似乎是不可避免的
    【解决方案3】:

    我认为您不应该专注于某些replaceString 方法,因为在每次迭代中您都会收到一个新字符串。这效率不高。

    你为什么不用StringBuilder

    public static String replaceRegexp(String str, String placeHolder, String... words) {
        int expectedLength = str.length() - placeHolder.length() * words.length + Arrays.stream(words).mapToInt(String::length).sum();
        StringBuilder buf = new StringBuilder(expectedLength);
        int prv = 0;
        int i = 0;
        int pos;
    
        while ((pos = str.indexOf(placeHolder, prv)) != -1 && i < words.length) {
            buf.append(str.substring(prv, pos));
            buf.append(words[i++]);
            prv = pos + placeHolder.length();
        }
    
        return buf.append(str.substring(prv)).toString();
    }
    

    【讨论】:

    • 仅供参考,StringUtils.replaceEach 正在使用 StringBuilder
    • @SharonBenAsher 是的,我忘了这个。
    【解决方案4】:

    我推荐第三种解决方案。

    试试这个。

    public static void main(String[] args) {
        String string = "Hi$?Hello$?";
        String[] rep = {"there", "world"};
        String output = string.replaceFirst(
            "\\$\\?(.*)\\$\\?", rep[0] + "$1" + rep[1]);
        System.out.println(output);
    }
    

    输出:

    HithereHelloworld
    

    或者

    static final Pattern PAT = Pattern.compile("\\$\\?");
    
    public static void main(String[] args) {
        String string = "Hi$?Hello$?";
        String[] rep = {"there", "world"};
        int[] i = {0};
        String output = PAT.matcher(string).replaceAll(m -> rep[i[0]++]);
        System.out.println(output);
    }
    

    或者

    static final Pattern PAT = Pattern.compile("\\$\\?");
    
    public static void main(String[] args) {
        String string = "Hi$?Hello$?";
        List<String> rep = List.of("there", "world");
        Iterator<String> iter = rep.iterator();
        String output = PAT.matcher(string).replaceAll(m -> iter.next());
        System.out.println(output);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-27
      • 2017-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多