使用Java的replaceAll替换整个字符串

时间:2014-10-07 16:16:27

标签: java regex replaceall

我正在尝试使用以下代码来替换整个字符串:

代码: String a = "Hello"; String b = a.replaceAll("(?s).*", "US"); 输出:

USUS

问题: 为什么字符串" US"重复了两次? 如何使用replaceAll函数替换整个字符串,使用正则表达式?

为什么我需要这样做: 我需要使用其中给出的值来获取json文件中指定的替换模式。在这个模型中,我想给用户独立(json configurer)来定义一个模式,这样整个字符串就可以被替换,而不需要对字符串替换的特殊处理进行编码。

2 个答案:

答案 0 :(得分:3)

这是因为Matcher类处理可能与空字符串匹配的模式。 replaceAll String方法的定义方式与replaceAll Matcher方法的工作方式相同,其工作原理如下:

  

此方法首先重置此匹配器。然后它扫描输入   序列寻找模式的匹配。不是的字符   匹配的一部分直接附加到结果字符串;该   匹配由替换字符串替换为结果。该   替换字符串可能包含对捕获的子序列的引用   在appendReplacement方法中。

当匹配器尝试查找模式时,如果源中的子序列是空字符串,则匹配器返回空字符串,但然后将当前索引加上1,这样它就不会返回空的无限循环字符串。所以这是它在"Hello"上的运作方式:

1)匹配器查找.*。由于这是一个贪婪的匹配,匹配尽可能多的字符,它将找到子字符串"Hello",并使用它,将其替换为"US"。然后将当前索引定位在'o'之后。

2)匹配器再次查找.*。由于它位于输入的末尾,但允许模式匹配空字符串,因此它匹配空字符串并将其替换为另一个"US"。但随后它突破了目前的指数,目前该指数处于源头结束时的位置。

3)匹配器再次查找.*,但由于当前索引超过了源的末尾,因此找不到任何内容。

要了解其运作方式,请尝试使用".*?"作为模式。现在,匹配器总是使用空字符串,因为?告诉它使用最短的字符串。每次找到空字符串时,它还会将当前索引增加1。结果:

a.replaceAll("(?s).*?", ".-")  //returns
".-H.-e.-l.-l.-o.-"

也就是说,它用".-"替换每对字符之间的所有空字符串,并保留实际字符。

道德:要非常小心可以匹配空字符串的模式。

更多:在阅读您的评论后,您指出该模式可以由用户输入,我认为您可以将其用作测试,以查看该模式是否可以匹配空字符串:

if ("".matches(inputPattern)) {
    // ???
}

我不确定你用它做什么。也许情况总是如此,如果这是真的,您的replaceAll会在最后添加额外的US,您可以安全地将其删除。或许你可以告诉他们尝试不同的模式。

PPS。我不确定匹配器的这种行为(即当匹配为空字符串时将当前索引增加1)的位置。我没有在Matcher javadoc中看到它。我想这意味着JRE的未来版本可能会有不同的表现,尽管这似乎不太可能。

答案 1 :(得分:1)

因为.*可以匹配空字符串。所以第一个匹配是所有字符串(从开始),第二个是空字符串(从最后一个字符后面的字符串的最后一个位置)

您可以使用+量词而不是*来避免此行为。但它不会取代空字符串。