As you no doubt have gathered, the only sensible way to do this kind of thing is to make all the replacements in one pass, generating the replacement strings dynamically based on what was matched.
Java seems to be unique among today's major languages in not providing a convenient way to do that, but it can be done. You just have to use the lower-level API provided by the Matcher class. Here's a demonstration, based on Elliott Hughes's definitive Rewriter class:
import java.util.regex.*;
/**
* A Rewriter does a global substitution in the strings passed to its
* 'rewrite' method. It uses the pattern supplied to its constructor, and is
* like 'String.replaceAll' except for the fact that its replacement strings
* are generated by invoking a method you write, rather than from another
* string. This class is supposed to be equivalent to Ruby's 'gsub' when
* given a block. This is the nicest syntax I've managed to come up with in
* Java so far. It's not too bad, and might actually be preferable if you
* want to do the same rewriting to a number of strings in the same method
* or class. See the example 'main' for a sample of how to use this class.
*
* @author Elliott Hughes
*/
public abstract class Rewriter
{
private Pattern pattern;
private Matcher matcher;
/**
* Constructs a rewriter using the given regular expression; the syntax is
* the same as for 'Pattern.compile'.
*/
public Rewriter(String regex)
{
this.pattern = Pattern.compile(regex);
}
/**
* Returns the input subsequence captured by the given group during the
* previous match operation.
*/
public String group(int i)
{
return matcher.group(i);
}
/**
* Overridden to compute a replacement for each match. Use the method
* 'group' to access the captured groups.
*/
public abstract String replacement();
/**
* Returns the result of rewriting 'original' by invoking the method
* 'replacement' for each match of the regular expression supplied to the
* constructor.
*/
public String rewrite(CharSequence original)
{
this.matcher = pattern.matcher(original);
StringBuffer result = new StringBuffer(original.length());
while (matcher.find())
{
matcher.appendReplacement(result, "");
result.append(replacement());
}
matcher.appendTail(result);
return result.toString();
}
public static void main(String... args) throws Exception
{
String str = ">Foo baR<";
// anonymous subclass example:
Rewriter caseSwapper = new Rewriter("[A-Za-z]")
{
public String replacement()
{
char ch0 = group(0).charAt(0);
char ch1 = Character.isUpperCase(ch0) ?
Character.toLowerCase(ch0) :
Character.toUpperCase(ch0);
return String.valueOf(ch1);
}
};
System.out.println(caseSwapper.rewrite(str));
// inline subclass example:
System.out.println(new Rewriter(">(\\w+)|(\\w+)<")
{
public String replacement()
{
return group(1) != null ? group(1) + "<"
: ">" + group(2);
}
}.rewrite(str));
}
}