Pattern p = Pattern.compile("cat");
Matcher m = p.matcher("one cat two cats in the yard");
StringBuffer sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, "dog");
}
m.appendTail(sb);
System.out.println(sb.toString());
public Matcher appendReplacement(StringBuffer sb, String replacement) {
// If no match, return error
if (first < 0) //first表示正则匹配到的第一个字符在字符串(one cat two cats in the yard)中的下标
throw new IllegalStateException("No match available");
// Process substitution string to replace group references with groups
int cursor = 0; //当前操作字符在替代字符串(dog)中的下标
StringBuilder result = new StringBuilder();//解析替代字符串的结果
//开始解析
while (cursor < replacement.length()) {
char nextChar = replacement.charAt(cursor);//获取当前操作的字符
if (nextChar == '\\') {//如果当前操作的字符是转义符号
//下面就是解析replacement转义符号的过程
cursor++;//跳过转义符号
if (cursor == replacement.length())
throw new IllegalArgumentException(
"character to be escaped is missing");
nextChar = replacement.charAt(cursor);//获取转义符号后面的字符
result.append(nextChar);//添加到result
cursor++;//下标加一 回到上面while循环
} else if (nextChar == '$') {//如果当前操作的字符是$
//下面就是解析replacement中如何引用捕获组的内容
// Skip past $
cursor++;// 跳过$符号
// Throw IAE if this "$" is the last character in replacement
if (cursor == replacement.length())
throw new IllegalArgumentException(
"Illegal group reference: group index is missing");
nextChar = replacement.charAt(cursor);//获取$后面的字符
int refNum = -1;
if (nextChar == '{') {//解析命名捕获组
cursor++;
StringBuilder gsb = new StringBuilder();//提取${groupname}中的groupname字符串
while (cursor < replacement.length()) {
nextChar = replacement.charAt(cursor);//获取{的下一个字符
if (ASCII.isLower(nextChar) ||
ASCII.isUpper(nextChar) ||
ASCII.isDigit(nextChar)) {//这个字符是大小写的字母或数字
gsb.append(nextChar);
cursor++;
} else {//不是的话退出循环 后面判断是不是这个字符是不是},不是就抛异常
break;
}
}
if (gsb.length() == 0)
throw new IllegalArgumentException(
"named capturing group has 0 length name");
if (nextChar != '}')
throw new IllegalArgumentException(
"named capturing group is missing trailing '}'");
String gname = gsb.toString();// group name
if (ASCII.isDigit(gname.charAt(0))) //group name 不能以数字开头
throw new IllegalArgumentException(
"capturing group name {" + gname +
"} starts with digit character");
if (!parentPattern.namedGroups().containsKey(gname)) //捕获组的Map中要有相对应的group name
throw new IllegalArgumentException(
"No group with name {" + gname + "}");
refNum = parentPattern.namedGroups().get(gname);//获取在捕获组中是第几个 begin with 1
cursor++;
} else {
// The first number is always a group
refNum = (int)nextChar - '0'; //减去字符0的ASCII码
if ((refNum < 0)||(refNum > 9))//不是数字的话 抛异常
throw new IllegalArgumentException(
"Illegal group reference");
cursor++;
// Capture the largest legal group string
boolean done = false;
while (!done) {
if (cursor >= replacement.length()) {//当前操作是最后一个字符或者后面已经没有字符了
break;
}
int nextDigit = replacement.charAt(cursor) - '0';//减去字符0的ASCII码
if ((nextDigit < 0)||(nextDigit > 9)) { // not a number 数字后面不是数字了
break;
}
int newRefNum = (refNum * 10) + nextDigit;//还是数字 乘10累加上去
if (groupCount() < newRefNum) {//累加后发现数值大于捕获组的总数
done = true;//结束返回refNum中的值
} else {//累加后的数值小于或等于捕获组总数 继续循环下一个字符
refNum = newRefNum;/
cursor++;
}
}
}
// Append group
if (start(refNum) != -1 && end(refNum) != -1)
result.append(text, start(refNum), end(refNum)); //获取对应捕获组的开始下标和结束下标
} else {//正常字符直接添加
result.append(nextChar);
cursor++;
}
}
// Append the intervening text
sb.append(text, lastAppendPosition, first);//上一次添加位置到捕获组第一个字符位置
// Append the match substitution
sb.append(result);//添加解析后的替代字符串
lastAppendPosition = last;
return this;
}