code: public static String replaceFirst(final CharSequence self, final Pattern pattern, final @ClosureParams(value=FromString.class, options={"List<String>","String[]"}) Closure closure) {
          final String s = self.toString();
          final Matcher matcher = pattern.matcher(s);
          if (matcher.find()) {
              final StringBuffer sb = new StringBuffer(s.length() + 16);
              String replacement = getReplacement(matcher, closure);
              matcher.appendReplacement(sb, Matcher.quoteReplacement(replacement));
              matcher.appendTail(sb);
              return sb.toString();
          } else {
              return s;
          }
      }
docs: Replaces the first occurrence of a captured group by the result of a closure call on that text.
  <p>
  For example (with some replaceAll variants thrown in for comparison purposes),
  <pre>
  assert "hellO world" == "hello world".replaceFirst(~"(o)") { it[0].toUpperCase() } // first match
  assert "hellO wOrld" == "hello world".replaceAll(~"(o)") { it[0].toUpperCase() }   // all matches
  
  assert '1-FISH, two fish' == "one fish, two fish".replaceFirst(~/([a-z]{3})\s([a-z]{4})/) { [one:1, two:2][it[1]] + '-' + it[2].toUpperCase() }
  assert '1-FISH, 2-FISH' == "one fish, two fish".replaceAll(~/([a-z]{3})\s([a-z]{4})/) { [one:1, two:2][it[1]] + '-' + it[2].toUpperCase() }
  </pre>
  
  @param self    a CharSequence
  @param pattern the capturing regex Pattern
  @param closure the closure to apply on the first captured group
  @return a CharSequence with replaced content
  @since 1.8.2