文档章节

Java Matcher源码学习记录

zhuqianli
 zhuqianli
发布于 2017/09/11 20:33
字数 764
阅读 2
收藏 0
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;
}

© 著作权归作者所有

共有 人打赏支持
上一篇: 内网穿透工具
下一篇: 小算法记录
zhuqianli
粉丝 5
博文 131
码字总数 57017
作品 0
杭州
程序员
私信 提问
java正则表达式对字符串的操作

学习java正则表达式的都知道,它的重要性;但同时也了解它的难度和复杂性。所以为了加深我们对它的了解。我举了几个例子: 例子1、 查找以Java开头,任意结尾的字符串 Pattern pattern = Patt...

goqin
2012/06/29
0
0
String类replaceAll方法正则替换深入分析

背景: 前几天有人发了一个关于下面问题的贴,对这个有点好奇,故花时间做了点研究。 对单个反斜杠字符串替换成双斜杠的Java实现如下: String s = ""; 方法一:String sr1 = s.replaceAll("...

囚兔
2012/12/28
0
1
Java 正则表达式功能及应用

正则表达式,就是用某种模式去匹配一类字符串的一个公式,正则表达式由一些普通字符和一些元字符(metacharacters)组成。普通字符包括大小写的字母和数字,而元字符则具有特殊的含义,不管是...

浮躁的码农
2015/07/29
0
0
java RegularExpression

/* * * 使用Matcher的find() appendReplacement() appednTail()方法可以很灵活的进行替换, * * 相当强劲 太优雅了 * */ public static void MatcherReplacement() { Pattern p=Pattern.com......

TracyZhang
2012/06/25
0
0
java.util.regex Pattern 正则

/**String 中 replaceAll(),matches(),split() 等方法,都是调用Pattern中的方法。学习了,瞬间觉得Pattern强大了 public String replaceAll(String regex, String replacement) {return Pat......

happycode
2014/04/02
0
1

没有更多内容

加载失败,请刷新页面

加载更多

Sentry使用

Sentry使用 以django为例.实际上sentry本身文档已经有介绍了.这里只是再总结 1、全局异常捕获 此方法可以全局捕获任何的异常(甚至包括你自己raise的异常),在实际使用过程中不太推荐.但胜在快...

_Change_
23分钟前
1
0
linux系统包管理工具详解 yum rpm apt-get pip wget

在Linux系统下,根据系统版本的不同会有各种各样的包管理工具,下面就简单的梳理一下这几种安装命令. 1、yum Yum(全称为 Yellow dog Updater, Modified)是一个在Fedora、RedHat、CentOS中的...

huoyoung
27分钟前
1
0
阿里巴巴Dubbo实现的源码分析

1. Dubbo概述 Dubbo是阿里巴巴开源出来的一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及作为SOA服务治理的方案。它的核心功能包括: #remoting:远程通讯基础,提...

别打我会飞
28分钟前
6
0
tomcat的maxThreads、acceptCount(最大线程数、最大排队数)

tomcat 6的Connector配置如下: <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" maxThreads......

为了美好的明天
31分钟前
3
0
阿里P9架构师谈:高并发网站的监控系统选型、比较、核心监控指标

在高并发分布式环境下,对于访问量大的业务、接口等,需要及时的监控网站的健康程度,防止网站出现访问缓慢,甚至在特殊情况出现应用服务器雪崩等场景,在高并发场景下网站无法正常访问的情况...

架构师springboot
31分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部