在Java中,如果没有正则表达式,如何只替换字符串一次?
我需要用更大的字符串替换动态子字符串,但只能替换一次(即第一次匹配)。String类仅提供替换子字符串的所有实例的在Java中,如果没有正则表达式,如何只替换字符串一次?,java,string,Java,String,我需要用更大的字符串替换动态子字符串,但只能替换一次(即第一次匹配)。String类仅提供替换子字符串的所有实例的replace();有一个replaceFirst()方法,但它只接受regexp而不是常规字符串。我对使用regex有两个顾虑: 1) 我的子字符串是动态的,所以可能包含在正则表达式中表示其他内容的奇怪字符,我不想处理字符转义 2) 这种替换经常发生,我不确定使用regex是否会影响性能。我不能事先编译正则表达式,因为正则表达式本身是动态的 我一定是错过了什么,因为在我看来这是一件
replace()
;有一个replaceFirst()
方法,但它只接受regexp而不是常规字符串。我对使用regex有两个顾虑:
1) 我的子字符串是动态的,所以可能包含在正则表达式中表示其他内容的奇怪字符,我不想处理字符转义
2) 这种替换经常发生,我不确定使用regex是否会影响性能。我不能事先编译正则表达式,因为正则表达式本身是动态的
我一定是错过了什么,因为在我看来这是一件非常基本的事情。。。java franework中是否有replaceFirst方法在其他地方使用正则字符串?使用
bigString.indexof(smallString)
获取大字符串中第一次出现的小字符串的索引(如果没有,则为-1,这样就完成了)。然后,使用<代码> BigString。子字符串< /代码>获得匹配之前和之后的大字符串的片段,最后<代码> CONTACA/COD>将之前和之后的部分放在一起,用你想要的替换在中间。 < P>如劳伦斯建议的,你可以使用<代码>模式。
newString = string.replaceFirst(Pattern.quote(substring),
Matcher.quoteReplacement(replacement));
newString = Pattern.compile(substring, Pattern.LITERAL).
matcher(string).replaceFirst(Matcher.quoteReplacement(replacement));
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
quote
创建一个与子字符串完全匹配的正则表达式,quoteReplacement
创建一个文字替换字符串
另一种方法是将子字符串编译为文本正则表达式,如下所示:
newString = string.replaceFirst(Pattern.quote(substring),
Matcher.quoteReplacement(replacement));
newString = Pattern.compile(substring, Pattern.LITERAL).
matcher(string).replaceFirst(Matcher.quoteReplacement(replacement));
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
这可能会稍微有效一些,但也不太清楚
您也可以手动执行,因为您只想替换第一个事件。但是正则表达式非常有效,所以不要过早地进行优化 为了编写自己的代码,您应该使用已经测试过且文档完整的库
StringUtils.replaceOnce("aba", "a", "") = "ba"
StringUtils
类来自包,可以像这样在Maven中导入:
newString = string.replaceFirst(Pattern.quote(substring),
Matcher.quoteReplacement(replacement));
newString = Pattern.compile(substring, Pattern.LITERAL).
matcher(string).replaceFirst(Matcher.quoteReplacement(replacement));
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
org.apache.commons
commons-lang3
3.8.1
确保在更换中也更换\s
和$s
。这可能是您想要的,因为您的(
)无法删除任何子组
Pattern.quote似乎并非在所有情况下都有效。试试'Pattern.quote(“:-”) java中的StringBuilder类可以很容易地用于用一个字符串替换另一个字符串,而不是基于正则表达式
private static String replace(String in, String ths, String that) {
StringBuilder sb = new StringBuilder(in);
int idx = sb.indexOf(ths);
while (idx > -1) {
sb.replace(idx, idx + ths.length(), that);
idx = sb.indexOf(ths);
}
return sb.toString();
}
具有模式的解决方案
您还可以更改使用字符的文字解释的方法,以仅替换目标
字符序列的第一次出现:
/**
* Replaces the first subsequence of the <tt>source</tt> character sequence
* that matches the literal target sequence with the specified literal
* replacement sequence.
*
* @param source source sequence on which the replacement is made
* @param target the sequence of char values to be replaced
* @param replacement the replacement sequence of char values
* @return the resulting string
*/
private static String replaceFirst1(CharSequence source, CharSequence target, CharSequence replacement) {
return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
source).replaceFirst(Matcher.quoteReplacement(replacement.toString()));
}
时间测量 基于10次运行,
replaceFirst2
方法的执行速度大约是replaceFirst1
方法的5倍。我将这两种方法放在一个循环中,重复次数为100.000次,并以毫秒为单位得到以下结果:
Method Results (in ms) Average
replaceFirst1: 220 187 249 186 199 211 172 199 281 199 | 210
replaceFirst2: 40 39 58 45 48 40 42 42 43 59 | 45
方法结果(单位:ms)平均值
替换优先1:220 187 249 186 199 211 172 199 281 199 | 210
replaceFirst2:40 39 58 45 48 40 42 42 43 59 | 45amen-这个答案展示了软件开发的一个关键原则:仅仅因为你有一个工具,并不意味着你必须使用它。我不能告诉你们有多少次我看到中级程序员对列表进行排序以找到最小的元素。这是一个很好的评论。但是请注意,这种手动方法需要几行代码,这可能需要注释和单元测试来避免bug。使用单行“replaceFirst”调用更清晰,更不容易出错,即使在运行时也可能较慢。不要过早地优化。我很惊讶没有一个简单的库函数来编码上面提到的复杂算法!例如,请参见(python):您的第二个问题可能是正确的,但对于第一个问题,您可以使用Pattern.quote来构造一个与给定字符串完全匹配的正则表达式。也就是说,它将为你处理逃跑问题。这将更适合作为对劳伦特·冈萨尔维斯关于这个问题或班纳特·麦克尔韦的回答的评论,而不是作为一个单独的回答,因为你没有回答这个问题本身。你在这里有一个很好的观点,但你没有直接回答这个问题。作为对Bennet McElwee答案的评论更合适。您建议包含一个完整的库,用于简单的字符串替换。你觉得值得吗?忘记它是否存在;It’值不值得。。仅仅为了一个简单的功能,我就必须去一个新的库,这不是很奇怪吗?这没有提到替换也需要被引用。@Clashsoft Good point(其他人也提出)-我已经更新了答案。这与
String.replace一样,即更换所有occurrences@Clashsoft将替换为而将循环替换为如果
条件,则只替换第一次出现的循环。