文档章节

Java Matcher源码学习记录

zhuqianli
 zhuqianli
发布于 2017/09/11 20:33
字数 764
阅读 1
收藏 0
点赞 0
评论 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
博文 130
码字总数 56976
作品 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
js和java中正则表达式的易混淆点

js中正则表达式的使用 对表单中的值进行正则表达式匹配一般有两种方法: var reg = new RegExp(regStr); reg.test(value); 如下: var reg = new RegExp(“\d{3}”); reg.test(“abc123def”...

绝影jy
2014/07/30
0
0
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
关于java中split的使用

之前在http://shukuiyan.iteye.com/blog/507915文中已经叙述过这个问题,但是最近一次笔试中居然有碰到了这个知识点,而且还做错了,囧!学艺不精啊。题目大概是这样的: Java代码 String s...

墨梅
2014/04/28
0
0
简化你的 java 字符串操作:Guava 之 CharMatcher 用法简介

对字符串的处理应该是编程活动中最频繁的操作了,而原生的 JDK 以及 Java 本身的语法特性使得在 Java 中进行字符串操作是一件极其麻烦的事情,如果你熟悉 Shell/Awk/Sed/Perl/Python 等脚本语...

大数据之路
2013/11/24
0
5
sharding-jdbc源码分析—准备工作

原文作者:阿飞Javaer 原文链接:https://www.jianshu.com/p/7831817c1da8 接下来对sharding-jdbc源码的分析基于tag为源码,根据sharding-jdbc Features深入学习sharding-jdbc的几个主要特性...

飞哥-Javaer
05/03
0
0
111 多线程JUC包下代码分析

Java多线程系列目录(共43篇) AtomicLongFieldUpdater:通过反射+CAS实现对传入对象的指定long字段实现类似AtomicLong的操作 http://www.cnblogs.com/skywang12345/p/javathreadscategory.ht...

素雷
2017/10/31
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

实现异步有哪些方法

有哪些方法可以实现异步呢? 方式一:java 线程池 示例: @Test public final void test_ThreadPool() throws InterruptedException { ScheduledThreadPoolExecutor scheduledThre......

黄威
今天
0
0
linux服务器修改mtu值优化cpu

一、jumbo frames 相关 1、什么是jumbo frames Jumbo frames 是指比标准Ethernet Frames长的frame,即比1518/1522 bit大的frames,Jumbo frame的大小是每个设备厂商规定的,不属于IEEE标准;...

六库科技
今天
0
0
牛客网刷题

1. 二维数组中的查找(难度:易) 题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入...

大不了敲一辈子代码
今天
0
0
linux系统的任务计划、服务管理

linux任务计划cron 在linux下,有时候要在我们不在的时候执行一项命令,或启动一个脚本,可以使用任务计划cron功能。 任务计划要用crontab命令完成 选项: -u 指定某个用户,不加-u表示当前用...

黄昏残影
昨天
0
0
设计模式:单例模式

单例模式的定义是确保某个类在任何情况下都只有一个实例,并且需要提供一个全局的访问点供调用者访问该实例的一种模式。 实现以上模式基于以下必须遵守的两点: 1.构造方法私有化 2.提供一个...

人觉非常君
昨天
0
0
《Linux Perf Master》Edition 0.4 发布

在线阅读:https://riboseyim.gitbook.io/perf 在线阅读:https://www.gitbook.com/book/riboseyim/linux-perf-master/details 百度网盘【pdf、mobi、ePub】:https://pan.baidu.com/s/1C20T......

RiboseYim
昨天
1
0
conda 换源

https://mirrors.tuna.tsinghua.edu.cn/help/anaconda/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/conda config --add channels https://mir......

阿豪boy
昨天
1
0
Confluence 6 安装补丁类文件

Atlassian 支持或者 Atlassian 缺陷修复小组可能针对有一些关键问题会提供补丁来解决这些问题,但是这些问题还没有放到下一个更新版本中。这些问题将会使用 Class 类文件同时在官方 Jira bug...

honeymose
昨天
0
0
非常实用的IDEA插件之总结

1、Alibaba Java Coding Guidelines 经过247天的持续研发,阿里巴巴于10月14日在杭州云栖大会上,正式发布众所期待的《阿里巴巴Java开发规约》扫描插件!该插件由阿里巴巴P3C项目组研发。P3C...

Gibbons
昨天
1
0
Tomcat介绍,安装jdk,安装tomcat,配置Tomcat监听80端口

Tomcat介绍 Tomcat是Apache软件基金会(Apache Software Foundation)的Jakarta项目中的一个核心项目,由Apache、Sun和其他一些公司及个人共同开发而成。 java程序写的网站用tomcat+jdk来运行...

TaoXu
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部