文档章节

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
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

没有更多内容

加载失败,请刷新页面

加载更多

Kafka技术资料总结(不断更新中)

1、Kafka实践:到底该不该把不同类型的消息放在同一个主题中 2、Kafka剖析系列: Kafka剖析(一):Kafka背景及架构介绍 Kafka设计解析(二):Kafka High Availability (上)...

九州暮云
39分钟前
1
0
面向对象设计原则(OOP)

单一职责原则(Single responsibility principle)又称单一功能原则。它规定一个类应该只有一个发生变化的原因。 核心原则:低耦合,高内聚。 一个类,应该只有一个引起它变化的原因,也就是...

gackey
今天
4
0
C++ 锁

C++提供了两种常用的锁,std::lock_guard<Lockable &T>和std::unique_lock<Lockable &T>。通常使用场景下,这两个锁用法一致。即,在构造锁对象时上锁,在析构锁对象时解锁。使用户从上锁/解...

yepanl
今天
4
0
Kali Linux Docker 練習

docker pull kalilinux/kali-linux-docker docker run -t -i kalilinux/kali-linux-docker /bin/bash apt-get update apt-get install htop apt-get install nmap apt-get install wpscan ap......

BaiyuanLab
今天
4
0
通俗大白话来理解TCP协议的三次握手和四次分手

最近在恶补计算机网络方面的知识,之前对于TCP的三次握手和四次分手也是模模糊糊,对于其中的细节更是浑然不知,最近看了很多这方面的知识,也在系统的学习计算机网络,加深自己的CS功底,就...

onedotdot
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部