关于Java中Match类的appendReplacement()方法的一个坑{java.lang.IllegalArgumentException: character to be escaped is missing}

问题描述

在向替换结果中追加信息的时候,调用match.appendReplacement(buffer,str)时出现了上述异常。
    class XX{public String renderString(String source, Map<String, Object> context, Map<String, Object> data) throws OgnlException {Pattern pattern = Pattern.compile(DELIM);Matcher matcher = pattern.matcher(source);StringBuffer buffer = new StringBuffer();while (matcher.find()) {String e = matcher.group(1);if (e == null) throw new NullPointerException("expression can not be null");Object value = Ognl.getValue(e, context, data);String str = null == value ? "null" : value.toString();matcher.appendReplacement(buffer, str); //在此处报错}matcher.appendTail(buffer);return buffer.toString();}}

问题原因

通过阅读Matcher类的源码并查阅文档得知,在 matcher.appendReplacement(buffer, str)方法中str中若含有'\'、'$'字符时,将存在特殊含义,
'$n'代表匹配的第n组结果,'\'将对其之后的字符进行转义。

文档如下

    实现非终端添加和替换步骤。 此方法执行以下操作: 它从添加位置开始在输入序列读取字符,并将其添加到给定字符串缓冲区。在读取以前匹配之前的最后字符(即位于索引 start() - 1 处的字符)之后,它就会停止。它将给定替换字符串添加到字符串缓冲区。 它将此匹配器的添加位置设置为最后匹配位置的索引加 1,即 end()。 替换字符串可能包含到以前匹配期间所捕获的子序列的引用:$g 每次出现时,都将被 group(g) 的计算结果替换。$ 之后的第一个数始终被视为组引用的一部分。如果后续的数可以形成合法组引用,则将被合并到 g 中。只有数字 '0' 到 '9' 被视为组引用的可能组件。例如,如果第二个组匹配字符串 "foo",则传递替换字符串 "$2bar" 将导致 "foobar" 被添加到字符串缓冲区。可能将美元符号 ($) 作为替换字符串中的字面值(通过前面使用一个反斜线 (\$))包括进来。 注意,在替换字符串中使用反斜线 (\) 和美元符号 ($) 可能导致与作为字面值替换字符串时所产生的结果不同。美元符号可视为到如上所述已捕获子序列的引用,反斜线可用于转义替换字符串中的字面值字符。 此方法设计用于循环以及 appendTail 和 find 方法中。例如,以下代码将 one dog two dogs in the yard 写入标准输出流中: 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());参数:sb - 目标字符串缓冲区。replacement - 替换字符串。 返回:匹配器。 抛出: IllegalStateException - 如果没有尝试任何匹配,或者以前的匹配操作失败。 IndexOutOfBoundsException - 如果替换字符串引用模式中不存在的捕获组。

源码如下

public final class Matcher implements MatchResult {//省略public Matcher appendReplacement(StringBuffer sb, String replacement) {//省略while (cursor < replacement.length()) {char nextChar = replacement.charAt(cursor);if (nextChar == '\\') {cursor++;if (cursor == replacement.length())throw new IllegalArgumentException("character to be escaped is missing");nextChar = replacement.charAt(cursor);result.append(nextChar);cursor++;} else if (nextChar == '$') {//省略} else {result.append(nextChar);cursor++;}}// Append the intervening textsb.append(text, lastAppendPosition, first);// Append the match substitutionsb.append(result);lastAppendPosition = last;return this;}
}

关于Java中Match类的appendReplacement()方法的一个坑{ character to be escaped }相关推荐

  1. Java中String类的concat方法___java的String字符串的concat()方法连接字符串和“+“连接字符串解释

    Java中String类的concat方法 在了解concat()之前,首先需要明确的是String的两点特殊性. 长度不可变 值不可变 这两点从源码中对String的声明可以体现: private ...

  2. Java 中Date类getTime()的方法

    Java 中Date类getTime()的方法 1.getTime() /**Returns the number of milliseconds since January 1, 1970, 00: ...

  3. Java中List集合的addAll方法的小坑

    Java中List集合的addAll方法的小坑 遇到的问题 已有一个封装类的ArrayList的集合,命名为firstList,现在需要把firstList中的值复制给另一个List,另一个List命 ...

  4. Java中abstract类和abstract方法的相关问题

    当知道一个类的子类将不同的实现某个方法时,把该类声明为抽象类很有用,可以共用相同的父类方法,不必再定义. 抽象类和抽象方法的关系:含有抽象方法的类一定是抽象类,抽象类里不一定含有抽象方法. 抽象类存在 ...

  5. Java中Scanner类的close()方法所引发的错误

    Java通过系统类System实现标准输入/输出的功能 我们经常通过实例化Scanner类的方式实现从键盘的数据输入 但其中的如果对其中一些细节不了解,就会引发不能理解的错误 比如close方法: i ...

  6. Java中BigInteger类的使用方法详解,常用最全系列!

    原创博文,欢迎转载,转载时请务必附上博文链接,感谢您的尊重. 在 Java 中,有许多数字处理的类,比如 Integer类,但是Integer类有一定的局限性. 我们都知道 Integer 是 Int ...

  7. JAVA中Math类的random()方法使用

    使用了Math类的random()方法, 由于Math类是出于java.lang包(Package),故使用时不必import这个包. 此外本例还使用了移位运算符 /*** 使用了Math类的rand ...

  8. 关于Java中String类的intern()方法

    首先intern()方法的定义:当调用这个方法的时候,如果字符串常量池中有这个对象,就把常量池中的这个对象返回,没有就把当前对象加入到常量池并且返回当前对象的引用: jdk1.6之前:将对象存入常量池 ...

  9. Java中BigDecimal类的使用方法详解,常用最全系列!

    Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算.对于Double类型的运算,通常使用此类处理,来有效避免精度问题. 下面,我们从五个功能点 ...

最新文章

  1. php的反射作用是什么意思,php反射的作用是什么
  2. nodejs、gulp调试工具node-inspector使用
  3. java websocket_理清 WebSocket 和 HTTP 的关系
  4. DPDK — App 的 Makefile 解析
  5. Object Hook 简单介绍
  6. 布道微服务_06微服务调用的监控
  7. php中的id怎么传值,uniapp如何跳转页面传值
  8. 在linux下解压jdk时出现的问题
  9. LeetCode 88. Merge Sorted Array
  10. 公开课精华 | 无人驾驶中感知的挑战与尝试
  11. HTML 5 aside 标签
  12. 对 SharePoint WebService 的调用
  13. Arduion 底层原理之 Uart函数 串口收发 串口协议解析
  14. 使用SpringSide 3.1.4.3开发Web项目的全过程(中下)
  15. 插头DP/轮廓线DP
  16. 那些有趣的网站系列(六)
  17. 时钟、背景音乐、背景图片
  18. 上传文件到服务器太大怎么办,超大文件怎么上传到云服务器
  19. windows下bat文件一直循环一句话如何解决
  20. 微信小游戏保存自定义分享图到相册实例

热门文章

  1. linux下的IO重定向与管道相关的知识简析
  2. zabbix lld使用trapper方式(zabbix_sender)
  3. js-url转换blob以及blob与base64的相互转换
  4. iMazing2.15.9版app苹果手机备份同步神器存档恢复超方便
  5. 短信业务 防恶意攻击解决方案
  6. 设计模式-设计原则-开闭原则是目标,里氏代换原则是基础,依赖倒转原则是手段...
  7. Apple Lossless Audio Codec 苹果无损音频解码器
  8. 聊聊 8种 架构模式
  9. 计算机系统原理实验——微程序控制器
  10. java 记录微信转发次数_微信分享朋友圈记录分享次数统计实现