tags:

views:

292

answers:

3

I need to replace a dynamic substring withing a larger string, but only once (i.e. first match). The String class provides only replace(), which replaces ALL instances of the substring; there is a replaceFirst() method but it only takes regexp instead of a regular string. I have two concerns with using regex:

1) my substring is dynamic, so might contain weird characters that mean something else in regex, and I don't want deal with character escaping.

2) this replacement happens very often, and I'm not sure whether using regex will impact performance. I can't compile the regex beforehand since the regex itself is dynamic!

I must be missing something here since this seems to me is a very basic thing... Is there a replaceFirst method taking regular string somewhere else in the java franework?


[rant] I have to say I'm surprised that, as the answer confirms, java framework does not offer such a basic method; sure it's easy to cook one up, but really? [/rant]

+7  A: 

Use bigString.indexof(smallString) to get the index of the first occurrence of the small string in the big one (or -1 if none, in which case you're done). Then, use bigString.substring to get the pieces of the big string before and after the match, and finally concat to put those before and after pieces back together, with your intended replacement in the middle.

Alex Martelli
amen - this answer demonstrates a key principle of s/w development: just because you have a tool, doesn't mean you have to use it. I can't tell you how many times I see mid-level programmers sort list to find the smallest element.
Kevin Day
That's a good comment. But note that this manual approach takes several lines of code, which may require comments and unit tests to avoid bugs. Using a single line `replaceFirst' call is clearer and less error-prone, even though it may also be slower at runtime. Don't optimise prematurely.
Bennett McElwee
A: 

Take a look at this sample

adatapost
A: 

As Laurence suggested, you can use Pattern.quote like this:

newString = string.replaceFirst(Pattern.quote(substring), replacement);

This creates a new regex that literally matches the substring. Another approach is simply to compile the substring as a literal regex like this:

newString = Pattern.compile(substring, Pattern.LITERAL).
        matcher(string).replaceFirst(replacement);

This might be slightly more efficient, but also a bit less clear.

You could also do it manually, since you're only wanting to replace the first occurrence. But regexes are pretty efficient, so don't optimise prematurely!

Bennett McElwee