title: Using Matcher.appendReplacement() with multiple regions
body: <p>The java Matcher.appendReplacement() method (with appendTail()) is supposed to let me transform a source text into a result text while replacing all occurrences of a pattern.
  The algorithm in pseudolanguage would be something like:</p>
  
  <pre><code>while Matcher.find() {
    call Matcher.appendReplacement()
  }
  call Matcher.appendTail()
  </code></pre>
  
  <p>If the pattern is searched only inside a given region, all is fine:</p>
  
  <pre><code>call Matcher.region()
  while Matcher.find() {
    call Matcher.appendReplacement()
  }
  call Matcher.appendTail()
  </code></pre>
  
  <p>The problem arises when, after matching inside a region, I want to move the region further:</p>
  
  <pre><code>call Matcher.region()
  while Matcher.find() {
    call Matcher.appendReplacement()
  }
  call Matcher.region()
  while Matcher.find() {
    call Matcher.appendReplacement()
  }
  call Matcher.appendTail()
  </code></pre>
  
  <p>This doesn't work because region() resets the matcher so that Matcher.appendReplacement() restarts from the beginning of the text, causing the result to contain duplication of some part of the source.</p>
  
  <p>This happens by design, as the javadoc says.</p>
  
  <p>What is the correct way of replacing a pattern that can be located inside more than one region?</p>
  
  <p><em>Edit: java example added, text example removed</em></p>
  
  <p>The following java example shows that from an input like </p>
  
  <p>dog1 start dog2a dog2b end dog3 start dog4a dog4b end dog5</p>
  
  <p>you don't get the expected output</p>
  
  <p>dog1 start cat2a cat2b end dog3 start cat4a cat4b end dog5</p>
  
  <pre><code>package test;
  
  import java.util.regex.Matcher;
  import java.util.regex.Pattern;
  
  public class TestMatcher {
  
      public static void main(String[] args) throws Exception {
          String inputText = "dog1 start dog2a dog2b end dog3 start dog4a dog4b end dog5";
          System.out.println("input  = " + inputText);
          StringBuffer result = new StringBuffer();
          Pattern pattern = Pattern.compile("dog");
          Matcher matcher = pattern.matcher(inputText);
  
          int startPos = inputText.indexOf("start");
          int endPos = inputText.indexOf("end");
          System.out.println("Setting region to " + startPos + "," + endPos);
          matcher.region(startPos, endPos);
          while (matcher.find()) {
              matcher.appendReplacement(result, "cat");
          }
          System.out.println("Partial result = " + result);
  
          startPos = inputText.indexOf("start", endPos);
          endPos = inputText.indexOf("end", startPos);
          System.out.println("Setting region to " + startPos + "," + endPos);
          matcher.region(startPos, endPos);
          while (matcher.find()) {
              matcher.appendReplacement(result, "cat");
          }
          matcher.appendTail(result);
          System.out.println("Final result   = " + result);
      }
  }
  </code></pre>
  
  <p>Output:</p>
  
  <pre><code>input  = dog1 start dog2a dog2b end dog3 start dog4a dog4b end dog5
  Setting region to 5,23
  Partial result = dog1 start cat2a cat
  Setting region to 32,50
  Final result   = dog1 start cat2a catdog1 start dog2a dog2b end dog3 start cat4a cat4b end dog5
  </code></pre>