繁体   English   中英

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

[英]Using Java's replaceAll to replace the whole string

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

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

USUS

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

为什么需要这样做:我需要使用在其中提供的值来选择json文件中指定的替换模式。 在此模型中,我想赋予用户(json configurer)独立性以定义一种模式,以便可以替换整个字符串,而无需编写特殊的字符串替换处理代码。

这是因为Matcher类如何处理可能与空字符串匹配的模式。 StringreplaceAll方法被定义为与MatcherreplaceAll方法以相同的方式工作,如下所示:

此方法首先重置此匹配器。 然后,它扫描输入序列以查找模式匹配。 不属于匹配项的字符将直接附加到结果字符串中; 匹配项将在结果中替换为替换字符串。 替换字符串可能包含对捕获的子序列的引用,如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版本可能会表现不同,尽管这似乎不太可能。

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

您可以使用+量词代替*来避免这种现象。 但是它不会替换空字符串。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM