Thomas S.
Thomas S.

Reputation: 6365

Java Regular expressions search and replace

When writing a text editor with find and replace functionality the user has the ability to search multiple times and then replace. In Java the search part is quite easy:

Pattern pattern = Pattern.compile(userInput);
...
String line = ...
Matcher matcher = pattern.matcher(line);
int from = 0;
while (from < line.length() && matcher.find(from)) {
  int start = matcher.start();
  int length = matcher.end() - start;
  // pseudo-code:
  if (askUser()) {
    return ...
  }

  from = start + 1;
}

But how to handle the replace of the n-th match? Matcher has replaceAll and replaceFirst. The first obviously will not be suitable, but for the replaceFirst the documentation says:

Replaces the first subsequence of the input sequence that matches the pattern with the given replacement string. This method first resets this matcher. It then scans the input sequence looking for a match of the pattern.

where the bold sentence makes me worry whether it would be suitable here. I'd need something to replace the current match with a certain pattern.

Upvotes: 4

Views: 104

Answers (2)

Erwin Bolwidt
Erwin Bolwidt

Reputation: 31299

If you want to replace with the full Matcher.replaceFirst syntax, which includes possible references to capture groups, you can look at the source of replaceFirst. It calls two public methods in Matcher: appendReplacement and appendTail. You can call them too without first resetting the matcher and without doing a find call:

StringBuffer sb = new StringBuffer();
matcher.appendReplacement(sb, replacement);
matcher.appendTail(sb);

This results in a new Stringbuffer with the input string except that the current match is replaced by your replacement String (which can contain references to capture groups)

Upvotes: 1

Sweeper
Sweeper

Reputation: 274470

If you want to replace a specific match, call find() multiple times and replace the matched portion using the start() and end() methods.

StringBuilder builder = new StringBuilder(stringToMatch);
Matcher m = Pattern.compile(yourRegex).matcher(stringToMatch);
for (int i = 0 ; i < n ; i++) { // n is the nth match you want to replace
    m.find();
}
builder.replace(m.start(), m.end(), yourReplacement);

Upvotes: 6

Related Questions