为什么

由于工作是做数据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. openstack中使用linux_bridge实现vxlan网络

    openstack环境: 1 版本:ocata 2 系统:ubuntu16.04.2 3 控制节点 1个 + 计算节点 1个 4 控制节点网卡为ens33,ip = 172.171.5.200 ens ...

  2. 进阶篇之纯css+字体实现五角星(半颗星)评分

    1.前言 之前写了一篇实现五角星打分效果的demo.这个demo用来实现打分效果绰绰有余,那么有时候我们在统计评分的时候,就会有半颗星或者1/3颗星星这样的那要如何实现呢?来来来,纯字体+css实现! ...

  3. IEnumerable & IEnumerator

    IEnumerable 只有一个方法:IEnumerator GetEnumerator(). INumerable 是集合应该实现的一个接口,这样,就能用 foreach 来遍历这个集合. IEnu ...

  4. ASP.NET MVC 开发微信支付H5(外置浏览器支付)

    H5支付是指商户在微信客户端外的移动端网页展示商品或服务,用户在前述页面确认使用微信支付时,商户发起本服务呼起微信客户端进行支付. 主要用于触屏版的手机浏览器请求微信支付的场景.可以方便的从外部浏览器 ...

  5. css中的几个小tip(一)

    原博:http://www.webhek.com/post/7-tips-web-front-developer-must-know__trashed.html 1.元素的margin-top.mar ...

  6. python关于list的三个内置函数filter(), map(), reduce()

    ''' Python --version :Python 2.7.11 Quote : https://docs.python.org/2/tutorial/datastructures.html#m ...

  7. Monotonicity 2[POI2010]

    题目描述 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k].选出一个长度为L的子序列(不要求连续),要求这个子序列的第i项和第i+1项的的大小关系为s[(i-1 ...

  8. Git分支使用心得

    在去年的大约这个时候,我的领导让我研究一下git的使用方法,方便我们自己的代码管理,因为我们原先使用的是SVN,使用起来没那么方便,所以让我研究研究git的使用.我就简单的研究了两天,用我的IDE(v ...

  9. 搭建 keras + tensorflow

    每次搭建深度学习环境的总要搜索各类参考.  这次搭环境,自己做个记录.这样以后搭建环境就拿自己 的文章做主线索引.  (如果参照我的博客安装的,欢迎转载分享 ) 1. 安装操作系统 (ubuntu-1 ...

  10. 安卓手机测试常见BUG

    安装 覆盖安装 跨版本安装 卸载后重新装 2.网络 2G网络下访问应用 网络不好的情况下,访问应用,是否会有数据返回 网络不好的情况下,切换到有网时,数据是否正常展示 WIFI断开时,再进入应用,之前 ...