为什么

由于工作是做数据ETL的,很多时候会使用到正则对数据进行提取,但是java的正则中的groupname不支持'_',官方的文档中是这样的:

Group name

A capturing group can also be assigned a "name", a named-capturing group, and then be back-referenced later by the "name". Group names are composed of the following characters. The first character must be a letter.

The uppercase letters 'A' through 'Z' ('\u0041' through '\u005a'),

The lowercase letters 'a' through 'z' ('\u0061' through '\u007a'),

The digits '0' through '9' ('\u0030' through '\u0039'),

A named-capturing group is still numbered as described in Group number.

The captured input associated with a group is always the subsequence that the group most recently matched. If a group is evaluated a second time because of quantification then its previously-captured value, if any, will be retained if the second evaluation fails. Matching the string "aba" against the expression (a(b)?)+, for example, leaves group two set to "b". All captured input is discarded at the beginning of each match.

Groups beginning with (? are either pure, non-capturing groups that do not capture text and do not count towards the group total, or named-capturing group.

可以看到,只支持大写字母A-Z、小写字母a-z、数字0-9

查找源代码

在java.util.regex.Pattern类的以下源码中(jdk1.8.141是2789行)有下面这个方法:

    /**
* Parses and returns the name of a "named capturing group", the trailing
* ">" is consumed after parsing.
*/
private String groupname(int ch) {
StringBuilder sb = new StringBuilder();
sb.append(Character.toChars(ch));
while (ASCII.isLower(ch=read()) || ASCII.isUpper(ch) ||
ASCII.isDigit(ch)) {
sb.append(Character.toChars(ch));
}
if (sb.length() == 0)
throw error("named capturing group has 0 length name");
if (ch != '>')
throw error("named capturing group is missing trailing '>'");
return sb.toString();
}

可以看到,源代码中对groupname的提取是一个while循环,当读取到的字符是小写字母(ASCII.isLower)、大写字母(ASCII.isUpper)、数字(ASCII.isDigit)的时候,会把这个字符添加到StringBuilder中,然后读取下个字符,知道不满足这个条件。

修改源代码

好,现在知道是这个原因了,怎么进行修改呢?

有很多人说不要修改大神写的代码,但是没办法。

由于不支持'_', 给工作带来挺多其它麻烦的,比如数据库中的字段名有'_',如果正则组不支持下划线的话,就需要一个正则组名和列名的映射关系,或者不用正则组名,使用正则组下标0,1,2...来映射。比较繁琐。

修改其实很简单,由于Pattern这个类在源代码中定义为final的,没法直接继承然后overwrite这个方法,就只能在自己的项目下新建一个regex包,将java.util.regex包的类都copy出来,总共是6个

修改Pattern的上述方法,'_'这个字符在ASCII中是95,所以添加一个判断就可以了:

    private String groupname(int ch) {
StringBuilder sb = new StringBuilder();
sb.append(Character.toChars(ch));
//TODO 增加了ch==95这个条件来支持正则组名支持下划线('_'),
//源码为java.util.regex.Pattern的2793行
while (ASCII.isLower(ch=read()) || ASCII.isUpper(ch) ||
ASCII.isDigit(ch) || ch == 95) {
sb.append(Character.toChars(ch));
}
if (sb.length() == 0)
throw error("named capturing group has 0 length name");
if (ch != '>')
throw error("named capturing group is missing trailing '>'");
return sb.toString();
}

这样就可以使用我们自己Pattern类了,最后成功运行

public class MyTest {
public static void main(String[] args) {
Pattern pattern = Pattern.compile("\\s\\|\\s(?<my_name>worker_\\d+)\\s\\|");
Matcher matcher = pattern.matcher("2017-02-14 23:58:04 | worker_10 | [ATMP05]");
if (matcher.find()){
//打印出来是"worker_10"
System.out.println(matcher.group("my_name"));
}
}
}

最后,这个源码值改了一小部分,但是却让工作轻松了

当然,这样改是否会影响到其它东西需要时间的检验。

修改 Pattern代码使 Java 正则表达式支持下划线 '_'的更多相关文章

  1. 昨天发现的nginx默认不支持下划线引起angular-phonecat项目部分文件404问题

    今天发现原来确实是不存在这个文件... 因为我的Ubuntu的git没有安装,所以导致bower install时没有拉下来依赖包,因为bower是使用的git拉的包. 但是同时也搜到了nginx不支 ...

  2. java驼峰法和下划线法字符串的相互转换

    java驼峰法和下划线法字符串的相互转换 1 import java.util.regex.Matcher; import java.util.regex.Pattern; public class ...

  3. 去掉VS2010代码中文注释的红色下划线

    VS2010代码中文注释出现红色下划线,代码看上去很不美观,发现是由于安装Visual Assist X插件造成的. 解决办法:打开VAX的Options对话框,取消Advanced --> U ...

  4. scala中的下划线_

    1.作为“通配符”,类似Java中的*. 例如 import scala.math._ 2.:_*作为一个整体,告诉编译器你希望将某个参数当作参数序列处理! 例如 val s = sum(1 to 5 ...

  5. css命名为何不推荐使用下划线_

    一直习惯了在命名CSS样式名时使用下划线“_”做为单词的分隔符,这也是在写JS时惯用的写法. 用过CSS hack的朋友应该知道,用下划线命名也是一种hack,如使用“_style”这样的命名,可以让 ...

  6. 为什么我不建议在C#中用下划线_开头来表示私有字段

    我在C#官方文档的使用属性里看到这种代码: public class Date { private int _month = 7; // Backing store public int Month ...

  7. Scala 神奇的下划线 _

    引言 在 Scala 中,下划线 _ 有很多种用法,作为 Scala 初学者也经常被下划线 _ 搞得晕头转向,下面是对 Scala 中下划线 _ 使用的简单总结~ 导包时, 下划线 _ 表示引用多个方 ...

  8. Python 私有变量中两个下划线 _ _item 与 一个下划线的区别 _item

    python中没有常量的说法, 但是可以通过元组实现一个常量 在python的私有变量中, 存在两个下划线 _ _item 与一个下划线 _item 的区别 前面带两个下划线的私有变量: 只能在本类中 ...

  9. python中有两个下划线__的是内置方法,一个下划线_或者没有下划线的可能是属性,也可能是方法,也可能是类名

    python中有两个下划线__的是内置方法,一个下划线_或者没有下划线的可能是属性,也可能是方法,也可能是类名,如果在类中定义的就是类的私有成员. >>> dir(__builtin ...

随机推荐

  1. Django中ORM模型总结(一)[概述,查询语句]

    理解ORM框架 概述 O:(objects)->类和对象. R:(Relation)->关系,关系数据库中的表格. M:(Mapping)->映射. 作用: 可以通过类和类对象就可以 ...

  2. 第五章之S5PV210将u-boot.bin从SD卡中搬到DDR中

    1,在完成上一节的memory初始化后,接下来在arch/arm/cpu/armv7/start.S的160行:如下图 2,跳转到arch/arm/lib/board.c下的board_init_f函 ...

  3. 23. leetcode 169. Majority Element

    169. Majority Element Given an array of size n, find the majority element. The majority element is t ...

  4. vscode--搭建自动编译sass环境

    一,安装插件及使用步骤 1.vscode安装Live Sass Compiler,由于该插件依赖Live Server ,所以会自动安装Live Server 2.点击vscode底部的Watch m ...

  5. SSRF漏洞学习

    SSRF SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞.一般情况下,SSRF攻击的目标是从外网无法访问的内 ...

  6. CI框架主题切换的功能

    CI框架主题切换的功能 本人接触到这个框架不就,属于菜鸟 , 公司现在用CI框架做项目 ,老大要做一个主题切换的功能,说明功能的要求我的脑子里瞬间有几个想法. 脑子里最简单的就是设置全局变量 如 : ...

  7. Handler实现线程之间的通信-下载文件动态更新进度条

    1. 原理 每一个线程对应一个消息队列MessageQueue,实现线程之间的通信,可通过Handler对象将数据装进Message中,再将消息加入消息队列,而后线程会依次处理消息队列中的消息. 2. ...

  8. 安徽省2016“京胜杯”程序设计大赛_E_转啊转

    转啊转 Time Limit: 1000 MS Memory Limit: 65536 KB Total Submissions: 59 Accepted: 15 Description     在二 ...

  9. js复习---string

    对js的string的方法复习: 1.charCodeAt()  返回一个整数,代表指定位置字符串的unicode编码. strObj.charCodeAt(index) index 是处理字符的从零 ...

  10. NYOJ 289 苹果(01背包)

    苹果 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 ctest有n个苹果,要将它放入容量为v的背包.给出第i个苹果的大小和价钱,求出能放入背包的苹果的总价钱最大值. ...